Merge "Execute transition by starting window only if visible requested" into tm-qpr-dev
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
index 18665e7..f49cdbf 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobInfo.java
@@ -241,7 +241,7 @@
 
     /**
      * Default value for all regular jobs. As noted in {@link JobScheduler},
-     * these jobs have a general maximum execution time of 10 minutes.
+     * these jobs have a general execution time of 10 minutes.
      * Receives the standard job management policy.
      */
     public static final int PRIORITY_DEFAULT = 300;
@@ -250,7 +250,7 @@
      * This task should be ordered ahead of most other tasks. It may be
      * deferred a little, but if it doesn't run at some point, the user may think
      * something is wrong. Assuming all constraints remain satisfied
-     * (including ideal system load conditions), these jobs will have a maximum
+     * (including ideal system load conditions), these jobs can have an
      * execution time of at least 4 minutes. Setting all of your jobs to high
      * priority will not be beneficial to your app and in fact may hurt its
      * performance in the long run.
@@ -260,7 +260,7 @@
     /**
      * This task should be run ahead of all other tasks. Only Expedited Jobs
      * {@link Builder#setExpedited(boolean)} can have this priority and as such,
-     * are subject to the same maximum execution time details noted in
+     * are subject to the same execution time details noted in
      * {@link Builder#setExpedited(boolean)}.
      * A sample task of max priority: receiving a text message and processing it to
      * show a notification
@@ -1414,6 +1414,15 @@
          * you also need to define the network traffic used by each work item
          * when constructing them.
          *
+         * <p class="note">
+         * Prior to Android version {@link Build.VERSION_CODES#TIRAMISU}, JobScheduler used the
+         * estimated transfer numbers in a similar fashion to
+         * {@link #setMinimumNetworkChunkBytes(long)} (to estimate if the work would complete
+         * within the time available to job). In other words, JobScheduler treated the transfer as
+         * all-or-nothing. Starting from Android version {@link Build.VERSION_CODES#TIRAMISU},
+         * JobScheduler will only use the estimated transfer numbers in this manner if minimum
+         * chunk sizes have not been provided via {@link #setMinimumNetworkChunkBytes(long)}.
+         *
          * @param downloadBytes The estimated size of network traffic that will
          *            be downloaded by this job, in bytes.
          * @param uploadBytes The estimated size of network traffic that will be
@@ -1756,14 +1765,19 @@
          *
          * <p>
          * Assuming all constraints remain satisfied (including ideal system load conditions),
-         * expedited jobs will have a maximum execution time of at least 1 minute. If your
+         * expedited jobs can have an execution time of at least 1 minute. If your
          * app has remaining expedited job quota, then the expedited job <i>may</i> potentially run
          * longer until remaining quota is used up. Just like with regular jobs, quota is not
          * consumed while the app is on top and visible to the user.
          *
-         * <p>
+         * <p class="note">
          * Note: Even though expedited jobs are meant to run as soon as possible, they may be
          * deferred if the system is under heavy load or requested constraints are not satisfied.
+         * This delay may be true for expedited jobs of the foreground app on Android version
+         * {@link Build.VERSION_CODES#S}, but starting from Android version
+         * {@link Build.VERSION_CODES#TIRAMISU}, expedited jobs for the foreground app are
+         * guaranteed to be started before {@link JobScheduler#schedule(JobInfo)} returns (assuming
+         * all requested constraints are satisfied), similar to foreground services.
          *
          * @see JobInfo#isExpedited()
          */
@@ -1799,6 +1813,9 @@
          * and in the background, or the job failed due to unsatisfied constraints,
          * this job should be expected to behave like other jobs without this flag.
          *
+         * <p>
+         * Jobs marked as important-while-foreground are given {@link #PRIORITY_HIGH} by default.
+         *
          * @param importantWhileForeground whether to relax doze restrictions for this job when the
          *                                 app is in the foreground. False by default.
          * @see JobInfo#isImportantWhileForeground()
@@ -1831,8 +1848,9 @@
          * the specific user of this device. For example, fetching top headlines
          * of interest to the current user.
          * <p>
-         * Starting with Android version {@link Build.VERSION_CODES#TIRAMISU}, prefetch jobs are
-         * not allowed to have deadlines (set via {@link #setOverrideDeadline(long)}.
+         * Apps targeting Android version {@link Build.VERSION_CODES#TIRAMISU} or later are
+         * not allowed to have deadlines (set via {@link #setOverrideDeadline(long)} on their
+         * prefetch jobs.
          * <p>
          * The system may use this signal to relax the network constraints you
          * originally requested, such as allowing a
diff --git a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
index 1429c45..ed72530 100644
--- a/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
+++ b/apex/jobscheduler/framework/java/android/app/job/JobParameters.java
@@ -167,7 +167,7 @@
     /**
      * The job used up its maximum execution time and timed out. Each individual job has a maximum
      * execution time limit, regardless of how much total quota the app has. See the note on
-     * {@link JobScheduler} for the execution time limits.
+     * {@link JobScheduler} and {@link JobInfo} for the execution time limits.
      */
     public static final int STOP_REASON_TIMEOUT = 3;
     /**
diff --git a/apex/jobscheduler/framework/java/android/app/tare/EconomyManager.java b/apex/jobscheduler/framework/java/android/app/tare/EconomyManager.java
index dd0d07f..c3fc7b1 100644
--- a/apex/jobscheduler/framework/java/android/app/tare/EconomyManager.java
+++ b/apex/jobscheduler/framework/java/android/app/tare/EconomyManager.java
@@ -16,8 +16,10 @@
 
 package android.app.tare;
 
+import android.annotation.Nullable;
 import android.annotation.SystemService;
 import android.content.Context;
+import android.util.Log;
 
 /**
  * Provides access to the resource economy service.
@@ -26,6 +28,69 @@
  */
 @SystemService(Context.RESOURCE_ECONOMY_SERVICE)
 public class EconomyManager {
+    private static final String TAG = "TARE-" + EconomyManager.class.getSimpleName();
+
+    /**
+     * 1 ARC = 1 GIGA-CAKE!
+     *
+     * @hide
+     */
+    public static final long CAKE_IN_ARC = 1_000_000_000L;
+
+    /** @hide */
+    public static long arcToCake(int arcs) {
+        return arcs * CAKE_IN_ARC;
+    }
+
+    /**
+     * Parses a configuration string to get the value in cakes.
+     *
+     * @hide
+     */
+    public static long parseCreditValue(@Nullable final String val, final long defaultValCakes) {
+        String trunc;
+        if (val == null || (trunc = val.trim()).isEmpty()) {
+            return defaultValCakes;
+        }
+        long multiplier;
+        if (trunc.endsWith("c")) {
+            trunc = trunc.substring(0, trunc.length() - 1);
+            multiplier = 1;
+        } else if (trunc.endsWith("ck")) {
+            trunc = trunc.substring(0, trunc.length() - 2);
+            multiplier = 1;
+        } else if (trunc.endsWith("A")) {
+            trunc = trunc.substring(0, trunc.length() - 1);
+            multiplier = CAKE_IN_ARC;
+        } else if (trunc.endsWith("ARC")) {
+            trunc = trunc.substring(0, trunc.length() - 3);
+            multiplier = CAKE_IN_ARC;
+        } else {
+            // Don't risk using the wrong units
+            Log.e(TAG, "Couldn't determine units of credit value: " + val);
+            return defaultValCakes;
+        }
+
+        // Allow people to shorten notation (eg. Mc for Megacake).
+        if (trunc.endsWith("k")) {
+            trunc = trunc.substring(0, trunc.length() - 1);
+            multiplier *= 1_000;
+        } else if (trunc.endsWith("M")) {
+            trunc = trunc.substring(0, trunc.length() - 1);
+            multiplier *= 1_000_000;
+        } else if (trunc.endsWith("G")) {
+            trunc = trunc.substring(0, trunc.length() - 1);
+            multiplier *= 1_000_000_000;
+        }
+
+        try {
+            return Long.parseLong(trunc) * multiplier;
+        } catch (NumberFormatException e) {
+            Log.e(TAG, "Malformed config string: " + val + " to " + trunc, e);
+            return defaultValCakes;
+        }
+    }
+
     // Keys for AlarmManager TARE factors
     /** @hide */
     public static final String KEY_AM_MIN_SATIATED_BALANCE_EXEMPTED =
@@ -276,179 +341,201 @@
 
     // Default values AlarmManager factors
     /** @hide */
-    public static final int DEFAULT_AM_MIN_SATIATED_BALANCE_EXEMPTED = 500;
+    public static final long DEFAULT_AM_MIN_SATIATED_BALANCE_EXEMPTED_CAKES = arcToCake(500);
     /** @hide */
-    public static final int DEFAULT_AM_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP = 200;
+    public static final long DEFAULT_AM_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP_CAKES =
+            arcToCake(256);
     /** @hide */
-    public static final int DEFAULT_AM_MIN_SATIATED_BALANCE_OTHER_APP = 160;
+    public static final long DEFAULT_AM_MIN_SATIATED_BALANCE_OTHER_APP_CAKES = arcToCake(160);
     /** @hide */
-    public static final int DEFAULT_AM_MAX_SATIATED_BALANCE = 1440;
+    public static final long DEFAULT_AM_MAX_SATIATED_BALANCE_CAKES = arcToCake(960);
     /** @hide */
-    public static final int DEFAULT_AM_INITIAL_CONSUMPTION_LIMIT = 4000;
+    public static final long DEFAULT_AM_INITIAL_CONSUMPTION_LIMIT_CAKES = arcToCake(2880);
     /** @hide */
-    public static final int DEFAULT_AM_HARD_CONSUMPTION_LIMIT = 28_800;
+    public static final long DEFAULT_AM_HARD_CONSUMPTION_LIMIT_CAKES = arcToCake(15_000);
     // TODO: add AlarmManager modifier default values
     /** @hide */
-    public static final int DEFAULT_AM_REWARD_TOP_ACTIVITY_INSTANT = 0;
+    public static final long DEFAULT_AM_REWARD_TOP_ACTIVITY_INSTANT_CAKES = arcToCake(0);
     /** @hide */
-    public static final float DEFAULT_AM_REWARD_TOP_ACTIVITY_ONGOING = 0.01f;
+    // 10 megacakes = .01 ARC
+    public static final long DEFAULT_AM_REWARD_TOP_ACTIVITY_ONGOING_CAKES = 10_000_000;
     /** @hide */
-    public static final int DEFAULT_AM_REWARD_TOP_ACTIVITY_MAX = 500;
+    public static final long DEFAULT_AM_REWARD_TOP_ACTIVITY_MAX_CAKES = arcToCake(500);
     /** @hide */
-    public static final int DEFAULT_AM_REWARD_NOTIFICATION_SEEN_INSTANT = 3;
+    public static final long DEFAULT_AM_REWARD_NOTIFICATION_SEEN_INSTANT_CAKES = arcToCake(3);
     /** @hide */
-    public static final int DEFAULT_AM_REWARD_NOTIFICATION_SEEN_ONGOING = 0;
+    public static final long DEFAULT_AM_REWARD_NOTIFICATION_SEEN_ONGOING_CAKES = arcToCake(0);
     /** @hide */
-    public static final int DEFAULT_AM_REWARD_NOTIFICATION_SEEN_MAX = 60;
+    public static final long DEFAULT_AM_REWARD_NOTIFICATION_SEEN_MAX_CAKES = arcToCake(60);
     /** @hide */
-    public static final int DEFAULT_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_INSTANT = 5;
+    public static final long DEFAULT_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_INSTANT_CAKES =
+            arcToCake(5);
     /** @hide */
-    public static final int DEFAULT_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_ONGOING = 0;
+    public static final long DEFAULT_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_ONGOING_CAKES =
+            arcToCake(0);
     /** @hide */
-    public static final int DEFAULT_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_MAX = 500;
+    public static final long DEFAULT_AM_REWARD_NOTIFICATION_SEEN_WITHIN_15_MAX_CAKES =
+            arcToCake(500);
     /** @hide */
-    public static final int DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_INSTANT = 5;
+    public static final long DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_INSTANT_CAKES =
+            arcToCake(5);
     /** @hide */
-    public static final int DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_ONGOING = 0;
+    public static final long DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_ONGOING_CAKES =
+            arcToCake(0);
     /** @hide */
-    public static final int DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_MAX = 500;
+    public static final long DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_MAX_CAKES = arcToCake(500);
     /** @hide */
-    public static final int DEFAULT_AM_REWARD_WIDGET_INTERACTION_INSTANT = 10;
+    public static final long DEFAULT_AM_REWARD_WIDGET_INTERACTION_INSTANT_CAKES = arcToCake(10);
     /** @hide */
-    public static final int DEFAULT_AM_REWARD_WIDGET_INTERACTION_ONGOING = 0;
+    public static final long DEFAULT_AM_REWARD_WIDGET_INTERACTION_ONGOING_CAKES = arcToCake(0);
     /** @hide */
-    public static final int DEFAULT_AM_REWARD_WIDGET_INTERACTION_MAX = 500;
+    public static final long DEFAULT_AM_REWARD_WIDGET_INTERACTION_MAX_CAKES = arcToCake(500);
     /** @hide */
-    public static final int DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_INSTANT = 10;
+    public static final long DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_INSTANT_CAKES = arcToCake(10);
     /** @hide */
-    public static final int DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_ONGOING = 0;
+    public static final long DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_ONGOING_CAKES = arcToCake(0);
     /** @hide */
-    public static final int DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_MAX = 500;
+    public static final long DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_MAX_CAKES = arcToCake(500);
     /** @hide */
-    public static final int DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_CTP = 3;
+    public static final long DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_CTP_CAKES =
+            arcToCake(3);
     /** @hide */
-    public static final int DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_CTP = 3;
+    public static final long DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_CTP_CAKES =
+            arcToCake(3);
     /** @hide */
-    public static final int DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_CTP = 3;
+    public static final long DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_CTP_CAKES = arcToCake(3);
     /** @hide */
-    public static final int DEFAULT_AM_ACTION_ALARM_INEXACT_WAKEUP_CTP = 3;
+    public static final long DEFAULT_AM_ACTION_ALARM_INEXACT_WAKEUP_CTP_CAKES = arcToCake(3);
     /** @hide */
-    public static final int DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_CTP = 1;
+    public static final long DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_CTP_CAKES =
+            arcToCake(1);
     /** @hide */
-    public static final int DEFAULT_AM_ACTION_ALARM_EXACT_NONWAKEUP_CTP = 1;
+    public static final long DEFAULT_AM_ACTION_ALARM_EXACT_NONWAKEUP_CTP_CAKES = arcToCake(1);
     /** @hide */
-    public static final int DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_CTP = 1;
+    public static final long DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_CTP_CAKES =
+            arcToCake(1);
     /** @hide */
-    public static final int DEFAULT_AM_ACTION_ALARM_INEXACT_NONWAKEUP_CTP = 1;
+    public static final long DEFAULT_AM_ACTION_ALARM_INEXACT_NONWAKEUP_CTP_CAKES = arcToCake(1);
     /** @hide */
-    public static final int DEFAULT_AM_ACTION_ALARM_ALARMCLOCK_CTP = 5;
+    public static final long DEFAULT_AM_ACTION_ALARM_ALARMCLOCK_CTP_CAKES = arcToCake(5);
     /** @hide */
-    public static final int DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_BASE_PRICE = 5;
+    public static final long
+            DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_BASE_PRICE_CAKES = arcToCake(5);
     /** @hide */
-    public static final int DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_BASE_PRICE = 4;
+    public static final long
+            DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_BASE_PRICE_CAKES = arcToCake(4);
     /** @hide */
-    public static final int DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE = 4;
+    public static final long DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE_CAKES = arcToCake(4);
     /** @hide */
-    public static final int DEFAULT_AM_ACTION_ALARM_INEXACT_WAKEUP_BASE_PRICE = 3;
+    public static final long DEFAULT_AM_ACTION_ALARM_INEXACT_WAKEUP_BASE_PRICE_CAKES = arcToCake(3);
     /** @hide */
-    public static final int DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_BASE_PRICE = 3;
+    public static final long
+            DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_BASE_PRICE_CAKES =
+            arcToCake(3);
     /** @hide */
-    public static final int DEFAULT_AM_ACTION_ALARM_EXACT_NONWAKEUP_BASE_PRICE = 2;
+    public static final long DEFAULT_AM_ACTION_ALARM_EXACT_NONWAKEUP_BASE_PRICE_CAKES =
+            arcToCake(2);
     /** @hide */
-    public static final int DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_BASE_PRICE =
-            2;
+    public static final long
+            DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_BASE_PRICE_CAKES =
+            arcToCake(2);
     /** @hide */
-    public static final int DEFAULT_AM_ACTION_ALARM_INEXACT_NONWAKEUP_BASE_PRICE = 1;
+    public static final long DEFAULT_AM_ACTION_ALARM_INEXACT_NONWAKEUP_BASE_PRICE_CAKES =
+            arcToCake(1);
     /** @hide */
-    public static final int DEFAULT_AM_ACTION_ALARM_ALARMCLOCK_BASE_PRICE = 10;
+    public static final long DEFAULT_AM_ACTION_ALARM_ALARMCLOCK_BASE_PRICE_CAKES = arcToCake(10);
 
     // Default values JobScheduler factors
     // TODO: add time_since_usage variable to min satiated balance factors
     /** @hide */
-    public static final int DEFAULT_JS_MIN_SATIATED_BALANCE_EXEMPTED = 20000;
+    public static final long DEFAULT_JS_MIN_SATIATED_BALANCE_EXEMPTED_CAKES = arcToCake(15000);
     /** @hide */
-    public static final int DEFAULT_JS_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP = 10000;
+    public static final long DEFAULT_JS_MIN_SATIATED_BALANCE_HEADLESS_SYSTEM_APP_CAKES =
+            arcToCake(7500);
     /** @hide */
-    public static final int DEFAULT_JS_MIN_SATIATED_BALANCE_OTHER_APP = 2000;
+    public static final long DEFAULT_JS_MIN_SATIATED_BALANCE_OTHER_APP_CAKES = arcToCake(2000);
     /** @hide */
-    public static final int DEFAULT_JS_MAX_SATIATED_BALANCE = 60000;
+    public static final long DEFAULT_JS_MAX_SATIATED_BALANCE_CAKES = arcToCake(60000);
     /** @hide */
-    public static final int DEFAULT_JS_INITIAL_CONSUMPTION_LIMIT = 100_000;
+    public static final long DEFAULT_JS_INITIAL_CONSUMPTION_LIMIT_CAKES = arcToCake(29_000);
     /** @hide */
-    public static final int DEFAULT_JS_HARD_CONSUMPTION_LIMIT = 460_000;
+    // TODO: set hard limit based on device type (phone vs tablet vs etc) + battery size
+    public static final long DEFAULT_JS_HARD_CONSUMPTION_LIMIT_CAKES = arcToCake(250_000);
     // TODO: add JobScheduler modifier default values
     /** @hide */
-    public static final int DEFAULT_JS_REWARD_TOP_ACTIVITY_INSTANT = 0;
+    public static final long DEFAULT_JS_REWARD_TOP_ACTIVITY_INSTANT_CAKES = arcToCake(0);
     /** @hide */
-    public static final float DEFAULT_JS_REWARD_TOP_ACTIVITY_ONGOING = 0.5f;
+    public static final long DEFAULT_JS_REWARD_TOP_ACTIVITY_ONGOING_CAKES = CAKE_IN_ARC / 2;
     /** @hide */
-    public static final int DEFAULT_JS_REWARD_TOP_ACTIVITY_MAX = 15000;
+    public static final long DEFAULT_JS_REWARD_TOP_ACTIVITY_MAX_CAKES = arcToCake(15000);
     /** @hide */
-    public static final int DEFAULT_JS_REWARD_NOTIFICATION_SEEN_INSTANT = 1;
+    public static final long DEFAULT_JS_REWARD_NOTIFICATION_SEEN_INSTANT_CAKES = arcToCake(1);
     /** @hide */
-    public static final int DEFAULT_JS_REWARD_NOTIFICATION_SEEN_ONGOING = 0;
+    public static final long DEFAULT_JS_REWARD_NOTIFICATION_SEEN_ONGOING_CAKES = arcToCake(0);
     /** @hide */
-    public static final int DEFAULT_JS_REWARD_NOTIFICATION_SEEN_MAX = 10;
+    public static final long DEFAULT_JS_REWARD_NOTIFICATION_SEEN_MAX_CAKES = arcToCake(10);
     /** @hide */
-    public static final int DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_INSTANT = 5;
+    public static final long DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_INSTANT_CAKES =
+            arcToCake(5);
     /** @hide */
-    public static final int DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_ONGOING = 0;
+    public static final long DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_ONGOING_CAKES =
+            arcToCake(0);
     /** @hide */
-    public static final int DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_MAX = 5000;
+    public static final long DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_MAX_CAKES = arcToCake(5000);
     /** @hide */
-    public static final int DEFAULT_JS_REWARD_WIDGET_INTERACTION_INSTANT = 10;
+    public static final long DEFAULT_JS_REWARD_WIDGET_INTERACTION_INSTANT_CAKES = arcToCake(10);
     /** @hide */
-    public static final int DEFAULT_JS_REWARD_WIDGET_INTERACTION_ONGOING = 0;
+    public static final long DEFAULT_JS_REWARD_WIDGET_INTERACTION_ONGOING_CAKES = arcToCake(0);
     /** @hide */
-    public static final int DEFAULT_JS_REWARD_WIDGET_INTERACTION_MAX = 5000;
+    public static final long DEFAULT_JS_REWARD_WIDGET_INTERACTION_MAX_CAKES = arcToCake(5000);
     /** @hide */
-    public static final int DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_INSTANT = 10;
+    public static final long DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_INSTANT_CAKES = arcToCake(10);
     /** @hide */
-    public static final int DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_ONGOING = 0;
+    public static final long DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_ONGOING_CAKES = arcToCake(0);
     /** @hide */
-    public static final int DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_MAX = 5000;
+    public static final long DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_MAX_CAKES = arcToCake(5000);
     /** @hide */
-    public static final int DEFAULT_JS_ACTION_JOB_MAX_START_CTP = 3;
+    public static final long DEFAULT_JS_ACTION_JOB_MAX_START_CTP_CAKES = arcToCake(3);
     /** @hide */
-    public static final int DEFAULT_JS_ACTION_JOB_MAX_RUNNING_CTP = 2;
+    public static final long DEFAULT_JS_ACTION_JOB_MAX_RUNNING_CTP_CAKES = arcToCake(2);
     /** @hide */
-    public static final int DEFAULT_JS_ACTION_JOB_HIGH_START_CTP = 3;
+    public static final long DEFAULT_JS_ACTION_JOB_HIGH_START_CTP_CAKES = arcToCake(3);
     /** @hide */
-    public static final int DEFAULT_JS_ACTION_JOB_HIGH_RUNNING_CTP = 2;
+    public static final long DEFAULT_JS_ACTION_JOB_HIGH_RUNNING_CTP_CAKES = arcToCake(2);
     /** @hide */
-    public static final int DEFAULT_JS_ACTION_JOB_DEFAULT_START_CTP = 3;
+    public static final long DEFAULT_JS_ACTION_JOB_DEFAULT_START_CTP_CAKES = arcToCake(3);
     /** @hide */
-    public static final int DEFAULT_JS_ACTION_JOB_DEFAULT_RUNNING_CTP = 2;
+    public static final long DEFAULT_JS_ACTION_JOB_DEFAULT_RUNNING_CTP_CAKES = arcToCake(2);
     /** @hide */
-    public static final int DEFAULT_JS_ACTION_JOB_LOW_START_CTP = 3;
+    public static final long DEFAULT_JS_ACTION_JOB_LOW_START_CTP_CAKES = arcToCake(3);
     /** @hide */
-    public static final int DEFAULT_JS_ACTION_JOB_LOW_RUNNING_CTP = 2;
+    public static final long DEFAULT_JS_ACTION_JOB_LOW_RUNNING_CTP_CAKES = arcToCake(2);
     /** @hide */
-    public static final int DEFAULT_JS_ACTION_JOB_MIN_START_CTP = 3;
+    public static final long DEFAULT_JS_ACTION_JOB_MIN_START_CTP_CAKES = arcToCake(3);
     /** @hide */
-    public static final int DEFAULT_JS_ACTION_JOB_MIN_RUNNING_CTP = 2;
+    public static final long DEFAULT_JS_ACTION_JOB_MIN_RUNNING_CTP_CAKES = arcToCake(2);
     /** @hide */
-    public static final int DEFAULT_JS_ACTION_JOB_TIMEOUT_PENALTY_CTP = 30;
+    public static final long DEFAULT_JS_ACTION_JOB_TIMEOUT_PENALTY_CTP_CAKES = arcToCake(30);
     /** @hide */
-    public static final int DEFAULT_JS_ACTION_JOB_MAX_START_BASE_PRICE = 10;
+    public static final long DEFAULT_JS_ACTION_JOB_MAX_START_BASE_PRICE_CAKES = arcToCake(10);
     /** @hide */
-    public static final int DEFAULT_JS_ACTION_JOB_MAX_RUNNING_BASE_PRICE = 5;
+    public static final long DEFAULT_JS_ACTION_JOB_MAX_RUNNING_BASE_PRICE_CAKES = arcToCake(5);
     /** @hide */
-    public static final int DEFAULT_JS_ACTION_JOB_HIGH_START_BASE_PRICE = 8;
+    public static final long DEFAULT_JS_ACTION_JOB_HIGH_START_BASE_PRICE_CAKES = arcToCake(8);
     /** @hide */
-    public static final int DEFAULT_JS_ACTION_JOB_HIGH_RUNNING_BASE_PRICE = 4;
+    public static final long DEFAULT_JS_ACTION_JOB_HIGH_RUNNING_BASE_PRICE_CAKES = arcToCake(4);
     /** @hide */
-    public static final int DEFAULT_JS_ACTION_JOB_DEFAULT_START_BASE_PRICE = 6;
+    public static final long DEFAULT_JS_ACTION_JOB_DEFAULT_START_BASE_PRICE_CAKES = arcToCake(6);
     /** @hide */
-    public static final int DEFAULT_JS_ACTION_JOB_DEFAULT_RUNNING_BASE_PRICE = 3;
+    public static final long DEFAULT_JS_ACTION_JOB_DEFAULT_RUNNING_BASE_PRICE_CAKES = arcToCake(3);
     /** @hide */
-    public static final int DEFAULT_JS_ACTION_JOB_LOW_START_BASE_PRICE = 4;
+    public static final long DEFAULT_JS_ACTION_JOB_LOW_START_BASE_PRICE_CAKES = arcToCake(4);
     /** @hide */
-    public static final int DEFAULT_JS_ACTION_JOB_LOW_RUNNING_BASE_PRICE = 2;
+    public static final long DEFAULT_JS_ACTION_JOB_LOW_RUNNING_BASE_PRICE_CAKES = arcToCake(2);
     /** @hide */
-    public static final int DEFAULT_JS_ACTION_JOB_MIN_START_BASE_PRICE = 2;
+    public static final long DEFAULT_JS_ACTION_JOB_MIN_START_BASE_PRICE_CAKES = arcToCake(2);
     /** @hide */
-    public static final int DEFAULT_JS_ACTION_JOB_MIN_RUNNING_BASE_PRICE = 1;
+    public static final long DEFAULT_JS_ACTION_JOB_MIN_RUNNING_BASE_PRICE_CAKES = arcToCake(1);
     /** @hide */
-    public static final int DEFAULT_JS_ACTION_JOB_TIMEOUT_PENALTY_BASE_PRICE = 60;
+    public static final long DEFAULT_JS_ACTION_JOB_TIMEOUT_PENALTY_BASE_PRICE_CAKES = arcToCake(60);
 }
diff --git a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
index c8ec894..c86353c 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java
@@ -690,6 +690,12 @@
         int projectedRunningCount = numRunningJobs;
         while ((nextPending = pendingJobQueue.next()) != null) {
             if (mRunningJobs.contains(nextPending)) {
+                // Should never happen.
+                Slog.wtf(TAG, "Pending queue contained a running job");
+                if (DEBUG) {
+                    Slog.e(TAG, "Pending+running job: " + nextPending);
+                }
+                pendingJobQueue.remove(nextPending);
                 continue;
             }
 
@@ -1137,7 +1143,8 @@
             }
         }
 
-        if (mActiveServices.size() >= STANDARD_CONCURRENCY_LIMIT) {
+        final PendingJobQueue pendingJobQueue = mService.getPendingJobQueue();
+        if (mActiveServices.size() >= STANDARD_CONCURRENCY_LIMIT || pendingJobQueue.size() == 0) {
             worker.clearPreferredUid();
             // We're over the limit (because the TOP app scheduled a lot of EJs). Don't start
             // running anything new until we get back below the limit.
@@ -1145,7 +1152,6 @@
             return;
         }
 
-        final PendingJobQueue pendingJobQueue = mService.getPendingJobQueue();
         if (worker.getPreferredUid() != JobServiceContext.NO_PREFERRED_UID) {
             updateCounterConfigLocked();
             // Preemption case needs special care.
@@ -1162,6 +1168,12 @@
             pendingJobQueue.resetIterator();
             while ((nextPending = pendingJobQueue.next()) != null) {
                 if (mRunningJobs.contains(nextPending)) {
+                    // Should never happen.
+                    Slog.wtf(TAG, "Pending queue contained a running job");
+                    if (DEBUG) {
+                        Slog.e(TAG, "Pending+running job: " + nextPending);
+                    }
+                    pendingJobQueue.remove(nextPending);
                     continue;
                 }
 
@@ -1239,6 +1251,12 @@
             while ((nextPending = pendingJobQueue.next()) != null) {
 
                 if (mRunningJobs.contains(nextPending)) {
+                    // Should never happen.
+                    Slog.wtf(TAG, "Pending queue contained a running job");
+                    if (DEBUG) {
+                        Slog.e(TAG, "Pending+running job: " + nextPending);
+                    }
+                    pendingJobQueue.remove(nextPending);
                     continue;
                 }
 
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 9e13133..358c327 100644
--- a/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
+++ b/apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java
@@ -1749,8 +1749,13 @@
         if (!removed) {
             // We never create JobStatus objects for the express purpose of removing them, and this
             // method is only ever called for jobs that were saved in the JobStore at some point,
-            // so if we can't find it, something went seriously wrong.
-            Slog.wtfStack(TAG, "Job didn't exist in JobStore");
+            // so if we can't find it, something may be wrong. As of Android T, there is a
+            // legitimate code path where removed is false --- when an actively running job is
+            // cancelled (eg. via JobScheduler.cancel() or the app scheduling a new job with the
+            // same job ID), we remove it from the JobStore and tell the JobServiceContext to stop
+            // running the job. Once the job stops running, we then call this method again.
+            // TODO: rework code so we don't intentionally call this method twice for the same job
+            Slog.w(TAG, "Job didn't exist in JobStore");
         }
         if (mReadyToRock) {
             for (int i = 0; i < mControllers.size(); i++) {
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/AlarmManagerEconomicPolicy.java b/apex/jobscheduler/service/java/com/android/server/tare/AlarmManagerEconomicPolicy.java
index c2e8188..d0f719b 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/AlarmManagerEconomicPolicy.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/AlarmManagerEconomicPolicy.java
@@ -16,43 +16,43 @@
 
 package com.android.server.tare;
 
-import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALARMCLOCK_BASE_PRICE;
-import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALARMCLOCK_CTP;
-import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_CTP;
-import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_BASE_PRICE;
-import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_CTP;
-import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_BASE_PRICE;
-import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_CTP;
-import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_BASE_PRICE;
-import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_CTP;
-import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_EXACT_NONWAKEUP_BASE_PRICE;
-import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_EXACT_NONWAKEUP_CTP;
-import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE;
-import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_CTP;
-import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_INEXACT_NONWAKEUP_BASE_PRICE;
-import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_INEXACT_NONWAKEUP_CTP;
-import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_INEXACT_WAKEUP_BASE_PRICE;
-import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_INEXACT_WAKEUP_CTP;
-import static android.app.tare.EconomyManager.DEFAULT_AM_HARD_CONSUMPTION_LIMIT;
-import static android.app.tare.EconomyManager.DEFAULT_AM_INITIAL_CONSUMPTION_LIMIT;
-import static android.app.tare.EconomyManager.DEFAULT_AM_MAX_SATIATED_BALANCE;
-import static android.app.tare.EconomyManager.DEFAULT_AM_MIN_SATIATED_BALANCE_EXEMPTED;
-import static android.app.tare.EconomyManager.DEFAULT_AM_MIN_SATIATED_BALANCE_OTHER_APP;
-import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_INSTANT;
-import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_MAX;
-import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_ONGOING;
-import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_SEEN_INSTANT;
-import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_SEEN_MAX;
-import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_SEEN_ONGOING;
-import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_INSTANT;
-import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_MAX;
-import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_ONGOING;
-import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_TOP_ACTIVITY_INSTANT;
-import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_TOP_ACTIVITY_MAX;
-import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_TOP_ACTIVITY_ONGOING;
-import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_WIDGET_INTERACTION_INSTANT;
-import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_WIDGET_INTERACTION_MAX;
-import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_WIDGET_INTERACTION_ONGOING;
+import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALARMCLOCK_BASE_PRICE_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALARMCLOCK_CTP_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_CTP_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_BASE_PRICE_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_CTP_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_BASE_PRICE_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_CTP_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_BASE_PRICE_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_CTP_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_EXACT_NONWAKEUP_BASE_PRICE_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_EXACT_NONWAKEUP_CTP_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_CTP_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_INEXACT_NONWAKEUP_BASE_PRICE_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_INEXACT_NONWAKEUP_CTP_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_INEXACT_WAKEUP_BASE_PRICE_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_ACTION_ALARM_INEXACT_WAKEUP_CTP_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_HARD_CONSUMPTION_LIMIT_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_INITIAL_CONSUMPTION_LIMIT_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_MAX_SATIATED_BALANCE_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_MIN_SATIATED_BALANCE_EXEMPTED_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_MIN_SATIATED_BALANCE_OTHER_APP_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_INSTANT_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_MAX_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_ONGOING_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_SEEN_INSTANT_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_SEEN_MAX_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_NOTIFICATION_SEEN_ONGOING_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_INSTANT_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_MAX_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_ONGOING_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_TOP_ACTIVITY_INSTANT_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_TOP_ACTIVITY_MAX_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_TOP_ACTIVITY_ONGOING_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_WIDGET_INTERACTION_INSTANT_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_WIDGET_INTERACTION_MAX_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_AM_REWARD_WIDGET_INTERACTION_ONGOING_CAKES;
 import static android.app.tare.EconomyManager.KEY_AM_ACTION_ALARM_ALARMCLOCK_BASE_PRICE;
 import static android.app.tare.EconomyManager.KEY_AM_ACTION_ALARM_ALARMCLOCK_CTP;
 import static android.app.tare.EconomyManager.KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_BASE_PRICE;
@@ -97,12 +97,12 @@
 import static com.android.server.tare.Modifier.COST_MODIFIER_DEVICE_IDLE;
 import static com.android.server.tare.Modifier.COST_MODIFIER_POWER_SAVE_MODE;
 import static com.android.server.tare.Modifier.COST_MODIFIER_PROCESS_STATE;
-import static com.android.server.tare.TareUtils.arcToCake;
 import static com.android.server.tare.TareUtils.cakeToString;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.ContentResolver;
+import android.provider.DeviceConfig;
 import android.provider.Settings;
 import android.util.IndentingPrintWriter;
 import android.util.KeyValueListParser;
@@ -157,14 +157,15 @@
     AlarmManagerEconomicPolicy(InternalResourceService irs) {
         super(irs);
         mInternalResourceService = irs;
-        loadConstants("");
+        loadConstants("", null);
     }
 
     @Override
-    void setup() {
-        super.setup();
+    void setup(@NonNull DeviceConfig.Properties properties) {
+        super.setup(properties);
         ContentResolver resolver = mInternalResourceService.getContext().getContentResolver();
-        loadConstants(Settings.Global.getString(resolver, TARE_ALARM_MANAGER_CONSTANTS));
+        loadConstants(Settings.Global.getString(resolver, TARE_ALARM_MANAGER_CONSTANTS),
+                properties);
     }
 
     @Override
@@ -178,6 +179,11 @@
 
     @Override
     long getMaxSatiatedBalance() {
+        // TODO(230501287): adjust balance based on whether the app has the SCHEDULE_EXACT_ALARM
+        // permission granted. Apps without the permission granted shouldn't need a high balance
+        // since they won't be able to use exact alarms. Apps with the permission granted could
+        // have a higher balance, or perhaps just those with the USE_EXACT_ALARM permission since
+        // that is limited to specific use cases.
         return mMaxSatiatedBalance;
     }
 
@@ -209,7 +215,8 @@
         return mRewards.get(rewardId);
     }
 
-    private void loadConstants(String policyValuesString) {
+    private void loadConstants(String policyValuesString,
+            @Nullable DeviceConfig.Properties properties) {
         mActions.clear();
         mRewards.clear();
 
@@ -219,145 +226,159 @@
             Slog.e(TAG, "Global setting key incorrect: ", e);
         }
 
-        mMinSatiatedBalanceExempted = arcToCake(mParser.getInt(KEY_AM_MIN_SATIATED_BALANCE_EXEMPTED,
-                DEFAULT_AM_MIN_SATIATED_BALANCE_EXEMPTED));
-        mMinSatiatedBalanceOther = arcToCake(mParser.getInt(KEY_AM_MIN_SATIATED_BALANCE_OTHER_APP,
-                DEFAULT_AM_MIN_SATIATED_BALANCE_OTHER_APP));
-        mMaxSatiatedBalance = arcToCake(mParser.getInt(KEY_AM_MAX_SATIATED_BALANCE,
-                DEFAULT_AM_MAX_SATIATED_BALANCE));
-        mInitialSatiatedConsumptionLimit = arcToCake(mParser.getInt(
-                KEY_AM_INITIAL_CONSUMPTION_LIMIT, DEFAULT_AM_INITIAL_CONSUMPTION_LIMIT));
+        mMinSatiatedBalanceExempted = getConstantAsCake(mParser, properties,
+                KEY_AM_MIN_SATIATED_BALANCE_EXEMPTED,
+                DEFAULT_AM_MIN_SATIATED_BALANCE_EXEMPTED_CAKES);
+        mMinSatiatedBalanceOther = getConstantAsCake(mParser, properties,
+                KEY_AM_MIN_SATIATED_BALANCE_OTHER_APP,
+                DEFAULT_AM_MIN_SATIATED_BALANCE_OTHER_APP_CAKES);
+        mMaxSatiatedBalance = getConstantAsCake(mParser, properties,
+                KEY_AM_MAX_SATIATED_BALANCE,
+                DEFAULT_AM_MAX_SATIATED_BALANCE_CAKES);
+        mInitialSatiatedConsumptionLimit = getConstantAsCake(mParser, properties,
+                KEY_AM_INITIAL_CONSUMPTION_LIMIT, DEFAULT_AM_INITIAL_CONSUMPTION_LIMIT_CAKES);
         mHardSatiatedConsumptionLimit = Math.max(mInitialSatiatedConsumptionLimit,
-                arcToCake(mParser.getInt(
-                        KEY_AM_HARD_CONSUMPTION_LIMIT, DEFAULT_AM_HARD_CONSUMPTION_LIMIT)));
+                getConstantAsCake(mParser, properties,
+                        KEY_AM_HARD_CONSUMPTION_LIMIT, DEFAULT_AM_HARD_CONSUMPTION_LIMIT_CAKES));
 
-        final long exactAllowWhileIdleWakeupBasePrice = arcToCake(
-                mParser.getInt(KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_BASE_PRICE,
-                        DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_BASE_PRICE));
+        final long exactAllowWhileIdleWakeupBasePrice = getConstantAsCake(mParser, properties,
+                KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_BASE_PRICE,
+                DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_BASE_PRICE_CAKES);
 
         mActions.put(ACTION_ALARM_WAKEUP_EXACT_ALLOW_WHILE_IDLE,
                 new Action(ACTION_ALARM_WAKEUP_EXACT_ALLOW_WHILE_IDLE,
-                        arcToCake(mParser.getInt(
+                        getConstantAsCake(mParser, properties,
                                 KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_CTP,
-                                DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_CTP)),
+                                DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_WAKEUP_CTP_CAKES),
                         exactAllowWhileIdleWakeupBasePrice));
         mActions.put(ACTION_ALARM_WAKEUP_EXACT,
                 new Action(ACTION_ALARM_WAKEUP_EXACT,
-                        arcToCake(mParser.getInt(KEY_AM_ACTION_ALARM_EXACT_WAKEUP_CTP,
-                                DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_CTP)),
-                        arcToCake(mParser.getInt(KEY_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE,
-                                DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE))));
+                        getConstantAsCake(mParser, properties,
+                                KEY_AM_ACTION_ALARM_EXACT_WAKEUP_CTP,
+                                DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_CTP_CAKES),
+                        getConstantAsCake(mParser, properties,
+                                KEY_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE,
+                                DEFAULT_AM_ACTION_ALARM_EXACT_WAKEUP_BASE_PRICE_CAKES)));
 
         final long inexactAllowWhileIdleWakeupBasePrice =
-                arcToCake(mParser.getInt(
+                getConstantAsCake(mParser, properties,
                         KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_BASE_PRICE,
-                        DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_BASE_PRICE));
+                        DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_BASE_PRICE_CAKES);
 
         mActions.put(ACTION_ALARM_WAKEUP_INEXACT_ALLOW_WHILE_IDLE,
                 new Action(ACTION_ALARM_WAKEUP_INEXACT_ALLOW_WHILE_IDLE,
-                        arcToCake(mParser.getInt(
+                        getConstantAsCake(mParser, properties,
                                 KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_CTP,
-                                DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_CTP)),
+                                DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_WAKEUP_CTP_CAKES),
                         inexactAllowWhileIdleWakeupBasePrice));
         mActions.put(ACTION_ALARM_WAKEUP_INEXACT,
                 new Action(ACTION_ALARM_WAKEUP_INEXACT,
-                        arcToCake(mParser.getInt(
+                        getConstantAsCake(mParser, properties,
                                 KEY_AM_ACTION_ALARM_INEXACT_WAKEUP_CTP,
-                                DEFAULT_AM_ACTION_ALARM_INEXACT_WAKEUP_CTP)),
-                        arcToCake(mParser.getInt(
+                                DEFAULT_AM_ACTION_ALARM_INEXACT_WAKEUP_CTP_CAKES),
+                        getConstantAsCake(mParser, properties,
                                 KEY_AM_ACTION_ALARM_INEXACT_WAKEUP_BASE_PRICE,
-                                DEFAULT_AM_ACTION_ALARM_INEXACT_WAKEUP_BASE_PRICE))));
+                                DEFAULT_AM_ACTION_ALARM_INEXACT_WAKEUP_BASE_PRICE_CAKES)));
 
-        final long exactAllowWhileIdleNonWakeupBasePrice =
-                arcToCake(mParser.getInt(
-                        KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_BASE_PRICE,
-                        DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_BASE_PRICE));
-
+        final long exactAllowWhileIdleNonWakeupBasePrice = getConstantAsCake(mParser, properties,
+                KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_BASE_PRICE,
+                DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_BASE_PRICE_CAKES);
         mActions.put(ACTION_ALARM_NONWAKEUP_EXACT_ALLOW_WHILE_IDLE,
                 new Action(ACTION_ALARM_NONWAKEUP_EXACT_ALLOW_WHILE_IDLE,
-                        arcToCake(mParser.getInt(
+                        getConstantAsCake(mParser, properties,
                                 KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_CTP,
-                                DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_CTP)),
+                                DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_EXACT_NONWAKEUP_CTP_CAKES),
                         exactAllowWhileIdleNonWakeupBasePrice));
+
         mActions.put(ACTION_ALARM_NONWAKEUP_EXACT,
                 new Action(ACTION_ALARM_NONWAKEUP_EXACT,
-                        arcToCake(mParser.getInt(
+                        getConstantAsCake(mParser, properties,
                                 KEY_AM_ACTION_ALARM_EXACT_NONWAKEUP_CTP,
-                                DEFAULT_AM_ACTION_ALARM_EXACT_NONWAKEUP_CTP)),
-                        arcToCake(mParser.getInt(
+                                DEFAULT_AM_ACTION_ALARM_EXACT_NONWAKEUP_CTP_CAKES),
+                        getConstantAsCake(mParser, properties,
                                 KEY_AM_ACTION_ALARM_EXACT_NONWAKEUP_BASE_PRICE,
-                                DEFAULT_AM_ACTION_ALARM_EXACT_NONWAKEUP_BASE_PRICE))));
+                                DEFAULT_AM_ACTION_ALARM_EXACT_NONWAKEUP_BASE_PRICE_CAKES)));
 
-        final long inexactAllowWhileIdleNonWakeupBasePrice =
-                arcToCake(mParser.getInt(
-                        KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_BASE_PRICE,
-                        DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_BASE_PRICE));
-
+        final long inexactAllowWhileIdleNonWakeupBasePrice = getConstantAsCake(mParser, properties,
+                KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_BASE_PRICE,
+                DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_BASE_PRICE_CAKES);
+        final long inexactAllowWhileIdleNonWakeupCtp = getConstantAsCake(mParser, properties,
+                KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_CTP,
+                DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_CTP_CAKES);
         mActions.put(ACTION_ALARM_NONWAKEUP_INEXACT_ALLOW_WHILE_IDLE,
                 new Action(ACTION_ALARM_NONWAKEUP_INEXACT_ALLOW_WHILE_IDLE,
-                        arcToCake(mParser.getInt(
-                                KEY_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_CTP,
-                                DEFAULT_AM_ACTION_ALARM_ALLOW_WHILE_IDLE_INEXACT_NONWAKEUP_CTP)),
+                        inexactAllowWhileIdleNonWakeupCtp,
                         inexactAllowWhileIdleNonWakeupBasePrice));
+
         mActions.put(ACTION_ALARM_NONWAKEUP_INEXACT,
                 new Action(ACTION_ALARM_NONWAKEUP_INEXACT,
-                        arcToCake(mParser.getInt(
+                        getConstantAsCake(mParser, properties,
                                 KEY_AM_ACTION_ALARM_INEXACT_NONWAKEUP_CTP,
-                                DEFAULT_AM_ACTION_ALARM_INEXACT_NONWAKEUP_CTP)),
-                        arcToCake(mParser.getInt(
+                                DEFAULT_AM_ACTION_ALARM_INEXACT_NONWAKEUP_CTP_CAKES),
+                        getConstantAsCake(mParser, properties,
                                 KEY_AM_ACTION_ALARM_INEXACT_NONWAKEUP_BASE_PRICE,
-                                DEFAULT_AM_ACTION_ALARM_INEXACT_NONWAKEUP_BASE_PRICE))));
+                                DEFAULT_AM_ACTION_ALARM_INEXACT_NONWAKEUP_BASE_PRICE_CAKES)));
         mActions.put(ACTION_ALARM_CLOCK,
                 new Action(ACTION_ALARM_CLOCK,
-                        arcToCake(mParser.getInt(
+                        getConstantAsCake(mParser, properties,
                                 KEY_AM_ACTION_ALARM_ALARMCLOCK_CTP,
-                                DEFAULT_AM_ACTION_ALARM_ALARMCLOCK_CTP)),
-                        arcToCake(mParser.getInt(
+                                DEFAULT_AM_ACTION_ALARM_ALARMCLOCK_CTP_CAKES),
+                        getConstantAsCake(mParser, properties,
                                 KEY_AM_ACTION_ALARM_ALARMCLOCK_BASE_PRICE,
-                                DEFAULT_AM_ACTION_ALARM_ALARMCLOCK_BASE_PRICE))));
+                                DEFAULT_AM_ACTION_ALARM_ALARMCLOCK_BASE_PRICE_CAKES)));
 
         mRewards.put(REWARD_TOP_ACTIVITY, new Reward(REWARD_TOP_ACTIVITY,
-                arcToCake(mParser.getInt(KEY_AM_REWARD_TOP_ACTIVITY_INSTANT,
-                        DEFAULT_AM_REWARD_TOP_ACTIVITY_INSTANT)),
-                (long) (arcToCake(1) * mParser.getFloat(KEY_AM_REWARD_TOP_ACTIVITY_ONGOING,
-                        DEFAULT_AM_REWARD_TOP_ACTIVITY_ONGOING)),
-                arcToCake(mParser.getInt(KEY_AM_REWARD_TOP_ACTIVITY_MAX,
-                        DEFAULT_AM_REWARD_TOP_ACTIVITY_MAX))));
+                getConstantAsCake(mParser, properties,
+                        KEY_AM_REWARD_TOP_ACTIVITY_INSTANT,
+                        DEFAULT_AM_REWARD_TOP_ACTIVITY_INSTANT_CAKES),
+                getConstantAsCake(mParser, properties,
+                        KEY_AM_REWARD_TOP_ACTIVITY_ONGOING,
+                        DEFAULT_AM_REWARD_TOP_ACTIVITY_ONGOING_CAKES),
+                getConstantAsCake(mParser, properties,
+                        KEY_AM_REWARD_TOP_ACTIVITY_MAX,
+                        DEFAULT_AM_REWARD_TOP_ACTIVITY_MAX_CAKES)));
         mRewards.put(REWARD_NOTIFICATION_SEEN, new Reward(REWARD_NOTIFICATION_SEEN,
-                arcToCake(mParser.getInt(KEY_AM_REWARD_NOTIFICATION_SEEN_INSTANT,
-                        DEFAULT_AM_REWARD_NOTIFICATION_SEEN_INSTANT)),
-                arcToCake(mParser.getInt(KEY_AM_REWARD_NOTIFICATION_SEEN_ONGOING,
-                        DEFAULT_AM_REWARD_NOTIFICATION_SEEN_ONGOING)),
-                arcToCake(mParser.getInt(KEY_AM_REWARD_NOTIFICATION_SEEN_MAX,
-                        DEFAULT_AM_REWARD_NOTIFICATION_SEEN_MAX))));
+                getConstantAsCake(mParser, properties,
+                        KEY_AM_REWARD_NOTIFICATION_SEEN_INSTANT,
+                        DEFAULT_AM_REWARD_NOTIFICATION_SEEN_INSTANT_CAKES),
+                getConstantAsCake(mParser, properties,
+                        KEY_AM_REWARD_NOTIFICATION_SEEN_ONGOING,
+                        DEFAULT_AM_REWARD_NOTIFICATION_SEEN_ONGOING_CAKES),
+                getConstantAsCake(mParser, properties,
+                        KEY_AM_REWARD_NOTIFICATION_SEEN_MAX,
+                        DEFAULT_AM_REWARD_NOTIFICATION_SEEN_MAX_CAKES)));
         mRewards.put(REWARD_NOTIFICATION_INTERACTION,
                 new Reward(REWARD_NOTIFICATION_INTERACTION,
-                        arcToCake(mParser.getInt(
+                        getConstantAsCake(mParser, properties,
                                 KEY_AM_REWARD_NOTIFICATION_INTERACTION_INSTANT,
-                                DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_INSTANT)),
-                        arcToCake(mParser.getInt(
+                                DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_INSTANT_CAKES),
+                        getConstantAsCake(mParser, properties,
                                 KEY_AM_REWARD_NOTIFICATION_INTERACTION_ONGOING,
-                                DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_ONGOING)),
-                        arcToCake(mParser.getInt(
+                                DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_ONGOING_CAKES),
+                        getConstantAsCake(mParser, properties,
                                 KEY_AM_REWARD_NOTIFICATION_INTERACTION_MAX,
-                                DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_MAX))));
+                                DEFAULT_AM_REWARD_NOTIFICATION_INTERACTION_MAX_CAKES)));
         mRewards.put(REWARD_WIDGET_INTERACTION, new Reward(REWARD_WIDGET_INTERACTION,
-                arcToCake(mParser.getInt(KEY_AM_REWARD_WIDGET_INTERACTION_INSTANT,
-                        DEFAULT_AM_REWARD_WIDGET_INTERACTION_INSTANT)),
-                arcToCake(mParser.getInt(KEY_AM_REWARD_WIDGET_INTERACTION_ONGOING,
-                        DEFAULT_AM_REWARD_WIDGET_INTERACTION_ONGOING)),
-                arcToCake(mParser.getInt(KEY_AM_REWARD_WIDGET_INTERACTION_MAX,
-                        DEFAULT_AM_REWARD_WIDGET_INTERACTION_MAX))));
+                getConstantAsCake(mParser, properties,
+                        KEY_AM_REWARD_WIDGET_INTERACTION_INSTANT,
+                        DEFAULT_AM_REWARD_WIDGET_INTERACTION_INSTANT_CAKES),
+                getConstantAsCake(mParser, properties,
+                        KEY_AM_REWARD_WIDGET_INTERACTION_ONGOING,
+                        DEFAULT_AM_REWARD_WIDGET_INTERACTION_ONGOING_CAKES),
+                getConstantAsCake(mParser, properties,
+                        KEY_AM_REWARD_WIDGET_INTERACTION_MAX,
+                        DEFAULT_AM_REWARD_WIDGET_INTERACTION_MAX_CAKES)));
         mRewards.put(REWARD_OTHER_USER_INTERACTION,
                 new Reward(REWARD_OTHER_USER_INTERACTION,
-                        arcToCake(mParser.getInt(KEY_AM_REWARD_OTHER_USER_INTERACTION_INSTANT,
-                                DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_INSTANT)),
-                        arcToCake(mParser.getInt(
+                        getConstantAsCake(mParser, properties,
+                                KEY_AM_REWARD_OTHER_USER_INTERACTION_INSTANT,
+                                DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_INSTANT_CAKES),
+                        getConstantAsCake(mParser, properties,
                                 KEY_AM_REWARD_OTHER_USER_INTERACTION_ONGOING,
-                                DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_ONGOING)),
-                        arcToCake(mParser.getInt(
+                                DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_ONGOING_CAKES),
+                        getConstantAsCake(mParser, properties,
                                 KEY_AM_REWARD_OTHER_USER_INTERACTION_MAX,
-                                DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_MAX))));
+                                DEFAULT_AM_REWARD_OTHER_USER_INTERACTION_MAX_CAKES)));
     }
 
     @Override
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/CompleteEconomicPolicy.java b/apex/jobscheduler/service/java/com/android/server/tare/CompleteEconomicPolicy.java
index 2109a85..c3eb5bf 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/CompleteEconomicPolicy.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/CompleteEconomicPolicy.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.provider.DeviceConfig;
 import android.util.ArraySet;
 import android.util.IndentingPrintWriter;
 import android.util.SparseArray;
@@ -57,10 +58,10 @@
     }
 
     @Override
-    void setup() {
-        super.setup();
+    void setup(@NonNull DeviceConfig.Properties properties) {
+        super.setup(properties);
         for (int i = 0; i < mEnabledEconomicPolicies.size(); ++i) {
-            mEnabledEconomicPolicies.valueAt(i).setup();
+            mEnabledEconomicPolicies.valueAt(i).setup(properties);
         }
         updateMaxBalances();
     }
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java b/apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java
index 3a26aae..d401373 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/EconomicPolicy.java
@@ -16,6 +16,8 @@
 
 package com.android.server.tare;
 
+import static android.app.tare.EconomyManager.parseCreditValue;
+
 import static com.android.server.tare.Modifier.COST_MODIFIER_CHARGING;
 import static com.android.server.tare.Modifier.COST_MODIFIER_DEVICE_IDLE;
 import static com.android.server.tare.Modifier.COST_MODIFIER_POWER_SAVE_MODE;
@@ -27,7 +29,9 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.provider.DeviceConfig;
 import android.util.IndentingPrintWriter;
+import android.util.KeyValueListParser;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -170,7 +174,7 @@
     }
 
     @CallSuper
-    void setup() {
+    void setup(@NonNull DeviceConfig.Properties properties) {
         for (int i = 0; i < NUM_COST_MODIFIERS; ++i) {
             final Modifier modifier = COST_MODIFIER_BY_INDEX[i];
             if (modifier != null) {
@@ -409,6 +413,22 @@
         return "UNKNOWN_REWARD:" + Integer.toHexString(eventId);
     }
 
+    protected long getConstantAsCake(@NonNull KeyValueListParser parser,
+            @Nullable DeviceConfig.Properties properties, String key, long defaultValCake) {
+        // Don't cross the streams! Mixing Settings/local user config changes with DeviceConfig
+        // config can cause issues since the scales may be different, so use one or the other.
+        if (parser.size() > 0) {
+            // User settings take precedence. Just stick with the Settings constants, even if there
+            // are invalid values. It's not worth the time to evaluate all the key/value pairs to
+            // make sure there are valid ones before deciding.
+            return parseCreditValue(parser.getString(key, null), defaultValCake);
+        }
+        if (properties != null) {
+            return parseCreditValue(properties.getString(key, null), defaultValCake);
+        }
+        return defaultValCake;
+    }
+
     protected static void dumpActiveModifiers(IndentingPrintWriter pw) {
         for (int i = 0; i < NUM_COST_MODIFIERS; ++i) {
             pw.print("Modifier ");
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
index ce4604f..2118eeb 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/InternalResourceService.java
@@ -731,7 +731,7 @@
             registerListeners();
             mCurrentBatteryLevel = getCurrentBatteryLevel();
             mHandler.post(this::setupHeavyWork);
-            mCompleteEconomicPolicy.setup();
+            mCompleteEconomicPolicy.setup(mConfigObserver.getAllDeviceConfigProperties());
         }
     }
 
@@ -1014,10 +1014,17 @@
                     Settings.Global.getUriFor(TARE_ALARM_MANAGER_CONSTANTS), false, this);
             mContentResolver.registerContentObserver(
                     Settings.Global.getUriFor(TARE_JOB_SCHEDULER_CONSTANTS), false, this);
-            onPropertiesChanged(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_TARE));
+            onPropertiesChanged(getAllDeviceConfigProperties());
             updateEnabledStatus();
         }
 
+        @NonNull
+        DeviceConfig.Properties getAllDeviceConfigProperties() {
+            // Don't want to cache the Properties object locally in case it ends up being large,
+            // especially since it'll only be used once/infrequently (during setup or on a change).
+            return DeviceConfig.getProperties(DeviceConfig.NAMESPACE_TARE);
+        }
+
         @Override
         public void onChange(boolean selfChange, Uri uri) {
             if (uri.equals(Settings.Global.getUriFor(Settings.Global.ENABLE_TARE))) {
@@ -1030,6 +1037,7 @@
 
         @Override
         public void onPropertiesChanged(DeviceConfig.Properties properties) {
+            boolean economicPolicyUpdated = false;
             synchronized (mLock) {
                 for (String name : properties.getKeyset()) {
                     if (name == null) {
@@ -1039,6 +1047,12 @@
                         case KEY_DC_ENABLE_TARE:
                             updateEnabledStatus();
                             break;
+                        default:
+                            if (!economicPolicyUpdated
+                                    && (name.startsWith("am") || name.startsWith("js"))) {
+                                updateEconomicPolicy();
+                                economicPolicyUpdated = true;
+                            }
                     }
                 }
             }
@@ -1072,7 +1086,7 @@
                 mCompleteEconomicPolicy.tearDown();
                 mCompleteEconomicPolicy = new CompleteEconomicPolicy(InternalResourceService.this);
                 if (mIsEnabled && mBootPhase >= PHASE_SYSTEM_SERVICES_READY) {
-                    mCompleteEconomicPolicy.setup();
+                    mCompleteEconomicPolicy.setup(getAllDeviceConfigProperties());
                     if (initialLimit != mCompleteEconomicPolicy.getInitialSatiatedConsumptionLimit()
                             || hardLimit
                             != mCompleteEconomicPolicy.getHardSatiatedConsumptionLimit()) {
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/JobSchedulerEconomicPolicy.java b/apex/jobscheduler/service/java/com/android/server/tare/JobSchedulerEconomicPolicy.java
index 99b93ce..948f0a7 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/JobSchedulerEconomicPolicy.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/JobSchedulerEconomicPolicy.java
@@ -16,48 +16,48 @@
 
 package com.android.server.tare;
 
-import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_DEFAULT_RUNNING_BASE_PRICE;
-import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_DEFAULT_RUNNING_CTP;
-import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_DEFAULT_START_BASE_PRICE;
-import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_DEFAULT_START_CTP;
-import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_HIGH_RUNNING_BASE_PRICE;
-import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_HIGH_RUNNING_CTP;
-import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_HIGH_START_BASE_PRICE;
-import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_HIGH_START_CTP;
-import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_LOW_RUNNING_BASE_PRICE;
-import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_LOW_RUNNING_CTP;
-import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_LOW_START_BASE_PRICE;
-import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_LOW_START_CTP;
-import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_MAX_RUNNING_BASE_PRICE;
-import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_MAX_RUNNING_CTP;
-import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_MAX_START_BASE_PRICE;
-import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_MAX_START_CTP;
-import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_MIN_RUNNING_BASE_PRICE;
-import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_MIN_RUNNING_CTP;
-import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_MIN_START_BASE_PRICE;
-import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_MIN_START_CTP;
-import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_TIMEOUT_PENALTY_BASE_PRICE;
-import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_TIMEOUT_PENALTY_CTP;
-import static android.app.tare.EconomyManager.DEFAULT_JS_HARD_CONSUMPTION_LIMIT;
-import static android.app.tare.EconomyManager.DEFAULT_JS_INITIAL_CONSUMPTION_LIMIT;
-import static android.app.tare.EconomyManager.DEFAULT_JS_MAX_SATIATED_BALANCE;
-import static android.app.tare.EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_EXEMPTED;
-import static android.app.tare.EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_OTHER_APP;
-import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_INSTANT;
-import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_MAX;
-import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_ONGOING;
-import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_SEEN_INSTANT;
-import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_SEEN_MAX;
-import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_SEEN_ONGOING;
-import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_INSTANT;
-import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_MAX;
-import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_ONGOING;
-import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_TOP_ACTIVITY_INSTANT;
-import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_TOP_ACTIVITY_MAX;
-import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_TOP_ACTIVITY_ONGOING;
-import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_WIDGET_INTERACTION_INSTANT;
-import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_WIDGET_INTERACTION_MAX;
-import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_WIDGET_INTERACTION_ONGOING;
+import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_DEFAULT_RUNNING_BASE_PRICE_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_DEFAULT_RUNNING_CTP_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_DEFAULT_START_BASE_PRICE_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_DEFAULT_START_CTP_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_HIGH_RUNNING_BASE_PRICE_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_HIGH_RUNNING_CTP_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_HIGH_START_BASE_PRICE_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_HIGH_START_CTP_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_LOW_RUNNING_BASE_PRICE_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_LOW_RUNNING_CTP_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_LOW_START_BASE_PRICE_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_LOW_START_CTP_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_MAX_RUNNING_BASE_PRICE_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_MAX_RUNNING_CTP_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_MAX_START_BASE_PRICE_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_MAX_START_CTP_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_MIN_RUNNING_BASE_PRICE_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_MIN_RUNNING_CTP_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_MIN_START_BASE_PRICE_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_MIN_START_CTP_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_TIMEOUT_PENALTY_BASE_PRICE_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_ACTION_JOB_TIMEOUT_PENALTY_CTP_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_HARD_CONSUMPTION_LIMIT_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_INITIAL_CONSUMPTION_LIMIT_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_MAX_SATIATED_BALANCE_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_EXEMPTED_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_MIN_SATIATED_BALANCE_OTHER_APP_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_INSTANT_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_MAX_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_ONGOING_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_SEEN_INSTANT_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_SEEN_MAX_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_NOTIFICATION_SEEN_ONGOING_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_INSTANT_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_MAX_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_ONGOING_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_TOP_ACTIVITY_INSTANT_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_TOP_ACTIVITY_MAX_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_TOP_ACTIVITY_ONGOING_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_WIDGET_INTERACTION_INSTANT_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_WIDGET_INTERACTION_MAX_CAKES;
+import static android.app.tare.EconomyManager.DEFAULT_JS_REWARD_WIDGET_INTERACTION_ONGOING_CAKES;
 import static android.app.tare.EconomyManager.KEY_JS_ACTION_JOB_DEFAULT_RUNNING_BASE_PRICE;
 import static android.app.tare.EconomyManager.KEY_JS_ACTION_JOB_DEFAULT_RUNNING_CTP;
 import static android.app.tare.EconomyManager.KEY_JS_ACTION_JOB_DEFAULT_START_BASE_PRICE;
@@ -106,12 +106,12 @@
 import static com.android.server.tare.Modifier.COST_MODIFIER_DEVICE_IDLE;
 import static com.android.server.tare.Modifier.COST_MODIFIER_POWER_SAVE_MODE;
 import static com.android.server.tare.Modifier.COST_MODIFIER_PROCESS_STATE;
-import static com.android.server.tare.TareUtils.arcToCake;
 import static com.android.server.tare.TareUtils.cakeToString;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.ContentResolver;
+import android.provider.DeviceConfig;
 import android.provider.Settings;
 import android.util.IndentingPrintWriter;
 import android.util.KeyValueListParser;
@@ -159,14 +159,15 @@
     JobSchedulerEconomicPolicy(InternalResourceService irs) {
         super(irs);
         mInternalResourceService = irs;
-        loadConstants("");
+        loadConstants("", null);
     }
 
     @Override
-    void setup() {
-        super.setup();
+    void setup(@NonNull DeviceConfig.Properties properties) {
+        super.setup(properties);
         ContentResolver resolver = mInternalResourceService.getContext().getContentResolver();
-        loadConstants(Settings.Global.getString(resolver, TARE_JOB_SCHEDULER_CONSTANTS));
+        loadConstants(Settings.Global.getString(resolver, TARE_JOB_SCHEDULER_CONSTANTS),
+                properties);
     }
 
     @Override
@@ -211,7 +212,8 @@
         return mRewards.get(rewardId);
     }
 
-    private void loadConstants(String policyValuesString) {
+    private void loadConstants(String policyValuesString,
+            @Nullable DeviceConfig.Properties properties) {
         mActions.clear();
         mRewards.clear();
 
@@ -221,118 +223,153 @@
             Slog.e(TAG, "Global setting key incorrect: ", e);
         }
 
-        mMinSatiatedBalanceExempted = arcToCake(
-                mParser.getInt(KEY_JS_MIN_SATIATED_BALANCE_EXEMPTED,
-                        DEFAULT_JS_MIN_SATIATED_BALANCE_EXEMPTED));
-        mMinSatiatedBalanceOther = arcToCake(
-                mParser.getInt(KEY_JS_MIN_SATIATED_BALANCE_OTHER_APP,
-                        DEFAULT_JS_MIN_SATIATED_BALANCE_OTHER_APP));
-        mMaxSatiatedBalance = arcToCake(mParser.getInt(KEY_JS_MAX_SATIATED_BALANCE,
-                DEFAULT_JS_MAX_SATIATED_BALANCE));
-        mInitialSatiatedConsumptionLimit = arcToCake(mParser.getInt(
-                KEY_JS_INITIAL_CONSUMPTION_LIMIT, DEFAULT_JS_INITIAL_CONSUMPTION_LIMIT));
+        mMinSatiatedBalanceExempted = getConstantAsCake(mParser, properties,
+                KEY_JS_MIN_SATIATED_BALANCE_EXEMPTED,
+                DEFAULT_JS_MIN_SATIATED_BALANCE_EXEMPTED_CAKES);
+        mMinSatiatedBalanceOther = getConstantAsCake(mParser, properties,
+                KEY_JS_MIN_SATIATED_BALANCE_OTHER_APP,
+                DEFAULT_JS_MIN_SATIATED_BALANCE_OTHER_APP_CAKES);
+        mMaxSatiatedBalance = getConstantAsCake(mParser, properties,
+                KEY_JS_MAX_SATIATED_BALANCE,
+                DEFAULT_JS_MAX_SATIATED_BALANCE_CAKES);
+        mInitialSatiatedConsumptionLimit = getConstantAsCake(mParser, properties,
+                KEY_JS_INITIAL_CONSUMPTION_LIMIT,
+                DEFAULT_JS_INITIAL_CONSUMPTION_LIMIT_CAKES);
         mHardSatiatedConsumptionLimit = Math.max(mInitialSatiatedConsumptionLimit,
-                arcToCake(mParser.getInt(
-                        KEY_JS_HARD_CONSUMPTION_LIMIT, DEFAULT_JS_HARD_CONSUMPTION_LIMIT)));
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_HARD_CONSUMPTION_LIMIT,
+                        DEFAULT_JS_HARD_CONSUMPTION_LIMIT_CAKES));
 
         mActions.put(ACTION_JOB_MAX_START, new Action(ACTION_JOB_MAX_START,
-                arcToCake(mParser.getInt(KEY_JS_ACTION_JOB_MAX_START_CTP,
-                        DEFAULT_JS_ACTION_JOB_MAX_START_CTP)),
-                arcToCake(mParser.getInt(KEY_JS_ACTION_JOB_MAX_START_BASE_PRICE,
-                        DEFAULT_JS_ACTION_JOB_MAX_START_BASE_PRICE))));
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_ACTION_JOB_MAX_START_CTP,
+                        DEFAULT_JS_ACTION_JOB_MAX_START_CTP_CAKES),
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_ACTION_JOB_MAX_START_BASE_PRICE,
+                        DEFAULT_JS_ACTION_JOB_MAX_START_BASE_PRICE_CAKES)));
         mActions.put(ACTION_JOB_MAX_RUNNING, new Action(ACTION_JOB_MAX_RUNNING,
-                arcToCake(mParser.getInt(KEY_JS_ACTION_JOB_MAX_RUNNING_CTP,
-                        DEFAULT_JS_ACTION_JOB_MAX_RUNNING_CTP)),
-                arcToCake(mParser.getInt(KEY_JS_ACTION_JOB_MAX_RUNNING_BASE_PRICE,
-                        DEFAULT_JS_ACTION_JOB_MAX_RUNNING_BASE_PRICE))));
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_ACTION_JOB_MAX_RUNNING_CTP,
+                        DEFAULT_JS_ACTION_JOB_MAX_RUNNING_CTP_CAKES),
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_ACTION_JOB_MAX_RUNNING_BASE_PRICE,
+                        DEFAULT_JS_ACTION_JOB_MAX_RUNNING_BASE_PRICE_CAKES)));
         mActions.put(ACTION_JOB_HIGH_START, new Action(ACTION_JOB_HIGH_START,
-                arcToCake(mParser.getInt(KEY_JS_ACTION_JOB_HIGH_START_CTP,
-                        DEFAULT_JS_ACTION_JOB_HIGH_START_CTP)),
-                arcToCake(mParser.getInt(KEY_JS_ACTION_JOB_HIGH_START_BASE_PRICE,
-                        DEFAULT_JS_ACTION_JOB_HIGH_START_BASE_PRICE))));
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_ACTION_JOB_HIGH_START_CTP,
+                        DEFAULT_JS_ACTION_JOB_HIGH_START_CTP_CAKES),
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_ACTION_JOB_HIGH_START_BASE_PRICE,
+                        DEFAULT_JS_ACTION_JOB_HIGH_START_BASE_PRICE_CAKES)));
         mActions.put(ACTION_JOB_HIGH_RUNNING, new Action(ACTION_JOB_HIGH_RUNNING,
-                arcToCake(mParser.getInt(KEY_JS_ACTION_JOB_HIGH_RUNNING_CTP,
-                        DEFAULT_JS_ACTION_JOB_HIGH_RUNNING_CTP)),
-                arcToCake(mParser.getInt(KEY_JS_ACTION_JOB_HIGH_RUNNING_BASE_PRICE,
-                        DEFAULT_JS_ACTION_JOB_HIGH_RUNNING_BASE_PRICE))));
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_ACTION_JOB_HIGH_RUNNING_CTP,
+                        DEFAULT_JS_ACTION_JOB_HIGH_RUNNING_CTP_CAKES),
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_ACTION_JOB_HIGH_RUNNING_BASE_PRICE,
+                        DEFAULT_JS_ACTION_JOB_HIGH_RUNNING_BASE_PRICE_CAKES)));
         mActions.put(ACTION_JOB_DEFAULT_START, new Action(ACTION_JOB_DEFAULT_START,
-                arcToCake(mParser.getInt(KEY_JS_ACTION_JOB_DEFAULT_START_CTP,
-                        DEFAULT_JS_ACTION_JOB_DEFAULT_START_CTP)),
-                arcToCake(mParser.getInt(KEY_JS_ACTION_JOB_DEFAULT_START_BASE_PRICE,
-                        DEFAULT_JS_ACTION_JOB_DEFAULT_START_BASE_PRICE))));
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_ACTION_JOB_DEFAULT_START_CTP,
+                        DEFAULT_JS_ACTION_JOB_DEFAULT_START_CTP_CAKES),
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_ACTION_JOB_DEFAULT_START_BASE_PRICE,
+                        DEFAULT_JS_ACTION_JOB_DEFAULT_START_BASE_PRICE_CAKES)));
         mActions.put(ACTION_JOB_DEFAULT_RUNNING, new Action(ACTION_JOB_DEFAULT_RUNNING,
-                arcToCake(mParser.getInt(KEY_JS_ACTION_JOB_DEFAULT_RUNNING_CTP,
-                        DEFAULT_JS_ACTION_JOB_DEFAULT_RUNNING_CTP)),
-                arcToCake(mParser.getInt(KEY_JS_ACTION_JOB_DEFAULT_RUNNING_BASE_PRICE,
-                        DEFAULT_JS_ACTION_JOB_DEFAULT_RUNNING_BASE_PRICE))));
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_ACTION_JOB_DEFAULT_RUNNING_CTP,
+                        DEFAULT_JS_ACTION_JOB_DEFAULT_RUNNING_CTP_CAKES),
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_ACTION_JOB_DEFAULT_RUNNING_BASE_PRICE,
+                        DEFAULT_JS_ACTION_JOB_DEFAULT_RUNNING_BASE_PRICE_CAKES)));
         mActions.put(ACTION_JOB_LOW_START, new Action(ACTION_JOB_LOW_START,
-                arcToCake(mParser.getInt(KEY_JS_ACTION_JOB_LOW_START_CTP,
-                        DEFAULT_JS_ACTION_JOB_LOW_START_CTP)),
-                arcToCake(mParser.getInt(KEY_JS_ACTION_JOB_LOW_START_BASE_PRICE,
-                        DEFAULT_JS_ACTION_JOB_LOW_START_BASE_PRICE))));
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_ACTION_JOB_LOW_START_CTP,
+                        DEFAULT_JS_ACTION_JOB_LOW_START_CTP_CAKES),
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_ACTION_JOB_LOW_START_BASE_PRICE,
+                        DEFAULT_JS_ACTION_JOB_LOW_START_BASE_PRICE_CAKES)));
         mActions.put(ACTION_JOB_LOW_RUNNING, new Action(ACTION_JOB_LOW_RUNNING,
-                arcToCake(mParser.getInt(KEY_JS_ACTION_JOB_LOW_RUNNING_CTP,
-                        DEFAULT_JS_ACTION_JOB_LOW_RUNNING_CTP)),
-                arcToCake(mParser.getInt(KEY_JS_ACTION_JOB_LOW_RUNNING_BASE_PRICE,
-                        DEFAULT_JS_ACTION_JOB_LOW_RUNNING_BASE_PRICE))));
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_ACTION_JOB_LOW_RUNNING_CTP,
+                        DEFAULT_JS_ACTION_JOB_LOW_RUNNING_CTP_CAKES),
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_ACTION_JOB_LOW_RUNNING_BASE_PRICE,
+                        DEFAULT_JS_ACTION_JOB_LOW_RUNNING_BASE_PRICE_CAKES)));
         mActions.put(ACTION_JOB_MIN_START, new Action(ACTION_JOB_MIN_START,
-                arcToCake(mParser.getInt(KEY_JS_ACTION_JOB_MIN_START_CTP,
-                        DEFAULT_JS_ACTION_JOB_MIN_START_CTP)),
-                arcToCake(mParser.getInt(KEY_JS_ACTION_JOB_MIN_START_BASE_PRICE,
-                        DEFAULT_JS_ACTION_JOB_MIN_START_BASE_PRICE))));
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_ACTION_JOB_MIN_START_CTP,
+                        DEFAULT_JS_ACTION_JOB_MIN_START_CTP_CAKES),
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_ACTION_JOB_MIN_START_BASE_PRICE,
+                        DEFAULT_JS_ACTION_JOB_MIN_START_BASE_PRICE_CAKES)));
         mActions.put(ACTION_JOB_MIN_RUNNING, new Action(ACTION_JOB_MIN_RUNNING,
-                arcToCake(mParser.getInt(KEY_JS_ACTION_JOB_MIN_RUNNING_CTP,
-                        DEFAULT_JS_ACTION_JOB_MIN_RUNNING_CTP)),
-                arcToCake(mParser.getInt(KEY_JS_ACTION_JOB_MIN_RUNNING_BASE_PRICE,
-                        DEFAULT_JS_ACTION_JOB_MIN_RUNNING_BASE_PRICE))));
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_ACTION_JOB_MIN_RUNNING_CTP,
+                        DEFAULT_JS_ACTION_JOB_MIN_RUNNING_CTP_CAKES),
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_ACTION_JOB_MIN_RUNNING_BASE_PRICE,
+                        DEFAULT_JS_ACTION_JOB_MIN_RUNNING_BASE_PRICE_CAKES)));
         mActions.put(ACTION_JOB_TIMEOUT, new Action(ACTION_JOB_TIMEOUT,
-                arcToCake(mParser.getInt(KEY_JS_ACTION_JOB_TIMEOUT_PENALTY_CTP,
-                        DEFAULT_JS_ACTION_JOB_TIMEOUT_PENALTY_CTP)),
-                arcToCake(mParser.getInt(KEY_JS_ACTION_JOB_TIMEOUT_PENALTY_BASE_PRICE,
-                        DEFAULT_JS_ACTION_JOB_TIMEOUT_PENALTY_BASE_PRICE))));
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_ACTION_JOB_TIMEOUT_PENALTY_CTP,
+                        DEFAULT_JS_ACTION_JOB_TIMEOUT_PENALTY_CTP_CAKES),
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_ACTION_JOB_TIMEOUT_PENALTY_BASE_PRICE,
+                        DEFAULT_JS_ACTION_JOB_TIMEOUT_PENALTY_BASE_PRICE_CAKES)));
 
         mRewards.put(REWARD_TOP_ACTIVITY, new Reward(REWARD_TOP_ACTIVITY,
-                arcToCake(mParser.getInt(KEY_JS_REWARD_TOP_ACTIVITY_INSTANT,
-                        DEFAULT_JS_REWARD_TOP_ACTIVITY_INSTANT)),
-                (long) (arcToCake(1) * mParser.getFloat(KEY_JS_REWARD_TOP_ACTIVITY_ONGOING,
-                        DEFAULT_JS_REWARD_TOP_ACTIVITY_ONGOING)),
-                arcToCake(mParser.getInt(KEY_JS_REWARD_TOP_ACTIVITY_MAX,
-                        DEFAULT_JS_REWARD_TOP_ACTIVITY_MAX))));
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_REWARD_TOP_ACTIVITY_INSTANT,
+                        DEFAULT_JS_REWARD_TOP_ACTIVITY_INSTANT_CAKES),
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_REWARD_TOP_ACTIVITY_ONGOING,
+                        DEFAULT_JS_REWARD_TOP_ACTIVITY_ONGOING_CAKES),
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_REWARD_TOP_ACTIVITY_MAX,
+                        DEFAULT_JS_REWARD_TOP_ACTIVITY_MAX_CAKES)));
         mRewards.put(REWARD_NOTIFICATION_SEEN, new Reward(REWARD_NOTIFICATION_SEEN,
-                arcToCake(mParser.getInt(KEY_JS_REWARD_NOTIFICATION_SEEN_INSTANT,
-                        DEFAULT_JS_REWARD_NOTIFICATION_SEEN_INSTANT)),
-                arcToCake(mParser.getInt(KEY_JS_REWARD_NOTIFICATION_SEEN_ONGOING,
-                        DEFAULT_JS_REWARD_NOTIFICATION_SEEN_ONGOING)),
-                arcToCake(mParser.getInt(KEY_JS_REWARD_NOTIFICATION_SEEN_MAX,
-                        DEFAULT_JS_REWARD_NOTIFICATION_SEEN_MAX))));
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_REWARD_NOTIFICATION_SEEN_INSTANT,
+                        DEFAULT_JS_REWARD_NOTIFICATION_SEEN_INSTANT_CAKES),
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_REWARD_NOTIFICATION_SEEN_ONGOING,
+                        DEFAULT_JS_REWARD_NOTIFICATION_SEEN_ONGOING_CAKES),
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_REWARD_NOTIFICATION_SEEN_MAX,
+                        DEFAULT_JS_REWARD_NOTIFICATION_SEEN_MAX_CAKES)));
         mRewards.put(REWARD_NOTIFICATION_INTERACTION,
                 new Reward(REWARD_NOTIFICATION_INTERACTION,
-                        arcToCake(mParser.getInt(
+                        getConstantAsCake(mParser, properties,
                                 KEY_JS_REWARD_NOTIFICATION_INTERACTION_INSTANT,
-                                DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_INSTANT)),
-                        arcToCake(mParser.getInt(
+                                DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_INSTANT_CAKES),
+                        getConstantAsCake(mParser, properties,
                                 KEY_JS_REWARD_NOTIFICATION_INTERACTION_ONGOING,
-                                DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_ONGOING)),
-                        arcToCake(mParser.getInt(
+                                DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_ONGOING_CAKES),
+                        getConstantAsCake(mParser, properties,
                                 KEY_JS_REWARD_NOTIFICATION_INTERACTION_MAX,
-                                DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_MAX))));
+                                DEFAULT_JS_REWARD_NOTIFICATION_INTERACTION_MAX_CAKES)));
         mRewards.put(REWARD_WIDGET_INTERACTION, new Reward(REWARD_WIDGET_INTERACTION,
-                arcToCake(mParser.getInt(KEY_JS_REWARD_WIDGET_INTERACTION_INSTANT,
-                        DEFAULT_JS_REWARD_WIDGET_INTERACTION_INSTANT)),
-                arcToCake(mParser.getInt(KEY_JS_REWARD_WIDGET_INTERACTION_ONGOING,
-                        DEFAULT_JS_REWARD_WIDGET_INTERACTION_ONGOING)),
-                arcToCake(mParser.getInt(KEY_JS_REWARD_WIDGET_INTERACTION_MAX,
-                        DEFAULT_JS_REWARD_WIDGET_INTERACTION_MAX))));
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_REWARD_WIDGET_INTERACTION_INSTANT,
+                        DEFAULT_JS_REWARD_WIDGET_INTERACTION_INSTANT_CAKES),
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_REWARD_WIDGET_INTERACTION_ONGOING,
+                        DEFAULT_JS_REWARD_WIDGET_INTERACTION_ONGOING_CAKES),
+                getConstantAsCake(mParser, properties,
+                        KEY_JS_REWARD_WIDGET_INTERACTION_MAX,
+                        DEFAULT_JS_REWARD_WIDGET_INTERACTION_MAX_CAKES)));
         mRewards.put(REWARD_OTHER_USER_INTERACTION,
                 new Reward(REWARD_OTHER_USER_INTERACTION,
-                        arcToCake(mParser.getInt(KEY_JS_REWARD_OTHER_USER_INTERACTION_INSTANT,
-                                DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_INSTANT)),
-                        arcToCake(mParser.getInt(
+                        getConstantAsCake(mParser, properties,
+                                KEY_JS_REWARD_OTHER_USER_INTERACTION_INSTANT,
+                                DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_INSTANT_CAKES),
+                        getConstantAsCake(mParser, properties,
                                 KEY_JS_REWARD_OTHER_USER_INTERACTION_ONGOING,
-                                DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_ONGOING)),
-                        arcToCake(mParser.getInt(
+                                DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_ONGOING_CAKES),
+                        getConstantAsCake(mParser, properties,
                                 KEY_JS_REWARD_OTHER_USER_INTERACTION_MAX,
-                                DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_MAX))));
+                                DEFAULT_JS_REWARD_OTHER_USER_INTERACTION_MAX_CAKES)));
     }
 
     @Override
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/README.md b/apex/jobscheduler/service/java/com/android/server/tare/README.md
index 72d5069..e338ed1 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/README.md
+++ b/apex/jobscheduler/service/java/com/android/server/tare/README.md
@@ -18,16 +18,17 @@
 In an ideal world, the system could be said to most efficiently allocate resources by maximizing its
 profits &mdash; by maximizing the aggregate sum of the difference between an action's price (that
 the app ends up paying) and the cost to produce by the system. This assumes that more important
-actions have a higher price than less important actions. With this assumption, maximizing profits
-implies that the system runs the most important work first and proceeds in decreasing order of
-importance. Of course, that also means the system will not run anything where an app would pay less
-for the action than the system's cost to produce that action. Some of this breaks down when we throw
-TOP apps into the mix &mdash; TOP apps pay 0 for all actions, even though the CTP may be greater
-than 0. This is to ensure ideal user experience for the app the user is actively interacting with.
-Similar caveats exist for system-critical processes (such as the OS itself) and apps running
-foreground services (since those could be critical to user experience, as is the case for media and
-navigation apps). Excluding those caveats/special situations, maximizing profits of actions
-performed by apps in the background should be the target.
+actions have a higher price than less important actions and all actors have perfect information and
+convey that information accurately. With these assumptions, maximizing profits implies that the
+system runs the most important work first and proceeds in decreasing order of importance. Of course,
+that also means the system will not run anything where an app would pay less for the action than the
+system's cost to produce that action. Some of this breaks down when we throw TOP apps into the mix
+&mdash; TOP apps pay 0 for all actions, even though the CTP may be greater than 0. This is to ensure
+ideal user experience for the app the user is actively interacting with. Similar caveats exist for
+system-critical processes (such as the OS itself) and apps running foreground services (since those
+could be critical to user experience, as is the case for media and navigation apps). Excluding those
+caveats/special situations, maximizing profits of actions performed by apps in the background should
+be the target.
 
 To achieve the goal laid out by TARE, we use Android Resource Credits (ARCs for short) as the
 internal/representative currency of the system.
@@ -101,11 +102,37 @@
 allowed apps to accrue credits as appropriate while still limiting the total number of credits
 consumed.
 
+# Potential Future Changes
+
+These are some ideas for further changes. There's no guarantee that they'll be implemented.
+
+* Include additional components and policies for them. TARE may benefit from adding policies for
+  components such as broadcast dispatching, network traffic, location requests, and sensor usage.
+* Have a separate "account" for critical/special actions. In other words, have two accounts for each
+  app, where one acts like a special savings account and is only allowed to be used for special
+  actions such as expedited job execution. The second account would have a lower maximum than the
+  main account, but would help to make sure that normal actions don't interfere too much with more
+  critical actions.
+* Transferring credits from one app to another. For apps that rely on others for some pieces of
+  work, it may be beneficial to allow the requesting app to transfer, donate, or somehow make
+  available some of its own credits to the app doing the work in order to make sure the working app
+  has enough credits available to do the work.
+* Formulate values based on device hardware. For example, adjust the consumption limit based on the
+  battery size, or the price and/or CTP of actions based on hardware efficiency.
+* Price discovery via an auction system. Instead of just setting a fixed price that may be modified
+  by device and app states, let an app say how much it's willing to pay for a specific action and
+  then have a small auction when the system needs to decide which app to perform the action for
+  first or how much to charge the app.
+
 # Definitions
 
 * ARC: Android Resource Credits are the "currency" units used as an abstraction layer over the real
   battery drain. They allow the system to standardize costs and prices across various devices.
 * Cake: A lie; also the smallest unit of an ARC (1 cake = one-billionth of an ARC = 1 nano-ARC).
   When the apps request to do something, we shall let them eat cake.
-* NARC: The smallest unit of an ARC. A narc is 1 nano-ARC.
+* Cost to produce (CTP): An economic term that refers to the total cost incurred by a business to
+  produce a specific quantity of a product or offer a service. In TARE's context, CTP is meant to be
+  the estimated cost t ohe system to accomplish a certain action. These "actions" are basically APIs
+  that apps use to get something done. So the idea is to define the base cost for an app to use a
+  specific API.
 * Satiated: used to refer to when the device is fully charged (at 100% battery level)
\ No newline at end of file
diff --git a/apex/jobscheduler/service/java/com/android/server/tare/TareUtils.java b/apex/jobscheduler/service/java/com/android/server/tare/TareUtils.java
index 87db863..6b6984f 100644
--- a/apex/jobscheduler/service/java/com/android/server/tare/TareUtils.java
+++ b/apex/jobscheduler/service/java/com/android/server/tare/TareUtils.java
@@ -16,6 +16,8 @@
 
 package com.android.server.tare;
 
+import static android.app.tare.EconomyManager.CAKE_IN_ARC;
+
 import android.annotation.NonNull;
 import android.annotation.SuppressLint;
 import android.util.IndentingPrintWriter;
@@ -26,8 +28,6 @@
 import java.time.Clock;
 
 class TareUtils {
-    private static final long CAKE_IN_ARC = 1_000_000_000L;
-
     @SuppressLint("SimpleDateFormat")
     private static final SimpleDateFormat sDumpDateFormat =
             new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
@@ -35,10 +35,6 @@
     @VisibleForTesting
     static Clock sSystemClock = Clock.systemUTC();
 
-    static long arcToCake(int arcs) {
-        return arcs * CAKE_IN_ARC;
-    }
-
     static void dumpTime(IndentingPrintWriter pw, long time) {
         pw.print(sDumpDateFormat.format(time));
     }
@@ -56,7 +52,7 @@
         if (cakes == 0) {
             return "0 ARCs";
         }
-        final long sub = Math.abs(cakes) % CAKE_IN_ARC;
+        final long sub = cakes % CAKE_IN_ARC;
         final long arcs = cakeToArc(cakes);
         if (arcs == 0) {
             return sub == 1
@@ -65,11 +61,11 @@
         }
         StringBuilder sb = new StringBuilder();
         sb.append(arcs);
-        if (sub > 0) {
-            sb.append(".").append(sub / (CAKE_IN_ARC / 1000));
+        if (sub != 0) {
+            sb.append(".").append(String.format("%03d", Math.abs(sub) / (CAKE_IN_ARC / 1000)));
         }
         sb.append(" ARC");
-        if (arcs != 1 || sub > 0) {
+        if (arcs != 1 || sub != 0) {
             sb.append("s");
         }
         return sb.toString();
diff --git a/core/api/module-lib-lint-baseline.txt b/core/api/module-lib-lint-baseline.txt
index 0c1ebb3..27436ce 100644
--- a/core/api/module-lib-lint-baseline.txt
+++ b/core/api/module-lib-lint-baseline.txt
@@ -1,4 +1,6 @@
 // Baseline format: 1.0
+SamShouldBeLast: android.app.Activity#convertToTranslucent(android.app.Activity.TranslucentConversionListener, android.app.ActivityOptions):
+    SAM-compatible parameters (such as parameter 1, "callback", in android.app.Activity.convertToTranslucent) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.app.ActivityManager#addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int):
     SAM-compatible parameters (such as parameter 1, "listener", in android.app.ActivityManager.addOnUidImportanceListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.app.PendingIntent#send(android.content.Context, int, android.content.Intent, android.app.PendingIntent.OnFinished, android.os.Handler):
@@ -9,6 +11,24 @@
     SAM-compatible parameters (such as parameter 4, "onFinished", in android.app.PendingIntent.send) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.app.PendingIntent#send(int, android.app.PendingIntent.OnFinished, android.os.Handler):
     SAM-compatible parameters (such as parameter 2, "onFinished", in android.app.PendingIntent.send) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.content.pm.ApplicationInfo#dump(android.util.Printer, String):
+    SAM-compatible parameters (such as parameter 1, "pw", in android.content.pm.ApplicationInfo.dump) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.content.pm.PackageItemInfo#dumpBack(android.util.Printer, String):
+    SAM-compatible parameters (such as parameter 1, "pw", in android.content.pm.PackageItemInfo.dumpBack) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.content.pm.PackageItemInfo#dumpFront(android.util.Printer, String):
+    SAM-compatible parameters (such as parameter 1, "pw", in android.content.pm.PackageItemInfo.dumpFront) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#addNmeaListener(android.location.OnNmeaMessageListener, android.os.Handler):
+    SAM-compatible parameters (such as parameter 1, "listener", in android.location.LocationManager.addNmeaListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(String, long, float, android.location.LocationListener, android.os.Looper):
+    SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(android.location.LocationRequest, android.location.LocationListener, android.os.Looper):
+    SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(long, float, android.location.Criteria, android.location.LocationListener, android.os.Looper):
+    SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(String, android.location.LocationListener, android.os.Looper):
+    SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(android.location.Criteria, android.location.LocationListener, android.os.Looper):
+    SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.media.AudioManager#abandonAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes):
     SAM-compatible parameters (such as parameter 1, "l", in android.media.AudioManager.abandonAudioFocus) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.media.AudioManager#requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, android.media.AudioAttributes, int, int):
diff --git a/core/api/system-lint-baseline.txt b/core/api/system-lint-baseline.txt
index 1b45e88..025e862 100644
--- a/core/api/system-lint-baseline.txt
+++ b/core/api/system-lint-baseline.txt
@@ -1,36 +1,20 @@
 // Baseline format: 1.0
 ArrayReturn: android.view.contentcapture.ViewNode#getAutofillOptions():
-
-ExecutorRegistration: android.media.MediaPlayer#setOnRtpRxNoticeListener(android.content.Context, android.media.MediaPlayer.OnRtpRxNoticeListener, android.os.Handler):
-    Registration methods should have overload that accepts delivery Executor: `setOnRtpRxNoticeListener`
+    Method should return Collection<CharSequence> (or subclass) instead of raw array; was `java.lang.CharSequence[]`
 
 
 GenericException: android.app.prediction.AppPredictor#finalize():
-    
+    Methods must not throw generic exceptions (`java.lang.Throwable`)
 GenericException: android.hardware.location.ContextHubClient#finalize():
-    
+    Methods must not throw generic exceptions (`java.lang.Throwable`)
 GenericException: android.service.autofill.augmented.FillWindow#finalize():
-    
-
-
-IntentBuilderName: android.app.search.SearchAction#getIntent():
-    
-IntentBuilderName: android.app.smartspace.SmartspaceAction#getIntent():
-    Methods creating an Intent should be named `create<Foo>Intent()`, was `getIntent`
+    Methods must not throw generic exceptions (`java.lang.Throwable`)
 
 
 KotlinKeyword: android.app.Notification#when:
-    
+    Avoid field names that are Kotlin hard keywords ("when"); see https://android.github.io/kotlin-guides/interop.html#no-hard-keywords
 
 
-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):
-    android.service.autofill.Dataset does not declare a `getFieldInlinePresentation()` method matching method android.service.autofill.Dataset.Builder.setFieldInlinePresentation(android.view.autofill.AutofillId,android.view.autofill.AutofillValue,java.util.regex.Pattern,android.service.autofill.InlinePresentation)
 MissingGetterMatchingBuilder: android.telecom.CallScreeningService.CallResponse.Builder#setShouldScreenCallViaAudioProcessing(boolean):
     android.telecom.CallScreeningService.CallResponse does not declare a `shouldScreenCallViaAudioProcessing()` method matching method android.telecom.CallScreeningService.CallResponse.Builder.setShouldScreenCallViaAudioProcessing(boolean)
 MissingGetterMatchingBuilder: android.telephony.mbms.DownloadRequest.Builder#setServiceId(String):
@@ -38,175 +22,135 @@
 
 
 MissingNullability: android.media.soundtrigger.SoundTriggerDetectionService#onUnbind(android.content.Intent) parameter #0:
-    
+    Missing nullability on parameter `intent` in method `onUnbind`
 MissingNullability: android.media.tv.TvRecordingClient.RecordingCallback#onEvent(String, String, android.os.Bundle) parameter #0:
-    
+    Missing nullability on parameter `inputId` in method `onEvent`
 MissingNullability: android.media.tv.TvRecordingClient.RecordingCallback#onEvent(String, String, android.os.Bundle) parameter #1:
-    
+    Missing nullability on parameter `eventType` in method `onEvent`
 MissingNullability: android.media.tv.TvRecordingClient.RecordingCallback#onEvent(String, String, android.os.Bundle) parameter #2:
-    
+    Missing nullability on parameter `eventArgs` in method `onEvent`
 MissingNullability: android.printservice.recommendation.RecommendationService#attachBaseContext(android.content.Context) parameter #0:
-    
+    Missing nullability on parameter `base` in method `attachBaseContext`
 MissingNullability: android.provider.ContactsContract.MetadataSync#CONTENT_URI:
-    
+    Missing nullability on field `CONTENT_URI` in class `class android.provider.ContactsContract.MetadataSync`
 MissingNullability: android.provider.ContactsContract.MetadataSync#METADATA_AUTHORITY_URI:
-    
+    Missing nullability on field `METADATA_AUTHORITY_URI` in class `class android.provider.ContactsContract.MetadataSync`
 MissingNullability: android.provider.ContactsContract.MetadataSyncState#CONTENT_URI:
-    
+    Missing nullability on field `CONTENT_URI` in class `class android.provider.ContactsContract.MetadataSyncState`
 MissingNullability: android.provider.SearchIndexablesProvider#attachInfo(android.content.Context, android.content.pm.ProviderInfo) parameter #0:
-    
+    Missing nullability on parameter `context` in method `attachInfo`
 MissingNullability: android.provider.SearchIndexablesProvider#attachInfo(android.content.Context, android.content.pm.ProviderInfo) parameter #1:
-    
+    Missing nullability on parameter `info` in method `attachInfo`
 MissingNullability: android.service.autofill.augmented.AugmentedAutofillService#onUnbind(android.content.Intent) parameter #0:
-    
+    Missing nullability on parameter `intent` in method `onUnbind`
 MissingNullability: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #0:
-    
+    Missing nullability on parameter `fd` in method `dump`
 MissingNullability: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #1:
-    
+    Missing nullability on parameter `pw` in method `dump`
 MissingNullability: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #2:
-    
+    Missing nullability on parameter `args` in method `dump`
 MissingNullability: android.service.notification.NotificationAssistantService#attachBaseContext(android.content.Context) parameter #0:
-    
+    Missing nullability on parameter `base` in method `attachBaseContext`
 MissingNullability: android.telephony.NetworkService#onUnbind(android.content.Intent) parameter #0:
-    
-MissingNullability: android.telephony.SubscriptionPlan.Builder#createRecurringDaily(java.time.ZonedDateTime) parameter #0:
-    
-MissingNullability: android.telephony.SubscriptionPlan.Builder#createRecurringMonthly(java.time.ZonedDateTime) parameter #0:
-    
-MissingNullability: android.telephony.SubscriptionPlan.Builder#createRecurringWeekly(java.time.ZonedDateTime) parameter #0:
-    
+    Missing nullability on parameter `intent` in method `onUnbind`
 MissingNullability: android.telephony.data.DataService#onUnbind(android.content.Intent) parameter #0:
-    
+    Missing nullability on parameter `intent` in method `onUnbind`
 MissingNullability: android.telephony.mbms.DownloadRequest.Builder#setServiceId(String):
-    
+    Missing nullability on method `setServiceId` return
 MissingNullability: android.telephony.mbms.DownloadRequest.Builder#setServiceId(String) parameter #0:
-    
-
-
-NoSettingsProvider: android.provider.Settings.Secure#FAST_PAIR_SCAN_ENABLED:
-    New setting keys are not allowed (Field: FAST_PAIR_SCAN_ENABLED); use getters/setters in relevant manager class
-
-
-OnNameExpected: android.service.smartspace.SmartspaceService#notifySmartspaceEvent(android.app.smartspace.SmartspaceSessionId, android.app.smartspace.SmartspaceTargetEvent):
-    Methods implemented by developers should follow the on<Something> style, was `notifySmartspaceEvent`
+    Missing nullability on parameter `serviceId` in method `setServiceId`
 
 
 ProtectedMember: android.printservice.recommendation.RecommendationService#attachBaseContext(android.content.Context):
-    
+    Protected methods not allowed; must be public: method android.printservice.recommendation.RecommendationService.attachBaseContext(android.content.Context)}
 ProtectedMember: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]):
-    
+    Protected methods not allowed; must be public: method android.service.contentcapture.ContentCaptureService.dump(java.io.FileDescriptor,java.io.PrintWriter,String[])}
 ProtectedMember: android.service.notification.NotificationAssistantService#attachBaseContext(android.content.Context):
-    
-
-
-RethrowRemoteException: android.app.WallpaperManager#getWallpaperDimAmount():
-    Methods calling system APIs should rethrow `RemoteException` as `RuntimeException` (but do not list it in the throws clause)
-RethrowRemoteException: android.app.WallpaperManager#getWallpaperDimmingAmount():
-    Methods calling system APIs should rethrow `RemoteException` as `RuntimeException` (but do not list it in the throws clause)
-RethrowRemoteException: android.app.WallpaperManager#setWallpaperDimAmount(float):
-    Methods calling system APIs should rethrow `RemoteException` as `RuntimeException` (but do not list it in the throws clause)
-RethrowRemoteException: android.app.WallpaperManager#setWallpaperDimmingAmount(float):
-    Methods calling system APIs should rethrow `RemoteException` as `RuntimeException` (but do not list it in the throws clause)
+    Protected methods not allowed; must be public: method android.service.notification.NotificationAssistantService.attachBaseContext(android.content.Context)}
 
 
 SamShouldBeLast: android.accounts.AccountManager#addAccount(String, String, String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 6, "callback", in android.accounts.AccountManager.addAccount) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.accounts.AccountManager#addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean):
-    
+    SAM-compatible parameters (such as parameter 1, "listener", in android.accounts.AccountManager.addOnAccountsUpdatedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.accounts.AccountManager#addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean, String[]):
-    
+    SAM-compatible parameters (such as parameter 1, "listener", in android.accounts.AccountManager.addOnAccountsUpdatedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.accounts.AccountManager#confirmCredentials(android.accounts.Account, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 4, "callback", in android.accounts.AccountManager.confirmCredentials) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.accounts.AccountManager#editProperties(String, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 3, "callback", in android.accounts.AccountManager.editProperties) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.accounts.AccountManager#finishSession(android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 3, "callback", in android.accounts.AccountManager.finishSession) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.accounts.AccountManager#getAccountsByTypeAndFeatures(String, String[], android.accounts.AccountManagerCallback<android.accounts.Account[]>, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 3, "callback", in android.accounts.AccountManager.getAccountsByTypeAndFeatures) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.accounts.AccountManager#getAuthToken(android.accounts.Account, String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 5, "callback", in android.accounts.AccountManager.getAuthToken) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.accounts.AccountManager#getAuthToken(android.accounts.Account, String, android.os.Bundle, boolean, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 5, "callback", in android.accounts.AccountManager.getAuthToken) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.accounts.AccountManager#getAuthToken(android.accounts.Account, String, boolean, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 4, "callback", in android.accounts.AccountManager.getAuthToken) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.accounts.AccountManager#getAuthTokenByFeatures(String, String, String[], android.app.Activity, android.os.Bundle, android.os.Bundle, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 7, "callback", in android.accounts.AccountManager.getAuthTokenByFeatures) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.accounts.AccountManager#hasFeatures(android.accounts.Account, String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 3, "callback", in android.accounts.AccountManager.hasFeatures) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.accounts.AccountManager#isCredentialsUpdateSuggested(android.accounts.Account, String, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 3, "callback", in android.accounts.AccountManager.isCredentialsUpdateSuggested) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.accounts.AccountManager#removeAccount(android.accounts.Account, android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 2, "callback", in android.accounts.AccountManager.removeAccount) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.accounts.AccountManager#removeAccount(android.accounts.Account, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 3, "callback", in android.accounts.AccountManager.removeAccount) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.accounts.AccountManager#renameAccount(android.accounts.Account, String, android.accounts.AccountManagerCallback<android.accounts.Account>, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 3, "callback", in android.accounts.AccountManager.renameAccount) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.accounts.AccountManager#startAddAccountSession(String, String, String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 6, "callback", in android.accounts.AccountManager.startAddAccountSession) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.accounts.AccountManager#startUpdateCredentialsSession(android.accounts.Account, String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 5, "callback", in android.accounts.AccountManager.startUpdateCredentialsSession) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.accounts.AccountManager#updateCredentials(android.accounts.Account, String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 5, "callback", in android.accounts.AccountManager.updateCredentials) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.app.AlarmManager#set(int, long, String, android.app.AlarmManager.OnAlarmListener, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 4, "listener", in android.app.AlarmManager.set) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.app.AlarmManager#setExact(int, long, String, android.app.AlarmManager.OnAlarmListener, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 4, "listener", in android.app.AlarmManager.setExact) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.app.AlarmManager#setWindow(int, long, long, String, android.app.AlarmManager.OnAlarmListener, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 5, "listener", in android.app.AlarmManager.setWindow) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.app.WallpaperInfo#dump(android.util.Printer, String):
-    
+    SAM-compatible parameters (such as parameter 1, "pw", in android.app.WallpaperInfo.dump) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.app.WallpaperManager#addOnColorsChangedListener(android.app.WallpaperManager.OnColorsChangedListener, android.os.Handler):
-    
-SamShouldBeLast: android.app.admin.DevicePolicyManager#installSystemUpdate(android.content.ComponentName, android.net.Uri, java.util.concurrent.Executor, android.app.admin.DevicePolicyManager.InstallSystemUpdateCallback):
-    
+    SAM-compatible parameters (such as parameter 1, "listener", in android.app.WallpaperManager.addOnColorsChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.content.IntentFilter#dump(android.util.Printer, String):
-    
+    SAM-compatible parameters (such as parameter 1, "du", in android.content.IntentFilter.dump) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.content.pm.ApplicationInfo#dump(android.util.Printer, String):
-    
+    SAM-compatible parameters (such as parameter 1, "pw", in android.content.pm.ApplicationInfo.dump) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.content.pm.PackageItemInfo#dumpBack(android.util.Printer, String):
-    
+    SAM-compatible parameters (such as parameter 1, "pw", in android.content.pm.PackageItemInfo.dumpBack) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.content.pm.PackageItemInfo#dumpFront(android.util.Printer, String):
-    
+    SAM-compatible parameters (such as parameter 1, "pw", in android.content.pm.PackageItemInfo.dumpFront) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.content.pm.ResolveInfo#dump(android.util.Printer, String):
-    
+    SAM-compatible parameters (such as parameter 1, "pw", in android.content.pm.ResolveInfo.dump) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.location.Location#dump(android.util.Printer, String):
-    
+    SAM-compatible parameters (such as parameter 1, "pw", in android.location.Location.dump) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.location.LocationManager#addNmeaListener(android.location.OnNmeaMessageListener, android.os.Handler):
-    
-SamShouldBeLast: android.location.LocationManager#registerGnssMeasurementsCallback(java.util.concurrent.Executor, android.location.GnssMeasurementsEvent.Callback):
-    
-SamShouldBeLast: android.location.LocationManager#registerGnssNavigationMessageCallback(java.util.concurrent.Executor, android.location.GnssNavigationMessage.Callback):
-    
-SamShouldBeLast: android.location.LocationManager#registerGnssStatusCallback(java.util.concurrent.Executor, android.location.GnssStatus.Callback):
-    
+    SAM-compatible parameters (such as parameter 1, "listener", in android.location.LocationManager.addNmeaListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(String, long, float, android.location.LocationListener, android.os.Looper):
-    
-SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(String, long, float, java.util.concurrent.Executor, android.location.LocationListener):
-    
-SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(android.location.LocationRequest, java.util.concurrent.Executor, android.location.LocationListener):
-    
+    SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(long, float, android.location.Criteria, android.location.LocationListener, android.os.Looper):
-    
-SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(long, float, android.location.Criteria, java.util.concurrent.Executor, android.location.LocationListener):
-    
+    SAM-compatible parameters (such as parameter 4, "listener", in android.location.LocationManager.requestLocationUpdates) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(String, android.location.LocationListener, android.os.Looper):
-    
+    SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.location.LocationManager#requestSingleUpdate(android.location.Criteria, android.location.LocationListener, android.os.Looper):
-    
+    SAM-compatible parameters (such as parameter 2, "listener", in android.location.LocationManager.requestSingleUpdate) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.media.AudioFocusRequest.Builder#setOnAudioFocusChangeListener(android.media.AudioManager.OnAudioFocusChangeListener, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioFocusRequest.Builder.setOnAudioFocusChangeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.media.AudioManager#requestAudioFocus(android.media.AudioManager.OnAudioFocusChangeListener, int, int):
-    
+    SAM-compatible parameters (such as parameter 1, "l", in android.media.AudioManager.requestAudioFocus) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.media.AudioRecord#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
-    
-SamShouldBeLast: android.media.AudioRecord#registerAudioRecordingCallback(java.util.concurrent.Executor, android.media.AudioManager.AudioRecordingCallback):
-    
-SamShouldBeLast: android.media.AudioRecordingMonitor#registerAudioRecordingCallback(java.util.concurrent.Executor, android.media.AudioManager.AudioRecordingCallback):
-    
+    SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioRecord.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.media.AudioRouting#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioRouting.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.media.AudioTrack#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 1, "listener", in android.media.AudioTrack.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
+SamShouldBeLast: android.media.MediaCodec#setOnFrameRenderedListener(android.media.MediaCodec.OnFrameRenderedListener, android.os.Handler):
+    SAM-compatible parameters (such as parameter 1, "listener", in android.media.MediaCodec.setOnFrameRenderedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.media.MediaPlayer#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
     SAM-compatible parameters (such as parameter 1, "listener", in android.media.MediaPlayer.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.media.MediaPlayer#setOnDrmInfoListener(android.media.MediaPlayer.OnDrmInfoListener, android.os.Handler):
@@ -215,82 +159,65 @@
     SAM-compatible parameters (such as parameter 1, "listener", in android.media.MediaPlayer.setOnDrmPreparedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.media.MediaPlayer#setOnMediaTimeDiscontinuityListener(android.media.MediaPlayer.OnMediaTimeDiscontinuityListener, android.os.Handler):
     SAM-compatible parameters (such as parameter 1, "listener", in android.media.MediaPlayer.setOnMediaTimeDiscontinuityListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
-SamShouldBeLast: android.media.MediaPlayer#setOnRtpRxNoticeListener(android.content.Context, android.media.MediaPlayer.OnRtpRxNoticeListener, android.os.Handler):
-    SAM-compatible parameters (such as parameter 2, "listener", in android.media.MediaPlayer.setOnRtpRxNoticeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.media.MediaPlayer#setOnSubtitleDataListener(android.media.MediaPlayer.OnSubtitleDataListener, android.os.Handler):
     SAM-compatible parameters (such as parameter 1, "listener", in android.media.MediaPlayer.setOnSubtitleDataListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.media.MediaRecorder#addOnRoutingChangedListener(android.media.AudioRouting.OnRoutingChangedListener, android.os.Handler):
-    
-SamShouldBeLast: android.media.MediaRecorder#registerAudioRecordingCallback(java.util.concurrent.Executor, android.media.AudioManager.AudioRecordingCallback):
-    
+    SAM-compatible parameters (such as parameter 1, "listener", in android.media.MediaRecorder.addOnRoutingChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.media.session.MediaSessionManager#addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName):
-    
+    SAM-compatible parameters (such as parameter 1, "sessionListener", in android.media.session.MediaSessionManager.addOnActiveSessionsChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.media.session.MediaSessionManager#addOnActiveSessionsChangedListener(android.media.session.MediaSessionManager.OnActiveSessionsChangedListener, android.content.ComponentName, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 1, "sessionListener", in android.media.session.MediaSessionManager.addOnActiveSessionsChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.media.session.MediaSessionManager#addOnSession2TokensChangedListener(android.media.session.MediaSessionManager.OnSession2TokensChangedListener, android.os.Handler):
-    
-SamShouldBeLast: android.media.session.MediaSessionManager#registerCallback(java.util.concurrent.Executor, android.media.session.MediaSessionManager.Callback):
-    
+    SAM-compatible parameters (such as parameter 1, "listener", in android.media.session.MediaSessionManager.addOnSession2TokensChangedListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.nfc.NfcAdapter#enableReaderMode(android.app.Activity, android.nfc.NfcAdapter.ReaderCallback, int, android.os.Bundle):
-    
+    SAM-compatible parameters (such as parameter 2, "callback", in android.nfc.NfcAdapter.enableReaderMode) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.nfc.NfcAdapter#ignore(android.nfc.Tag, int, android.nfc.NfcAdapter.OnTagRemovedListener, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 3, "tagRemovedListener", in android.nfc.NfcAdapter.ignore) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.nfc.NfcAdapter#setBeamPushUrisCallback(android.nfc.NfcAdapter.CreateBeamUrisCallback, android.app.Activity):
-    
+    SAM-compatible parameters (such as parameter 1, "callback", in android.nfc.NfcAdapter.setBeamPushUrisCallback) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.nfc.NfcAdapter#setNdefPushMessageCallback(android.nfc.NfcAdapter.CreateNdefMessageCallback, android.app.Activity, android.app.Activity...):
-    
+    SAM-compatible parameters (such as parameter 1, "callback", in android.nfc.NfcAdapter.setNdefPushMessageCallback) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.nfc.NfcAdapter#setOnNdefPushCompleteCallback(android.nfc.NfcAdapter.OnNdefPushCompleteCallback, android.app.Activity, android.app.Activity...):
-    
+    SAM-compatible parameters (such as parameter 1, "callback", in android.nfc.NfcAdapter.setOnNdefPushCompleteCallback) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.os.Binder#attachInterface(android.os.IInterface, String):
-    
+    SAM-compatible parameters (such as parameter 1, "owner", in android.os.Binder.attachInterface) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.os.Binder#linkToDeath(android.os.IBinder.DeathRecipient, int):
-    
+    SAM-compatible parameters (such as parameter 1, "recipient", in android.os.Binder.linkToDeath) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.os.Binder#unlinkToDeath(android.os.IBinder.DeathRecipient, int):
-    
+    SAM-compatible parameters (such as parameter 1, "recipient", in android.os.Binder.unlinkToDeath) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.os.Handler#dump(android.util.Printer, String):
-    
+    SAM-compatible parameters (such as parameter 1, "pw", in android.os.Handler.dump) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.os.Handler#postAtTime(Runnable, Object, long):
-    
+    SAM-compatible parameters (such as parameter 1, "r", in android.os.Handler.postAtTime) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.os.Handler#postAtTime(Runnable, long):
-    
+    SAM-compatible parameters (such as parameter 1, "r", in android.os.Handler.postAtTime) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.os.Handler#postDelayed(Runnable, Object, long):
-    
+    SAM-compatible parameters (such as parameter 1, "r", in android.os.Handler.postDelayed) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.os.Handler#postDelayed(Runnable, long):
-    
+    SAM-compatible parameters (such as parameter 1, "r", in android.os.Handler.postDelayed) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.os.Handler#removeCallbacks(Runnable, Object):
-    
+    SAM-compatible parameters (such as parameter 1, "r", in android.os.Handler.removeCallbacks) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.os.IBinder#linkToDeath(android.os.IBinder.DeathRecipient, int):
-    
+    SAM-compatible parameters (such as parameter 1, "recipient", in android.os.IBinder.linkToDeath) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.os.IBinder#unlinkToDeath(android.os.IBinder.DeathRecipient, int):
-    
+    SAM-compatible parameters (such as parameter 1, "recipient", in android.os.IBinder.unlinkToDeath) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.os.RecoverySystem#verifyPackage(java.io.File, android.os.RecoverySystem.ProgressListener, java.io.File):
-    
+    SAM-compatible parameters (such as parameter 2, "listener", in android.os.RecoverySystem.verifyPackage) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.security.KeyChain#choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, String[], java.security.Principal[], String, int, String):
     SAM-compatible parameters (such as parameter 2, "response", in android.security.KeyChain.choosePrivateKeyAlias) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.security.KeyChain#choosePrivateKeyAlias(android.app.Activity, android.security.KeyChainAliasCallback, String[], java.security.Principal[], android.net.Uri, String):
     SAM-compatible parameters (such as parameter 2, "response", in android.security.KeyChain.choosePrivateKeyAlias) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.view.View#postDelayed(Runnable, long):
-    
+    SAM-compatible parameters (such as parameter 1, "action", in android.view.View.postDelayed) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.view.View#postOnAnimationDelayed(Runnable, long):
-    
+    SAM-compatible parameters (such as parameter 1, "action", in android.view.View.postOnAnimationDelayed) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.view.View#scheduleDrawable(android.graphics.drawable.Drawable, Runnable, long):
-    
+    SAM-compatible parameters (such as parameter 2, "what", in android.view.View.scheduleDrawable) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.view.Window#addOnFrameMetricsAvailableListener(android.view.Window.OnFrameMetricsAvailableListener, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 1, "listener", in android.view.Window.addOnFrameMetricsAvailableListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.view.accessibility.AccessibilityManager#addAccessibilityStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityStateChangeListener, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 1, "listener", in android.view.accessibility.AccessibilityManager.addAccessibilityStateChangeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.view.accessibility.AccessibilityManager#addTouchExplorationStateChangeListener(android.view.accessibility.AccessibilityManager.TouchExplorationStateChangeListener, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 1, "listener", in android.view.accessibility.AccessibilityManager.addTouchExplorationStateChangeListener) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.webkit.WebChromeClient#onShowFileChooser(android.webkit.WebView, android.webkit.ValueCallback<android.net.Uri[]>, android.webkit.WebChromeClient.FileChooserParams):
-    
-
-
-ServiceName: android.content.Context#CLOUDSEARCH_SERVICE:
-
-
-UserHandleName: android.app.search.SearchAction.Builder#setUserHandle(android.os.UserHandle):
-    Method taking UserHandle should be named `doFooAsUser` or `queryFooForUser`, was `setUserHandle`
-UserHandleName: android.app.search.SearchTarget.Builder#setUserHandle(android.os.UserHandle):
-    
-UserHandleName: android.app.smartspace.SmartspaceAction.Builder#setUserHandle(android.os.UserHandle):
-    Method taking UserHandle should be named `doFooAsUser` or `queryFooForUser`, was `setUserHandle`
+    SAM-compatible parameters (such as parameter 2, "filePathCallback", in android.webkit.WebChromeClient.onShowFileChooser) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
diff --git a/core/api/test-lint-baseline.txt b/core/api/test-lint-baseline.txt
index 01604e6..0a906be 100644
--- a/core/api/test-lint-baseline.txt
+++ b/core/api/test-lint-baseline.txt
@@ -1,920 +1,270 @@
 // Baseline format: 1.0
 AcronymName: android.app.NotificationChannel#isImportanceLockedByOEM():
-    
+    Acronyms should not be capitalized in method names: was `isImportanceLockedByOEM`, should this be `isImportanceLockedByOem`?
 AcronymName: android.app.NotificationChannel#setImportanceLockedByOEM(boolean):
-    
+    Acronyms should not be capitalized in method names: was `setImportanceLockedByOEM`, should this be `setImportanceLockedByOem`?
 
 
-ActionValue: android.location.Location#EXTRA_NO_GPS_LOCATION:
-    
-ActionValue: android.net.TetheringManager#ACTION_TETHER_STATE_CHANGED:
-    
-ActionValue: android.net.TetheringManager#EXTRA_ACTIVE_TETHER:
-    
-ActionValue: android.net.TetheringManager#EXTRA_AVAILABLE_TETHER:
-    
-ActionValue: android.net.TetheringManager#EXTRA_ERRORED_TETHER:
-    
-ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_ADDITIONAL_CALL_INFO:
-    
-ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_CALL_RAT_TYPE:
-    
-ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_CHILD_NUMBER:
-    
-ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_CNA:
-    
-ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_CNAP:
-    
-ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_CODEC:
-    
-ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_DIALSTRING:
-    
-ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_DISPLAY_TEXT:
-    
-ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_EMERGENCY_CALL:
-    
-ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_IS_CALL_PULL:
-    
-ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_OI:
-    
-ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_OIR:
-    
-ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_REMOTE_URI:
-    
-ActionValue: android.telephony.ims.ImsCallProfile#EXTRA_USSD:
-    
-ActionValue: android.telephony.ims.ImsReasonInfo#EXTRA_MSG_SERVICE_NOT_AUTHORIZED:
-    
-ActionValue: android.telephony.mbms.vendor.VendorUtils#ACTION_CLEANUP:
-    
-ActionValue: android.telephony.mbms.vendor.VendorUtils#ACTION_DOWNLOAD_RESULT_INTERNAL:
-    
-ActionValue: android.telephony.mbms.vendor.VendorUtils#ACTION_FILE_DESCRIPTOR_REQUEST:
-    
-ActionValue: android.telephony.mbms.vendor.VendorUtils#EXTRA_FD_COUNT:
-    
-ActionValue: android.telephony.mbms.vendor.VendorUtils#EXTRA_FINAL_URI:
-    
-ActionValue: android.telephony.mbms.vendor.VendorUtils#EXTRA_FREE_URI_LIST:
-    
-ActionValue: android.telephony.mbms.vendor.VendorUtils#EXTRA_PAUSED_LIST:
-    
-ActionValue: android.telephony.mbms.vendor.VendorUtils#EXTRA_PAUSED_URI_LIST:
-    
-ActionValue: android.telephony.mbms.vendor.VendorUtils#EXTRA_SERVICE_ID:
-    
-ActionValue: android.telephony.mbms.vendor.VendorUtils#EXTRA_TEMP_FILES_IN_USE:
-    
-ActionValue: android.telephony.mbms.vendor.VendorUtils#EXTRA_TEMP_FILE_ROOT:
-    
-ActionValue: android.telephony.mbms.vendor.VendorUtils#EXTRA_TEMP_LIST:
-    
-
-
-AllUpper: android.media.audiopolicy.AudioProductStrategy#sDefaultAttributes:
-    Constant field names must be named with only upper case characters: `android.media.audiopolicy.AudioProductStrategy#sDefaultAttributes`, should be `S_DEFAULT_ATTRIBUTES`?
-
-
-ArrayReturn: android.app.UiAutomation#executeShellCommandRw(String):
-    
-ArrayReturn: android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel#KeyphraseSoundModel(java.util.UUID, java.util.UUID, byte[], android.hardware.soundtrigger.SoundTrigger.Keyphrase[]) parameter #3:
-    
-ArrayReturn: android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel#KeyphraseSoundModel(java.util.UUID, java.util.UUID, byte[], android.hardware.soundtrigger.SoundTrigger.Keyphrase[], int) parameter #3:
-    
-ArrayReturn: android.hardware.soundtrigger.SoundTrigger.KeyphraseSoundModel#getKeyphrases():
-    
-ArrayReturn: android.location.GnssMeasurementsEvent#GnssMeasurementsEvent(android.location.GnssClock, android.location.GnssMeasurement[]) parameter #1:
-    
 ArrayReturn: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String, int, boolean, int, android.media.audiofx.AudioEffect.Descriptor[], android.media.audiofx.AudioEffect.Descriptor[]) parameter #10:
-    
+    Method parameter should be Collection<Descriptor> (or subclass) instead of raw array; was `android.media.audiofx.AudioEffect.Descriptor[]`
 ArrayReturn: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String, int, boolean, int, android.media.audiofx.AudioEffect.Descriptor[], android.media.audiofx.AudioEffect.Descriptor[]) parameter #11:
-    
-ArrayReturn: android.metrics.LogMaker#LogMaker(Object[]) parameter #0:
-    
-ArrayReturn: android.metrics.LogMaker#deserialize(Object[]) parameter #0:
-    
-ArrayReturn: android.metrics.LogMaker#serialize():
-    
-ArrayReturn: android.net.TestNetworkManager#createTunInterface(android.net.LinkAddress[]) parameter #0:
-    
-ArrayReturn: android.os.HwBlob#wrapArray(boolean[]):
-    
-ArrayReturn: android.os.HwBlob#wrapArray(byte[]):
-    
-ArrayReturn: android.os.HwBlob#wrapArray(double[]):
-    
-ArrayReturn: android.os.HwBlob#wrapArray(float[]):
-    
-ArrayReturn: android.os.HwBlob#wrapArray(int[]):
-    
-ArrayReturn: android.os.HwBlob#wrapArray(long[]):
-    
-ArrayReturn: android.os.HwBlob#wrapArray(short[]):
-    
-ArrayReturn: android.os.NativeHandle#NativeHandle(java.io.FileDescriptor[], int[], boolean) parameter #0:
-    
-ArrayReturn: android.os.NativeHandle#getFileDescriptors():
-    
-ArrayReturn: android.security.keystore.AttestationUtils#attestDeviceIds(android.content.Context, int[], byte[]):
-    
-ArrayReturn: android.telephony.ims.ImsUtListener#onUtConfigurationCallBarringQueried(int, android.telephony.ims.ImsSsInfo[]) parameter #1:
-    
-ArrayReturn: android.telephony.ims.ImsUtListener#onUtConfigurationCallForwardQueried(int, android.telephony.ims.ImsCallForwardInfo[]) parameter #1:
-    
-ArrayReturn: android.telephony.ims.ImsUtListener#onUtConfigurationCallWaitingQueried(int, android.telephony.ims.ImsSsInfo[]) parameter #1:
-    
-ArrayReturn: android.telephony.ims.stub.ImsRegistrationImplBase#onSubscriberAssociatedUriChanged(android.net.Uri[]) parameter #0:
-    
+    Method parameter should be Collection<Descriptor> (or subclass) instead of raw array; was `android.media.audiofx.AudioEffect.Descriptor[]`
 ArrayReturn: android.view.Display#getSupportedWideColorGamut():
-    
+    Method should return Collection<ColorSpace> (or subclass) instead of raw array; was `android.graphics.ColorSpace[]`
 ArrayReturn: android.view.FocusFinder#sort(android.view.View[], int, int, android.view.ViewGroup, boolean) parameter #0:
-    
-ArrayReturn: android.view.contentcapture.ViewNode#getAutofillOptions():
-    
+    Method parameter should be Collection<View> (or subclass) instead of raw array; was `android.view.View[]`
 ArrayReturn: android.view.contentcapture.ViewNode.ViewStructureImpl#setAutofillOptions(CharSequence[]) parameter #0:
-    
-ArrayReturn: android.view.inspector.InspectableProperty#enumMapping():
-    
-ArrayReturn: android.view.inspector.InspectableProperty#flagMapping():
-    
+    Method parameter should be Collection<CharSequence> (or subclass) instead of raw array; was `java.lang.CharSequence[]`
 
 
-AutoBoxing: android.os.HwBlob#wrapArray(byte[]):
-    
-AutoBoxing: android.os.HwBlob#wrapArray(double[]):
-    
-AutoBoxing: android.os.HwBlob#wrapArray(float[]):
-    
-AutoBoxing: android.os.HwBlob#wrapArray(int[]):
-    
-AutoBoxing: android.os.HwBlob#wrapArray(long[]):
-    
-AutoBoxing: android.os.HwBlob#wrapArray(short[]):
-    
 AutoBoxing: android.os.VintfObject#getTargetFrameworkCompatibilityMatrixVersion():
-    
+    Must avoid boxed primitives (`java.lang.Long`)
 
 
-BannedThrow: android.app.ActivityTaskManager#removeStacksInWindowingModes(int[]):
-    
-BannedThrow: android.app.ActivityTaskManager#removeStacksWithActivityTypes(int[]):
-    
-BannedThrow: android.app.ActivityTaskManager#setTaskWindowingMode(int, int, boolean):
-    
-BannedThrow: android.app.ActivityTaskManager#setTaskWindowingModeSplitScreenPrimary(int, int, boolean, boolean, android.graphics.Rect, boolean):
-    
-BannedThrow: android.media.audiofx.AudioEffect#getParameter(byte[], byte[]):
-    
-BannedThrow: android.media.audiofx.AudioEffect#getParameter(int, byte[]):
-    
-BannedThrow: android.media.audiofx.AudioEffect#getParameter(int, int[]):
-    
-BannedThrow: android.media.audiofx.AudioEffect#getParameter(int, short[]):
-    
-BannedThrow: android.media.audiofx.AudioEffect#getParameter(int[], short[]):
-    
-BannedThrow: android.media.audiofx.AudioEffect#setParameter(byte[], byte[]):
-    
-BannedThrow: android.media.audiofx.AudioEffect#setParameter(int, byte[]):
-    
-BannedThrow: android.media.audiofx.AudioEffect#setParameter(int, int):
-    
-BannedThrow: android.media.audiofx.AudioEffect#setParameter(int, short):
-    
-BannedThrow: android.media.audiofx.AudioEffect#setParameter(int[], byte[]):
-    
-BannedThrow: android.media.audiofx.AudioEffect#setParameter(int[], int[]):
-    
-BannedThrow: android.media.audiopolicy.AudioMix.Builder#Builder(android.media.audiopolicy.AudioMixingRule):
-    
-BannedThrow: android.media.audiopolicy.AudioMix.Builder#build():
-    
-BannedThrow: android.media.audiopolicy.AudioMix.Builder#setDevice(android.media.AudioDeviceInfo):
-    
-BannedThrow: android.media.audiopolicy.AudioMix.Builder#setFormat(android.media.AudioFormat):
-    
-BannedThrow: android.media.audiopolicy.AudioMix.Builder#setRouteFlags(int):
-    
-BannedThrow: android.media.audiopolicy.AudioMixingRule.Builder#addMixRule(int, Object):
-    
-BannedThrow: android.media.audiopolicy.AudioMixingRule.Builder#addRule(android.media.AudioAttributes, int):
-    
-BannedThrow: android.media.audiopolicy.AudioMixingRule.Builder#excludeMixRule(int, Object):
-    
-BannedThrow: android.media.audiopolicy.AudioMixingRule.Builder#excludeRule(android.media.AudioAttributes, int):
-    
-BannedThrow: android.media.audiopolicy.AudioPolicy#createAudioRecordSink(android.media.audiopolicy.AudioMix):
-    
-BannedThrow: android.media.audiopolicy.AudioPolicy#createAudioTrackSource(android.media.audiopolicy.AudioMix):
-    
-BannedThrow: android.media.audiopolicy.AudioPolicy#setFocusDuckingBehavior(int):
-    
-BannedThrow: android.media.audiopolicy.AudioPolicy.Builder#addMix(android.media.audiopolicy.AudioMix):
-    
-BannedThrow: android.media.audiopolicy.AudioPolicy.Builder#setLooper(android.os.Looper):
-    
-BannedThrow: android.os.HwBinder#getService(String, String):
-    
-BannedThrow: android.os.HwBinder#getService(String, String, boolean):
-    
-BannedThrow: android.os.Process#getThreadScheduler(int):
-    
-
-
-BuilderSetStyle: android.media.audiopolicy.AudioMixingRule.Builder#allowPrivilegedPlaybackCapture(boolean):
-    
-BuilderSetStyle: android.media.audiopolicy.AudioMixingRule.Builder#excludeMixRule(int, Object):
-    
-BuilderSetStyle: android.media.audiopolicy.AudioMixingRule.Builder#excludeRule(android.media.AudioAttributes, int):
-    
-BuilderSetStyle: android.net.NetworkCapabilities.Builder#removeCapability(int):
-    
-BuilderSetStyle: android.net.NetworkCapabilities.Builder#removeTransportType(int):
-    
-BuilderSetStyle: android.net.metrics.RaEvent.Builder#updateDnsslLifetime(long):
-    
-BuilderSetStyle: android.net.metrics.RaEvent.Builder#updatePrefixPreferredLifetime(long):
-    
-BuilderSetStyle: android.net.metrics.RaEvent.Builder#updatePrefixValidLifetime(long):
-    
-BuilderSetStyle: android.net.metrics.RaEvent.Builder#updateRdnssLifetime(long):
-    
-BuilderSetStyle: android.net.metrics.RaEvent.Builder#updateRouteInfoLifetime(long):
-    
-BuilderSetStyle: android.net.metrics.RaEvent.Builder#updateRouterLifetime(long):
-    
 BuilderSetStyle: android.os.StrictMode.ThreadPolicy.Builder#detectExplicitGc():
-    
-BuilderSetStyle: android.os.StrictMode.VmPolicy.Builder#detectIncorrectContextUse():
-    
+    Builder methods names should use setFoo() / addFoo() / clearFoo() style: method android.os.StrictMode.ThreadPolicy.Builder.detectExplicitGc()
 BuilderSetStyle: android.os.StrictMode.VmPolicy.Builder#permitIncorrectContextUse():
-    
-
-
-CallbackInterface: android.app.prediction.AppPredictor.Callback:
-    
-CallbackInterface: android.permission.PermissionControllerManager.OnGetAppPermissionResultCallback:
-    
-CallbackInterface: android.widget.Magnifier.Callback:
-    
-
-
-CallbackMethodName: android.os.RemoteCallback:
-    
+    Builder methods names should use setFoo() / addFoo() / clearFoo() style: method android.os.StrictMode.VmPolicy.Builder.permitIncorrectContextUse()
 
 
 ConcreteCollection: android.content.AutofillOptions#disabledActivities:
-    
+    Field type is concrete collection (`android.util.ArrayMap`); must be higher-level interface
 ConcreteCollection: android.content.AutofillOptions#whitelistedActivitiesForAugmentedAutofill:
-    
+    Field type is concrete collection (`android.util.ArraySet`); must be higher-level interface
 ConcreteCollection: android.content.ContentCaptureOptions#ContentCaptureOptions(int, int, int, int, int, android.util.ArraySet<android.content.ComponentName>) parameter #5:
-    
+    Parameter type is concrete collection (`android.util.ArraySet`); must be higher-level interface
 ConcreteCollection: android.content.ContentCaptureOptions#whitelistedComponents:
-    
+    Field type is concrete collection (`android.util.ArraySet`); must be higher-level interface
 ConcreteCollection: android.database.sqlite.SQLiteDebug.PagerStats#dbStats:
-    
-ConcreteCollection: android.os.HwParcel#readBoolVector():
-    
-ConcreteCollection: android.os.HwParcel#readDoubleVector():
-    
-ConcreteCollection: android.os.HwParcel#readFloatVector():
-    
-ConcreteCollection: android.os.HwParcel#readInt16Vector():
-    
-ConcreteCollection: android.os.HwParcel#readInt32Vector():
-    
-ConcreteCollection: android.os.HwParcel#readInt64Vector():
-    
-ConcreteCollection: android.os.HwParcel#readInt8Vector():
-    
-ConcreteCollection: android.os.HwParcel#readNativeHandleVector():
-    
-ConcreteCollection: android.os.HwParcel#readStringVector():
-    
-ConcreteCollection: android.os.HwParcel#writeBoolVector(java.util.ArrayList<java.lang.Boolean>) parameter #0:
-    
-ConcreteCollection: android.os.HwParcel#writeDoubleVector(java.util.ArrayList<java.lang.Double>) parameter #0:
-    
-ConcreteCollection: android.os.HwParcel#writeFloatVector(java.util.ArrayList<java.lang.Float>) parameter #0:
-    
-ConcreteCollection: android.os.HwParcel#writeInt16Vector(java.util.ArrayList<java.lang.Short>) parameter #0:
-    
-ConcreteCollection: android.os.HwParcel#writeInt32Vector(java.util.ArrayList<java.lang.Integer>) parameter #0:
-    
-ConcreteCollection: android.os.HwParcel#writeInt64Vector(java.util.ArrayList<java.lang.Long>) parameter #0:
-    
-ConcreteCollection: android.os.HwParcel#writeInt8Vector(java.util.ArrayList<java.lang.Byte>) parameter #0:
-    
-ConcreteCollection: android.os.HwParcel#writeNativeHandleVector(java.util.ArrayList<android.os.NativeHandle>) parameter #0:
-    
-ConcreteCollection: android.os.HwParcel#writeStringVector(java.util.ArrayList<java.lang.String>) parameter #0:
-    
+    Field type is concrete collection (`java.util.ArrayList`); must be higher-level interface
 ConcreteCollection: android.service.autofill.CompositeUserData#getFieldClassificationAlgorithms():
-    
+    Return type is concrete collection (`android.util.ArrayMap`); must be higher-level interface
 ConcreteCollection: android.service.autofill.CompositeUserData#getFieldClassificationArgs():
-    
+    Return type is concrete collection (`android.util.ArrayMap`); must be higher-level interface
 ConcreteCollection: android.service.autofill.InternalTransformation#batchApply(android.service.autofill.ValueFinder, android.widget.RemoteViews, java.util.ArrayList<android.util.Pair<java.lang.Integer,android.service.autofill.InternalTransformation>>) parameter #2:
-    
+    Parameter type is concrete collection (`java.util.ArrayList`); must be higher-level interface
 ConcreteCollection: android.service.autofill.UserData#getFieldClassificationAlgorithms():
-    
-ConcreteCollection: android.telephony.ims.ImsConferenceState#mParticipants:
-    
+    Return type is concrete collection (`android.util.ArrayMap`); must be higher-level interface
 
 
 ContextFirst: android.os.VibrationEffect#get(android.net.Uri, android.content.Context) parameter #1:
-    
-
-
-ContextNameSuffix: android.telephony.mbms.vendor.MbmsGroupCallServiceBase:
-    
+    Context is distinct, so it must be the first argument (method `get`)
 
 
 EndsWithImpl: android.view.contentcapture.ViewNode.ViewStructureImpl:
-    
+    Don't expose your implementation details: `ViewStructureImpl` ends with `Impl`
 
 
 Enum: android.view.inspector.InspectableProperty.ValueType:
-    
+    Enums are discouraged in Android APIs
 
 
-EqualsAndHashCode: android.app.prediction.AppPredictionContext#equals(Object):
-    
-EqualsAndHashCode: android.app.prediction.AppTarget#equals(Object):
-    
-EqualsAndHashCode: android.app.prediction.AppTargetEvent#equals(Object):
-    
-EqualsAndHashCode: android.net.apf.ApfCapabilities#equals(Object):
-    
-EqualsAndHashCode: android.net.metrics.ApfProgramEvent#equals(Object):
-    
-EqualsAndHashCode: android.net.metrics.ApfStats#equals(Object):
-    
-EqualsAndHashCode: android.net.metrics.DhcpClientEvent#equals(Object):
-    
-EqualsAndHashCode: android.net.metrics.IpManagerEvent#equals(Object):
-    
-EqualsAndHashCode: android.net.metrics.IpReachabilityEvent#equals(Object):
-    
-EqualsAndHashCode: android.net.metrics.NetworkEvent#equals(Object):
-    
-EqualsAndHashCode: android.net.metrics.RaEvent#equals(Object):
-    
-EqualsAndHashCode: android.net.metrics.ValidationProbeEvent#equals(Object):
-    
-EqualsAndHashCode: android.os.IncidentManager.PendingReport#equals(Object):
-    
 EqualsAndHashCode: android.os.StrictMode.ViolationInfo#hashCode():
-    
+    Must override both equals and hashCode; missing one in android.os.StrictMode.ViolationInfo
 
 
-ExecutorRegistration: android.content.pm.PackageManager#addOnPermissionsChangeListener(android.content.pm.PackageManager.OnPermissionsChangedListener):
-    
-ExecutorRegistration: android.hardware.camera2.CameraDevice#createCustomCaptureSession(android.hardware.camera2.params.InputConfiguration, java.util.List<android.hardware.camera2.params.OutputConfiguration>, int, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler):
-    
 ExecutorRegistration: android.media.audiofx.AudioEffect#setParameterListener(android.media.audiofx.AudioEffect.OnParameterChangeListener):
-    
-ExecutorRegistration: android.media.audiopolicy.AudioPolicy.Builder#setAudioPolicyFocusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener):
-    
-ExecutorRegistration: android.media.audiopolicy.AudioPolicy.Builder#setAudioPolicyStatusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListener):
-    
-ExecutorRegistration: android.media.audiopolicy.AudioPolicy.Builder#setAudioPolicyVolumeCallback(android.media.audiopolicy.AudioPolicy.AudioPolicyVolumeCallback):
-    
-ExecutorRegistration: android.os.IncidentManager#cancelAuthorization(android.os.IncidentManager.AuthListener):
-    
-ExecutorRegistration: android.os.IncidentManager#requestAuthorization(int, String, int, android.os.IncidentManager.AuthListener):
-    
-ExecutorRegistration: android.os.RemoteCallback#RemoteCallback(android.os.RemoteCallback.OnResultListener, android.os.Handler):
-    
+    Registration methods should have overload that accepts delivery Executor: `setParameterListener`
 ExecutorRegistration: android.permission.PermissionControllerManager#countPermissionApps(java.util.List<java.lang.String>, int, android.permission.PermissionControllerManager.OnCountPermissionAppsResultCallback, android.os.Handler):
-    
+    Registration methods should have overload that accepts delivery Executor: `countPermissionApps`
 ExecutorRegistration: android.permission.PermissionControllerManager#getAppPermissions(String, android.permission.PermissionControllerManager.OnGetAppPermissionResultCallback, android.os.Handler):
-    
+    Registration methods should have overload that accepts delivery Executor: `getAppPermissions`
 ExecutorRegistration: android.service.watchdog.ExplicitHealthCheckService#setCallback(android.os.RemoteCallback):
-    
-ExecutorRegistration: android.telephony.ims.stub.ImsCallSessionImplBase#setListener(android.telephony.ims.ImsCallSessionListener):
-    
-ExecutorRegistration: android.telephony.ims.stub.ImsUtImplBase#setListener(android.telephony.ims.ImsUtListener):
-    
-ExecutorRegistration: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener):
-    
-ExecutorRegistration: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener):
-    
-ExecutorRegistration: android.telephony.mbms.vendor.MbmsDownloadServiceBase#initialize(int, android.telephony.mbms.MbmsDownloadSessionCallback):
-    
-ExecutorRegistration: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#initialize(android.telephony.mbms.MbmsGroupCallSessionCallback, int):
-    
-ExecutorRegistration: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#startGroupCall(int, long, java.util.List<java.lang.Integer>, java.util.List<java.lang.Integer>, android.telephony.mbms.GroupCallCallback):
-    
-ExecutorRegistration: android.telephony.mbms.vendor.MbmsStreamingServiceBase#initialize(android.telephony.mbms.MbmsStreamingSessionCallback, int):
-    
-ExecutorRegistration: android.telephony.mbms.vendor.MbmsStreamingServiceBase#startStreaming(int, String, android.telephony.mbms.StreamingServiceCallback):
-    
+    Registration methods should have overload that accepts delivery Executor: `setCallback`
 ExecutorRegistration: android.window.WindowOrganizer#applySyncTransaction(android.window.WindowContainerTransaction, android.window.WindowContainerTransactionCallback):
-    
+    Registration methods should have overload that accepts delivery Executor: `applySyncTransaction`
 
 
 ForbiddenSuperClass: android.app.AppDetailsActivity:
-    
+    AppDetailsActivity should not extend `Activity`. Activity subclasses are impossible to compose. Expose a composable API instead.
 
 
-GenericException: android.app.prediction.AppPredictor#finalize():
-    
 GenericException: android.service.autofill.CharSequenceTransformation#apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int):
-    
+    Methods must not throw generic exceptions (`java.lang.Exception`)
 GenericException: android.service.autofill.DateTransformation#apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int):
-    
+    Methods must not throw generic exceptions (`java.lang.Exception`)
 GenericException: android.service.autofill.ImageTransformation#apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int):
-    
-GenericException: android.service.autofill.augmented.FillWindow#finalize():
-    
+    Methods must not throw generic exceptions (`java.lang.Exception`)
 
 
-GetterOnBuilder: android.hardware.display.BrightnessConfiguration.Builder#getMaxCorrectionsByCategory():
-    
-GetterOnBuilder: android.hardware.display.BrightnessConfiguration.Builder#getMaxCorrectionsByPackageName():
-    
-
-
-GetterSetterNames: android.app.NotificationChannel#isBlockableSystem():
-    
-GetterSetterNames: android.app.NotificationChannel#isImportanceLockedByCriticalDeviceFunction():
-    
-GetterSetterNames: android.app.NotificationChannel#isImportanceLockedByOEM():
-    
 GetterSetterNames: android.location.GnssClock#setBiasNanos(double):
-    
+    Symmetric method for `hasBiasNanos` must be named `setHasBiasNanos`; was `setBiasNanos`
 GetterSetterNames: android.location.GnssClock#setBiasUncertaintyNanos(double):
-    
+    Symmetric method for `hasBiasUncertaintyNanos` must be named `setHasBiasUncertaintyNanos`; was `setBiasUncertaintyNanos`
 GetterSetterNames: android.location.GnssClock#setDriftNanosPerSecond(double):
-    
+    Symmetric method for `hasDriftNanosPerSecond` must be named `setHasDriftNanosPerSecond`; was `setDriftNanosPerSecond`
 GetterSetterNames: android.location.GnssClock#setDriftUncertaintyNanosPerSecond(double):
-    
+    Symmetric method for `hasDriftUncertaintyNanosPerSecond` must be named `setHasDriftUncertaintyNanosPerSecond`; was `setDriftUncertaintyNanosPerSecond`
 GetterSetterNames: android.location.GnssClock#setElapsedRealtimeNanos(long):
-    
+    Symmetric method for `hasElapsedRealtimeNanos` must be named `setHasElapsedRealtimeNanos`; was `setElapsedRealtimeNanos`
 GetterSetterNames: android.location.GnssClock#setElapsedRealtimeUncertaintyNanos(double):
-    
+    Symmetric method for `hasElapsedRealtimeUncertaintyNanos` must be named `setHasElapsedRealtimeUncertaintyNanos`; was `setElapsedRealtimeUncertaintyNanos`
 GetterSetterNames: android.location.GnssClock#setFullBiasNanos(long):
-    
+    Symmetric method for `hasFullBiasNanos` must be named `setHasFullBiasNanos`; was `setFullBiasNanos`
 GetterSetterNames: android.location.GnssClock#setLeapSecond(int):
-    
+    Symmetric method for `hasLeapSecond` must be named `setHasLeapSecond`; was `setLeapSecond`
 GetterSetterNames: android.location.GnssClock#setReferenceCarrierFrequencyHzForIsb(double):
-    
+    Symmetric method for `hasReferenceCarrierFrequencyHzForIsb` must be named `setHasReferenceCarrierFrequencyHzForIsb`; was `setReferenceCarrierFrequencyHzForIsb`
 GetterSetterNames: android.location.GnssClock#setReferenceCodeTypeForIsb(String):
-    
+    Symmetric method for `hasReferenceCodeTypeForIsb` must be named `setHasReferenceCodeTypeForIsb`; was `setReferenceCodeTypeForIsb`
 GetterSetterNames: android.location.GnssClock#setReferenceConstellationTypeForIsb(int):
-    
+    Symmetric method for `hasReferenceConstellationTypeForIsb` must be named `setHasReferenceConstellationTypeForIsb`; was `setReferenceConstellationTypeForIsb`
 GetterSetterNames: android.location.GnssClock#setTimeUncertaintyNanos(double):
-    
+    Symmetric method for `hasTimeUncertaintyNanos` must be named `setHasTimeUncertaintyNanos`; was `setTimeUncertaintyNanos`
 GetterSetterNames: android.location.GnssMeasurement#setBasebandCn0DbHz(double):
-    
+    Symmetric method for `hasBasebandCn0DbHz` must be named `setHasBasebandCn0DbHz`; was `setBasebandCn0DbHz`
 GetterSetterNames: android.location.GnssMeasurement#setCarrierFrequencyHz(float):
-    
+    Symmetric method for `hasCarrierFrequencyHz` must be named `setHasCarrierFrequencyHz`; was `setCarrierFrequencyHz`
 GetterSetterNames: android.location.GnssMeasurement#setCodeType(String):
-    
+    Symmetric method for `hasCodeType` must be named `setHasCodeType`; was `setCodeType`
 GetterSetterNames: android.location.GnssMeasurement#setCorrelationVectors(java.util.Collection<android.location.CorrelationVector>):
-    
+    Symmetric method for `hasCorrelationVectors` must be named `setHasCorrelationVectors`; was `setCorrelationVectors`
 GetterSetterNames: android.location.GnssMeasurement#setFullInterSignalBiasNanos(double):
-    
+    Symmetric method for `hasFullInterSignalBiasNanos` must be named `setHasFullInterSignalBiasNanos`; was `setFullInterSignalBiasNanos`
 GetterSetterNames: android.location.GnssMeasurement#setFullInterSignalBiasUncertaintyNanos(double):
-    
+    Symmetric method for `hasFullInterSignalBiasUncertaintyNanos` must be named `setHasFullInterSignalBiasUncertaintyNanos`; was `setFullInterSignalBiasUncertaintyNanos`
 GetterSetterNames: android.location.GnssMeasurement#setSatelliteInterSignalBiasNanos(double):
-    
+    Symmetric method for `hasSatelliteInterSignalBiasNanos` must be named `setHasSatelliteInterSignalBiasNanos`; was `setSatelliteInterSignalBiasNanos`
 GetterSetterNames: android.location.GnssMeasurement#setSatelliteInterSignalBiasUncertaintyNanos(double):
-    
+    Symmetric method for `hasSatelliteInterSignalBiasUncertaintyNanos` must be named `setHasSatelliteInterSignalBiasUncertaintyNanos`; was `setSatelliteInterSignalBiasUncertaintyNanos`
 GetterSetterNames: android.location.GnssMeasurement#setSatellitePvt(android.location.SatellitePvt):
-    
+    Symmetric method for `hasSatellitePvt` must be named `setHasSatellitePvt`; was `setSatellitePvt`
 GetterSetterNames: android.location.GnssMeasurement#setSnrInDb(double):
-    
-GetterSetterNames: android.location.LocationRequest#isLocationSettingsIgnored():
-    
-GetterSetterNames: android.location.LocationRequest#isLowPowerMode():
-    
+    Symmetric method for `hasSnrInDb` must be named `setHasSnrInDb`; was `setSnrInDb`
 GetterSetterNames: android.net.NetworkPolicyManager#getRestrictBackground():
     Symmetric method for `setRestrictBackground` must be named `isRestrictBackground`; was `getRestrictBackground`
-GetterSetterNames: android.os.IncidentReportArgs#isAll():
-    
-GetterSetterNames: android.service.notification.NotificationStats#setDirectReplied():
-    
-GetterSetterNames: android.service.notification.NotificationStats#setExpanded():
-    
-GetterSetterNames: android.service.notification.NotificationStats#setSeen():
-    
-GetterSetterNames: android.service.notification.NotificationStats#setSnoozed():
-    
-GetterSetterNames: android.service.notification.NotificationStats#setViewedSettings():
-    
-GetterSetterNames: android.view.View#isAutofilled():
-    
-GetterSetterNames: android.view.View#isDefaultFocusHighlightEnabled():
-    
 
 
-IllegalStateException: android.media.audiopolicy.AudioMix.Builder#build():
-    
-
-
-IntentBuilderName: android.app.backup.BackupManager#getConfigurationIntent(String):
-    
-IntentBuilderName: android.app.backup.BackupManager#getDataManagementIntent(String):
-    
 IntentBuilderName: android.hardware.soundtrigger.KeyphraseEnrollmentInfo#getManageKeyphraseIntent(int, String, java.util.Locale):
-    
+    Methods creating an Intent should be named `create<Foo>Intent()`, was `getManageKeyphraseIntent`
 
 
 IntentName: android.provider.Settings.Secure#VOICE_INTERACTION_SERVICE:
-    
+    Intent action constant name must be ACTION_FOO: VOICE_INTERACTION_SERVICE
 IntentName: android.provider.Telephony.Sms.Intents#SMS_CARRIER_PROVISION_ACTION:
-    
-IntentName: android.service.notification.Adjustment#KEY_CONTEXTUAL_ACTIONS:
-    
+    Intent action constant name must be ACTION_FOO: SMS_CARRIER_PROVISION_ACTION
 
 
-InterfaceConstant: android.service.autofill.AutofillFieldClassificationService#SERVICE_INTERFACE:
-    
-InterfaceConstant: android.service.autofill.augmented.AugmentedAutofillService#SERVICE_INTERFACE:
-    
-InterfaceConstant: android.service.contentcapture.ContentCaptureService#SERVICE_INTERFACE:
-    
-InterfaceConstant: android.service.notification.NotificationAssistantService#SERVICE_INTERFACE:
-    
-InterfaceConstant: android.telecom.PhoneAccountSuggestionService#SERVICE_INTERFACE:
-    
-
-
-InternalField: android.media.audiopolicy.AudioProductStrategy#sDefaultAttributes:
-    Internal field sDefaultAttributes must not be exposed
-InternalField: android.telephony.ims.ImsConferenceState#mParticipants:
-    
-
-
-KotlinOperator: android.os.WorkSource#get(int):
-    
+KotlinOperator: android.os.PackageTagsList#contains(android.os.PackageTagsList):
+    Method can be invoked as a "in" operator from Kotlin: `contains` (this is usually desirable; just make sure it makes sense for this type of object)
 KotlinOperator: android.util.SparseArrayMap#get(int, K):
-    
-KotlinOperator: android.util.SparseArrayMap#get(int, String):
-    
+    Method can be invoked with an indexing operator from Kotlin: `get` (this is usually desirable; just make sure it makes sense for this type of object)
 
 
-ListenerInterface: android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener:
-    
-ListenerInterface: android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListener:
-    
-ListenerInterface: android.os.IncidentManager.AuthListener:
-    
-ListenerInterface: android.telephony.ims.ImsCallSessionListener:
-    
-ListenerInterface: android.telephony.ims.ImsUtListener:
-    
-
-
-ListenerLast: android.hardware.camera2.CameraDevice#createCustomCaptureSession(android.hardware.camera2.params.InputConfiguration, java.util.List<android.hardware.camera2.params.OutputConfiguration>, int, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) parameter #4:
-    
-ListenerLast: android.location.LocationManager#requestLocationUpdates(android.location.LocationRequest, android.location.LocationListener, android.os.Looper) parameter #2:
-    
 ListenerLast: android.permission.PermissionControllerManager#countPermissionApps(java.util.List<java.lang.String>, int, android.permission.PermissionControllerManager.OnCountPermissionAppsResultCallback, android.os.Handler) parameter #3:
-    
+    Listeners should always be at end of argument list (method `countPermissionApps`)
 ListenerLast: android.permission.PermissionControllerManager#getAppPermissions(String, android.permission.PermissionControllerManager.OnGetAppPermissionResultCallback, android.os.Handler) parameter #2:
-    
-ListenerLast: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#initialize(android.telephony.mbms.MbmsGroupCallSessionCallback, int) parameter #1:
-    
-ListenerLast: android.telephony.mbms.vendor.MbmsStreamingServiceBase#initialize(android.telephony.mbms.MbmsStreamingSessionCallback, int) parameter #1:
-    
+    Listeners should always be at end of argument list (method `getAppPermissions`)
 
 
 ManagerConstructor: android.content.pm.ShortcutManager#ShortcutManager(android.content.Context):
-    
-
-
-ManagerLookup: android.telephony.ims.ImsMmTelManager#createForSubscriptionId(int):
-    
-ManagerLookup: android.telephony.ims.ProvisioningManager#createForSubscriptionId(int):
-    
-
-
-MethodNameTense: android.telephony.ims.feature.CapabilityChangeRequest#getCapabilitiesToEnable():
-    
-
-
-MethodNameUnits: android.telephony.ims.ImsCallForwardInfo#getTimeSeconds():
-    
+    Managers must always be obtained from Context; no direct constructors
 
 
 MinMaxConstant: android.os.UserHandle#MIN_SECONDARY_USER_ID:
-    
+    If min/max could change in future, make them dynamic methods: android.os.UserHandle#MIN_SECONDARY_USER_ID
 MinMaxConstant: android.view.autofill.AutofillManager#MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS:
-    
+    If min/max could change in future, make them dynamic methods: android.view.autofill.AutofillManager#MAX_TEMP_AUGMENTED_SERVICE_DURATION_MS
 
 
-MissingGetterMatchingBuilder: android.app.AppOpsManager.HistoricalOpsRequest.Builder#setFlags(int):
-    
-MissingGetterMatchingBuilder: android.app.AppOpsManager.HistoricalOpsRequest.Builder#setOpNames(java.util.List<java.lang.String>):
-    
-MissingGetterMatchingBuilder: android.app.AppOpsManager.HistoricalOpsRequest.Builder#setPackageName(String):
-    
-MissingGetterMatchingBuilder: android.app.AppOpsManager.HistoricalOpsRequest.Builder#setUid(int):
-    
-MissingGetterMatchingBuilder: android.content.integrity.RuleSet.Builder#addRules(java.util.List<android.content.integrity.Rule>):
-    
-MissingGetterMatchingBuilder: android.hardware.display.BrightnessConfiguration.Builder#addCorrectionByCategory(int, android.hardware.display.BrightnessCorrection):
-    
-MissingGetterMatchingBuilder: android.hardware.display.BrightnessConfiguration.Builder#addCorrectionByPackageName(String, android.hardware.display.BrightnessCorrection):
-    
-MissingGetterMatchingBuilder: android.hardware.display.BrightnessConfiguration.Builder#setDescription(String):
-    
-MissingGetterMatchingBuilder: android.hardware.lights.LightsRequest.Builder#setLight(android.hardware.lights.Light, android.hardware.lights.LightState):
-    
 MissingGetterMatchingBuilder: android.media.VolumeShaper.Configuration.Builder#setOptionFlags(int):
-    
-MissingGetterMatchingBuilder: android.media.audiopolicy.AudioMix.Builder#setDevice(android.media.AudioDeviceInfo):
-    
-MissingGetterMatchingBuilder: android.media.audiopolicy.AudioMix.Builder#setFormat(android.media.AudioFormat):
-    
-MissingGetterMatchingBuilder: android.media.audiopolicy.AudioMix.Builder#setRouteFlags(int):
-    
-MissingGetterMatchingBuilder: android.media.audiopolicy.AudioMixingRule.Builder#addMixRule(int, Object):
-    
-MissingGetterMatchingBuilder: android.media.audiopolicy.AudioMixingRule.Builder#addRule(android.media.AudioAttributes, int):
-    
-MissingGetterMatchingBuilder: android.media.audiopolicy.AudioPolicy.Builder#addMix(android.media.audiopolicy.AudioMix):
-    
-MissingGetterMatchingBuilder: android.media.audiopolicy.AudioPolicy.Builder#setAudioPolicyFocusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener):
-    
-MissingGetterMatchingBuilder: android.media.audiopolicy.AudioPolicy.Builder#setAudioPolicyStatusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListener):
-    
-MissingGetterMatchingBuilder: android.media.audiopolicy.AudioPolicy.Builder#setAudioPolicyVolumeCallback(android.media.audiopolicy.AudioPolicy.AudioPolicyVolumeCallback):
-    
-MissingGetterMatchingBuilder: android.media.audiopolicy.AudioPolicy.Builder#setIsAudioFocusPolicy(boolean):
-    
+    android.media.VolumeShaper.Configuration does not declare a `getOptionFlags()` method matching method android.media.VolumeShaper.Configuration.Builder.setOptionFlags(int)
 MissingGetterMatchingBuilder: android.media.audiopolicy.AudioPolicy.Builder#setIsTestFocusPolicy(boolean):
-    
-MissingGetterMatchingBuilder: android.media.audiopolicy.AudioPolicy.Builder#setLooper(android.os.Looper):
-    
-MissingGetterMatchingBuilder: android.net.CaptivePortalData.Builder#setBytesRemaining(long):
-    
-MissingGetterMatchingBuilder: android.net.CaptivePortalData.Builder#setExpiryTime(long):
-    
-MissingGetterMatchingBuilder: android.net.CaptivePortalData.Builder#setRefreshTime(long):
-    
-MissingGetterMatchingBuilder: android.net.NetworkCapabilities.Builder#addCapability(int):
-    
-MissingGetterMatchingBuilder: android.net.NetworkCapabilities.Builder#setRequestorPackageName(String):
-    
-MissingGetterMatchingBuilder: android.net.NetworkCapabilities.Builder#setRequestorUid(int):
-    
-MissingGetterMatchingBuilder: android.net.TetheringManager.TetheringRequest.Builder#setShouldShowEntitlementUi(boolean):
-    
-MissingGetterMatchingBuilder: android.net.TetheringManager.TetheringRequest.Builder#setStaticIpv4Addresses(android.net.LinkAddress, android.net.LinkAddress):
-    
-MissingGetterMatchingBuilder: android.net.metrics.ApfProgramEvent.Builder#setActualLifetime(long):
-    
-MissingGetterMatchingBuilder: android.net.metrics.ApfProgramEvent.Builder#setCurrentRas(int):
-    
-MissingGetterMatchingBuilder: android.net.metrics.ApfProgramEvent.Builder#setFilteredRas(int):
-    
-MissingGetterMatchingBuilder: android.net.metrics.ApfProgramEvent.Builder#setFlags(boolean, boolean):
-    
-MissingGetterMatchingBuilder: android.net.metrics.ApfProgramEvent.Builder#setLifetime(long):
-    
-MissingGetterMatchingBuilder: android.net.metrics.ApfProgramEvent.Builder#setProgramLength(int):
-    
-MissingGetterMatchingBuilder: android.net.metrics.ApfStats.Builder#setDroppedRas(int):
-    
-MissingGetterMatchingBuilder: android.net.metrics.ApfStats.Builder#setDurationMs(long):
-    
-MissingGetterMatchingBuilder: android.net.metrics.ApfStats.Builder#setMatchingRas(int):
-    
-MissingGetterMatchingBuilder: android.net.metrics.ApfStats.Builder#setMaxProgramSize(int):
-    
-MissingGetterMatchingBuilder: android.net.metrics.ApfStats.Builder#setParseErrors(int):
-    
-MissingGetterMatchingBuilder: android.net.metrics.ApfStats.Builder#setProgramUpdates(int):
-    
-MissingGetterMatchingBuilder: android.net.metrics.ApfStats.Builder#setProgramUpdatesAll(int):
-    
-MissingGetterMatchingBuilder: android.net.metrics.ApfStats.Builder#setProgramUpdatesAllowingMulticast(int):
-    
-MissingGetterMatchingBuilder: android.net.metrics.ApfStats.Builder#setReceivedRas(int):
-    
-MissingGetterMatchingBuilder: android.net.metrics.ApfStats.Builder#setZeroLifetimeRas(int):
-    
-MissingGetterMatchingBuilder: android.net.metrics.DhcpClientEvent.Builder#setDurationMs(int):
-    
-MissingGetterMatchingBuilder: android.net.metrics.DhcpClientEvent.Builder#setMsg(String):
-    
-MissingGetterMatchingBuilder: android.net.metrics.ValidationProbeEvent.Builder#setDurationMs(long):
-    
-MissingGetterMatchingBuilder: android.net.metrics.ValidationProbeEvent.Builder#setProbeType(int, boolean):
-    
-MissingGetterMatchingBuilder: android.net.metrics.ValidationProbeEvent.Builder#setReturnCode(int):
-    
+    android.media.audiopolicy.AudioPolicy does not declare a `isIsTestFocusPolicy()` method matching method android.media.audiopolicy.AudioPolicy.Builder.setIsTestFocusPolicy(boolean)
 MissingGetterMatchingBuilder: android.security.keystore.KeyGenParameterSpec.Builder#setUniqueIdIncluded(boolean):
-    
-MissingGetterMatchingBuilder: android.service.autofill.Dataset.Builder#setFieldInlinePresentation(android.view.autofill.AutofillId, android.view.autofill.AutofillValue, java.util.regex.Pattern, android.service.autofill.InlinePresentation):
-    
-MissingGetterMatchingBuilder: android.service.autofill.augmented.FillResponse.Builder#setClientState(android.os.Bundle):
-    
-MissingGetterMatchingBuilder: android.service.autofill.augmented.FillResponse.Builder#setFillWindow(android.service.autofill.augmented.FillWindow):
-    
-MissingGetterMatchingBuilder: android.service.autofill.augmented.FillResponse.Builder#setInlineSuggestions(java.util.List<android.service.autofill.Dataset>):
-    
-MissingGetterMatchingBuilder: android.telecom.CallScreeningService.CallResponse.Builder#setShouldScreenCallViaAudioProcessing(boolean):
-    
+    android.security.keystore.KeyGenParameterSpec does not declare a `isUniqueIdIncluded()` method matching method android.security.keystore.KeyGenParameterSpec.Builder.setUniqueIdIncluded(boolean)
 MissingGetterMatchingBuilder: android.telecom.ConnectionRequest.Builder#setIsAdhocConferenceCall(boolean):
-    
+    android.telecom.ConnectionRequest does not declare a `isIsAdhocConferenceCall()` method matching method android.telecom.ConnectionRequest.Builder.setIsAdhocConferenceCall(boolean)
 MissingGetterMatchingBuilder: android.telecom.ConnectionRequest.Builder#setRttPipeFromInCall(android.os.ParcelFileDescriptor):
-    
+    android.telecom.ConnectionRequest does not declare a `getRttPipeFromInCall()` method matching method android.telecom.ConnectionRequest.Builder.setRttPipeFromInCall(android.os.ParcelFileDescriptor)
 MissingGetterMatchingBuilder: android.telecom.ConnectionRequest.Builder#setRttPipeToInCall(android.os.ParcelFileDescriptor):
-    
+    android.telecom.ConnectionRequest does not declare a `getRttPipeToInCall()` method matching method android.telecom.ConnectionRequest.Builder.setRttPipeToInCall(android.os.ParcelFileDescriptor)
 MissingGetterMatchingBuilder: android.telecom.ConnectionRequest.Builder#setShouldShowIncomingCallUi(boolean):
-    
-MissingGetterMatchingBuilder: android.telecom.PhoneAccount.Builder#setGroupId(String):
-    
-MissingGetterMatchingBuilder: android.telephony.NetworkRegistrationInfo.Builder#setEmergencyOnly(boolean):
-    
-MissingGetterMatchingBuilder: android.telephony.ims.ImsSsData.Builder#setCallForwardingInfo(java.util.List<android.telephony.ims.ImsCallForwardInfo>):
-    
-MissingGetterMatchingBuilder: android.telephony.ims.stub.ImsFeatureConfiguration.Builder#addFeature(int, int):
-    
-MissingGetterMatchingBuilder: android.telephony.mbms.DownloadRequest.Builder#setServiceId(String):
-    
+    android.telecom.ConnectionRequest does not declare a `shouldShowIncomingCallUi()` method matching method android.telecom.ConnectionRequest.Builder.setShouldShowIncomingCallUi(boolean)
 MissingGetterMatchingBuilder: android.view.Display.Mode.Builder#setResolution(int, int):
     android.view.Display.Mode does not declare a `getResolution()` method matching method android.view.Display.Mode.Builder.setResolution(int,int)
 
 
 MissingNullability: android.app.Activity#onMovedToDisplay(int, android.content.res.Configuration) parameter #1:
-    
-MissingNullability: android.app.ActivityManager#addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int) parameter #0:
-    
+    Missing nullability on parameter `config` in method `onMovedToDisplay`
 MissingNullability: android.app.ActivityManager#alwaysShowUnsupportedCompileSdkWarning(android.content.ComponentName) parameter #0:
-    
-MissingNullability: android.app.ActivityManager#forceStopPackage(String) parameter #0:
-    
-MissingNullability: android.app.ActivityManager#getPackageImportance(String) parameter #0:
-    
+    Missing nullability on parameter `activity` in method `alwaysShowUnsupportedCompileSdkWarning`
 MissingNullability: android.app.ActivityManager#holdLock(android.os.IBinder, int) parameter #0:
-    
-MissingNullability: android.app.ActivityManager#removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener) parameter #0:
-    
+    Missing nullability on parameter `token` in method `holdLock`
 MissingNullability: android.app.ActivityManager#scheduleApplicationInfoChanged(java.util.List<java.lang.String>, int) parameter #0:
-    
+    Missing nullability on parameter `packages` in method `scheduleApplicationInfoChanged`
 MissingNullability: android.app.ActivityManager.TaskDescription#getIconFilename():
-    
+    Missing nullability on method `getIconFilename` return
 MissingNullability: android.app.ActivityTaskManager#clearLaunchParamsForPackages(java.util.List<java.lang.String>) parameter #0:
-    
-MissingNullability: android.app.ActivityTaskManager#listAllStacks():
-    
-MissingNullability: android.app.ActivityTaskManager#moveTopActivityToPinnedStack(int, android.graphics.Rect) parameter #1:
-    
-MissingNullability: android.app.ActivityTaskManager#removeStacksInWindowingModes(int[]) parameter #0:
-    
-MissingNullability: android.app.ActivityTaskManager#removeStacksWithActivityTypes(int[]) parameter #0:
-    
-MissingNullability: android.app.ActivityTaskManager#resizeDockedStack(android.graphics.Rect, android.graphics.Rect) parameter #0:
-    
-MissingNullability: android.app.ActivityTaskManager#resizeDockedStack(android.graphics.Rect, android.graphics.Rect) parameter #1:
-    
-MissingNullability: android.app.ActivityTaskManager#resizePinnedStack(int, android.graphics.Rect, boolean) parameter #1:
-    
+    Missing nullability on parameter `packageNames` in method `clearLaunchParamsForPackages`
 MissingNullability: android.app.ActivityTaskManager#resizeTask(int, android.graphics.Rect) parameter #1:
-    
-MissingNullability: android.app.ActivityTaskManager#setTaskWindowingModeSplitScreenPrimary(int, int, boolean, boolean, android.graphics.Rect, boolean) parameter #4:
-    
+    Missing nullability on parameter `bounds` in method `resizeTask`
 MissingNullability: android.app.ActivityTaskManager#supportsMultiWindow(android.content.Context) parameter #0:
-    
+    Missing nullability on parameter `context` in method `supportsMultiWindow`
 MissingNullability: android.app.ActivityTaskManager#supportsSplitScreenMultiWindow(android.content.Context) parameter #0:
-    
+    Missing nullability on parameter `context` in method `supportsSplitScreenMultiWindow`
 MissingNullability: android.app.AppDetailsActivity#onCreate(android.os.Bundle) parameter #0:
-    
-MissingNullability: android.app.AppOpsManager#getOpStrs():
-    
+    Missing nullability on parameter `savedInstanceState` in method `onCreate`
 MissingNullability: android.app.AppOpsManager#isOperationActive(int, int, String) parameter #2:
-    
+    Missing nullability on parameter `packageName` in method `isOperationActive`
 MissingNullability: android.app.AppOpsManager#opToPermission(int):
-    
+    Missing nullability on method `opToPermission` return
 MissingNullability: android.app.AppOpsManager#permissionToOpCode(String) parameter #0:
-    
-MissingNullability: android.app.AppOpsManager#setMode(String, int, String, int) parameter #0:
-    
-MissingNullability: android.app.AppOpsManager#setMode(String, int, String, int) parameter #2:
-    
+    Missing nullability on parameter `permission` in method `permissionToOpCode`
 MissingNullability: android.app.AppOpsManager#setMode(int, int, String, int) parameter #2:
-    
-MissingNullability: android.app.AppOpsManager#setUidMode(String, int, int) parameter #0:
-    
-MissingNullability: android.app.AppOpsManager.HistoricalOp#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.app.AppOpsManager.HistoricalOps#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.app.AppOpsManager.HistoricalUidOps#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.app.AppOpsManager.OpEntry#writeToParcel(android.os.Parcel, int) parameter #0:
-    
+    Missing nullability on parameter `packageName` in method `setMode`
 MissingNullability: android.app.NotificationManager#allowAssistantAdjustment(String) parameter #0:
-    
+    Missing nullability on parameter `capability` in method `allowAssistantAdjustment`
 MissingNullability: android.app.NotificationManager#disallowAssistantAdjustment(String) parameter #0:
-    
+    Missing nullability on parameter `capability` in method `disallowAssistantAdjustment`
 MissingNullability: android.app.NotificationManager#getEffectsSuppressor():
-    
-MissingNullability: android.app.NotificationManager#matchesCallFilter(android.os.Bundle) parameter #0:
-    
-MissingNullability: android.app.PictureInPictureParams#getActions():
-    
-MissingNullability: android.app.PictureInPictureParams#getSourceRectHint():
-    
+    Missing nullability on method `getEffectsSuppressor` return
 MissingNullability: android.app.TimePickerDialog#getTimePicker():
-    
-MissingNullability: android.app.UiAutomation#executeShellCommandRw(String):
-    
-MissingNullability: android.app.UiAutomation#executeShellCommandRw(String) parameter #0:
-    
-MissingNullability: android.app.UiAutomation#grantRuntimePermission(String, String, android.os.UserHandle) parameter #0:
-    
-MissingNullability: android.app.UiAutomation#grantRuntimePermission(String, String, android.os.UserHandle) parameter #1:
-    
-MissingNullability: android.app.UiAutomation#grantRuntimePermission(String, String, android.os.UserHandle) parameter #2:
-    
-MissingNullability: android.app.UiAutomation#revokeRuntimePermission(String, String, android.os.UserHandle) parameter #0:
-    
-MissingNullability: android.app.UiAutomation#revokeRuntimePermission(String, String, android.os.UserHandle) parameter #1:
-    
-MissingNullability: android.app.UiAutomation#revokeRuntimePermission(String, String, android.os.UserHandle) parameter #2:
-    
-MissingNullability: android.app.WallpaperManager#setWallpaperComponent(android.content.ComponentName) parameter #0:
-    
+    Missing nullability on method `getTimePicker` return
 MissingNullability: android.app.WindowConfiguration#compareTo(android.app.WindowConfiguration) parameter #0:
-    
+    Missing nullability on parameter `that` in method `compareTo`
 MissingNullability: android.app.WindowConfiguration#getAppBounds():
-    
+    Missing nullability on method `getAppBounds` return
 MissingNullability: android.app.WindowConfiguration#getBounds():
-    
+    Missing nullability on method `getBounds` return
 MissingNullability: android.app.WindowConfiguration#setAppBounds(android.graphics.Rect) parameter #0:
-    
+    Missing nullability on parameter `rect` in method `setAppBounds`
 MissingNullability: android.app.WindowConfiguration#setBounds(android.graphics.Rect) parameter #0:
-    
+    Missing nullability on parameter `rect` in method `setBounds`
 MissingNullability: android.app.WindowConfiguration#setTo(android.app.WindowConfiguration) parameter #0:
-    
+    Missing nullability on parameter `other` in method `setTo`
 MissingNullability: android.app.WindowConfiguration#writeToParcel(android.os.Parcel, int) parameter #0:
-    
+    Missing nullability on parameter `dest` in method `writeToParcel`
 MissingNullability: android.app.admin.DevicePolicyManager#getOwnerInstalledCaCerts(android.os.UserHandle):
-    
+    Missing nullability on method `getOwnerInstalledCaCerts` return
 MissingNullability: android.app.admin.SecurityLog.SecurityEvent#SecurityEvent(long, byte[]) parameter #1:
-    
-MissingNullability: android.app.backup.BackupManager#getConfigurationIntent(String):
-    
-MissingNullability: android.app.backup.BackupManager#getConfigurationIntent(String) parameter #0:
-    
-MissingNullability: android.app.backup.BackupManager#getDataManagementIntent(String):
-    
-MissingNullability: android.app.backup.BackupManager#getDataManagementIntent(String) parameter #0:
-    
-MissingNullability: android.app.backup.BackupManager#getDestinationString(String):
-    
-MissingNullability: android.app.backup.BackupManager#getDestinationString(String) parameter #0:
-    
-MissingNullability: android.app.prediction.AppPredictionSessionId#writeToParcel(android.os.Parcel, int) parameter #0:
-    
+    Missing nullability on parameter `data` in method `SecurityEvent`
 MissingNullability: android.app.prediction.AppPredictor#getSessionId():
-    
-MissingNullability: android.app.prediction.AppTarget#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.app.prediction.AppTargetEvent#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.app.prediction.AppTargetId#writeToParcel(android.os.Parcel, int) parameter #0:
-    
+    Missing nullability on method `getSessionId` return
 MissingNullability: android.content.AutofillOptions#forWhitelistingItself():
-    
+    Missing nullability on method `forWhitelistingItself` return
 MissingNullability: android.content.AutofillOptions#writeToParcel(android.os.Parcel, int) parameter #0:
-    
+    Missing nullability on parameter `parcel` in method `writeToParcel`
 MissingNullability: android.content.ContentCaptureOptions#forWhitelistingItself():
-    
+    Missing nullability on method `forWhitelistingItself` return
 MissingNullability: android.content.ContentCaptureOptions#writeToParcel(android.os.Parcel, int) parameter #0:
-    
+    Missing nullability on parameter `parcel` in method `writeToParcel`
 MissingNullability: android.content.ContentResolver#getSyncAdapterPackagesForAuthorityAsUser(String, int):
-    
+    Missing nullability on method `getSyncAdapterPackagesForAuthorityAsUser` return
 MissingNullability: android.content.ContentResolver#getSyncAdapterPackagesForAuthorityAsUser(String, int) parameter #0:
-    
-MissingNullability: android.content.Context#getDisplay():
-    
-MissingNullability: android.content.Context#getUser():
-    
-MissingNullability: android.content.ContextWrapper#getDisplay():
-    
-MissingNullability: android.content.ContextWrapper#setContentCaptureOptions(android.content.ContentCaptureOptions) parameter #0:
-    
+    Missing nullability on parameter `authority` in method `getSyncAdapterPackagesForAuthorityAsUser`
 MissingNullability: android.content.pm.ActivityInfo#isTranslucentOrFloating(android.content.res.TypedArray) parameter #0:
-    
+    Missing nullability on parameter `attributes` in method `isTranslucentOrFloating`
 MissingNullability: android.content.pm.LauncherApps#LauncherApps(android.content.Context) parameter #0:
-    
-MissingNullability: android.content.pm.PackageInstaller.SessionParams#setGrantedRuntimePermissions(String[]) parameter #0:
-    
+    Missing nullability on parameter `context` in method `LauncherApps`
 MissingNullability: android.content.pm.PackageManager#getHoldLockToken():
-    Missing nullability on method `BINDER` return
+    Missing nullability on method `getHoldLockToken` return
 MissingNullability: android.content.pm.PackageManager#getNamesForUids(int[]) parameter #0:
-    
+    Missing nullability on parameter `uids` in method `getNamesForUids`
 MissingNullability: android.content.pm.PackageManager#holdLock(android.os.IBinder, int) parameter #0:
-    
+    Missing nullability on parameter `token` in method `holdLock`
 MissingNullability: android.content.pm.ShortcutManager#ShortcutManager(android.content.Context) parameter #0:
-    
+    Missing nullability on parameter `context` in method `ShortcutManager`
 MissingNullability: android.content.pm.UserInfo#UserInfo(android.content.pm.UserInfo) parameter #0:
     Missing nullability on parameter `orig` in method `UserInfo`
 MissingNullability: android.content.pm.UserInfo#UserInfo(int, String, String, int) parameter #1:
@@ -942,1469 +292,477 @@
 MissingNullability: android.content.pm.UserInfo#writeToParcel(android.os.Parcel, int) parameter #0:
     Missing nullability on parameter `dest` in method `writeToParcel`
 MissingNullability: android.content.res.AssetManager#getOverlayablesToString(String) parameter #0:
-    
+    Missing nullability on parameter `packageName` in method `getOverlayablesToString`
 MissingNullability: android.content.res.Configuration#windowConfiguration:
-    
-MissingNullability: android.content.rollback.PackageRollbackInfo#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.content.rollback.RollbackInfo#writeToParcel(android.os.Parcel, int) parameter #0:
-    
+    Missing nullability on field `windowConfiguration` in class `class android.content.res.Configuration`
 MissingNullability: android.database.sqlite.SQLiteDebug#dump(android.util.Printer, String[]) parameter #0:
-    
+    Missing nullability on parameter `printer` in method `dump`
 MissingNullability: android.database.sqlite.SQLiteDebug#dump(android.util.Printer, String[]) parameter #1:
-    
+    Missing nullability on parameter `args` in method `dump`
 MissingNullability: android.database.sqlite.SQLiteDebug#getDatabaseInfo():
-    
+    Missing nullability on method `getDatabaseInfo` return
 MissingNullability: android.database.sqlite.SQLiteDebug.DbStats#DbStats(String, long, long, int, int, int, int) parameter #0:
-    
+    Missing nullability on parameter `dbName` in method `DbStats`
 MissingNullability: android.database.sqlite.SQLiteDebug.DbStats#cache:
-    
+    Missing nullability on field `cache` in class `class android.database.sqlite.SQLiteDebug.DbStats`
 MissingNullability: android.database.sqlite.SQLiteDebug.DbStats#dbName:
-    
+    Missing nullability on field `dbName` in class `class android.database.sqlite.SQLiteDebug.DbStats`
 MissingNullability: android.database.sqlite.SQLiteDebug.PagerStats#dbStats:
-    
+    Missing nullability on field `dbStats` in class `class android.database.sqlite.SQLiteDebug.PagerStats`
 MissingNullability: android.database.sqlite.SQLiteDirectCursorDriver#SQLiteDirectCursorDriver(android.database.sqlite.SQLiteDatabase, String, String, android.os.CancellationSignal) parameter #0:
-    
+    Missing nullability on parameter `db` in method `SQLiteDirectCursorDriver`
 MissingNullability: android.database.sqlite.SQLiteDirectCursorDriver#SQLiteDirectCursorDriver(android.database.sqlite.SQLiteDatabase, String, String, android.os.CancellationSignal) parameter #1:
-    
+    Missing nullability on parameter `sql` in method `SQLiteDirectCursorDriver`
 MissingNullability: android.database.sqlite.SQLiteDirectCursorDriver#SQLiteDirectCursorDriver(android.database.sqlite.SQLiteDatabase, String, String, android.os.CancellationSignal) parameter #2:
-    
+    Missing nullability on parameter `editTable` in method `SQLiteDirectCursorDriver`
 MissingNullability: android.database.sqlite.SQLiteDirectCursorDriver#SQLiteDirectCursorDriver(android.database.sqlite.SQLiteDatabase, String, String, android.os.CancellationSignal) parameter #3:
-    
+    Missing nullability on parameter `cancellationSignal` in method `SQLiteDirectCursorDriver`
 MissingNullability: android.database.sqlite.SQLiteDirectCursorDriver#cursorRequeried(android.database.Cursor) parameter #0:
-    
+    Missing nullability on parameter `cursor` in method `cursorRequeried`
 MissingNullability: android.database.sqlite.SQLiteDirectCursorDriver#query(android.database.sqlite.SQLiteDatabase.CursorFactory, String[]):
-    
+    Missing nullability on method `query` return
 MissingNullability: android.database.sqlite.SQLiteDirectCursorDriver#query(android.database.sqlite.SQLiteDatabase.CursorFactory, String[]) parameter #0:
-    
+    Missing nullability on parameter `factory` in method `query`
 MissingNullability: android.database.sqlite.SQLiteDirectCursorDriver#query(android.database.sqlite.SQLiteDatabase.CursorFactory, String[]) parameter #1:
-    
+    Missing nullability on parameter `selectionArgs` in method `query`
 MissingNullability: android.database.sqlite.SQLiteDirectCursorDriver#setBindArguments(String[]) parameter #0:
-    
+    Missing nullability on parameter `bindArgs` in method `setBindArguments`
 MissingNullability: android.database.sqlite.SQLiteGlobal#getDefaultJournalMode():
-    
+    Missing nullability on method `getDefaultJournalMode` return
 MissingNullability: android.database.sqlite.SQLiteGlobal#getDefaultSyncMode():
-    
+    Missing nullability on method `getDefaultSyncMode` return
 MissingNullability: android.database.sqlite.SQLiteGlobal#getWALSyncMode():
-    
+    Missing nullability on method `getWALSyncMode` return
 MissingNullability: android.graphics.ImageDecoder#createSource(android.content.res.Resources, java.io.InputStream, int) parameter #0:
-    
-MissingNullability: android.graphics.ImageDecoder#createSource(android.content.res.Resources, java.io.InputStream, int) parameter #1:
-    
+    Missing nullability on parameter `res` in method `createSource`
 MissingNullability: android.graphics.drawable.AdaptiveIconDrawable#getSafeZone():
-    
+    Missing nullability on method `getSafeZone` return
 MissingNullability: android.graphics.drawable.ColorDrawable#getXfermode():
-    
-MissingNullability: android.hardware.camera2.CameraDevice#createCustomCaptureSession(android.hardware.camera2.params.InputConfiguration, java.util.List<android.hardware.camera2.params.OutputConfiguration>, int, android.hardware.camera2.CameraCaptureSession.StateCallback, android.os.Handler) parameter #0:
-    
+    Missing nullability on method `getXfermode` return
 MissingNullability: android.hardware.camera2.CameraManager#getCameraIdListNoLazy():
-    
-MissingNullability: android.hardware.display.AmbientBrightnessDayStats#getBucketBoundaries():
-    
-MissingNullability: android.hardware.display.AmbientBrightnessDayStats#getLocalDate():
-    
-MissingNullability: android.hardware.display.AmbientBrightnessDayStats#getStats():
-    
-MissingNullability: android.hardware.display.AmbientBrightnessDayStats#writeToParcel(android.os.Parcel, int) parameter #0:
-    
+    Missing nullability on method `getCameraIdListNoLazy` return
 MissingNullability: android.hardware.display.AmbientDisplayConfiguration#AmbientDisplayConfiguration(android.content.Context) parameter #0:
-    
-MissingNullability: android.hardware.display.BrightnessChangeEvent#luxTimestamps:
-    
-MissingNullability: android.hardware.display.BrightnessChangeEvent#luxValues:
-    
-MissingNullability: android.hardware.display.BrightnessChangeEvent#packageName:
-    
-MissingNullability: android.hardware.display.BrightnessChangeEvent#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.hardware.display.BrightnessConfiguration#getCurve():
-    
-MissingNullability: android.hardware.display.BrightnessConfiguration#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.hardware.display.BrightnessConfiguration.Builder#Builder(float[], float[]) parameter #0:
-    
-MissingNullability: android.hardware.display.BrightnessConfiguration.Builder#Builder(float[], float[]) parameter #1:
-    
-MissingNullability: android.hardware.display.BrightnessCorrection#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.hardware.display.DisplayManager#getAmbientBrightnessStats():
-    
-MissingNullability: android.hardware.display.DisplayManager#getBrightnessConfiguration():
-    
-MissingNullability: android.hardware.display.DisplayManager#getBrightnessEvents():
-    
-MissingNullability: android.hardware.display.DisplayManager#getStableDisplaySize():
-    
-MissingNullability: android.hardware.display.DisplayManager#setBrightnessConfiguration(android.hardware.display.BrightnessConfiguration) parameter #0:
-    
+    Missing nullability on parameter `context` in method `AmbientDisplayConfiguration`
 MissingNullability: android.location.GnssClock#set(android.location.GnssClock) parameter #0:
-    
+    Missing nullability on parameter `clock` in method `set`
 MissingNullability: android.location.GnssMeasurement#set(android.location.GnssMeasurement) parameter #0:
-    
-MissingNullability: android.location.GnssMeasurementsEvent#GnssMeasurementsEvent(android.location.GnssClock, android.location.GnssMeasurement[]) parameter #0:
-    
-MissingNullability: android.location.GnssMeasurementsEvent#GnssMeasurementsEvent(android.location.GnssClock, android.location.GnssMeasurement[]) parameter #1:
-    
+    Missing nullability on parameter `measurement` in method `set`
 MissingNullability: android.location.GnssNavigationMessage#set(android.location.GnssNavigationMessage) parameter #0:
-    
+    Missing nullability on parameter `navigationMessage` in method `set`
 MissingNullability: android.location.GnssNavigationMessage#setData(byte[]) parameter #0:
-    
-MissingNullability: android.location.LocationManager#getTestProviderCurrentRequests(String) parameter #0:
-    
-MissingNullability: android.location.LocationRequest#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.media.AudioAttributes#SDK_USAGES:
-    Missing nullability on field `SDK_USAGES` in class `class android.media.AudioAttributes`
+    Missing nullability on parameter `value` in method `setData`
 MissingNullability: android.media.AudioAttributes#getSdkUsages():
     Missing nullability on method `getSdkUsages` return
-MissingNullability: android.media.AudioFocusInfo#writeToParcel(android.os.Parcel, int) parameter #0:
-    
 MissingNullability: android.media.AudioManager#getPublicStreamTypes():
     Missing nullability on method `getPublicStreamTypes` return
 MissingNullability: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String) parameter #3:
-    
+    Missing nullability on parameter `clientFormat` in method `AudioRecordingConfiguration`
 MissingNullability: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String) parameter #4:
-    
+    Missing nullability on parameter `devFormat` in method `AudioRecordingConfiguration`
 MissingNullability: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String) parameter #6:
-    
+    Missing nullability on parameter `packageName` in method `AudioRecordingConfiguration`
 MissingNullability: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String, int, boolean, int, android.media.audiofx.AudioEffect.Descriptor[], android.media.audiofx.AudioEffect.Descriptor[]) parameter #10:
-    
+    Missing nullability on parameter `clientEffects` in method `AudioRecordingConfiguration`
 MissingNullability: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String, int, boolean, int, android.media.audiofx.AudioEffect.Descriptor[], android.media.audiofx.AudioEffect.Descriptor[]) parameter #11:
-    
+    Missing nullability on parameter `deviceEffects` in method `AudioRecordingConfiguration`
 MissingNullability: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String, int, boolean, int, android.media.audiofx.AudioEffect.Descriptor[], android.media.audiofx.AudioEffect.Descriptor[]) parameter #3:
-    
+    Missing nullability on parameter `clientFormat` in method `AudioRecordingConfiguration`
 MissingNullability: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String, int, boolean, int, android.media.audiofx.AudioEffect.Descriptor[], android.media.audiofx.AudioEffect.Descriptor[]) parameter #4:
-    
+    Missing nullability on parameter `devFormat` in method `AudioRecordingConfiguration`
 MissingNullability: android.media.AudioRecordingConfiguration#AudioRecordingConfiguration(int, int, int, android.media.AudioFormat, android.media.AudioFormat, int, String, int, boolean, int, android.media.audiofx.AudioEffect.Descriptor[], android.media.audiofx.AudioEffect.Descriptor[]) parameter #6:
-    
-MissingNullability: android.media.AudioSystem#streamToString(int):
-    Missing nullability on method `streamToString` return
+    Missing nullability on parameter `packageName` in method `AudioRecordingConfiguration`
 MissingNullability: android.media.PlaybackParams#setAudioStretchMode(int):
-    
+    Missing nullability on method `setAudioStretchMode` return
 MissingNullability: android.media.audiofx.AudioEffect#EFFECT_TYPE_NULL:
-    
+    Missing nullability on field `EFFECT_TYPE_NULL` in class `class android.media.audiofx.AudioEffect`
 MissingNullability: android.media.audiofx.AudioEffect#byteArrayToInt(byte[]) parameter #0:
-    
+    Missing nullability on parameter `valueBuf` in method `byteArrayToInt`
 MissingNullability: android.media.audiofx.AudioEffect#byteArrayToShort(byte[]) parameter #0:
-    
+    Missing nullability on parameter `valueBuf` in method `byteArrayToShort`
 MissingNullability: android.media.audiofx.AudioEffect#getParameter(byte[], byte[]) parameter #0:
-    
+    Missing nullability on parameter `param` in method `getParameter`
 MissingNullability: android.media.audiofx.AudioEffect#getParameter(byte[], byte[]) parameter #1:
-    
+    Missing nullability on parameter `value` in method `getParameter`
 MissingNullability: android.media.audiofx.AudioEffect#getParameter(int, byte[]) parameter #1:
-    
+    Missing nullability on parameter `value` in method `getParameter`
 MissingNullability: android.media.audiofx.AudioEffect#getParameter(int, int[]) parameter #1:
-    
+    Missing nullability on parameter `value` in method `getParameter`
 MissingNullability: android.media.audiofx.AudioEffect#getParameter(int, short[]) parameter #1:
-    
+    Missing nullability on parameter `value` in method `getParameter`
 MissingNullability: android.media.audiofx.AudioEffect#getParameter(int[], short[]) parameter #0:
-    
+    Missing nullability on parameter `param` in method `getParameter`
 MissingNullability: android.media.audiofx.AudioEffect#getParameter(int[], short[]) parameter #1:
-    
+    Missing nullability on parameter `value` in method `getParameter`
 MissingNullability: android.media.audiofx.AudioEffect#intToByteArray(int):
-    
+    Missing nullability on method `intToByteArray` return
 MissingNullability: android.media.audiofx.AudioEffect#isEffectTypeAvailable(java.util.UUID) parameter #0:
-    
+    Missing nullability on parameter `type` in method `isEffectTypeAvailable`
 MissingNullability: android.media.audiofx.AudioEffect#setParameter(byte[], byte[]) parameter #0:
-    
+    Missing nullability on parameter `param` in method `setParameter`
 MissingNullability: android.media.audiofx.AudioEffect#setParameter(byte[], byte[]) parameter #1:
-    
+    Missing nullability on parameter `value` in method `setParameter`
 MissingNullability: android.media.audiofx.AudioEffect#setParameter(int, byte[]) parameter #1:
-    
+    Missing nullability on parameter `value` in method `setParameter`
 MissingNullability: android.media.audiofx.AudioEffect#setParameter(int[], byte[]) parameter #0:
-    
+    Missing nullability on parameter `param` in method `setParameter`
 MissingNullability: android.media.audiofx.AudioEffect#setParameter(int[], byte[]) parameter #1:
-    
+    Missing nullability on parameter `value` in method `setParameter`
 MissingNullability: android.media.audiofx.AudioEffect#setParameter(int[], int[]) parameter #0:
-    
+    Missing nullability on parameter `param` in method `setParameter`
 MissingNullability: android.media.audiofx.AudioEffect#setParameter(int[], int[]) parameter #1:
-    
+    Missing nullability on parameter `value` in method `setParameter`
 MissingNullability: android.media.audiofx.AudioEffect#setParameterListener(android.media.audiofx.AudioEffect.OnParameterChangeListener) parameter #0:
-    
+    Missing nullability on parameter `listener` in method `setParameterListener`
 MissingNullability: android.media.audiofx.AudioEffect#shortToByteArray(short):
-    
+    Missing nullability on method `shortToByteArray` return
 MissingNullability: android.media.audiofx.AudioEffect.Descriptor#Descriptor(android.os.Parcel) parameter #0:
-    
+    Missing nullability on parameter `in` in method `Descriptor`
 MissingNullability: android.media.audiofx.AudioEffect.Descriptor#writeToParcel(android.os.Parcel) parameter #0:
-    
+    Missing nullability on parameter `dest` in method `writeToParcel`
 MissingNullability: android.media.audiofx.AudioEffect.OnParameterChangeListener#onParameterChange(android.media.audiofx.AudioEffect, int, byte[], byte[]) parameter #0:
-    
+    Missing nullability on parameter `effect` in method `onParameterChange`
 MissingNullability: android.media.audiofx.AudioEffect.OnParameterChangeListener#onParameterChange(android.media.audiofx.AudioEffect, int, byte[], byte[]) parameter #2:
-    
+    Missing nullability on parameter `param` in method `onParameterChange`
 MissingNullability: android.media.audiofx.AudioEffect.OnParameterChangeListener#onParameterChange(android.media.audiofx.AudioEffect, int, byte[], byte[]) parameter #3:
-    
-MissingNullability: android.media.audiopolicy.AudioMix.Builder#Builder(android.media.audiopolicy.AudioMixingRule) parameter #0:
-    
-MissingNullability: android.media.audiopolicy.AudioMix.Builder#build():
-    
-MissingNullability: android.media.audiopolicy.AudioMix.Builder#setDevice(android.media.AudioDeviceInfo):
-    
-MissingNullability: android.media.audiopolicy.AudioMix.Builder#setFormat(android.media.AudioFormat):
-    
-MissingNullability: android.media.audiopolicy.AudioMix.Builder#setFormat(android.media.AudioFormat) parameter #0:
-    
-MissingNullability: android.media.audiopolicy.AudioMix.Builder#setRouteFlags(int):
-    
-MissingNullability: android.media.audiopolicy.AudioMixingRule.Builder#addMixRule(int, Object):
-    
-MissingNullability: android.media.audiopolicy.AudioMixingRule.Builder#addMixRule(int, Object) parameter #1:
-    
-MissingNullability: android.media.audiopolicy.AudioMixingRule.Builder#addRule(android.media.AudioAttributes, int):
-    
-MissingNullability: android.media.audiopolicy.AudioMixingRule.Builder#addRule(android.media.AudioAttributes, int) parameter #0:
-    
-MissingNullability: android.media.audiopolicy.AudioMixingRule.Builder#build():
-    
-MissingNullability: android.media.audiopolicy.AudioMixingRule.Builder#excludeMixRule(int, Object):
-    
-MissingNullability: android.media.audiopolicy.AudioMixingRule.Builder#excludeMixRule(int, Object) parameter #1:
-    
-MissingNullability: android.media.audiopolicy.AudioMixingRule.Builder#excludeRule(android.media.AudioAttributes, int):
-    
-MissingNullability: android.media.audiopolicy.AudioMixingRule.Builder#excludeRule(android.media.AudioAttributes, int) parameter #0:
-    
-MissingNullability: android.media.audiopolicy.AudioPolicy#createAudioRecordSink(android.media.audiopolicy.AudioMix):
-    
-MissingNullability: android.media.audiopolicy.AudioPolicy#createAudioRecordSink(android.media.audiopolicy.AudioMix) parameter #0:
-    
-MissingNullability: android.media.audiopolicy.AudioPolicy#createAudioTrackSource(android.media.audiopolicy.AudioMix):
-    
-MissingNullability: android.media.audiopolicy.AudioPolicy#createAudioTrackSource(android.media.audiopolicy.AudioMix) parameter #0:
-    
-MissingNullability: android.media.audiopolicy.AudioPolicy#setRegistration(String) parameter #0:
-    
-MissingNullability: android.media.audiopolicy.AudioPolicy#toLogFriendlyString():
-    
-MissingNullability: android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener#onAudioFocusAbandon(android.media.AudioFocusInfo) parameter #0:
-    
-MissingNullability: android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener#onAudioFocusGrant(android.media.AudioFocusInfo, int) parameter #0:
-    
-MissingNullability: android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener#onAudioFocusLoss(android.media.AudioFocusInfo, boolean) parameter #0:
-    
-MissingNullability: android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener#onAudioFocusRequest(android.media.AudioFocusInfo, int) parameter #0:
-    
-MissingNullability: android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListener#onMixStateUpdate(android.media.audiopolicy.AudioMix) parameter #0:
-    
-MissingNullability: android.media.audiopolicy.AudioPolicy.Builder#Builder(android.content.Context) parameter #0:
-    
-MissingNullability: android.media.audiopolicy.AudioPolicy.Builder#setAudioPolicyFocusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener) parameter #0:
-    
-MissingNullability: android.media.audiopolicy.AudioPolicy.Builder#setAudioPolicyStatusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListener) parameter #0:
-    
-MissingNullability: android.metrics.LogMaker#LogMaker(Object[]) parameter #0:
-    
-MissingNullability: android.metrics.LogMaker#addTaggedData(int, Object):
-    
-MissingNullability: android.metrics.LogMaker#addTaggedData(int, Object) parameter #1:
-    
-MissingNullability: android.metrics.LogMaker#clearCategory():
-    
-MissingNullability: android.metrics.LogMaker#clearPackageName():
-    
-MissingNullability: android.metrics.LogMaker#clearSubtype():
-    
-MissingNullability: android.metrics.LogMaker#clearTaggedData(int):
-    
-MissingNullability: android.metrics.LogMaker#clearType():
-    
-MissingNullability: android.metrics.LogMaker#deserialize(Object[]) parameter #0:
-    
-MissingNullability: android.metrics.LogMaker#getCounterName():
-    
-MissingNullability: android.metrics.LogMaker#getPackageName():
-    
-MissingNullability: android.metrics.LogMaker#getTaggedData(int):
-    
-MissingNullability: android.metrics.LogMaker#isSubsetOf(android.metrics.LogMaker) parameter #0:
-    
-MissingNullability: android.metrics.LogMaker#isValidValue(Object) parameter #0:
-    
-MissingNullability: android.metrics.LogMaker#serialize():
-    
-MissingNullability: android.metrics.LogMaker#setCategory(int):
-    
-MissingNullability: android.metrics.LogMaker#setPackageName(String):
-    
-MissingNullability: android.metrics.LogMaker#setPackageName(String) parameter #0:
-    
-MissingNullability: android.metrics.LogMaker#setSubtype(int):
-    
-MissingNullability: android.metrics.LogMaker#setType(int):
-    
-MissingNullability: android.metrics.MetricsReader#next():
-    
-MissingNullability: android.net.NetworkCapabilities#getCapabilities():
-    
-MissingNullability: android.net.StaticIpConfiguration#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.net.TestNetworkInterface#CREATOR:
-    
-MissingNullability: android.net.TestNetworkInterface#TestNetworkInterface(android.os.ParcelFileDescriptor, String) parameter #0:
-    
-MissingNullability: android.net.TestNetworkInterface#TestNetworkInterface(android.os.ParcelFileDescriptor, String) parameter #1:
-    
-MissingNullability: android.net.TestNetworkInterface#getFileDescriptor():
-    
-MissingNullability: android.net.TestNetworkInterface#getInterfaceName():
-    
-MissingNullability: android.net.TestNetworkInterface#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.net.TestNetworkManager#createTapInterface():
-    
-MissingNullability: android.net.TestNetworkManager#createTunInterface(android.net.LinkAddress[]):
-    
-MissingNullability: android.net.apf.ApfCapabilities#CREATOR:
-    
-MissingNullability: android.net.apf.ApfCapabilities#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.net.metrics.DhcpClientEvent.Builder#setMsg(String) parameter #0:
-    
+    Missing nullability on parameter `value` in method `onParameterChange`
 MissingNullability: android.os.Build#is64BitAbi(String) parameter #0:
-    
+    Missing nullability on parameter `abi` in method `is64BitAbi`
 MissingNullability: android.os.Build.VERSION#ACTIVE_CODENAMES:
-    
+    Missing nullability on field `ACTIVE_CODENAMES` in class `class android.os.Build.VERSION`
 MissingNullability: android.os.Environment#buildPath(java.io.File, java.lang.String...):
-    
+    Missing nullability on method `buildPath` return
 MissingNullability: android.os.Environment#buildPath(java.io.File, java.lang.String...) parameter #0:
-    
+    Missing nullability on parameter `base` in method `buildPath`
 MissingNullability: android.os.Environment#buildPath(java.io.File, java.lang.String...) parameter #1:
-    
+    Missing nullability on parameter `segments` in method `buildPath`
 MissingNullability: android.os.FileUtils#contains(java.io.File, java.io.File) parameter #0:
-    
+    Missing nullability on parameter `dir` in method `contains`
 MissingNullability: android.os.FileUtils#contains(java.io.File, java.io.File) parameter #1:
-    
-MissingNullability: android.os.HwBinder#getService(String, String):
-    
-MissingNullability: android.os.HwBinder#getService(String, String) parameter #0:
-    
-MissingNullability: android.os.HwBinder#getService(String, String) parameter #1:
-    
-MissingNullability: android.os.HwBinder#getService(String, String, boolean):
-    
-MissingNullability: android.os.HwBinder#getService(String, String, boolean) parameter #0:
-    
-MissingNullability: android.os.HwBinder#getService(String, String, boolean) parameter #1:
-    
-MissingNullability: android.os.HwBinder#onTransact(int, android.os.HwParcel, android.os.HwParcel, int) parameter #1:
-    
-MissingNullability: android.os.HwBinder#onTransact(int, android.os.HwParcel, android.os.HwParcel, int) parameter #2:
-    
-MissingNullability: android.os.HwBinder#registerService(String) parameter #0:
-    
-MissingNullability: android.os.HwBinder#transact(int, android.os.HwParcel, android.os.HwParcel, int) parameter #1:
-    
-MissingNullability: android.os.HwBinder#transact(int, android.os.HwParcel, android.os.HwParcel, int) parameter #2:
-    
-MissingNullability: android.os.HwBlob#copyToBoolArray(long, boolean[], int) parameter #1:
-    
-MissingNullability: android.os.HwBlob#copyToDoubleArray(long, double[], int) parameter #1:
-    
-MissingNullability: android.os.HwBlob#copyToFloatArray(long, float[], int) parameter #1:
-    
-MissingNullability: android.os.HwBlob#copyToInt16Array(long, short[], int) parameter #1:
-    
-MissingNullability: android.os.HwBlob#copyToInt32Array(long, int[], int) parameter #1:
-    
-MissingNullability: android.os.HwBlob#copyToInt64Array(long, long[], int) parameter #1:
-    
-MissingNullability: android.os.HwBlob#copyToInt8Array(long, byte[], int) parameter #1:
-    
-MissingNullability: android.os.HwBlob#getString(long):
-    
-MissingNullability: android.os.HwBlob#putBlob(long, android.os.HwBlob) parameter #1:
-    
-MissingNullability: android.os.HwBlob#putBoolArray(long, boolean[]) parameter #1:
-    
-MissingNullability: android.os.HwBlob#putDoubleArray(long, double[]) parameter #1:
-    
-MissingNullability: android.os.HwBlob#putFloatArray(long, float[]) parameter #1:
-    
-MissingNullability: android.os.HwBlob#putInt16Array(long, short[]) parameter #1:
-    
-MissingNullability: android.os.HwBlob#putInt32Array(long, int[]) parameter #1:
-    
-MissingNullability: android.os.HwBlob#putInt64Array(long, long[]) parameter #1:
-    
-MissingNullability: android.os.HwBlob#putInt8Array(long, byte[]) parameter #1:
-    
-MissingNullability: android.os.HwBlob#putString(long, String) parameter #1:
-    
-MissingNullability: android.os.HwBlob#wrapArray(boolean[]):
-    
-MissingNullability: android.os.HwBlob#wrapArray(byte[]):
-    
-MissingNullability: android.os.HwBlob#wrapArray(double[]):
-    
-MissingNullability: android.os.HwBlob#wrapArray(float[]):
-    
-MissingNullability: android.os.HwBlob#wrapArray(int[]):
-    
-MissingNullability: android.os.HwBlob#wrapArray(long[]):
-    
-MissingNullability: android.os.HwBlob#wrapArray(short[]):
-    
-MissingNullability: android.os.HwParcel#enforceInterface(String) parameter #0:
-    
-MissingNullability: android.os.HwParcel#readBoolVector():
-    
-MissingNullability: android.os.HwParcel#readBuffer(long):
-    
-MissingNullability: android.os.HwParcel#readDoubleVector():
-    
-MissingNullability: android.os.HwParcel#readEmbeddedBuffer(long, long, long, boolean):
-    
-MissingNullability: android.os.HwParcel#readFloatVector():
-    
-MissingNullability: android.os.HwParcel#readInt16Vector():
-    
-MissingNullability: android.os.HwParcel#readInt32Vector():
-    
-MissingNullability: android.os.HwParcel#readInt64Vector():
-    
-MissingNullability: android.os.HwParcel#readInt8Vector():
-    
-MissingNullability: android.os.HwParcel#readString():
-    
-MissingNullability: android.os.HwParcel#readStringVector():
-    
-MissingNullability: android.os.HwParcel#readStrongBinder():
-    
-MissingNullability: android.os.HwParcel#writeBoolVector(java.util.ArrayList<java.lang.Boolean>) parameter #0:
-    
-MissingNullability: android.os.HwParcel#writeBuffer(android.os.HwBlob) parameter #0:
-    
-MissingNullability: android.os.HwParcel#writeDoubleVector(java.util.ArrayList<java.lang.Double>) parameter #0:
-    
-MissingNullability: android.os.HwParcel#writeFloatVector(java.util.ArrayList<java.lang.Float>) parameter #0:
-    
-MissingNullability: android.os.HwParcel#writeInt16Vector(java.util.ArrayList<java.lang.Short>) parameter #0:
-    
-MissingNullability: android.os.HwParcel#writeInt32Vector(java.util.ArrayList<java.lang.Integer>) parameter #0:
-    
-MissingNullability: android.os.HwParcel#writeInt64Vector(java.util.ArrayList<java.lang.Long>) parameter #0:
-    
-MissingNullability: android.os.HwParcel#writeInt8Vector(java.util.ArrayList<java.lang.Byte>) parameter #0:
-    
-MissingNullability: android.os.HwParcel#writeInterfaceToken(String) parameter #0:
-    
-MissingNullability: android.os.HwParcel#writeString(String) parameter #0:
-    
-MissingNullability: android.os.HwParcel#writeStringVector(java.util.ArrayList<java.lang.String>) parameter #0:
-    
-MissingNullability: android.os.HwParcel#writeStrongBinder(android.os.IHwBinder) parameter #0:
-    
-MissingNullability: android.os.IHwBinder#linkToDeath(android.os.IHwBinder.DeathRecipient, long) parameter #0:
-    
-MissingNullability: android.os.IHwBinder#queryLocalInterface(String):
-    
-MissingNullability: android.os.IHwBinder#queryLocalInterface(String) parameter #0:
-    
-MissingNullability: android.os.IHwBinder#transact(int, android.os.HwParcel, android.os.HwParcel, int) parameter #1:
-    
-MissingNullability: android.os.IHwBinder#transact(int, android.os.HwParcel, android.os.HwParcel, int) parameter #2:
-    
-MissingNullability: android.os.IHwBinder#unlinkToDeath(android.os.IHwBinder.DeathRecipient) parameter #0:
-    
-MissingNullability: android.os.IHwInterface#asBinder():
-    
-MissingNullability: android.os.IncidentManager#approveReport(android.net.Uri) parameter #0:
-    
-MissingNullability: android.os.IncidentManager#cancelAuthorization(android.os.IncidentManager.AuthListener) parameter #0:
-    
-MissingNullability: android.os.IncidentManager#deleteIncidentReports(android.net.Uri) parameter #0:
-    
-MissingNullability: android.os.IncidentManager#denyReport(android.net.Uri) parameter #0:
-    
-MissingNullability: android.os.IncidentManager#getIncidentReport(android.net.Uri) parameter #0:
-    
-MissingNullability: android.os.IncidentManager#getIncidentReportList(String) parameter #0:
-    
-MissingNullability: android.os.IncidentManager#getPendingReports():
-    
-MissingNullability: android.os.IncidentManager#reportIncident(android.os.IncidentReportArgs) parameter #0:
-    
-MissingNullability: android.os.IncidentManager#requestAuthorization(int, String, int, android.os.IncidentManager.AuthListener) parameter #1:
-    
-MissingNullability: android.os.IncidentManager#requestAuthorization(int, String, int, android.os.IncidentManager.AuthListener) parameter #3:
-    
-MissingNullability: android.os.IncidentManager.IncidentReport#IncidentReport(android.os.Parcel) parameter #0:
-    
-MissingNullability: android.os.IncidentManager.IncidentReport#getInputStream():
-    
-MissingNullability: android.os.IncidentManager.IncidentReport#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.os.IncidentReportArgs#IncidentReportArgs(android.os.Parcel) parameter #0:
-    
-MissingNullability: android.os.IncidentReportArgs#addHeader(byte[]) parameter #0:
-    
-MissingNullability: android.os.IncidentReportArgs#readFromParcel(android.os.Parcel) parameter #0:
-    
-MissingNullability: android.os.IncidentReportArgs#writeToParcel(android.os.Parcel, int) parameter #0:
-    
+    Missing nullability on parameter `file` in method `contains`
 MissingNullability: android.os.ParcelFileDescriptor#getFile(java.io.FileDescriptor):
-    
+    Missing nullability on method `getFile` return
 MissingNullability: android.os.ParcelFileDescriptor#getFile(java.io.FileDescriptor) parameter #0:
-    
-MissingNullability: android.os.RemoteCallback#RemoteCallback(android.os.RemoteCallback.OnResultListener) parameter #0:
-    
-MissingNullability: android.os.RemoteCallback#writeToParcel(android.os.Parcel, int) parameter #0:
-    
+    Missing nullability on parameter `fd` in method `getFile`
 MissingNullability: android.os.StrictMode#setViolationLogger(android.os.StrictMode.ViolationLogger) parameter #0:
-    
+    Missing nullability on parameter `listener` in method `setViolationLogger`
 MissingNullability: android.os.StrictMode.ViolationInfo#ViolationInfo(android.os.Parcel) parameter #0:
-    
+    Missing nullability on parameter `in` in method `ViolationInfo`
 MissingNullability: android.os.StrictMode.ViolationInfo#ViolationInfo(android.os.Parcel, boolean) parameter #0:
-    
+    Missing nullability on parameter `in` in method `ViolationInfo`
 MissingNullability: android.os.StrictMode.ViolationInfo#broadcastIntentAction:
-    
+    Missing nullability on field `broadcastIntentAction` in class `class android.os.StrictMode.ViolationInfo`
 MissingNullability: android.os.StrictMode.ViolationInfo#dump(android.util.Printer, String) parameter #0:
-    
+    Missing nullability on parameter `pw` in method `dump`
 MissingNullability: android.os.StrictMode.ViolationInfo#dump(android.util.Printer, String) parameter #1:
-    
+    Missing nullability on parameter `prefix` in method `dump`
 MissingNullability: android.os.StrictMode.ViolationInfo#getStackTrace():
-    
+    Missing nullability on method `getStackTrace` return
 MissingNullability: android.os.StrictMode.ViolationInfo#getViolationClass():
-    
+    Missing nullability on method `getViolationClass` return
 MissingNullability: android.os.StrictMode.ViolationInfo#getViolationDetails():
-    
+    Missing nullability on method `getViolationDetails` return
 MissingNullability: android.os.StrictMode.ViolationInfo#tags:
-    
+    Missing nullability on field `tags` in class `class android.os.StrictMode.ViolationInfo`
 MissingNullability: android.os.StrictMode.ViolationInfo#writeToParcel(android.os.Parcel, int) parameter #0:
-    
+    Missing nullability on parameter `dest` in method `writeToParcel`
 MissingNullability: android.os.StrictMode.ViolationLogger#log(android.os.StrictMode.ViolationInfo) parameter #0:
-    
-MissingNullability: android.os.UserHandle#of(int):
-    
+    Missing nullability on parameter `info` in method `log`
 MissingNullability: android.os.VibrationEffect#RINGTONES:
-    
+    Missing nullability on field `RINGTONES` in class `class android.os.VibrationEffect`
 MissingNullability: android.os.VibrationEffect#get(android.net.Uri, android.content.Context) parameter #0:
-    
+    Missing nullability on parameter `uri` in method `get`
 MissingNullability: android.os.VibrationEffect#get(android.net.Uri, android.content.Context) parameter #1:
-    
+    Missing nullability on parameter `context` in method `get`
 MissingNullability: android.os.VibrationEffect#get(int):
-    
+    Missing nullability on method `get` return
 MissingNullability: android.os.VibrationEffect#get(int, boolean):
-    
+    Missing nullability on method `get` return
 MissingNullability: android.os.VintfObject#getHalNamesAndVersions():
-    
+    Missing nullability on method `getHalNamesAndVersions` return
 MissingNullability: android.os.VintfObject#getSepolicyVersion():
-    
+    Missing nullability on method `getSepolicyVersion` return
 MissingNullability: android.os.VintfObject#getTargetFrameworkCompatibilityMatrixVersion():
-    
+    Missing nullability on method `getTargetFrameworkCompatibilityMatrixVersion` return
 MissingNullability: android.os.VintfObject#getVndkSnapshots():
-    
+    Missing nullability on method `getVndkSnapshots` return
 MissingNullability: android.os.VintfObject#report():
-    
+    Missing nullability on method `report` return
 MissingNullability: android.os.VintfRuntimeInfo#getCpuInfo():
-    
+    Missing nullability on method `getCpuInfo` return
 MissingNullability: android.os.VintfRuntimeInfo#getHardwareId():
-    
+    Missing nullability on method `getHardwareId` return
 MissingNullability: android.os.VintfRuntimeInfo#getKernelVersion():
-    
+    Missing nullability on method `getKernelVersion` return
 MissingNullability: android.os.VintfRuntimeInfo#getNodeName():
-    
+    Missing nullability on method `getNodeName` return
 MissingNullability: android.os.VintfRuntimeInfo#getOsName():
-    
+    Missing nullability on method `getOsName` return
 MissingNullability: android.os.VintfRuntimeInfo#getOsRelease():
-    
+    Missing nullability on method `getOsRelease` return
 MissingNullability: android.os.VintfRuntimeInfo#getOsVersion():
-    
+    Missing nullability on method `getOsVersion` return
 MissingNullability: android.os.WorkSource#add(int, String) parameter #1:
-    
-MissingNullability: android.os.WorkSource#addReturningNewbs(android.os.WorkSource) parameter #0:
-    
-MissingNullability: android.os.WorkSource#getName(int):
-    
-MissingNullability: android.os.WorkSource#setReturningDiffs(android.os.WorkSource) parameter #0:
-    
+    Missing nullability on parameter `name` in method `add`
 MissingNullability: android.os.health.HealthKeys.Constants#Constants(Class) parameter #0:
-    
+    Missing nullability on parameter `clazz` in method `Constants`
 MissingNullability: android.os.health.HealthKeys.Constants#getDataType():
-    
+    Missing nullability on method `getDataType` return
 MissingNullability: android.os.health.HealthKeys.Constants#getKeys(int):
-    
+    Missing nullability on method `getKeys` return
 MissingNullability: android.os.health.HealthStats#HealthStats(android.os.Parcel) parameter #0:
-    
+    Missing nullability on parameter `in` in method `HealthStats`
 MissingNullability: android.os.health.HealthStatsParceler#HealthStatsParceler(android.os.Parcel) parameter #0:
-    
+    Missing nullability on parameter `in` in method `HealthStatsParceler`
 MissingNullability: android.os.health.HealthStatsParceler#HealthStatsParceler(android.os.health.HealthStatsWriter) parameter #0:
-    
+    Missing nullability on parameter `writer` in method `HealthStatsParceler`
 MissingNullability: android.os.health.HealthStatsParceler#getHealthStats():
-    
+    Missing nullability on method `getHealthStats` return
 MissingNullability: android.os.health.HealthStatsParceler#writeToParcel(android.os.Parcel, int) parameter #0:
-    
+    Missing nullability on parameter `out` in method `writeToParcel`
 MissingNullability: android.os.health.HealthStatsWriter#HealthStatsWriter(android.os.health.HealthKeys.Constants) parameter #0:
-    
+    Missing nullability on parameter `constants` in method `HealthStatsWriter`
 MissingNullability: android.os.health.HealthStatsWriter#addMeasurements(int, String, long) parameter #1:
-    
+    Missing nullability on parameter `name` in method `addMeasurements`
 MissingNullability: android.os.health.HealthStatsWriter#addStats(int, String, android.os.health.HealthStatsWriter) parameter #1:
-    
+    Missing nullability on parameter `name` in method `addStats`
 MissingNullability: android.os.health.HealthStatsWriter#addStats(int, String, android.os.health.HealthStatsWriter) parameter #2:
-    
+    Missing nullability on parameter `value` in method `addStats`
 MissingNullability: android.os.health.HealthStatsWriter#addTimers(int, String, android.os.health.TimerStat) parameter #1:
-    
+    Missing nullability on parameter `name` in method `addTimers`
 MissingNullability: android.os.health.HealthStatsWriter#addTimers(int, String, android.os.health.TimerStat) parameter #2:
-    
+    Missing nullability on parameter `value` in method `addTimers`
 MissingNullability: android.os.health.HealthStatsWriter#flattenToParcel(android.os.Parcel) parameter #0:
-    
+    Missing nullability on parameter `out` in method `flattenToParcel`
 MissingNullability: android.os.storage.StorageVolume#getPath():
-    
-MissingNullability: android.permission.RuntimePermissionPresentationInfo#writeToParcel(android.os.Parcel, int) parameter #0:
-    
+    Missing nullability on method `getPath` return
 MissingNullability: android.provider.CalendarContract.Calendars#SYNC_WRITABLE_COLUMNS:
-    
+    Missing nullability on field `SYNC_WRITABLE_COLUMNS` in class `class android.provider.CalendarContract.Calendars`
 MissingNullability: android.provider.CalendarContract.Events#SYNC_WRITABLE_COLUMNS:
-    
-MissingNullability: android.provider.ContactsContract.CommonDataKinds.Phone#ENTERPRISE_CONTENT_URI:
-    
+    Missing nullability on field `SYNC_WRITABLE_COLUMNS` in class `class android.provider.CalendarContract.Events`
 MissingNullability: android.provider.ContactsContract.RawContactsEntity#CORP_CONTENT_URI:
-    
-MissingNullability: android.provider.DeviceConfig#getProperty(String, String):
-    
-MissingNullability: android.provider.DeviceConfig#getString(String, String, String):
-    
-MissingNullability: android.provider.MediaStore#deleteContributedMedia(android.content.Context, String, android.os.UserHandle) parameter #0:
-    
-MissingNullability: android.provider.MediaStore#deleteContributedMedia(android.content.Context, String, android.os.UserHandle) parameter #1:
-    
-MissingNullability: android.provider.MediaStore#deleteContributedMedia(android.content.Context, String, android.os.UserHandle) parameter #2:
-    
-MissingNullability: android.provider.MediaStore#getContributedMediaSize(android.content.Context, String, android.os.UserHandle) parameter #0:
-    
-MissingNullability: android.provider.MediaStore#getContributedMediaSize(android.content.Context, String, android.os.UserHandle) parameter #1:
-    
-MissingNullability: android.provider.MediaStore#getContributedMediaSize(android.content.Context, String, android.os.UserHandle) parameter #2:
-    
-MissingNullability: android.provider.MediaStore#scanFile(android.content.Context, java.io.File):
-    
-MissingNullability: android.provider.MediaStore#scanFile(android.content.Context, java.io.File) parameter #0:
-    
-MissingNullability: android.provider.MediaStore#scanFile(android.content.Context, java.io.File) parameter #1:
-    
-MissingNullability: android.provider.MediaStore#scanFileFromShell(android.content.Context, java.io.File):
-    
-MissingNullability: android.provider.MediaStore#scanFileFromShell(android.content.Context, java.io.File) parameter #0:
-    
-MissingNullability: android.provider.MediaStore#scanFileFromShell(android.content.Context, java.io.File) parameter #1:
-    
-MissingNullability: android.provider.MediaStore#scanVolume(android.content.Context, java.io.File) parameter #0:
-    
-MissingNullability: android.provider.MediaStore#scanVolume(android.content.Context, java.io.File) parameter #1:
-    
-MissingNullability: android.provider.MediaStore#waitForIdle(android.content.Context) parameter #0:
-    
-MissingNullability: android.security.KeyStoreException#KeyStoreException(int, String) parameter #1:
-    
-MissingNullability: android.security.keystore.AttestationUtils#attestDeviceIds(android.content.Context, int[], byte[]) parameter #0:
-    
+    Missing nullability on field `CORP_CONTENT_URI` in class `class android.provider.ContactsContract.RawContactsEntity`
 MissingNullability: android.security.keystore.KeyProtection.Builder#setBoundToSpecificSecureUserId(long):
-    
-MissingNullability: android.service.autofill.AutofillFieldClassificationService#onBind(android.content.Intent):
-    
-MissingNullability: android.service.autofill.AutofillFieldClassificationService#onBind(android.content.Intent) parameter #0:
-    
+    Missing nullability on method `setBoundToSpecificSecureUserId` return
 MissingNullability: android.service.autofill.CompositeUserData#getCategoryIds():
-    
+    Missing nullability on method `getCategoryIds` return
 MissingNullability: android.service.autofill.CompositeUserData#getDefaultFieldClassificationArgs():
-    
+    Missing nullability on method `getDefaultFieldClassificationArgs` return
 MissingNullability: android.service.autofill.CompositeUserData#getFieldClassificationAlgorithms():
-    
+    Missing nullability on method `getFieldClassificationAlgorithms` return
 MissingNullability: android.service.autofill.CompositeUserData#getFieldClassificationArgs():
-    
+    Missing nullability on method `getFieldClassificationArgs` return
 MissingNullability: android.service.autofill.CompositeUserData#getValues():
-    
+    Missing nullability on method `getValues` return
 MissingNullability: android.service.autofill.CompositeUserData#writeToParcel(android.os.Parcel, int) parameter #0:
-    
+    Missing nullability on parameter `parcel` in method `writeToParcel`
 MissingNullability: android.service.autofill.UserData#getFieldClassificationAlgorithms():
-    
-MissingNullability: android.service.autofill.augmented.AugmentedAutofillService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #0:
-    
-MissingNullability: android.service.autofill.augmented.AugmentedAutofillService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #1:
-    
-MissingNullability: android.service.autofill.augmented.AugmentedAutofillService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #2:
-    
-MissingNullability: android.service.autofill.augmented.AugmentedAutofillService#onUnbind(android.content.Intent) parameter #0:
-    
-MissingNullability: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #0:
-    
-MissingNullability: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #1:
-    
-MissingNullability: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #2:
-    
-MissingNullability: android.service.notification.Adjustment#Adjustment(String, String, android.os.Bundle, CharSequence, int) parameter #0:
-    
-MissingNullability: android.service.notification.Adjustment#Adjustment(String, String, android.os.Bundle, CharSequence, int) parameter #1:
-    
-MissingNullability: android.service.notification.Adjustment#Adjustment(String, String, android.os.Bundle, CharSequence, int) parameter #2:
-    
-MissingNullability: android.service.notification.Adjustment#Adjustment(String, String, android.os.Bundle, CharSequence, int) parameter #3:
-    
-MissingNullability: android.service.notification.Adjustment#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.service.notification.NotificationAssistantService#attachBaseContext(android.content.Context) parameter #0:
-    
-MissingNullability: android.service.notification.NotificationStats#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.service.notification.SnoozeCriterion#SnoozeCriterion(String, CharSequence, CharSequence) parameter #0:
-    
-MissingNullability: android.service.notification.SnoozeCriterion#SnoozeCriterion(String, CharSequence, CharSequence) parameter #1:
-    
-MissingNullability: android.service.notification.SnoozeCriterion#SnoozeCriterion(String, CharSequence, CharSequence) parameter #2:
-    
-MissingNullability: android.service.notification.SnoozeCriterion#SnoozeCriterion(android.os.Parcel) parameter #0:
-    
-MissingNullability: android.service.notification.SnoozeCriterion#getConfirmation():
-    
-MissingNullability: android.service.notification.SnoozeCriterion#getExplanation():
-    
-MissingNullability: android.service.notification.SnoozeCriterion#getId():
-    
-MissingNullability: android.service.notification.SnoozeCriterion#writeToParcel(android.os.Parcel, int) parameter #0:
-    
+    Missing nullability on method `getFieldClassificationAlgorithms` return
 MissingNullability: android.telecom.Call.Details#getTelecomCallId():
-    
-MissingNullability: android.telecom.CallScreeningService.CallResponse.Builder#setShouldScreenCallFurther(boolean):
-    
-MissingNullability: android.telecom.Conference#getPrimaryConnection():
-    
-MissingNullability: android.telecom.PhoneAccountSuggestionService#onBind(android.content.Intent):
-    
-MissingNullability: android.telecom.PhoneAccountSuggestionService#onBind(android.content.Intent) parameter #0:
-    
-MissingNullability: android.telephony.CallQuality#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.telephony.DataSpecificRegistrationInfo#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.telephony.LteVopsSupportInfo#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.telephony.NetworkRegistrationInfo#writeToParcel(android.os.Parcel, int) parameter #0:
-    
+    Missing nullability on method `getTelecomCallId` return
 MissingNullability: android.telephony.ServiceState#addNetworkRegistrationInfo(android.telephony.NetworkRegistrationInfo) parameter #0:
-    
+    Missing nullability on parameter `nri` in method `addNetworkRegistrationInfo`
 MissingNullability: android.telephony.ServiceState#setCellBandwidths(int[]) parameter #0:
-    
+    Missing nullability on parameter `bandwidths` in method `setCellBandwidths`
 MissingNullability: android.telephony.SmsManager#checkSmsShortCodeDestination(String, String) parameter #0:
-    
+    Missing nullability on parameter `destAddress` in method `checkSmsShortCodeDestination`
 MissingNullability: android.telephony.SmsManager#checkSmsShortCodeDestination(String, String) parameter #1:
-    
-MissingNullability: android.telephony.TelephonyManager#checkCarrierPrivilegesForPackage(String) parameter #0:
-    
-MissingNullability: android.telephony.TelephonyManager#getCarrierPackageNamesForIntent(android.content.Intent):
-    
-MissingNullability: android.telephony.TelephonyManager#getCarrierPackageNamesForIntent(android.content.Intent) parameter #0:
-    
+    Missing nullability on parameter `countryIso` in method `checkSmsShortCodeDestination`
 MissingNullability: android.telephony.TelephonyManager#getLine1AlphaTag():
-    
+    Missing nullability on method `getLine1AlphaTag` return
 MissingNullability: android.telephony.TelephonyManager#getRadioHalVersion():
-    
-MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String) parameter #0:
-    
-MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String) parameter #1:
-    
-MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String) parameter #2:
-    
-MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String) parameter #3:
-    
-MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String) parameter #4:
-    
-MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String) parameter #5:
-    
-MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String) parameter #6:
-    
+    Missing nullability on method `getRadioHalVersion` return
 MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #0:
-    
+    Missing nullability on parameter `mccmnc` in method `setCarrierTestOverride`
 MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #1:
-    
+    Missing nullability on parameter `imsi` in method `setCarrierTestOverride`
 MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #2:
-    
+    Missing nullability on parameter `iccid` in method `setCarrierTestOverride`
 MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #3:
-    
+    Missing nullability on parameter `gid1` in method `setCarrierTestOverride`
 MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #4:
-    
+    Missing nullability on parameter `gid2` in method `setCarrierTestOverride`
 MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #5:
-    
+    Missing nullability on parameter `plmn` in method `setCarrierTestOverride`
 MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #6:
-    
+    Missing nullability on parameter `spn` in method `setCarrierTestOverride`
 MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #7:
-    
+    Missing nullability on parameter `carrierPriviledgeRules` in method `setCarrierTestOverride`
 MissingNullability: android.telephony.TelephonyManager#setCarrierTestOverride(String, String, String, String, String, String, String, String, String) parameter #8:
-    
-MissingNullability: android.telephony.ims.ImsCallForwardInfo#getNumber():
-    
-MissingNullability: android.telephony.ims.ImsCallForwardInfo#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallProfile#ImsCallProfile(int, int, android.os.Bundle, android.telephony.ims.ImsStreamMediaProfile) parameter #2:
-    
-MissingNullability: android.telephony.ims.ImsCallProfile#ImsCallProfile(int, int, android.os.Bundle, android.telephony.ims.ImsStreamMediaProfile) parameter #3:
-    
-MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtra(String):
-    
-MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtra(String) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtra(String, String):
-    
-MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtra(String, String) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtra(String, String) parameter #1:
-    
-MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtraBoolean(String) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtraBoolean(String, boolean) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtraInt(String) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtraInt(String, int) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallProfile#getCallExtras():
-    
-MissingNullability: android.telephony.ims.ImsCallProfile#getMediaProfile():
-    
-MissingNullability: android.telephony.ims.ImsCallProfile#getVideoStateFromImsCallProfile(android.telephony.ims.ImsCallProfile) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallProfile#setCallExtra(String, String) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallProfile#setCallExtra(String, String) parameter #1:
-    
-MissingNullability: android.telephony.ims.ImsCallProfile#setCallExtraBoolean(String, boolean) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallProfile#setCallExtraInt(String, int) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallProfile#updateCallExtras(android.telephony.ims.ImsCallProfile) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallProfile#updateCallType(android.telephony.ims.ImsCallProfile) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallProfile#updateMediaProfile(android.telephony.ims.ImsCallProfile) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallProfile#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceExtendFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceExtendReceived(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceExtendReceived(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #1:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceExtended(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceExtended(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #1:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionConferenceStateUpdated(android.telephony.ims.ImsConferenceState) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionHandover(int, int, android.telephony.ims.ImsReasonInfo) parameter #2:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionHandoverFailed(int, int, android.telephony.ims.ImsReasonInfo) parameter #2:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionHeld(android.telephony.ims.ImsCallProfile) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionHoldFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionHoldReceived(android.telephony.ims.ImsCallProfile) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionInitiated(android.telephony.ims.ImsCallProfile) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionInitiatedFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionInviteParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionMergeComplete(android.telephony.ims.stub.ImsCallSessionImplBase) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionMergeFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionMergeStarted(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionMergeStarted(android.telephony.ims.stub.ImsCallSessionImplBase, android.telephony.ims.ImsCallProfile) parameter #1:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionProgressing(android.telephony.ims.ImsStreamMediaProfile) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionRemoveParticipantsRequestFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionResumeFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionResumeReceived(android.telephony.ims.ImsCallProfile) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionResumed(android.telephony.ims.ImsCallProfile) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionRttMessageReceived(String) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionRttModifyRequestReceived(android.telephony.ims.ImsCallProfile) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionSuppServiceReceived(android.telephony.ims.ImsSuppServiceNotification) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionTerminated(android.telephony.ims.ImsReasonInfo) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionUpdateFailed(android.telephony.ims.ImsReasonInfo) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionUpdateReceived(android.telephony.ims.ImsCallProfile) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionUpdated(android.telephony.ims.ImsCallProfile) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsCallSessionListener#callSessionUssdMessageReceived(int, String) parameter #1:
-    
-MissingNullability: android.telephony.ims.ImsConferenceState#getConnectionStateForStatus(String) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsConferenceState#mParticipants:
-    
-MissingNullability: android.telephony.ims.ImsConferenceState#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsExternalCallState#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsReasonInfo#ImsReasonInfo(int, int, String) parameter #2:
-    
-MissingNullability: android.telephony.ims.ImsReasonInfo#getExtraMessage():
-    
-MissingNullability: android.telephony.ims.ImsReasonInfo#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsService#createMmTelFeature(int):
-    
-MissingNullability: android.telephony.ims.ImsService#createRcsFeature(int):
-    
-MissingNullability: android.telephony.ims.ImsService#getConfig(int):
-    
-MissingNullability: android.telephony.ims.ImsService#getRegistration(int):
-    
-MissingNullability: android.telephony.ims.ImsService#onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsService#querySupportedImsFeatures():
-    
-MissingNullability: android.telephony.ims.ImsSsData#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsSsInfo#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsStreamMediaProfile#copyFrom(android.telephony.ims.ImsStreamMediaProfile) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsStreamMediaProfile#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsSuppServiceNotification#ImsSuppServiceNotification(int, int, int, int, String, String[]) parameter #4:
-    
-MissingNullability: android.telephony.ims.ImsSuppServiceNotification#ImsSuppServiceNotification(int, int, int, int, String, String[]) parameter #5:
-    
-MissingNullability: android.telephony.ims.ImsSuppServiceNotification#history:
-    
-MissingNullability: android.telephony.ims.ImsSuppServiceNotification#number:
-    
-MissingNullability: android.telephony.ims.ImsSuppServiceNotification#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsUtListener#onSupplementaryServiceIndication(android.telephony.ims.ImsSsData) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationCallBarringQueried(int, android.telephony.ims.ImsSsInfo[]) parameter #1:
-    
-MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationCallForwardQueried(int, android.telephony.ims.ImsCallForwardInfo[]) parameter #1:
-    
-MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationCallWaitingQueried(int, android.telephony.ims.ImsSsInfo[]) parameter #1:
-    
-MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationQueried(int, android.os.Bundle) parameter #1:
-    
-MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationQueryFailed(int, android.telephony.ims.ImsReasonInfo) parameter #1:
-    
-MissingNullability: android.telephony.ims.ImsUtListener#onUtConfigurationUpdateFailed(int, android.telephony.ims.ImsReasonInfo) parameter #1:
-    
-MissingNullability: android.telephony.ims.ImsVideoCallProvider#changeCameraCapabilities(android.telecom.VideoProfile.CameraCapabilities) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSendSessionModifyRequest(android.telecom.VideoProfile, android.telecom.VideoProfile) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSendSessionModifyRequest(android.telecom.VideoProfile, android.telecom.VideoProfile) parameter #1:
-    
-MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSendSessionModifyResponse(android.telecom.VideoProfile) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSetCamera(String) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSetCamera(String, int) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSetDisplaySurface(android.view.Surface) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSetPauseImage(android.net.Uri) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsVideoCallProvider#onSetPreviewSurface(android.view.Surface) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsVideoCallProvider#receiveSessionModifyRequest(android.telecom.VideoProfile) parameter #0:
-    
-MissingNullability: android.telephony.ims.ImsVideoCallProvider#receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile) parameter #1:
-    
-MissingNullability: android.telephony.ims.ImsVideoCallProvider#receiveSessionModifyResponse(int, android.telecom.VideoProfile, android.telecom.VideoProfile) parameter #2:
-    
-MissingNullability: android.telephony.ims.feature.CapabilityChangeRequest#getCapabilitiesToDisable():
-    
-MissingNullability: android.telephony.ims.feature.CapabilityChangeRequest#getCapabilitiesToEnable():
-    
-MissingNullability: android.telephony.ims.feature.CapabilityChangeRequest#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.telephony.ims.feature.ImsFeature#changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy) parameter #0:
-    
-MissingNullability: android.telephony.ims.feature.ImsFeature#changeEnabledCapabilities(android.telephony.ims.feature.CapabilityChangeRequest, android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy) parameter #1:
-    
-MissingNullability: android.telephony.ims.feature.MmTelFeature#queryCapabilityStatus():
-    
-MissingNullability: android.telephony.ims.feature.MmTelFeature.MmTelCapabilities#MmTelCapabilities(android.telephony.ims.feature.ImsFeature.Capabilities) parameter #0:
-    
-MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#accept(int, android.telephony.ims.ImsStreamMediaProfile) parameter #1:
-    
-MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#deflect(String) parameter #0:
-    
-MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#extendToConference(String[]) parameter #0:
-    
-MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getCallId():
-    
-MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getCallProfile():
-    
-MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getImsVideoCallProvider():
-    
-MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getLocalCallProfile():
-    
-MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getProperty(String):
-    
-MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getProperty(String) parameter #0:
-    
-MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#getRemoteCallProfile():
-    
-MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#hold(android.telephony.ims.ImsStreamMediaProfile) parameter #0:
-    
-MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#inviteParticipants(String[]) parameter #0:
-    
-MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#removeParticipants(String[]) parameter #0:
-    
-MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#resume(android.telephony.ims.ImsStreamMediaProfile) parameter #0:
-    
-MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#sendDtmf(char, android.os.Message) parameter #1:
-    
-MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#sendRttMessage(String) parameter #0:
-    
-MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#sendRttModifyRequest(android.telephony.ims.ImsCallProfile) parameter #0:
-    
-MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#sendUssd(String) parameter #0:
-    
-MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#setListener(android.telephony.ims.ImsCallSessionListener) parameter #0:
-    
-MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#start(String, android.telephony.ims.ImsCallProfile) parameter #0:
-    
-MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#start(String, android.telephony.ims.ImsCallProfile) parameter #1:
-    
-MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#startConference(String[], android.telephony.ims.ImsCallProfile) parameter #0:
-    
-MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#startConference(String[], android.telephony.ims.ImsCallProfile) parameter #1:
-    
-MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase#update(int, android.telephony.ims.ImsStreamMediaProfile) parameter #1:
-    
-MissingNullability: android.telephony.ims.stub.ImsCallSessionImplBase.State#toString(int):
-    
-MissingNullability: android.telephony.ims.stub.ImsConfigImplBase#getConfigString(int):
-    
-MissingNullability: android.telephony.ims.stub.ImsConfigImplBase#notifyProvisionedValueChanged(int, String) parameter #1:
-    
-MissingNullability: android.telephony.ims.stub.ImsConfigImplBase#setConfig(int, String) parameter #1:
-    
-MissingNullability: android.telephony.ims.stub.ImsFeatureConfiguration#getServiceFeatures():
-    
-MissingNullability: android.telephony.ims.stub.ImsFeatureConfiguration#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.telephony.ims.stub.ImsFeatureConfiguration.Builder#addFeature(int, int):
-    
-MissingNullability: android.telephony.ims.stub.ImsFeatureConfiguration.Builder#build():
-    
-MissingNullability: android.telephony.ims.stub.ImsMultiEndpointImplBase#onImsExternalCallStateUpdate(java.util.List<android.telephony.ims.ImsExternalCallState>) parameter #0:
-    
-MissingNullability: android.telephony.ims.stub.ImsRegistrationImplBase#onDeregistered(android.telephony.ims.ImsReasonInfo) parameter #0:
-    
-MissingNullability: android.telephony.ims.stub.ImsRegistrationImplBase#onSubscriberAssociatedUriChanged(android.net.Uri[]) parameter #0:
-    
-MissingNullability: android.telephony.ims.stub.ImsRegistrationImplBase#onTechnologyChangeFailed(int, android.telephony.ims.ImsReasonInfo) parameter #1:
-    
-MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#getSmsFormat():
-    
-MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsReceived(int, String, byte[]) parameter #1:
-    
-MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsReceived(int, String, byte[]) parameter #2:
-    
-MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsStatusReportReceived(int, String, byte[]) parameter #1:
-    
-MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsStatusReportReceived(int, String, byte[]) parameter #2:
-    
-MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsStatusReportReceived(int, int, String, byte[]) parameter #2:
-    
-MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#onSmsStatusReportReceived(int, int, String, byte[]) parameter #3:
-    
-MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#sendSms(int, int, String, String, boolean, byte[]) parameter #2:
-    
-MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#sendSms(int, int, String, String, boolean, byte[]) parameter #3:
-    
-MissingNullability: android.telephony.ims.stub.ImsSmsImplBase#sendSms(int, int, String, String, boolean, byte[]) parameter #5:
-    
-MissingNullability: android.telephony.ims.stub.ImsUtImplBase#queryCallForward(int, String) parameter #1:
-    
-MissingNullability: android.telephony.ims.stub.ImsUtImplBase#setListener(android.telephony.ims.ImsUtListener) parameter #0:
-    
-MissingNullability: android.telephony.ims.stub.ImsUtImplBase#transact(android.os.Bundle) parameter #0:
-    
-MissingNullability: android.telephony.ims.stub.ImsUtImplBase#updateCallBarring(int, int, String[]) parameter #2:
-    
-MissingNullability: android.telephony.ims.stub.ImsUtImplBase#updateCallBarringForServiceClass(int, int, String[], int) parameter #2:
-    
-MissingNullability: android.telephony.ims.stub.ImsUtImplBase#updateCallForward(int, int, String, int, int) parameter #2:
-    
-MissingNullability: android.telephony.mbms.DownloadRequest.Builder#setServiceId(String):
-    
-MissingNullability: android.telephony.mbms.DownloadRequest.Builder#setServiceId(String) parameter #0:
-    
-MissingNullability: android.telephony.mbms.FileInfo#FileInfo(android.net.Uri, String) parameter #0:
-    
-MissingNullability: android.telephony.mbms.FileInfo#FileInfo(android.net.Uri, String) parameter #1:
-    
-MissingNullability: android.telephony.mbms.FileServiceInfo#FileServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date, java.util.List<android.telephony.mbms.FileInfo>) parameter #0:
-    
-MissingNullability: android.telephony.mbms.FileServiceInfo#FileServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date, java.util.List<android.telephony.mbms.FileInfo>) parameter #1:
-    
-MissingNullability: android.telephony.mbms.FileServiceInfo#FileServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date, java.util.List<android.telephony.mbms.FileInfo>) parameter #2:
-    
-MissingNullability: android.telephony.mbms.FileServiceInfo#FileServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date, java.util.List<android.telephony.mbms.FileInfo>) parameter #3:
-    
-MissingNullability: android.telephony.mbms.FileServiceInfo#FileServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date, java.util.List<android.telephony.mbms.FileInfo>) parameter #4:
-    
-MissingNullability: android.telephony.mbms.FileServiceInfo#FileServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date, java.util.List<android.telephony.mbms.FileInfo>) parameter #5:
-    
-MissingNullability: android.telephony.mbms.FileServiceInfo#FileServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date, java.util.List<android.telephony.mbms.FileInfo>) parameter #6:
-    
-MissingNullability: android.telephony.mbms.StreamingServiceInfo#StreamingServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date) parameter #0:
-    
-MissingNullability: android.telephony.mbms.StreamingServiceInfo#StreamingServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date) parameter #1:
-    
-MissingNullability: android.telephony.mbms.StreamingServiceInfo#StreamingServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date) parameter #2:
-    
-MissingNullability: android.telephony.mbms.StreamingServiceInfo#StreamingServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date) parameter #3:
-    
-MissingNullability: android.telephony.mbms.StreamingServiceInfo#StreamingServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date) parameter #4:
-    
-MissingNullability: android.telephony.mbms.StreamingServiceInfo#StreamingServiceInfo(java.util.Map<java.util.Locale,java.lang.String>, String, java.util.List<java.util.Locale>, String, java.util.Date, java.util.Date) parameter #5:
-    
-MissingNullability: android.telephony.mbms.UriPathPair#getContentUri():
-    
-MissingNullability: android.telephony.mbms.UriPathPair#getFilePathUri():
-    
-MissingNullability: android.telephony.mbms.UriPathPair#writeToParcel(android.os.Parcel, int) parameter #0:
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) parameter #0:
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) parameter #1:
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) parameter #0:
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) parameter #1:
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#asBinder():
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#cancelDownload(android.telephony.mbms.DownloadRequest) parameter #0:
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#download(android.telephony.mbms.DownloadRequest) parameter #0:
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#initialize(int, android.telephony.mbms.MbmsDownloadSessionCallback) parameter #1:
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#onTransact(int, android.os.Parcel, android.os.Parcel, int) parameter #1:
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#onTransact(int, android.os.Parcel, android.os.Parcel, int) parameter #2:
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#removeProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) parameter #0:
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#removeProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener) parameter #1:
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#removeStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) parameter #0:
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#removeStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener) parameter #1:
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#requestDownloadState(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo) parameter #0:
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#requestDownloadState(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo) parameter #1:
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#requestUpdateFileServices(int, java.util.List<java.lang.String>) parameter #1:
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#resetDownloadKnowledge(android.telephony.mbms.DownloadRequest) parameter #0:
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsDownloadServiceBase#setTempFileRootDirectory(int, String) parameter #1:
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#onBind(android.content.Intent):
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#onBind(android.content.Intent) parameter #0:
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsStreamingServiceBase#asBinder():
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsStreamingServiceBase#getPlaybackUri(int, String) parameter #1:
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsStreamingServiceBase#initialize(android.telephony.mbms.MbmsStreamingSessionCallback, int) parameter #0:
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsStreamingServiceBase#onTransact(int, android.os.Parcel, android.os.Parcel, int) parameter #1:
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsStreamingServiceBase#onTransact(int, android.os.Parcel, android.os.Parcel, int) parameter #2:
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsStreamingServiceBase#requestUpdateStreamingServices(int, java.util.List<java.lang.String>) parameter #1:
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsStreamingServiceBase#startStreaming(int, String, android.telephony.mbms.StreamingServiceCallback) parameter #1:
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsStreamingServiceBase#startStreaming(int, String, android.telephony.mbms.StreamingServiceCallback) parameter #2:
-    
-MissingNullability: android.telephony.mbms.vendor.MbmsStreamingServiceBase#stopStreaming(int, String) parameter #1:
-    
-MissingNullability: android.telephony.mbms.vendor.VendorUtils#getAppReceiverFromPackageName(android.content.Context, String):
-    
-MissingNullability: android.telephony.mbms.vendor.VendorUtils#getAppReceiverFromPackageName(android.content.Context, String) parameter #0:
-    
-MissingNullability: android.telephony.mbms.vendor.VendorUtils#getAppReceiverFromPackageName(android.content.Context, String) parameter #1:
-    
+    Missing nullability on parameter `apn` in method `setCarrierTestOverride`
 MissingNullability: android.text.Selection.MemoryTextWatcher#afterTextChanged(android.text.Editable) parameter #0:
-    
+    Missing nullability on parameter `s` in method `afterTextChanged`
 MissingNullability: android.text.Selection.MemoryTextWatcher#beforeTextChanged(CharSequence, int, int, int) parameter #0:
-    
+    Missing nullability on parameter `s` in method `beforeTextChanged`
 MissingNullability: android.text.Selection.MemoryTextWatcher#onTextChanged(CharSequence, int, int, int) parameter #0:
-    
+    Missing nullability on parameter `s` in method `onTextChanged`
 MissingNullability: android.transition.TransitionManager#getTransition(android.transition.Scene):
-    
+    Missing nullability on method `getTransition` return
 MissingNullability: android.transition.TransitionManager#getTransition(android.transition.Scene) parameter #0:
-    
+    Missing nullability on parameter `scene` in method `getTransition`
 MissingNullability: android.util.FeatureFlagUtils#getAllFeatureFlags():
-    
+    Missing nullability on method `getAllFeatureFlags` return
 MissingNullability: android.util.FeatureFlagUtils#isEnabled(android.content.Context, String) parameter #0:
-    
+    Missing nullability on parameter `context` in method `isEnabled`
 MissingNullability: android.util.FeatureFlagUtils#isEnabled(android.content.Context, String) parameter #1:
-    
+    Missing nullability on parameter `feature` in method `isEnabled`
 MissingNullability: android.util.FeatureFlagUtils#setEnabled(android.content.Context, String, boolean) parameter #0:
-    
+    Missing nullability on parameter `context` in method `setEnabled`
 MissingNullability: android.util.FeatureFlagUtils#setEnabled(android.content.Context, String, boolean) parameter #1:
-    
+    Missing nullability on parameter `feature` in method `setEnabled`
 MissingNullability: android.util.TimeUtils#formatDuration(long):
-    
+    Missing nullability on method `formatDuration` return
 MissingNullability: android.util.proto.EncodedBuffer#dumpBuffers(String) parameter #0:
-    
+    Missing nullability on parameter `tag` in method `dumpBuffers`
 MissingNullability: android.util.proto.EncodedBuffer#dumpByteString(String, String, byte[]) parameter #0:
-    
+    Missing nullability on parameter `tag` in method `dumpByteString`
 MissingNullability: android.util.proto.EncodedBuffer#dumpByteString(String, String, byte[]) parameter #1:
-    
+    Missing nullability on parameter `prefix` in method `dumpByteString`
 MissingNullability: android.util.proto.EncodedBuffer#dumpByteString(String, String, byte[]) parameter #2:
-    
+    Missing nullability on parameter `buf` in method `dumpByteString`
 MissingNullability: android.util.proto.EncodedBuffer#getBytes(int):
-    
+    Missing nullability on method `getBytes` return
 MissingNullability: android.util.proto.EncodedBuffer#getDebugString():
-    
+    Missing nullability on method `getDebugString` return
 MissingNullability: android.util.proto.EncodedBuffer#writeRawBuffer(byte[]) parameter #0:
-    
+    Missing nullability on parameter `val` in method `writeRawBuffer`
 MissingNullability: android.util.proto.EncodedBuffer#writeRawBuffer(byte[], int, int) parameter #0:
-    
-MissingNullability: android.util.proto.ProtoOutputStream#ProtoOutputStream(java.io.FileDescriptor) parameter #0:
-    
-MissingNullability: android.util.proto.ProtoOutputStream#ProtoOutputStream(java.io.OutputStream) parameter #0:
-    
-MissingNullability: android.util.proto.ProtoOutputStream#dump(String) parameter #0:
-    
-MissingNullability: android.util.proto.ProtoOutputStream#getBytes():
-    
-MissingNullability: android.util.proto.ProtoOutputStream#write(long, String) parameter #1:
-    
-MissingNullability: android.util.proto.ProtoOutputStream#write(long, byte[]) parameter #1:
-    
-MissingNullability: android.util.proto.ProtoOutputStream#writeBytes(long, byte[]) parameter #1:
-    
-MissingNullability: android.util.proto.ProtoOutputStream#writeObject(long, byte[]) parameter #1:
-    
-MissingNullability: android.util.proto.ProtoOutputStream#writePackedBool(long, boolean[]) parameter #1:
-    
-MissingNullability: android.util.proto.ProtoOutputStream#writePackedDouble(long, double[]) parameter #1:
-    
-MissingNullability: android.util.proto.ProtoOutputStream#writePackedEnum(long, int[]) parameter #1:
-    
-MissingNullability: android.util.proto.ProtoOutputStream#writePackedFixed32(long, int[]) parameter #1:
-    
-MissingNullability: android.util.proto.ProtoOutputStream#writePackedFixed64(long, long[]) parameter #1:
-    
-MissingNullability: android.util.proto.ProtoOutputStream#writePackedFloat(long, float[]) parameter #1:
-    
-MissingNullability: android.util.proto.ProtoOutputStream#writePackedInt32(long, int[]) parameter #1:
-    
-MissingNullability: android.util.proto.ProtoOutputStream#writePackedInt64(long, long[]) parameter #1:
-    
-MissingNullability: android.util.proto.ProtoOutputStream#writePackedSFixed32(long, int[]) parameter #1:
-    
-MissingNullability: android.util.proto.ProtoOutputStream#writePackedSFixed64(long, long[]) parameter #1:
-    
-MissingNullability: android.util.proto.ProtoOutputStream#writePackedSInt32(long, int[]) parameter #1:
-    
-MissingNullability: android.util.proto.ProtoOutputStream#writePackedSInt64(long, long[]) parameter #1:
-    
-MissingNullability: android.util.proto.ProtoOutputStream#writePackedUInt32(long, int[]) parameter #1:
-    
-MissingNullability: android.util.proto.ProtoOutputStream#writePackedUInt64(long, long[]) parameter #1:
-    
-MissingNullability: android.util.proto.ProtoOutputStream#writeRepeatedBytes(long, byte[]) parameter #1:
-    
-MissingNullability: android.util.proto.ProtoOutputStream#writeRepeatedObject(long, byte[]) parameter #1:
-    
-MissingNullability: android.util.proto.ProtoOutputStream#writeRepeatedString(long, String) parameter #1:
-    
-MissingNullability: android.util.proto.ProtoOutputStream#writeString(long, String) parameter #1:
-    
+    Missing nullability on parameter `val` in method `writeRawBuffer`
 MissingNullability: android.util.proto.ProtoParseException#ProtoParseException(String) parameter #0:
-    
-MissingNullability: android.util.proto.ProtoStream#FIELD_TYPE_NAMES:
-    
-MissingNullability: android.util.proto.ProtoStream#getFieldCountString(long):
-    
-MissingNullability: android.util.proto.ProtoStream#getFieldIdString(long):
-    
-MissingNullability: android.util.proto.ProtoStream#getFieldTypeString(long):
-    
-MissingNullability: android.util.proto.ProtoStream#getWireTypeString(int):
-    
-MissingNullability: android.util.proto.ProtoStream#token2String(long):
-    
+    Missing nullability on parameter `msg` in method `ProtoParseException`
 MissingNullability: android.util.proto.WireTypeMismatchException#WireTypeMismatchException(String) parameter #0:
-    
+    Missing nullability on parameter `msg` in method `WireTypeMismatchException`
 MissingNullability: android.view.Choreographer#postCallback(int, Runnable, Object) parameter #1:
-    
+    Missing nullability on parameter `action` in method `postCallback`
 MissingNullability: android.view.Choreographer#postCallback(int, Runnable, Object) parameter #2:
-    
+    Missing nullability on parameter `token` in method `postCallback`
 MissingNullability: android.view.Choreographer#postCallbackDelayed(int, Runnable, Object, long) parameter #1:
-    
+    Missing nullability on parameter `action` in method `postCallbackDelayed`
 MissingNullability: android.view.Choreographer#postCallbackDelayed(int, Runnable, Object, long) parameter #2:
-    
+    Missing nullability on parameter `token` in method `postCallbackDelayed`
 MissingNullability: android.view.Choreographer#removeCallbacks(int, Runnable, Object) parameter #1:
-    
+    Missing nullability on parameter `action` in method `removeCallbacks`
 MissingNullability: android.view.Choreographer#removeCallbacks(int, Runnable, Object) parameter #2:
-    
+    Missing nullability on parameter `token` in method `removeCallbacks`
 MissingNullability: android.view.FocusFinder#sort(android.view.View[], int, int, android.view.ViewGroup, boolean) parameter #0:
-    
+    Missing nullability on parameter `views` in method `sort`
 MissingNullability: android.view.FocusFinder#sort(android.view.View[], int, int, android.view.ViewGroup, boolean) parameter #3:
-    
+    Missing nullability on parameter `root` in method `sort`
 MissingNullability: android.view.KeyEvent#actionToString(int):
-    
-MissingNullability: android.view.SurfaceControlViewHost#SurfaceControlViewHost(android.content.Context, android.view.Display, android.view.SurfaceControl) parameter #0:
-    
-MissingNullability: android.view.SurfaceControlViewHost#SurfaceControlViewHost(android.content.Context, android.view.Display, android.view.SurfaceControl) parameter #1:
-    
-MissingNullability: android.view.SurfaceControlViewHost#SurfaceControlViewHost(android.content.Context, android.view.Display, android.view.SurfaceControl) parameter #2:
-    
-MissingNullability: android.view.SurfaceControlViewHost#addView(android.view.View, android.view.WindowManager.LayoutParams) parameter #0:
-    
-MissingNullability: android.view.SurfaceControlViewHost#addView(android.view.View, android.view.WindowManager.LayoutParams) parameter #1:
-    
+    Missing nullability on method `actionToString` return
 MissingNullability: android.view.SurfaceControlViewHost#relayout(android.view.WindowManager.LayoutParams) parameter #0:
-    
+    Missing nullability on parameter `attrs` in method `relayout`
 MissingNullability: android.view.View#getTooltipView():
-    
+    Missing nullability on method `getTooltipView` return
 MissingNullability: android.view.View#isDefaultFocusHighlightNeeded(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable) parameter #0:
-    
+    Missing nullability on parameter `background` in method `isDefaultFocusHighlightNeeded`
 MissingNullability: android.view.View#isDefaultFocusHighlightNeeded(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable) parameter #1:
-    
+    Missing nullability on parameter `foreground` in method `isDefaultFocusHighlightNeeded`
 MissingNullability: android.view.ViewDebug#startRenderingCommandsCapture(android.view.View, java.util.concurrent.Executor, java.util.concurrent.Callable<java.io.OutputStream>) parameter #0:
-    
+    Missing nullability on parameter `tree` in method `startRenderingCommandsCapture`
 MissingNullability: android.view.ViewDebug#startRenderingCommandsCapture(android.view.View, java.util.concurrent.Executor, java.util.concurrent.Callable<java.io.OutputStream>) parameter #1:
-    
+    Missing nullability on parameter `executor` in method `startRenderingCommandsCapture`
 MissingNullability: android.view.ViewDebug#startRenderingCommandsCapture(android.view.View, java.util.concurrent.Executor, java.util.concurrent.Callable<java.io.OutputStream>) parameter #2:
-    
-MissingNullability: android.view.ViewDebug#startRenderingCommandsCapture(android.view.View, java.util.concurrent.Executor, java.util.function.Function<android.graphics.Picture,java.lang.Boolean>) parameter #0:
-    
-MissingNullability: android.view.ViewDebug#startRenderingCommandsCapture(android.view.View, java.util.concurrent.Executor, java.util.function.Function<android.graphics.Picture,java.lang.Boolean>) parameter #1:
-    
-MissingNullability: android.view.ViewDebug#startRenderingCommandsCapture(android.view.View, java.util.concurrent.Executor, java.util.function.Function<android.graphics.Picture,java.lang.Boolean>) parameter #2:
-    
+    Missing nullability on parameter `callback` in method `startRenderingCommandsCapture`
 MissingNullability: android.view.WindowManager#holdLock(android.os.IBinder, int) parameter #0:
-    
+    Missing nullability on parameter `token` in method `holdLock`
 MissingNullability: android.view.WindowManager.LayoutParams#accessibilityTitle:
-    
-MissingNullability: android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener#onAccessibilityServicesStateChanged(android.view.accessibility.AccessibilityManager) parameter #0:
-    
-MissingNullability: android.view.accessibility.AccessibilityNodeInfo#setNumInstancesInUseCounter(java.util.concurrent.atomic.AtomicInteger) parameter #0:
-    
+    Missing nullability on field `accessibilityTitle` in class `class android.view.WindowManager.LayoutParams`
 MissingNullability: android.view.accessibility.AccessibilityNodeInfo#writeToParcelNoRecycle(android.os.Parcel, int) parameter #0:
-    
+    Missing nullability on parameter `parcel` in method `writeToParcelNoRecycle`
 MissingNullability: android.view.accessibility.AccessibilityWindowInfo#setNumInstancesInUseCounter(java.util.concurrent.atomic.AtomicInteger) parameter #0:
-    
-MissingNullability: android.view.contentcapture.ContentCaptureEvent#writeToParcel(android.os.Parcel, int) parameter #0:
-    
+    Missing nullability on parameter `counter` in method `setNumInstancesInUseCounter`
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#asyncNewChild(int):
-    
+    Missing nullability on method `asyncNewChild` return
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#getAutofillId():
-    
+    Missing nullability on method `getAutofillId` return
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#getExtras():
-    
+    Missing nullability on method `getExtras` return
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#getHint():
-    
+    Missing nullability on method `getHint` return
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#getNode():
-    
+    Missing nullability on method `getNode` return
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#getTempRect():
-    
+    Missing nullability on method `getTempRect` return
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#getText():
-    
+    Missing nullability on method `getText` return
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#newChild(int):
-    
+    Missing nullability on method `newChild` return
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#newHtmlInfoBuilder(String):
-    
+    Missing nullability on method `newHtmlInfoBuilder` return
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#newHtmlInfoBuilder(String) parameter #0:
-    
+    Missing nullability on parameter `tagName` in method `newHtmlInfoBuilder`
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setAutofillHints(String[]) parameter #0:
-    
+    Missing nullability on parameter `hints` in method `setAutofillHints`
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setAutofillId(android.view.autofill.AutofillId) parameter #0:
-    
+    Missing nullability on parameter `id` in method `setAutofillId`
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setAutofillId(android.view.autofill.AutofillId, int) parameter #0:
-    
+    Missing nullability on parameter `parentId` in method `setAutofillId`
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setAutofillOptions(CharSequence[]) parameter #0:
-    
+    Missing nullability on parameter `options` in method `setAutofillOptions`
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setAutofillValue(android.view.autofill.AutofillValue) parameter #0:
-    
+    Missing nullability on parameter `value` in method `setAutofillValue`
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setClassName(String) parameter #0:
-    
+    Missing nullability on parameter `className` in method `setClassName`
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setContentDescription(CharSequence) parameter #0:
-    
+    Missing nullability on parameter `contentDescription` in method `setContentDescription`
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setHint(CharSequence) parameter #0:
-    
+    Missing nullability on parameter `hint` in method `setHint`
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setHintIdEntry(String) parameter #0:
-    
+    Missing nullability on parameter `entryName` in method `setHintIdEntry`
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setHtmlInfo(android.view.ViewStructure.HtmlInfo) parameter #0:
-    
+    Missing nullability on parameter `htmlInfo` in method `setHtmlInfo`
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setId(int, String, String, String) parameter #1:
-    
+    Missing nullability on parameter `packageName` in method `setId`
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setId(int, String, String, String) parameter #2:
-    
+    Missing nullability on parameter `typeName` in method `setId`
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setId(int, String, String, String) parameter #3:
-    
+    Missing nullability on parameter `entryName` in method `setId`
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setLocaleList(android.os.LocaleList) parameter #0:
-    
+    Missing nullability on parameter `localeList` in method `setLocaleList`
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setText(CharSequence) parameter #0:
-    
+    Missing nullability on parameter `text` in method `setText`
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setText(CharSequence, int, int) parameter #0:
-    
+    Missing nullability on parameter `text` in method `setText`
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setTextLines(int[], int[]) parameter #0:
-    
+    Missing nullability on parameter `charOffsets` in method `setTextLines`
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setTextLines(int[], int[]) parameter #1:
-    
+    Missing nullability on parameter `baselines` in method `setTextLines`
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setTransformation(android.graphics.Matrix) parameter #0:
-    
+    Missing nullability on parameter `matrix` in method `setTransformation`
 MissingNullability: android.view.contentcapture.ViewNode.ViewStructureImpl#setWebDomain(String) parameter #0:
-    
+    Missing nullability on parameter `domain` in method `setWebDomain`
 MissingNullability: android.widget.CalendarView#getBoundsForDate(long, android.graphics.Rect) parameter #1:
-    
+    Missing nullability on parameter `outBounds` in method `getBoundsForDate`
 MissingNullability: android.widget.ImageView#isDefaultFocusHighlightNeeded(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable) parameter #0:
-    
+    Missing nullability on parameter `background` in method `isDefaultFocusHighlightNeeded`
 MissingNullability: android.widget.ImageView#isDefaultFocusHighlightNeeded(android.graphics.drawable.Drawable, android.graphics.drawable.Drawable) parameter #1:
-    
+    Missing nullability on parameter `foreground` in method `isDefaultFocusHighlightNeeded`
 MissingNullability: android.widget.Magnifier#getMagnifierDefaultSize():
-    
+    Missing nullability on method `getMagnifierDefaultSize` return
 MissingNullability: android.widget.Magnifier#setOnOperationCompleteCallback(android.widget.Magnifier.Callback) parameter #0:
-    
+    Missing nullability on parameter `callback` in method `setOnOperationCompleteCallback`
 MissingNullability: android.widget.NumberPicker#getDisplayedValueForCurrentSelection():
-    
+    Missing nullability on method `getDisplayedValueForCurrentSelection` return
 MissingNullability: android.widget.PopupMenu#getMenuListView():
-    
+    Missing nullability on method `getMenuListView` return
 MissingNullability: android.widget.TimePicker#getAmView():
-    
+    Missing nullability on method `getAmView` return
 MissingNullability: android.widget.TimePicker#getHourView():
-    
+    Missing nullability on method `getHourView` return
 MissingNullability: android.widget.TimePicker#getMinuteView():
-    
+    Missing nullability on method `getMinuteView` return
 MissingNullability: android.widget.TimePicker#getPmView():
-    
+    Missing nullability on method `getPmView` return
 
 
 MutableBareField: android.content.AutofillOptions#appDisabledExpiration:
-    
+    Bare field appDisabledExpiration must be marked final, or moved behind accessors if mutable
 MutableBareField: android.content.AutofillOptions#augmentedAutofillEnabled:
-    
+    Bare field augmentedAutofillEnabled must be marked final, or moved behind accessors if mutable
 MutableBareField: android.content.AutofillOptions#disabledActivities:
-    
+    Bare field disabledActivities must be marked final, or moved behind accessors if mutable
 MutableBareField: android.content.AutofillOptions#whitelistedActivitiesForAugmentedAutofill:
-    
+    Bare field whitelistedActivitiesForAugmentedAutofill must be marked final, or moved behind accessors if mutable
 MutableBareField: android.content.pm.UserInfo#convertedFromPreCreated:
     Bare field convertedFromPreCreated must be marked final, or moved behind accessors if mutable
 MutableBareField: android.content.pm.UserInfo#creationTime:
@@ -2438,588 +796,230 @@
 MutableBareField: android.content.pm.UserInfo#userType:
     Bare field userType must be marked final, or moved behind accessors if mutable
 MutableBareField: android.database.sqlite.SQLiteDebug.DbStats#cache:
-    
+    Bare field cache must be marked final, or moved behind accessors if mutable
 MutableBareField: android.database.sqlite.SQLiteDebug.DbStats#dbName:
-    
+    Bare field dbName must be marked final, or moved behind accessors if mutable
 MutableBareField: android.database.sqlite.SQLiteDebug.DbStats#dbSize:
-    
+    Bare field dbSize must be marked final, or moved behind accessors if mutable
 MutableBareField: android.database.sqlite.SQLiteDebug.DbStats#lookaside:
-    
+    Bare field lookaside must be marked final, or moved behind accessors if mutable
 MutableBareField: android.database.sqlite.SQLiteDebug.DbStats#pageSize:
-    
+    Bare field pageSize must be marked final, or moved behind accessors if mutable
 MutableBareField: android.database.sqlite.SQLiteDebug.PagerStats#dbStats:
-    
+    Bare field dbStats must be marked final, or moved behind accessors if mutable
 MutableBareField: android.database.sqlite.SQLiteDebug.PagerStats#largestMemAlloc:
-    
+    Bare field largestMemAlloc must be marked final, or moved behind accessors if mutable
 MutableBareField: android.database.sqlite.SQLiteDebug.PagerStats#memoryUsed:
-    
+    Bare field memoryUsed must be marked final, or moved behind accessors if mutable
 MutableBareField: android.database.sqlite.SQLiteDebug.PagerStats#pageCacheOverflow:
-    
+    Bare field pageCacheOverflow must be marked final, or moved behind accessors if mutable
 MutableBareField: android.os.StrictMode.ViolationInfo#broadcastIntentAction:
-    
+    Bare field broadcastIntentAction must be marked final, or moved behind accessors if mutable
 MutableBareField: android.os.StrictMode.ViolationInfo#durationMillis:
-    
+    Bare field durationMillis must be marked final, or moved behind accessors if mutable
 MutableBareField: android.os.StrictMode.ViolationInfo#numAnimationsRunning:
-    
+    Bare field numAnimationsRunning must be marked final, or moved behind accessors if mutable
 MutableBareField: android.os.StrictMode.ViolationInfo#numInstances:
-    
+    Bare field numInstances must be marked final, or moved behind accessors if mutable
 MutableBareField: android.os.StrictMode.ViolationInfo#tags:
-    
+    Bare field tags must be marked final, or moved behind accessors if mutable
 MutableBareField: android.os.StrictMode.ViolationInfo#violationNumThisLoop:
-    
+    Bare field violationNumThisLoop must be marked final, or moved behind accessors if mutable
 MutableBareField: android.os.StrictMode.ViolationInfo#violationUptimeMillis:
-    
+    Bare field violationUptimeMillis must be marked final, or moved behind accessors if mutable
 
 
 NoByteOrShort: android.media.audiofx.AudioEffect#byteArrayToShort(byte[]):
-    
+    Should avoid odd sized primitives; use `int` instead of `short` in method android.media.audiofx.AudioEffect.byteArrayToShort(byte[])
 NoByteOrShort: android.media.audiofx.AudioEffect#setParameter(int, short) parameter #1:
-    
+    Should avoid odd sized primitives; use `int` instead of `short` in parameter value in android.media.audiofx.AudioEffect.setParameter(int param, short value)
 NoByteOrShort: android.media.audiofx.AudioEffect#shortToByteArray(short) parameter #0:
-    
-NoByteOrShort: android.os.HwBlob#getInt16(long):
-    
-NoByteOrShort: android.os.HwBlob#getInt8(long):
-    
-NoByteOrShort: android.os.HwBlob#putInt16(long, short) parameter #1:
-    
-NoByteOrShort: android.os.HwBlob#putInt8(long, byte) parameter #1:
-    
-NoByteOrShort: android.os.HwParcel#readInt16():
-    
-NoByteOrShort: android.os.HwParcel#readInt8():
-    
-NoByteOrShort: android.os.HwParcel#writeInt16(short) parameter #0:
-    
-NoByteOrShort: android.os.HwParcel#writeInt8(byte) parameter #0:
-    
+    Should avoid odd sized primitives; use `int` instead of `short` in parameter value in android.media.audiofx.AudioEffect.shortToByteArray(short value)
 NoByteOrShort: android.util.proto.EncodedBuffer#readRawByte():
-    
+    Should avoid odd sized primitives; use `int` instead of `byte` in method android.util.proto.EncodedBuffer.readRawByte()
 NoByteOrShort: android.util.proto.EncodedBuffer#writeRawByte(byte) parameter #0:
-    
-
-
-NoClone: android.net.util.SocketUtils#bindSocketToInterface(java.io.FileDescriptor, String) parameter #0:
-    
-NoClone: android.net.util.SocketUtils#closeSocket(java.io.FileDescriptor) parameter #0:
-    
-NoClone: android.os.NativeHandle#NativeHandle(java.io.FileDescriptor, boolean) parameter #0:
-    
-NoClone: android.os.NativeHandle#getFileDescriptor():
-    
-NoClone: android.os.ParcelFileDescriptor#getFile(java.io.FileDescriptor) parameter #0:
-    
-NoClone: android.service.autofill.augmented.AugmentedAutofillService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #0:
-    
-NoClone: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]) parameter #0:
-    
-NoClone: android.util.proto.ProtoOutputStream#ProtoOutputStream(java.io.FileDescriptor) parameter #0:
-    
+    Should avoid odd sized primitives; use `int` instead of `byte` in parameter val in android.util.proto.EncodedBuffer.writeRawByte(byte val)
 
 
 NoSettingsProvider: android.provider.Settings.Global#APP_OPS_CONSTANTS:
-    
-NoSettingsProvider: android.provider.Settings.Global#AUTOFILL_COMPAT_MODE_ALLOWED_PACKAGES:
-    
+    New setting keys are not allowed (Field: APP_OPS_CONSTANTS); use getters/setters in relevant manager class
 NoSettingsProvider: android.provider.Settings.Global#AUTOMATIC_POWER_SAVE_MODE:
-    
+    New setting keys are not allowed (Field: AUTOMATIC_POWER_SAVE_MODE); use getters/setters in relevant manager class
 NoSettingsProvider: android.provider.Settings.Global#BATTERY_SAVER_CONSTANTS:
-    
+    New setting keys are not allowed (Field: BATTERY_SAVER_CONSTANTS); use getters/setters in relevant manager class
 NoSettingsProvider: android.provider.Settings.Global#DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD:
-    
+    New setting keys are not allowed (Field: DYNAMIC_POWER_SAVINGS_DISABLE_THRESHOLD); use getters/setters in relevant manager class
 NoSettingsProvider: android.provider.Settings.Global#DYNAMIC_POWER_SAVINGS_ENABLED:
-    
+    New setting keys are not allowed (Field: DYNAMIC_POWER_SAVINGS_ENABLED); use getters/setters in relevant manager class
 NoSettingsProvider: android.provider.Settings.Global#HIDDEN_API_BLACKLIST_EXEMPTIONS:
-    
+    New setting keys are not allowed (Field: HIDDEN_API_BLACKLIST_EXEMPTIONS); use getters/setters in relevant manager class
 NoSettingsProvider: android.provider.Settings.Global#HIDDEN_API_POLICY:
-    
+    New setting keys are not allowed (Field: HIDDEN_API_POLICY); use getters/setters in relevant manager class
 NoSettingsProvider: android.provider.Settings.Global#HIDE_ERROR_DIALOGS:
-    
-NoSettingsProvider: android.provider.Settings.Global#LOCATION_GLOBAL_KILL_SWITCH:
-    
-NoSettingsProvider: android.provider.Settings.Global#LOCATION_IGNORE_SETTINGS_PACKAGE_WHITELIST:
-    
+    New setting keys are not allowed (Field: HIDE_ERROR_DIALOGS); use getters/setters in relevant manager class
 NoSettingsProvider: android.provider.Settings.Global#LOW_POWER_MODE:
-    
+    New setting keys are not allowed (Field: LOW_POWER_MODE); use getters/setters in relevant manager class
 NoSettingsProvider: android.provider.Settings.Global#LOW_POWER_MODE_STICKY:
-    
-NoSettingsProvider: android.provider.Settings.Global#NOTIFICATION_BUBBLES:
-    
+    New setting keys are not allowed (Field: LOW_POWER_MODE_STICKY); use getters/setters in relevant manager class
 NoSettingsProvider: android.provider.Settings.Global#OVERLAY_DISPLAY_DEVICES:
-    
-NoSettingsProvider: android.provider.Settings.Global#TETHER_OFFLOAD_DISABLED:
-    
-NoSettingsProvider: android.provider.Settings.Global#USE_OPEN_WIFI_PACKAGE:
-    
+    New setting keys are not allowed (Field: OVERLAY_DISPLAY_DEVICES); use getters/setters in relevant manager class
 NoSettingsProvider: android.provider.Settings.Secure#ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED:
-    
+    New setting keys are not allowed (Field: ACCESSIBILITY_DISPLAY_MAGNIFICATION_ENABLED); use getters/setters in relevant manager class
 NoSettingsProvider: android.provider.Settings.Secure#ACCESSIBILITY_MAGNIFICATION_CAPABILITY:
-    
+    New setting keys are not allowed (Field: ACCESSIBILITY_MAGNIFICATION_CAPABILITY); use getters/setters in relevant manager class
 NoSettingsProvider: android.provider.Settings.Secure#ACCESSIBILITY_MAGNIFICATION_MODE:
-    
-NoSettingsProvider: android.provider.Settings.Secure#ACCESSIBILITY_MAGNIFICATION_MODE_ALL:
-    
-NoSettingsProvider: android.provider.Settings.Secure#ACCESSIBILITY_MAGNIFICATION_MODE_FULLSCREEN:
-    
-NoSettingsProvider: android.provider.Settings.Secure#ACCESSIBILITY_MAGNIFICATION_MODE_WINDOW:
-    
+    New setting keys are not allowed (Field: ACCESSIBILITY_MAGNIFICATION_MODE); use getters/setters in relevant manager class
 NoSettingsProvider: android.provider.Settings.Secure#ACCESSIBILITY_SHORTCUT_TARGET_SERVICE:
-    
-NoSettingsProvider: android.provider.Settings.Secure#AUTOFILL_FEATURE_FIELD_CLASSIFICATION:
-    
+    New setting keys are not allowed (Field: ACCESSIBILITY_SHORTCUT_TARGET_SERVICE); use getters/setters in relevant manager class
 NoSettingsProvider: android.provider.Settings.Secure#AUTOFILL_SERVICE:
-    
-NoSettingsProvider: android.provider.Settings.Secure#AUTOFILL_USER_DATA_MAX_CATEGORY_COUNT:
-    
-NoSettingsProvider: android.provider.Settings.Secure#AUTOFILL_USER_DATA_MAX_FIELD_CLASSIFICATION_IDS_SIZE:
-    
-NoSettingsProvider: android.provider.Settings.Secure#AUTOFILL_USER_DATA_MAX_USER_DATA_SIZE:
-    
-NoSettingsProvider: android.provider.Settings.Secure#AUTOFILL_USER_DATA_MAX_VALUE_LENGTH:
-    
-NoSettingsProvider: android.provider.Settings.Secure#AUTOFILL_USER_DATA_MIN_VALUE_LENGTH:
-    
+    New setting keys are not allowed (Field: AUTOFILL_SERVICE); use getters/setters in relevant manager class
 NoSettingsProvider: android.provider.Settings.Secure#CONTENT_CAPTURE_ENABLED:
-    
+    New setting keys are not allowed (Field: CONTENT_CAPTURE_ENABLED); use getters/setters in relevant manager class
 NoSettingsProvider: android.provider.Settings.Secure#DISABLED_PRINT_SERVICES:
-    
-NoSettingsProvider: android.provider.Settings.Secure#DOZE_ALWAYS_ON:
-    
+    New setting keys are not allowed (Field: DISABLED_PRINT_SERVICES); use getters/setters in relevant manager class
 NoSettingsProvider: android.provider.Settings.Secure#ENABLED_VR_LISTENERS:
-    
+    New setting keys are not allowed (Field: ENABLED_VR_LISTENERS); use getters/setters in relevant manager class
 NoSettingsProvider: android.provider.Settings.Secure#IMMERSIVE_MODE_CONFIRMATIONS:
-    
-NoSettingsProvider: android.provider.Settings.Secure#LOCATION_ACCESS_CHECK_DELAY_MILLIS:
-    
-NoSettingsProvider: android.provider.Settings.Secure#LOCATION_ACCESS_CHECK_INTERVAL_MILLIS:
-    
-NoSettingsProvider: android.provider.Settings.Secure#LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS:
-    
-NoSettingsProvider: android.provider.Settings.Secure#LOCK_SCREEN_SHOW_NOTIFICATIONS:
-    
-NoSettingsProvider: android.provider.Settings.Secure#NFC_PAYMENT_DEFAULT_COMPONENT:
-    
+    New setting keys are not allowed (Field: IMMERSIVE_MODE_CONFIRMATIONS); use getters/setters in relevant manager class
 NoSettingsProvider: android.provider.Settings.Secure#NOTIFICATION_BADGING:
-    
+    New setting keys are not allowed (Field: NOTIFICATION_BADGING); use getters/setters in relevant manager class
 NoSettingsProvider: android.provider.Settings.Secure#POWER_MENU_LOCKED_SHOW_CONTENT:
-    
+    New setting keys are not allowed (Field: POWER_MENU_LOCKED_SHOW_CONTENT); use getters/setters in relevant manager class
 NoSettingsProvider: android.provider.Settings.Secure#SYNC_PARENT_SOUNDS:
-    
-NoSettingsProvider: android.provider.Settings.Secure#USER_SETUP_COMPLETE:
-    
+    New setting keys are not allowed (Field: SYNC_PARENT_SOUNDS); use getters/setters in relevant manager class
 NoSettingsProvider: android.provider.Settings.Secure#VOICE_INTERACTION_SERVICE:
-    
+    New setting keys are not allowed (Field: VOICE_INTERACTION_SERVICE); use getters/setters in relevant manager class
 
 
-NotCloseable: android.app.prediction.AppPredictor:
-    
-NotCloseable: android.net.EthernetManager.TetheredInterfaceRequest:
-    
-NotCloseable: android.os.HwParcel:
-    
-NotCloseable: android.telephony.ims.stub.ImsUtImplBase:
-    
-
-
-NullableCollection: android.os.UserManager#createProfileForUser(String, String, int, int, String[]) parameter #4:
-    Type of parameter disallowedPackages in android.os.UserManager.createProfileForUser(String name, String userType, int flags, int userId, String[] disallowedPackages) is a nullable collection (`java.lang.String[]`); must be non-null
-
-
-OnNameExpected: android.service.autofill.augmented.AugmentedAutofillService#dump(java.io.PrintWriter, String[]):
-    
-OnNameExpected: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]):
-    
 OnNameExpected: android.service.notification.ConditionProviderService#isBound():
-    
-OnNameExpected: android.service.notification.NotificationAssistantService#attachBaseContext(android.content.Context):
-    
-OnNameExpected: android.service.quicksettings.TileService#isQuickSettingsSupported():
-    
+    If implemented by developer, should follow the on<Something> style; otherwise consider marking final
 OnNameExpected: android.service.watchdog.ExplicitHealthCheckService#setCallback(android.os.RemoteCallback):
-    
-OnNameExpected: android.telephony.ims.ImsService#createMmTelFeature(int):
-    
-OnNameExpected: android.telephony.ims.ImsService#createRcsFeature(int):
-    
-OnNameExpected: android.telephony.ims.ImsService#disableIms(int):
-    
-OnNameExpected: android.telephony.ims.ImsService#enableIms(int):
-    
-OnNameExpected: android.telephony.ims.ImsService#getConfig(int):
-    
-OnNameExpected: android.telephony.ims.ImsService#getRegistration(int):
-    
-OnNameExpected: android.telephony.ims.ImsService#querySupportedImsFeatures():
-    
-OnNameExpected: android.telephony.ims.ImsService#readyForFeatureCreation():
-    
-OnNameExpected: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#dispose(int):
-    
-OnNameExpected: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#initialize(android.telephony.mbms.MbmsGroupCallSessionCallback, int):
-    
-OnNameExpected: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#startGroupCall(int, long, java.util.List<java.lang.Integer>, java.util.List<java.lang.Integer>, android.telephony.mbms.GroupCallCallback):
-    
-OnNameExpected: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#stopGroupCall(int, long):
-    
-OnNameExpected: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#updateGroupCall(int, long, java.util.List<java.lang.Integer>, java.util.List<java.lang.Integer>):
-    
-
-
-OptionalBuilderConstructorArgument: android.app.prediction.AppTargetEvent.Builder#Builder(android.app.prediction.AppTarget, int) parameter #0:
-    
-OptionalBuilderConstructorArgument: android.net.CaptivePortalData.Builder#Builder(android.net.CaptivePortalData) parameter #0:
-    
-OptionalBuilderConstructorArgument: android.os.VibrationAttributes.Builder#Builder(android.media.AudioAttributes, android.os.VibrationEffect) parameter #1:
-    
+    If implemented by developer, should follow the on<Something> style; otherwise consider marking final
 
 
 PackageLayering: android.util.FeatureFlagUtils:
-    
+    Method parameter type `android.content.Context` violates package layering: nothing in `package android.util` should depend on `package android.content`
 
 
-ParcelConstructor: android.os.IncidentManager.IncidentReport#IncidentReport(android.os.Parcel):
-    
-ParcelConstructor: android.os.IncidentReportArgs#IncidentReportArgs(android.os.Parcel):
-    
 ParcelConstructor: android.os.StrictMode.ViolationInfo#ViolationInfo(android.os.Parcel):
-    
+    Parcelable inflation is exposed through CREATOR, not raw constructors, in android.os.StrictMode.ViolationInfo
 ParcelConstructor: android.os.health.HealthStatsParceler#HealthStatsParceler(android.os.Parcel):
-    
-ParcelConstructor: android.service.notification.SnoozeCriterion#SnoozeCriterion(android.os.Parcel):
-    
+    Parcelable inflation is exposed through CREATOR, not raw constructors, in android.os.health.HealthStatsParceler
 
 
 ParcelCreator: android.app.WindowConfiguration:
-    
-ParcelCreator: android.net.metrics.ApfProgramEvent:
-    
-ParcelCreator: android.net.metrics.ApfStats:
-    
-ParcelCreator: android.net.metrics.DhcpClientEvent:
-    
-ParcelCreator: android.net.metrics.DhcpErrorEvent:
-    
-ParcelCreator: android.net.metrics.IpConnectivityLog.Event:
-    
-ParcelCreator: android.net.metrics.IpManagerEvent:
-    
-ParcelCreator: android.net.metrics.IpReachabilityEvent:
-    
-ParcelCreator: android.net.metrics.NetworkEvent:
-    
-ParcelCreator: android.net.metrics.RaEvent:
-    
-ParcelCreator: android.net.metrics.ValidationProbeEvent:
-    
+    Parcelable requires a `CREATOR` field; missing in android.app.WindowConfiguration
 ParcelCreator: android.service.autofill.InternalOnClickAction:
-    
+    Parcelable requires a `CREATOR` field; missing in android.service.autofill.InternalOnClickAction
 ParcelCreator: android.service.autofill.InternalSanitizer:
-    
+    Parcelable requires a `CREATOR` field; missing in android.service.autofill.InternalSanitizer
 ParcelCreator: android.service.autofill.InternalTransformation:
-    
+    Parcelable requires a `CREATOR` field; missing in android.service.autofill.InternalTransformation
 ParcelCreator: android.service.autofill.InternalValidator:
-    
+    Parcelable requires a `CREATOR` field; missing in android.service.autofill.InternalValidator
 
 
 ParcelNotFinal: android.app.WindowConfiguration:
-    
+    Parcelable classes must be final: android.app.WindowConfiguration is not final
 ParcelNotFinal: android.content.pm.UserInfo:
     Parcelable classes must be final: android.content.pm.UserInfo is not final
-ParcelNotFinal: android.net.metrics.IpConnectivityLog.Event:
-    
-ParcelNotFinal: android.os.IncidentManager.IncidentReport:
-    
 ParcelNotFinal: android.os.health.HealthStatsParceler:
-    
+    Parcelable classes must be final: android.os.health.HealthStatsParceler is not final
 ParcelNotFinal: android.service.autofill.InternalOnClickAction:
-    
+    Parcelable classes must be final: android.service.autofill.InternalOnClickAction is not final
 ParcelNotFinal: android.service.autofill.InternalSanitizer:
-    
+    Parcelable classes must be final: android.service.autofill.InternalSanitizer is not final
 ParcelNotFinal: android.service.autofill.InternalTransformation:
-    
+    Parcelable classes must be final: android.service.autofill.InternalTransformation is not final
 ParcelNotFinal: android.service.autofill.InternalValidator:
-    
+    Parcelable classes must be final: android.service.autofill.InternalValidator is not final
 
 
 ProtectedMember: android.app.AppDetailsActivity#onCreate(android.os.Bundle):
-    
-ProtectedMember: android.os.VibrationEffect#scale(int, float, int):
-    
-ProtectedMember: android.service.autofill.augmented.AugmentedAutofillService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]):
-    
-ProtectedMember: android.service.autofill.augmented.AugmentedAutofillService#dump(java.io.PrintWriter, String[]):
-    
-ProtectedMember: android.service.contentcapture.ContentCaptureService#dump(java.io.FileDescriptor, java.io.PrintWriter, String[]):
-    
-ProtectedMember: android.service.notification.NotificationAssistantService#attachBaseContext(android.content.Context):
-    
-ProtectedMember: android.util.proto.ProtoStream#FIELD_TYPE_NAMES:
-    
+    Protected methods not allowed; must be public: method android.app.AppDetailsActivity.onCreate(android.os.Bundle)}
 ProtectedMember: android.view.View#resetResolvedDrawables():
-    
+    Protected methods not allowed; must be public: method android.view.View.resetResolvedDrawables()}
 ProtectedMember: android.view.ViewGroup#resetResolvedDrawables():
-    
-
-
-RawAidl: android.telephony.mbms.vendor.MbmsDownloadServiceBase:
-    
-RawAidl: android.telephony.mbms.vendor.MbmsStreamingServiceBase:
-    
+    Protected methods not allowed; must be public: method android.view.ViewGroup.resetResolvedDrawables()}
 
 
 RethrowRemoteException: android.app.ActivityManager#resumeAppSwitches():
-    
-RethrowRemoteException: android.os.HwBinder#getService(String, String):
-    
-RethrowRemoteException: android.os.HwBinder#getService(String, String, boolean):
-    
-RethrowRemoteException: android.os.HwBinder#onTransact(int, android.os.HwParcel, android.os.HwParcel, int):
-    
-RethrowRemoteException: android.os.HwBinder#registerService(String):
-    
-RethrowRemoteException: android.os.HwBinder#transact(int, android.os.HwParcel, android.os.HwParcel, int):
-    
-RethrowRemoteException: android.os.IHwBinder#transact(int, android.os.HwParcel, android.os.HwParcel, int):
-    
-RethrowRemoteException: android.telephony.ims.ImsService#onUpdateSupportedImsFeatures(android.telephony.ims.stub.ImsFeatureConfiguration):
-    
-RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener):
-    
-RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#addStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener):
-    
-RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#cancelDownload(android.telephony.mbms.DownloadRequest):
-    
-RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#dispose(int):
-    
-RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#download(android.telephony.mbms.DownloadRequest):
-    
-RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#initialize(int, android.telephony.mbms.MbmsDownloadSessionCallback):
-    
-RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#listPendingDownloads(int):
-    
-RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#onTransact(int, android.os.Parcel, android.os.Parcel, int):
-    
-RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#removeProgressListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadProgressListener):
-    
-RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#removeStatusListener(android.telephony.mbms.DownloadRequest, android.telephony.mbms.DownloadStatusListener):
-    
-RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#requestDownloadState(android.telephony.mbms.DownloadRequest, android.telephony.mbms.FileInfo):
-    
-RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#requestUpdateFileServices(int, java.util.List<java.lang.String>):
-    
-RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#resetDownloadKnowledge(android.telephony.mbms.DownloadRequest):
-    
-RethrowRemoteException: android.telephony.mbms.vendor.MbmsDownloadServiceBase#setTempFileRootDirectory(int, String):
-    
-RethrowRemoteException: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#dispose(int):
-    
-RethrowRemoteException: android.telephony.mbms.vendor.MbmsGroupCallServiceBase#initialize(android.telephony.mbms.MbmsGroupCallSessionCallback, int):
-    
-RethrowRemoteException: android.telephony.mbms.vendor.MbmsStreamingServiceBase#dispose(int):
-    
-RethrowRemoteException: android.telephony.mbms.vendor.MbmsStreamingServiceBase#getPlaybackUri(int, String):
-    
-RethrowRemoteException: android.telephony.mbms.vendor.MbmsStreamingServiceBase#initialize(android.telephony.mbms.MbmsStreamingSessionCallback, int):
-    
-RethrowRemoteException: android.telephony.mbms.vendor.MbmsStreamingServiceBase#onTransact(int, android.os.Parcel, android.os.Parcel, int):
-    
-RethrowRemoteException: android.telephony.mbms.vendor.MbmsStreamingServiceBase#requestUpdateStreamingServices(int, java.util.List<java.lang.String>):
-    
-RethrowRemoteException: android.telephony.mbms.vendor.MbmsStreamingServiceBase#startStreaming(int, String, android.telephony.mbms.StreamingServiceCallback):
-    
-RethrowRemoteException: android.telephony.mbms.vendor.MbmsStreamingServiceBase#stopStreaming(int, String):
-    
+    Methods calling system APIs should rethrow `RemoteException` as `RuntimeException` (but do not list it in the throws clause)
 
 
-SamShouldBeLast: android.app.ActivityManager#addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int):
-    
 SamShouldBeLast: android.database.sqlite.SQLiteDebug#dump(android.util.Printer, String[]):
-    
+    SAM-compatible parameters (such as parameter 1, "printer", in android.database.sqlite.SQLiteDebug.dump) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.database.sqlite.SQLiteDirectCursorDriver#query(android.database.sqlite.SQLiteDatabase.CursorFactory, String[]):
-    
-SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(android.location.LocationRequest, android.location.LocationListener, android.os.Looper):
-    
-SamShouldBeLast: android.location.LocationManager#requestLocationUpdates(android.location.LocationRequest, java.util.concurrent.Executor, android.location.LocationListener):
-    
-SamShouldBeLast: android.os.BugreportManager#startBugreport(android.os.ParcelFileDescriptor, android.os.ParcelFileDescriptor, android.os.BugreportParams, java.util.concurrent.Executor, android.os.BugreportManager.BugreportCallback):
-    
-SamShouldBeLast: android.os.IHwBinder#linkToDeath(android.os.IHwBinder.DeathRecipient, long):
-    
+    SAM-compatible parameters (such as parameter 1, "factory", in android.database.sqlite.SQLiteDirectCursorDriver.query) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.os.StrictMode.ViolationInfo#dump(android.util.Printer, String):
-    
+    SAM-compatible parameters (such as parameter 1, "pw", in android.os.StrictMode.ViolationInfo.dump) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.permission.PermissionControllerManager#countPermissionApps(java.util.List<java.lang.String>, int, android.permission.PermissionControllerManager.OnCountPermissionAppsResultCallback, android.os.Handler):
-    
+    SAM-compatible parameters (such as parameter 3, "callback", in android.permission.PermissionControllerManager.countPermissionApps) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.permission.PermissionControllerManager#getAppPermissions(String, android.permission.PermissionControllerManager.OnGetAppPermissionResultCallback, android.os.Handler):
-    
-SamShouldBeLast: android.permission.PermissionControllerManager#revokeRuntimePermissions(java.util.Map<java.lang.String,java.util.List<java.lang.String>>, boolean, int, java.util.concurrent.Executor, android.permission.PermissionControllerManager.OnRevokeRuntimePermissionsCallback):
-    
+    SAM-compatible parameters (such as parameter 2, "callback", in android.permission.PermissionControllerManager.getAppPermissions) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.service.autofill.CharSequenceTransformation#apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int):
-    
+    SAM-compatible parameters (such as parameter 1, "finder", in android.service.autofill.CharSequenceTransformation.apply) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.service.autofill.DateTransformation#apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int):
-    
+    SAM-compatible parameters (such as parameter 1, "finder", in android.service.autofill.DateTransformation.apply) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.service.autofill.ImageTransformation#apply(android.service.autofill.ValueFinder, android.widget.RemoteViews, int):
-    
+    SAM-compatible parameters (such as parameter 1, "finder", in android.service.autofill.ImageTransformation.apply) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.service.autofill.InternalTransformation#batchApply(android.service.autofill.ValueFinder, android.widget.RemoteViews, java.util.ArrayList<android.util.Pair<java.lang.Integer,android.service.autofill.InternalTransformation>>):
-    
-SamShouldBeLast: android.telephony.ims.ImsMmTelManager#getFeatureState(java.util.function.Consumer<java.lang.Integer>, java.util.concurrent.Executor):
-    
+    SAM-compatible parameters (such as parameter 1, "finder", in android.service.autofill.InternalTransformation.batchApply) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.view.Choreographer#postCallback(int, Runnable, Object):
-    
+    SAM-compatible parameters (such as parameter 2, "action", in android.view.Choreographer.postCallback) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.view.Choreographer#postCallbackDelayed(int, Runnable, Object, long):
-    
+    SAM-compatible parameters (such as parameter 2, "action", in android.view.Choreographer.postCallbackDelayed) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 SamShouldBeLast: android.view.Choreographer#removeCallbacks(int, Runnable, Object):
-    
-SamShouldBeLast: android.view.ViewDebug#startRenderingCommandsCapture(android.view.View, java.util.concurrent.Executor, java.util.function.Function<android.graphics.Picture,java.lang.Boolean>):
-    
-SamShouldBeLast: android.view.accessibility.AccessibilityManager#addAccessibilityServicesStateChangeListener(android.view.accessibility.AccessibilityManager.AccessibilityServicesStateChangeListener, android.os.Handler):
-    
-
-
-ServiceName: android.Manifest.permission#BIND_CELL_BROADCAST_SERVICE:
-    
-ServiceName: android.app.AppOpsManager#OPSTR_BIND_ACCESSIBILITY_SERVICE:
-    
-ServiceName: android.provider.Settings.Secure#ACCESSIBILITY_SHORTCUT_TARGET_SERVICE:
-    
-ServiceName: android.provider.Settings.Secure#AUTOFILL_SERVICE:
-    
-ServiceName: android.provider.Settings.Secure#VOICE_INTERACTION_SERVICE:
-    
-
-
-SetterReturnsThis: android.media.audiopolicy.AudioPolicy.Builder#setAudioPolicyFocusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyFocusListener):
-    
-SetterReturnsThis: android.media.audiopolicy.AudioPolicy.Builder#setAudioPolicyStatusListener(android.media.audiopolicy.AudioPolicy.AudioPolicyStatusListener):
-    
-
-
-StartWithLower: android.content.pm.PackageManager#BINDER():
-    Method name must start with lowercase char: BINDER
-
-
-StaticFinalBuilder: android.content.integrity.RuleSet.Builder:
-    
-StaticFinalBuilder: android.hardware.display.BrightnessConfiguration.Builder:
-    
-StaticFinalBuilder: android.media.audiopolicy.AudioMix.Builder:
-    
-StaticFinalBuilder: android.media.audiopolicy.AudioMixingRule.Builder:
-    
-StaticFinalBuilder: android.media.audiopolicy.AudioPolicy.Builder:
-    
-StaticFinalBuilder: android.net.CaptivePortalData.Builder:
-    
-StaticFinalBuilder: android.net.TetheringManager.TetheringRequest.Builder:
-    
-StaticFinalBuilder: android.telephony.ims.stub.ImsFeatureConfiguration.Builder:
-    
+    SAM-compatible parameters (such as parameter 2, "action", in android.view.Choreographer.removeCallbacks) should be last to improve Kotlin interoperability; see https://kotlinlang.org/docs/reference/java-interop.html#sam-conversions
 
 
 StaticUtils: android.os.health.HealthKeys:
-    
+    Fully-static utility classes must not have constructor
 StaticUtils: android.service.autofill.InternalTransformation:
-    
-StaticUtils: android.telephony.mbms.vendor.VendorUtils:
-    
+    Fully-static utility classes must not have constructor
 StaticUtils: android.util.FeatureFlagUtils:
-    
-StaticUtils: android.util.proto.ProtoStream:
-    
+    Fully-static utility classes must not have constructor
 
 
 StreamFiles: android.os.Environment#buildPath(java.io.File, java.lang.String...):
-    
+    Methods accepting `File` should also accept `FileDescriptor` or streams: method android.os.Environment.buildPath(java.io.File,java.lang.String...)
 StreamFiles: android.os.FileUtils#contains(java.io.File, java.io.File):
-    
-StreamFiles: android.provider.MediaStore#scanFile(android.content.Context, java.io.File):
-    
-StreamFiles: android.provider.MediaStore#scanFileFromShell(android.content.Context, java.io.File):
-    
-StreamFiles: android.provider.MediaStore#scanVolume(android.content.Context, java.io.File):
-    
+    Methods accepting `File` should also accept `FileDescriptor` or streams: method android.os.FileUtils.contains(java.io.File,java.io.File)
 
 
 UseIcu: android.hardware.soundtrigger.KeyphraseEnrollmentInfo#getKeyphraseMetadata(String, java.util.Locale) parameter #1:
-    
+    Type `java.util.Locale` should be replaced with richer ICU type `android.icu.util.ULocale`
 UseIcu: android.hardware.soundtrigger.KeyphraseEnrollmentInfo#getManageKeyphraseIntent(int, String, java.util.Locale) parameter #2:
-    
+    Type `java.util.Locale` should be replaced with richer ICU type `android.icu.util.ULocale`
 UseIcu: android.hardware.soundtrigger.KeyphraseMetadata#supportsLocale(java.util.Locale) parameter #0:
-    
-UseIcu: android.hardware.soundtrigger.SoundTrigger.Keyphrase#Keyphrase(int, int, java.util.Locale, String, int[]) parameter #2:
-    
-UseIcu: android.hardware.soundtrigger.SoundTrigger.Keyphrase#getLocale():
-    
+    Type `java.util.Locale` should be replaced with richer ICU type `android.icu.util.ULocale`
 
 
-UseParcelFileDescriptor: android.util.proto.ProtoOutputStream#ProtoOutputStream(java.io.FileDescriptor) parameter #0:
-    
-
-
-UserHandle: android.app.ActivityManager#switchUser(android.os.UserHandle):
-    
 UserHandle: android.app.admin.DevicePolicyManager#getOwnerInstalledCaCerts(android.os.UserHandle):
-    
+    When a method overload is needed to target a specific UserHandle, callers should be directed to use Context.createPackageContextAsUser() and re-obtain the relevant Manager, and no new API should be added
 UserHandle: android.app.usage.StorageStatsManager#queryCratesForPackage(java.util.UUID, String, android.os.UserHandle):
-    
+    When a method overload is needed to target a specific UserHandle, callers should be directed to use Context.createPackageContextAsUser() and re-obtain the relevant Manager, and no new API should be added
 UserHandle: android.app.usage.StorageStatsManager#queryCratesForUser(java.util.UUID, android.os.UserHandle):
-    
-UserHandle: android.companion.CompanionDeviceManager#isDeviceAssociated(String, android.net.MacAddress, android.os.UserHandle):
-    
-UserHandle: android.companion.CompanionDeviceManager#isDeviceAssociatedForWifiConnection(String, android.net.MacAddress, android.os.UserHandle):
-    
+    When a method overload is needed to target a specific UserHandle, callers should be directed to use Context.createPackageContextAsUser() and re-obtain the relevant Manager, and no new API should be added
 UserHandle: android.content.pm.PackageManager#getInstallReason(String, android.os.UserHandle):
-    
-UserHandle: android.content.pm.PackageManager#getPermissionFlags(String, String, android.os.UserHandle):
-    
-UserHandle: android.content.pm.PackageManager#grantRuntimePermission(String, String, android.os.UserHandle):
-    
-UserHandle: android.content.pm.PackageManager#revokeRuntimePermission(String, String, android.os.UserHandle):
-    
-UserHandle: android.content.pm.PackageManager#revokeRuntimePermission(String, String, android.os.UserHandle, String):
-    
-UserHandle: android.content.pm.PackageManager#updatePermissionFlags(String, String, int, int, android.os.UserHandle):
-    
-UserHandle: android.location.LocationManager#setLocationEnabledForUser(boolean, android.os.UserHandle):
-    
-UserHandle: android.permission.PermissionControllerManager#applyStagedRuntimePermissionBackup(String, android.os.UserHandle, java.util.concurrent.Executor, java.util.function.Consumer<java.lang.Boolean>):
-    
-UserHandle: android.permission.PermissionControllerManager#getRuntimePermissionBackup(android.os.UserHandle, java.util.concurrent.Executor, java.util.function.Consumer<byte[]>):
-    
-UserHandle: android.permission.PermissionControllerManager#stageAndApplyRuntimePermissionsBackup(byte[], android.os.UserHandle):
-    
-UserHandle: android.telecom.TelecomManager#getDefaultDialerPackage(android.os.UserHandle):
-    
+    When a method overload is needed to target a specific UserHandle, callers should be directed to use Context.createPackageContextAsUser() and re-obtain the relevant Manager, and no new API should be added
 
 
 UserHandleName: android.content.AutofillOptions:
-    
+    Classes holding a set of parameters should be called `FooParams`, was `AutofillOptions`
 UserHandleName: android.content.ContentCaptureOptions:
-    
-UserHandleName: android.os.IncidentReportArgs:
-    
-UserHandleName: android.provider.MediaStore#deleteContributedMedia(android.content.Context, String, android.os.UserHandle):
-    
-UserHandleName: android.provider.MediaStore#getContributedMediaSize(android.content.Context, String, android.os.UserHandle):
-    
+    Classes holding a set of parameters should be called `FooParams`, was `ContentCaptureOptions`
 
 
-VisiblySynchronized: PsiClassObjectAccessExpression:
-    
-VisiblySynchronized: PsiThisExpression:
-    
-VisiblySynchronized: android.app.ActivityManager#addOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener, int):
-    
-VisiblySynchronized: android.app.ActivityManager#removeOnUidImportanceListener(android.app.ActivityManager.OnUidImportanceListener):
-    
-VisiblySynchronized: android.content.ContentProviderClient#setDetectNotResponding(long):
-    
+VisiblySynchronized: PsiThisExpression:this:
+    Internal locks must not be exposed (synchronizing on this or class is still externally observable): method android.content.res.AssetManager.getApkPaths()
 VisiblySynchronized: android.content.res.AssetManager#getApkPaths():
-    
+    Internal locks must not be exposed (synchronizing on this or class is still externally observable): method android.content.res.AssetManager.getApkPaths()
 VisiblySynchronized: android.content.res.AssetManager#getLastResourceResolution():
-    
+    Internal locks must not be exposed (synchronizing on this or class is still externally observable): method android.content.res.AssetManager.getLastResourceResolution()
 VisiblySynchronized: android.content.res.AssetManager#getOverlayablesToString(String):
-    
+    Internal locks must not be exposed (synchronizing on this or class is still externally observable): method android.content.res.AssetManager.getOverlayablesToString(String)
 VisiblySynchronized: android.content.res.AssetManager#setResourceResolutionLoggingEnabled(boolean):
-    
+    Internal locks must not be exposed (synchronizing on this or class is still externally observable): method android.content.res.AssetManager.setResourceResolutionLoggingEnabled(boolean)
 VisiblySynchronized: android.os.MessageQueue#removeSyncBarrier(int):
-    
+    Internal locks must not be exposed (synchronizing on this or class is still externally observable): method android.os.MessageQueue.removeSyncBarrier(int)
diff --git a/core/java/android/app/KeyguardManager.java b/core/java/android/app/KeyguardManager.java
index e9c29b8..c802d20 100644
--- a/core/java/android/app/KeyguardManager.java
+++ b/core/java/android/app/KeyguardManager.java
@@ -261,8 +261,10 @@
             CharSequence title, CharSequence description, int userId,
             boolean disallowBiometricsIfPolicyExists) {
         Intent intent = this.createConfirmDeviceCredentialIntent(title, description, userId);
-        intent.putExtra(EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS,
-                disallowBiometricsIfPolicyExists);
+        if (intent != null) {
+            intent.putExtra(EXTRA_DISALLOW_BIOMETRICS_IF_POLICY_EXISTS,
+                    disallowBiometricsIfPolicyExists);
+        }
         return intent;
     }
 
diff --git a/core/java/android/inputmethodservice/NavigationBarController.java b/core/java/android/inputmethodservice/NavigationBarController.java
index dc38db2..6910501 100644
--- a/core/java/android/inputmethodservice/NavigationBarController.java
+++ b/core/java/android/inputmethodservice/NavigationBarController.java
@@ -152,6 +152,7 @@
         private boolean mDrawLegacyNavigationBarBackground;
 
         private final Rect mTempRect = new Rect();
+        private final int[] mTempPos = new int[2];
 
         Impl(@NonNull InputMethodService inputMethodService) {
             mService = inputMethodService;
@@ -259,21 +260,28 @@
                 switch (originalInsets.touchableInsets) {
                     case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_FRAME:
                         if (inputFrame.getVisibility() == View.VISIBLE) {
-                            inputFrame.getBoundsOnScreen(mTempRect);
+                            inputFrame.getLocationInWindow(mTempPos);
+                            mTempRect.set(mTempPos[0], mTempPos[1],
+                                    mTempPos[0] + inputFrame.getWidth(),
+                                    mTempPos[1] + inputFrame.getHeight());
                             touchableRegion = new Region(mTempRect);
                         }
                         break;
                     case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_CONTENT:
                         if (inputFrame.getVisibility() == View.VISIBLE) {
-                            inputFrame.getBoundsOnScreen(mTempRect);
-                            mTempRect.top = originalInsets.contentTopInsets;
+                            inputFrame.getLocationInWindow(mTempPos);
+                            mTempRect.set(mTempPos[0], originalInsets.contentTopInsets,
+                                    mTempPos[0] + inputFrame.getWidth() ,
+                                    mTempPos[1] + inputFrame.getHeight());
                             touchableRegion = new Region(mTempRect);
                         }
                         break;
                     case ViewTreeObserver.InternalInsetsInfo.TOUCHABLE_INSETS_VISIBLE:
                         if (inputFrame.getVisibility() == View.VISIBLE) {
-                            inputFrame.getBoundsOnScreen(mTempRect);
-                            mTempRect.top = originalInsets.visibleTopInsets;
+                            inputFrame.getLocationInWindow(mTempPos);
+                            mTempRect.set(mTempPos[0], originalInsets.visibleTopInsets,
+                                    mTempPos[0] + inputFrame.getWidth(),
+                                    mTempPos[1] + inputFrame.getHeight());
                             touchableRegion = new Region(mTempRect);
                         }
                         break;
diff --git a/core/java/android/net/Uri.java b/core/java/android/net/Uri.java
index 815e4f0..d71faee4 100644
--- a/core/java/android/net/Uri.java
+++ b/core/java/android/net/Uri.java
@@ -1205,13 +1205,16 @@
         }
 
         static Uri readFrom(Parcel parcel) {
-            return new HierarchicalUri(
-                parcel.readString8(),
-                Part.readFrom(parcel),
-                PathPart.readFrom(parcel),
-                Part.readFrom(parcel),
-                Part.readFrom(parcel)
-            );
+            final String scheme = parcel.readString8();
+            final Part authority = Part.readFrom(parcel);
+            // In RFC3986 the path should be determined based on whether there is a scheme or
+            // authority present (https://www.rfc-editor.org/rfc/rfc3986.html#section-3.3).
+            final boolean hasSchemeOrAuthority =
+                    (scheme != null && scheme.length() > 0) || !authority.isEmpty();
+            final PathPart path = PathPart.readFrom(hasSchemeOrAuthority, parcel);
+            final Part query = Part.readFrom(parcel);
+            final Part fragment = Part.readFrom(parcel);
+            return new HierarchicalUri(scheme, authority, path, query, fragment);
         }
 
         public int describeContents() {
@@ -2270,6 +2273,11 @@
             }
         }
 
+        static PathPart readFrom(boolean hasSchemeOrAuthority, Parcel parcel) {
+            final PathPart path = readFrom(parcel);
+            return hasSchemeOrAuthority ? makeAbsolute(path) : path;
+        }
+
         /**
          * Creates a path from the encoded string.
          *
diff --git a/core/java/android/permission/ILegacyPermissionManager.aidl b/core/java/android/permission/ILegacyPermissionManager.aidl
index f1f0836..78e12de 100644
--- a/core/java/android/permission/ILegacyPermissionManager.aidl
+++ b/core/java/android/permission/ILegacyPermissionManager.aidl
@@ -49,4 +49,6 @@
     void grantDefaultPermissionsToActiveLuiApp(in String packageName, int userId);
 
     void revokeDefaultPermissionsFromLuiApps(in String[] packageNames, int userId);
+
+    void grantDefaultPermissionsToCarrierServiceApp(in String packageName, int userId);
 }
diff --git a/core/java/android/permission/LegacyPermissionManager.java b/core/java/android/permission/LegacyPermissionManager.java
index a4fa11b..5777685 100644
--- a/core/java/android/permission/LegacyPermissionManager.java
+++ b/core/java/android/permission/LegacyPermissionManager.java
@@ -22,6 +22,7 @@
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
 import android.annotation.SystemService;
+import android.annotation.UserIdInt;
 import android.content.Context;
 import android.content.pm.PackageManager;
 import android.os.RemoteException;
@@ -244,4 +245,20 @@
             e.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Grant permissions to a newly set Carrier Services app.
+     * @param packageName The newly set Carrier Services app
+     * @param userId The user for which to grant the permissions.
+     * @hide
+     */
+    public void grantDefaultPermissionsToCarrierServiceApp(@NonNull String packageName,
+            @UserIdInt int userId) {
+        try {
+            mLegacyPermissionManager.grantDefaultPermissionsToCarrierServiceApp(packageName,
+                    userId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index d25e456..37f44e9 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -731,6 +731,13 @@
     public static final String NAMESPACE_AMBIENT_CONTEXT_MANAGER_SERVICE =
             "ambient_context_manager_service";
 
+    /**
+     * Namespace for Vendor System Native related features.
+     *
+     * @hide
+     */
+    public static final String NAMESPACE_VENDOR_SYSTEM_NATIVE = "vendor_system_native";
+
     private static final Object sLock = new Object();
     @GuardedBy("sLock")
     private static ArrayMap<OnPropertiesChangedListener, Pair<String, Executor>> sListeners =
diff --git a/core/java/android/service/games/GameSession.java b/core/java/android/service/games/GameSession.java
index 0115294..e8d53d3 100644
--- a/core/java/android/service/games/GameSession.java
+++ b/core/java/android/service/games/GameSession.java
@@ -25,7 +25,6 @@
 import android.annotation.SystemApi;
 import android.app.ActivityTaskManager;
 import android.app.Instrumentation;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.res.Configuration;
@@ -511,14 +510,11 @@
                             callback.onActivityResult(result.getResultCode(), result.getData());
                         }, executor);
 
-        final Intent trampolineIntent = new Intent();
-        trampolineIntent.setComponent(
-                new ComponentName(
-                        "android", "android.service.games.GameSessionTrampolineActivity"));
-        trampolineIntent.putExtra(GameSessionTrampolineActivity.INTENT_KEY, intent);
-        trampolineIntent.putExtra(GameSessionTrampolineActivity.OPTIONS_KEY, options);
-        trampolineIntent.putExtra(
-                GameSessionTrampolineActivity.FUTURE_KEY, future);
+        final Intent trampolineIntent =
+                GameSessionTrampolineActivity.createIntent(
+                        intent,
+                        options,
+                        future);
 
         try {
             int result = ActivityTaskManager.getService().startActivityFromGameSession(
diff --git a/core/java/android/service/games/GameSessionActivityResult.java b/core/java/android/service/games/GameSessionActivityResult.java
index a2ec6ad..c8099e6 100644
--- a/core/java/android/service/games/GameSessionActivityResult.java
+++ b/core/java/android/service/games/GameSessionActivityResult.java
@@ -22,8 +22,12 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import com.android.internal.annotations.VisibleForTesting;
 
-final class GameSessionActivityResult implements Parcelable {
+
+/** @hide */
+@VisibleForTesting
+public final class GameSessionActivityResult implements Parcelable {
 
     public static final Creator<GameSessionActivityResult> CREATOR =
             new Creator<GameSessionActivityResult>() {
@@ -44,17 +48,17 @@
     @Nullable
     private final Intent mData;
 
-    GameSessionActivityResult(int resultCode, @Nullable Intent data) {
+    public GameSessionActivityResult(int resultCode, @Nullable Intent data) {
         mResultCode = resultCode;
         mData = data;
     }
 
-    int getResultCode() {
+    public int getResultCode() {
         return mResultCode;
     }
 
     @Nullable
-    Intent getData() {
+    public Intent getData() {
         return mData;
     }
 
diff --git a/core/java/android/service/games/GameSessionService.java b/core/java/android/service/games/GameSessionService.java
index df5bad5..52c8ec3 100644
--- a/core/java/android/service/games/GameSessionService.java
+++ b/core/java/android/service/games/GameSessionService.java
@@ -21,6 +21,7 @@
 import android.annotation.SdkConstant;
 import android.annotation.SystemApi;
 import android.app.Service;
+import android.content.Context;
 import android.content.Intent;
 import android.hardware.display.DisplayManager;
 import android.os.Binder;
@@ -28,6 +29,7 @@
 import android.os.IBinder;
 import android.view.Display;
 import android.view.SurfaceControlViewHost;
+import android.view.WindowManager;
 
 import com.android.internal.infra.AndroidFuture;
 import com.android.internal.util.function.pooled.PooledLambda;
@@ -117,13 +119,18 @@
         }
 
         IBinder hostToken = new Binder();
+
+        // Use a WindowContext so that views attached to the SurfaceControlViewHost will receive
+        // configuration changes (rather than always perceiving the global configuration).
+        final Context windowContext = createWindowContext(display,
+                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY, /*options=*/ null);
         SurfaceControlViewHost surfaceControlViewHost =
-                new SurfaceControlViewHost(this, display, hostToken);
+                new SurfaceControlViewHost(windowContext, display, hostToken);
 
         gameSession.attach(
                 gameSessionController,
                 createGameSessionRequest.getTaskId(),
-                this,
+                windowContext,
                 surfaceControlViewHost,
                 gameSessionViewHostConfiguration.mWidthPx,
                 gameSessionViewHostConfiguration.mHeightPx);
diff --git a/core/java/android/service/games/GameSessionTrampolineActivity.java b/core/java/android/service/games/GameSessionTrampolineActivity.java
index 3d97d0f..b237918 100644
--- a/core/java/android/service/games/GameSessionTrampolineActivity.java
+++ b/core/java/android/service/games/GameSessionTrampolineActivity.java
@@ -16,12 +16,15 @@
 
 package android.service.games;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.Activity;
+import android.content.ComponentName;
 import android.content.Intent;
 import android.os.Bundle;
 import android.util.Slog;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.infra.AndroidFuture;
 
 import java.util.concurrent.Executor;
@@ -35,6 +38,7 @@
  *
  * @hide
  */
+@VisibleForTesting
 public final class GameSessionTrampolineActivity extends Activity {
     private static final String TAG = "GameSessionTrampoline";
     private static final int REQUEST_CODE = 1;
@@ -42,11 +46,52 @@
     static final String FUTURE_KEY = "GameSessionTrampolineActivity.future";
     static final String INTENT_KEY = "GameSessionTrampolineActivity.intent";
     static final String OPTIONS_KEY = "GameSessionTrampolineActivity.options";
+    private static final String HAS_LAUNCHED_INTENT_KEY =
+            "GameSessionTrampolineActivity.hasLaunchedIntent";
+    private boolean mHasLaunchedIntent = false;
+
+    /**
+     * Create an {@link Intent} for the {@link GameSessionTrampolineActivity} with the given
+     * parameters.
+     *
+     * @param targetIntent the forwarded {@link Intent} that is associated with the Activity that
+     *                     will be launched by the {@link GameSessionTrampolineActivity}.
+     * @param options      Activity options. See {@link #startActivity(Intent, Bundle)}.
+     * @param resultFuture the {@link AndroidFuture} that will complete with the activity results of
+     *                     {@code targetIntent} launched.
+     * @return the Intent that will launch the {@link GameSessionTrampolineActivity} with the given
+     * parameters.
+     * @hide
+     */
+    @VisibleForTesting
+    public static Intent createIntent(
+            @NonNull Intent targetIntent,
+            @Nullable Bundle options,
+            @NonNull AndroidFuture<GameSessionActivityResult> resultFuture) {
+        final Intent trampolineIntent = new Intent();
+        trampolineIntent.setComponent(
+                new ComponentName(
+                        "android", "android.service.games.GameSessionTrampolineActivity"));
+        trampolineIntent.putExtra(INTENT_KEY, targetIntent);
+        trampolineIntent.putExtra(OPTIONS_KEY, options);
+        trampolineIntent.putExtra(FUTURE_KEY, resultFuture);
+
+        return trampolineIntent;
+    }
 
     @Override
     protected void onCreate(@Nullable Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
+        if (savedInstanceState != null) {
+            mHasLaunchedIntent = savedInstanceState.getBoolean(HAS_LAUNCHED_INTENT_KEY);
+        }
+
+        if (mHasLaunchedIntent) {
+            return;
+        }
+        mHasLaunchedIntent = true;
+
         try {
             startActivityAsCaller(
                     getIntent().getParcelableExtra(INTENT_KEY),
@@ -60,10 +105,17 @@
                     FUTURE_KEY);
             future.completeExceptionally(e);
             finish();
+            overridePendingTransition(0, 0);
         }
     }
 
     @Override
+    protected void onSaveInstanceState(Bundle outState) {
+        super.onSaveInstanceState(outState);
+        outState.putBoolean(HAS_LAUNCHED_INTENT_KEY, mHasLaunchedIntent);
+    }
+
+    @Override
     protected void onActivityResult(int requestCode, int resultCode, Intent data) {
         if (requestCode != REQUEST_CODE) {
             // Something went very wrong if we hit this code path, and we should bail.
@@ -74,5 +126,6 @@
                 FUTURE_KEY);
         future.complete(new GameSessionActivityResult(resultCode, data));
         finish();
+        overridePendingTransition(0, 0);
     }
 }
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 4bbfbc2..b783f6b8 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -1095,7 +1095,7 @@
             if (!mWindowVisible) {
                 mWindowVisible = true;
                 if (mUiEnabled) {
-                    mWindow.show();
+                    showWindow();
                 }
             }
             if (showCallback != null) {
@@ -1284,9 +1284,25 @@
         }
     }
 
+    void showWindow() {
+        if (mWindow != null) {
+            mWindow.show();
+            try {
+                mSystemService.setSessionWindowVisible(mToken, true);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed to notify session window shown", e);
+            }
+        }
+    }
+
     void ensureWindowHidden() {
         if (mWindow != null) {
             mWindow.hide();
+            try {
+                mSystemService.setSessionWindowVisible(mToken, false);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Failed to notify session window hidden", e);
+            }
         }
     }
 
@@ -1377,7 +1393,7 @@
             if (mWindowVisible) {
                 if (enabled) {
                     ensureWindowAdded();
-                    mWindow.show();
+                    showWindow();
                 } else {
                     ensureWindowHidden();
                 }
diff --git a/core/java/android/view/InsetsSource.java b/core/java/android/view/InsetsSource.java
index e6cf683..5832527 100644
--- a/core/java/android/view/InsetsSource.java
+++ b/core/java/android/view/InsetsSource.java
@@ -47,6 +47,7 @@
     private final Rect mFrame;
     private @Nullable Rect mVisibleFrame;
     private boolean mVisible;
+    private boolean mInsetsRoundedCornerFrame;
 
     private final Rect mTmpFrame = new Rect();
 
@@ -63,6 +64,7 @@
         mVisibleFrame = other.mVisibleFrame != null
                 ? new Rect(other.mVisibleFrame)
                 : null;
+        mInsetsRoundedCornerFrame = other.mInsetsRoundedCornerFrame;
     }
 
     public void set(InsetsSource other) {
@@ -71,6 +73,7 @@
         mVisibleFrame = other.mVisibleFrame != null
                 ? new Rect(other.mVisibleFrame)
                 : null;
+        mInsetsRoundedCornerFrame = other.mInsetsRoundedCornerFrame;
     }
 
     public void setFrame(int left, int top, int right, int bottom) {
@@ -110,6 +113,14 @@
         return mVisibleFrame == null || !mVisibleFrame.isEmpty();
     }
 
+    public boolean getInsetsRoundedCornerFrame() {
+        return mInsetsRoundedCornerFrame;
+    }
+
+    public void setInsetsRoundedCornerFrame(boolean insetsRoundedCornerFrame) {
+        mInsetsRoundedCornerFrame = insetsRoundedCornerFrame;
+    }
+
     /**
      * Calculates the insets this source will cause to a client window.
      *
@@ -225,6 +236,7 @@
             pw.print(" visibleFrame="); pw.print(mVisibleFrame.toShortString());
         }
         pw.print(" visible="); pw.print(mVisible);
+        pw.print(" insetsRoundedCornerFrame="); pw.print(mInsetsRoundedCornerFrame);
         pw.println();
     }
 
@@ -247,6 +259,7 @@
         if (mVisible != that.mVisible) return false;
         if (excludeInvisibleImeFrames && !mVisible && mType == ITYPE_IME) return true;
         if (!Objects.equals(mVisibleFrame, that.mVisibleFrame)) return false;
+        if (mInsetsRoundedCornerFrame != that.mInsetsRoundedCornerFrame) return false;
         return mFrame.equals(that.mFrame);
     }
 
@@ -256,6 +269,7 @@
         result = 31 * result + mFrame.hashCode();
         result = 31 * result + (mVisibleFrame != null ? mVisibleFrame.hashCode() : 0);
         result = 31 * result + (mVisible ? 1 : 0);
+        result = 31 * result + (mInsetsRoundedCornerFrame ? 1 : 0);
         return result;
     }
 
@@ -268,6 +282,7 @@
             mVisibleFrame = null;
         }
         mVisible = in.readBoolean();
+        mInsetsRoundedCornerFrame = in.readBoolean();
     }
 
     @Override
@@ -286,6 +301,7 @@
             dest.writeInt(0);
         }
         dest.writeBoolean(mVisible);
+        dest.writeBoolean(mInsetsRoundedCornerFrame);
     }
 
     @Override
@@ -294,6 +310,7 @@
                 + "mType=" + InsetsState.typeToString(mType)
                 + ", mFrame=" + mFrame.toShortString()
                 + ", mVisible=" + mVisible
+                + ", mInsetsRoundedCornerFrame=" + mInsetsRoundedCornerFrame
                 + "}";
     }
 
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index eb74608..9d6b982 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -294,9 +294,16 @@
             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);
+        // frame.
+        final Rect roundedCornerFrame = new Rect(mRoundedCornerFrame);
+        for (InsetsSource source : mSources) {
+            if (source != null && source.getInsetsRoundedCornerFrame()) {
+                final Insets insets = source.calculateInsets(roundedCornerFrame, false);
+                roundedCornerFrame.inset(insets);
+            }
+        }
+        if (!roundedCornerFrame.isEmpty() && !roundedCornerFrame.equals(mDisplayFrame)) {
+            return mRoundedCorners.insetWithFrame(frame, roundedCornerFrame);
         }
         if (mDisplayFrame.equals(frame)) {
             return mRoundedCorners;
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index cf5727e..62d0d37d 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -12066,8 +12066,8 @@
      * <p>In multiple-screen scenarios, if the surface spans multiple screens,
      * the coordinate space of the surface also spans multiple screens.
      *
-     * <p>After the method returns, the argument array contains the x- and
-     * y-coordinates of the view relative to the view's left and top edges,
+     * <p>After the method returns, the argument array contains the x and y
+     * coordinates of the view relative to the view's left and top edges,
      * respectively.
      *
      * @param location A two-element integer array in which the view coordinates
@@ -18743,18 +18743,37 @@
     }
 
     /**
-     * If some part of this view is not clipped by any of its parents, then
-     * return that area in r in global (root) coordinates. To convert r to local
-     * coordinates (without taking possible View rotations into account), offset
-     * it by -globalOffset (e.g. r.offset(-globalOffset.x, -globalOffset.y)).
-     * If the view is completely clipped or translated out, return false.
+     * Sets {@code r} to the coordinates of the non-clipped area of this view in
+     * the coordinate space of the view's root view. Sets {@code globalOffset}
+     * to the offset of the view's x and y coordinates from the coordinate space
+     * origin, which is the top left corner of the root view irrespective of
+     * screen decorations and system UI elements.
      *
-     * @param r If true is returned, r holds the global coordinates of the
-     *        visible portion of this view.
-     * @param globalOffset If true is returned, globalOffset holds the dx,dy
-     *        between this view and its root. globalOffet may be null.
-     * @return true if r is non-empty (i.e. part of the view is visible at the
-     *         root level.
+     * <p>To convert {@code r} to coordinates relative to the top left corner of
+     * this view (without taking view rotations into account), offset {@code r}
+     * by the inverse values of
+     * {@code globalOffset}&mdash;{@code r.offset(-globalOffset.x,
+     * -globalOffset.y)}&mdash;which is equivalent to calling
+     * {@link #getLocalVisibleRect(Rect) getLocalVisibleRect(Rect)}.
+     *
+     * <p><b>Note:</b> Do not use this method to determine the size of a window
+     * in multi-window mode; use
+     * {@link WindowManager#getCurrentWindowMetrics()}.
+     *
+     * @param r If the method returns true, contains the coordinates of the
+     *      visible portion of this view in the coordinate space of the view's
+     *      root view. If the method returns false, the contents of {@code r}
+     *      are undefined.
+     * @param globalOffset If the method returns true, contains the offset of
+     *      the x and y coordinates of this view from the top left corner of the
+     *      view's root view. If the method returns false, the contents of
+     *      {@code globalOffset} are undefined. The argument can be null (see
+     *      {@link #getGlobalVisibleRect(Rect) getGlobalVisibleRect(Rect)}.
+     * @return true if at least part of the view is visible within the root
+     *      view; false if the view is completely clipped or translated out of
+     *      the visible area of the root view.
+     *
+     * @see #getLocalVisibleRect(Rect)
      */
     public boolean getGlobalVisibleRect(Rect r, Point globalOffset) {
         int width = mRight - mLeft;
@@ -18769,10 +18788,48 @@
         return false;
     }
 
+    /**
+     * Sets {@code r} to the coordinates of the non-clipped area of this view in
+     * the coordinate space of the view's root view.
+     *
+     * <p>See {@link #getGlobalVisibleRect(Rect, Point)
+     * getGlobalVisibleRect(Rect, Point)} for more information.
+     *
+     * @param r If the method returns true, contains the coordinates of the
+     *      visible portion of this view in the coordinate space of the view's
+     *      root view. If the method returns false, the contents of {@code r}
+     *      are undefined.
+     * @return true if at least part of the view is visible within the root
+     *      view; otherwise false.
+     */
     public final boolean getGlobalVisibleRect(Rect r) {
         return getGlobalVisibleRect(r, null);
     }
 
+    /**
+     * Sets {@code r} to the coordinates of the non-clipped area of this view
+     * relative to the top left corner of the view.
+     *
+     * <p>If the view is clipped on the left or top, the left and top
+     * coordinates are offset from 0 by the clipped amount. For example, if the
+     * view is off screen 50px on the left and 30px at the top, the left and top
+     * coordinates are 50 and 30 respectively.
+     *
+     * <p>If the view is clipped on the right or bottom, the right and bottom
+     * coordinates are reduced by the clipped amount. For example, if the view
+     * is off screen 40px on the right and 20px at the bottom, the right
+     * coordinate is the view width - 40, and the bottom coordinate is the view
+     * height - 20.
+     *
+     * @param r If the method returns true, contains the coordinates of the
+     *      visible portion of this view relative to the top left corner of the
+     *      view. If the method returns false, the contents of {@code r} are
+     *      undefined.
+     * @return true if at least part of the view is visible; false if the view
+     *      is completely clipped or translated out of the visible area.
+     *
+     * @see #getGlobalVisibleRect(Rect, Point)
+     */
     public final boolean getLocalVisibleRect(Rect r) {
         final Point offset = mAttachInfo != null ? mAttachInfo.mPoint : new Point();
         if (getGlobalVisibleRect(r, offset)) {
@@ -25606,8 +25663,8 @@
      * multiple-screen environment, the coordinate space includes only the
      * screen on which the app is running.
      *
-     * <p>After the method returns, the argument array contains the x- and
-     * y-coordinates of the view relative to the view's left and top edges,
+     * <p>After the method returns, the argument array contains the x and y
+     * coordinates of the view relative to the view's left and top edges,
      * respectively.
      *
      * @param outLocation A two-element integer array in which the view
@@ -25637,8 +25694,8 @@
      * restricted to a single screen, the coordinate space includes only the
      * screen on which the app is running.
      *
-     * <p>After the method returns, the argument array contains the x- and
-     * y-coordinates of the view relative to the view's left and top edges,
+     * <p>After the method returns, the argument array contains the x and y
+     * coordinates of the view relative to the view's left and top edges,
      * respectively.
      *
      * @param outLocation A two-element integer array in which the view
diff --git a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
index 52d54cd..681693b 100644
--- a/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractionManagerService.aidl
@@ -284,4 +284,9 @@
      * Stops to listen the status of visible activity.
      */
     void stopListeningVisibleActivityChanged(in IBinder token);
+
+    /**
+     * Notifies when the session window is shown or hidden.
+     */
+    void setSessionWindowVisible(in IBinder token, boolean visible);
 }
diff --git a/core/java/com/android/internal/app/IVoiceInteractionSessionListener.aidl b/core/java/com/android/internal/app/IVoiceInteractionSessionListener.aidl
index bc757e2..6e40988 100644
--- a/core/java/com/android/internal/app/IVoiceInteractionSessionListener.aidl
+++ b/core/java/com/android/internal/app/IVoiceInteractionSessionListener.aidl
@@ -30,6 +30,11 @@
     void onVoiceSessionHidden();
 
     /**
+     * Called when a voice session window is shown/hidden.
+     */
+    void onVoiceSessionWindowVisibilityChanged(boolean visible);
+
+    /**
      * Called when UI hints were received.
      */
     void onSetUiHints(in Bundle args);
diff --git a/core/java/com/android/internal/app/LocalePickerWithRegion.java b/core/java/com/android/internal/app/LocalePickerWithRegion.java
index 314b0a0..a06ba9b 100644
--- a/core/java/com/android/internal/app/LocalePickerWithRegion.java
+++ b/core/java/com/android/internal/app/LocalePickerWithRegion.java
@@ -247,6 +247,7 @@
         // In order to make the list view work with CollapsingToolbarLayout,
         // we have to enable the nested scrolling feature of the list view.
         getListView().setNestedScrollingEnabled(true);
+        getListView().setDivider(null);
     }
 
     @Override
diff --git a/core/java/com/android/internal/app/ResolverListAdapter.java b/core/java/com/android/internal/app/ResolverListAdapter.java
index 351ac45..0a07e0a 100644
--- a/core/java/com/android/internal/app/ResolverListAdapter.java
+++ b/core/java/com/android/internal/app/ResolverListAdapter.java
@@ -233,8 +233,14 @@
         // copied the original unfiltered items to a separate List instance and can now filter
         // the remainder in-place without any further bookkeeping.
         boolean needsCopyOfUnfiltered = (mUnfilteredResolveList == currentResolveList);
-        mUnfilteredResolveList = performSecondaryResolveListFiltering(
+        List<ResolvedComponentInfo> originalList = performSecondaryResolveListFiltering(
                 currentResolveList, needsCopyOfUnfiltered);
+        if (originalList != null) {
+            // Only need the originalList value if there was a modification (otherwise it's null
+            // and shouldn't overwrite mUnfilteredResolveList).
+            mUnfilteredResolveList = originalList;
+        }
+
 
         return finishRebuildingListWithFilteredResults(currentResolveList, doPostProcessing);
     }
@@ -293,7 +299,7 @@
      * appearing in the rebuilt-list results, while still considering those items for the "other
      * profile" special-treatment described in {@code rebuildList()}.
      *
-     * @return the same (possibly null) List reference as {@code currentResolveList}, if the list is
+     * @return the same (possibly null) List reference as {@code currentResolveList} if the list is
      * unmodified as a result of filtering; or, if some item(s) were removed, then either a copy of
      * the original {@code currentResolveList} (if {@code returnCopyOfOriginalListIfModified} is
      * true), or null (otherwise).
diff --git a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
index 18fde47..5fe1111 100644
--- a/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
+++ b/core/java/com/android/internal/app/SuggestedLocaleAdapter.java
@@ -27,7 +27,6 @@
 import android.widget.BaseAdapter;
 import android.widget.Filter;
 import android.widget.Filterable;
-import android.widget.FrameLayout;
 import android.widget.TextView;
 
 import com.android.internal.R;
@@ -222,6 +221,7 @@
                         convertView = mInflater.inflate(
                                 R.layout.app_language_picker_current_locale_item, parent, false);
                         title = convertView.findViewById(R.id.language_picker_item);
+                        addStateDescriptionIntoCurrentLocaleItem(convertView);
                     } else {
                         convertView = mInflater.inflate(
                                 R.layout.language_picker_item, parent, false);
@@ -234,6 +234,7 @@
                 if (!(convertView instanceof ViewGroup)) {
                     convertView = mInflater.inflate(
                             R.layout.app_language_picker_current_locale_item, parent, false);
+                    addStateDescriptionIntoCurrentLocaleItem(convertView);
                 }
                 updateTextView(
                         convertView, convertView.findViewById(R.id.language_picker_item), position);
@@ -369,4 +370,9 @@
                     : View.TEXT_DIRECTION_LTR);
         }
     }
+
+    private void addStateDescriptionIntoCurrentLocaleItem(View root) {
+        String description = root.getContext().getResources().getString(R.string.checked);
+        root.setStateDescription(description);
+    }
 }
diff --git a/core/java/com/android/internal/jank/InteractionJankMonitor.java b/core/java/com/android/internal/jank/InteractionJankMonitor.java
index 6424989..1b52aa9 100644
--- a/core/java/com/android/internal/jank/InteractionJankMonitor.java
+++ b/core/java/com/android/internal/jank/InteractionJankMonitor.java
@@ -28,6 +28,7 @@
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_APP_LAUNCH_FROM_WIDGET;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_OPEN_ALL_APPS;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LAUNCHER_QUICK_SWITCH;
+import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_LAUNCH_CAMERA;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PASSWORD_APPEAR;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PASSWORD_DISAPPEAR;
 import static com.android.internal.util.FrameworkStatsLog.UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_PATTERN_APPEAR;
@@ -189,7 +190,8 @@
     public static final int CUJ_SUW_LOADING_SCREEN_FOR_STATUS = 48;
     public static final int CUJ_SPLIT_SCREEN_ENTER = 49;
     public static final int CUJ_SPLIT_SCREEN_EXIT = 50;
-    public static final int CUJ_SPLIT_SCREEN_RESIZE = 51;
+    public static final int CUJ_LOCKSCREEN_LAUNCH_CAMERA = 51; // reserved.
+    public static final int CUJ_SPLIT_SCREEN_RESIZE = 52;
 
     private static final int NO_STATSD_LOGGING = -1;
 
@@ -249,6 +251,7 @@
             UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SUW_LOADING_SCREEN_FOR_STATUS,
             UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_ENTER,
             UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_EXIT,
+            UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__LOCKSCREEN_LAUNCH_CAMERA,
             UIINTERACTION_FRAME_INFO_REPORTED__INTERACTION_TYPE__SPLIT_SCREEN_RESIZE,
     };
 
@@ -321,6 +324,7 @@
             CUJ_SUW_LOADING_SCREEN_FOR_STATUS,
             CUJ_SPLIT_SCREEN_ENTER,
             CUJ_SPLIT_SCREEN_EXIT,
+            CUJ_LOCKSCREEN_LAUNCH_CAMERA,
             CUJ_SPLIT_SCREEN_RESIZE
     })
     @Retention(RetentionPolicy.SOURCE)
@@ -742,6 +746,8 @@
                 return "SPLIT_SCREEN_ENTER";
             case CUJ_SPLIT_SCREEN_EXIT:
                 return "SPLIT_SCREEN_EXIT";
+            case CUJ_LOCKSCREEN_LAUNCH_CAMERA:
+                return "CUJ_LOCKSCREEN_LAUNCH_CAMERA";
             case CUJ_SPLIT_SCREEN_RESIZE:
                 return "CUJ_SPLIT_SCREEN_RESIZE";
         }
diff --git a/core/java/com/android/internal/view/ScrollCaptureViewSupport.java b/core/java/com/android/internal/view/ScrollCaptureViewSupport.java
index 94a8ae5..f2c27a4 100644
--- a/core/java/com/android/internal/view/ScrollCaptureViewSupport.java
+++ b/core/java/com/android/internal/view/ScrollCaptureViewSupport.java
@@ -76,6 +76,7 @@
         ContentResolver contentResolver = context.getContentResolver();
         mPostScrollDelayMillis = Settings.Global.getLong(contentResolver,
                 SETTING_CAPTURE_DELAY, SETTING_CAPTURE_DELAY_DEFAULT);
+        Log.d(TAG, "screenshot.scroll_capture_delay = " + mPostScrollDelayMillis);
     }
 
     /** Based on ViewRootImpl#updateColorModeIfNeeded */
@@ -271,6 +272,13 @@
         Rect viewCaptureArea = new Rect(scrollResult.availableArea);
         viewCaptureArea.offset(0, -scrollResult.scrollDelta);
 
+        view.postOnAnimationDelayed(
+                () -> doCapture(scrollResult, view, viewCaptureArea, onComplete),
+                mPostScrollDelayMillis);
+    }
+
+    private void doCapture(ScrollResult scrollResult, V view, Rect viewCaptureArea,
+            Consumer<Rect> onComplete) {
         int result = mRenderer.renderView(view, viewCaptureArea);
         if (result == HardwareRenderer.SYNC_OK
                 || result == HardwareRenderer.SYNC_REDRAW_REQUESTED) {
diff --git a/core/proto/android/os/appbackgroundrestrictioninfo.proto b/core/proto/android/os/appbackgroundrestrictioninfo.proto
index 502fd64..5bf8ea7 100644
--- a/core/proto/android/os/appbackgroundrestrictioninfo.proto
+++ b/core/proto/android/os/appbackgroundrestrictioninfo.proto
@@ -73,12 +73,17 @@
     optional FgsTrackerInfo fgs_tracker_info = 5;
 
     message BatteryTrackerInfo {
-        // total battery usage within last 24h (percentage)
+        // total battery usage within last 24h (1/10000th)
         optional int32 battery_24h = 1;
-        // background battery usage (percentage)
+        // background battery usage (1/10000th)
         optional int32 battery_usage_background = 2;
-        // FGS battery usage (percentage)
+        // FGS battery usage (1/10000th)
         optional int32 battery_usage_fgs = 3;
+        // Foreground battery usage (1/10000th)
+        optional int32 battery_usage_foreground = 4;
+        // Cached battery usage (1/10000th)
+        optional int32 battery_usage_cached = 5;
+
     }
     optional BatteryTrackerInfo battery_tracker_info = 6;
 
@@ -197,5 +202,8 @@
 
     // indicates if the current device is a low ram device.
     optional bool low_mem_device = 12;
+
+    // indicates previous background restriction level.
+    optional RestrictionLevel previous_restriction_level = 13;
 }
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 4075c5f..217166c 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -377,6 +377,8 @@
     <protected-broadcast android:name="com.android.server.action.REMOTE_BUGREPORT_SHARING_ACCEPTED" />
     <protected-broadcast android:name="com.android.server.action.REMOTE_BUGREPORT_SHARING_DECLINED" />
     <protected-broadcast android:name="com.android.internal.action.EUICC_FACTORY_RESET" />
+    <protected-broadcast
+        android:name="com.android.internal.action.EUICC_REMOVE_INVISIBLE_SUBSCRIPTIONS" />
     <protected-broadcast android:name="com.android.server.usb.ACTION_OPEN_IN_APPS" />
     <protected-broadcast android:name="com.android.server.am.DELETE_DUMPHEAP" />
     <protected-broadcast android:name="com.android.server.net.action.SNOOZE_WARNING" />
@@ -6790,7 +6792,7 @@
                   android:excludeFromRecents="true"
                   android:exported="true"
                   android:permission="android.permission.MANAGE_GAME_ACTIVITY"
-                  android:theme="@style/Theme.Translucent.NoTitleBar">
+                  android:theme="@style/Theme.GameSessionTrampoline">
         </activity>
 
         <receiver android:name="com.android.server.BootReceiver"
diff --git a/core/res/res/layout/app_language_picker_current_locale_item.xml b/core/res/res/layout/app_language_picker_current_locale_item.xml
index bf6d963..990e26c 100644
--- a/core/res/res/layout/app_language_picker_current_locale_item.xml
+++ b/core/res/res/layout/app_language_picker_current_locale_item.xml
@@ -39,6 +39,6 @@
             android:layout_width="24dp"
             android:layout_height="24dp"
             android:src="@drawable/ic_check_24dp"
-            app:tint="#0F9D58"/>
+            app:tint="?attr/colorAccentPrimaryVariant"/>
     </LinearLayout>
 </LinearLayout>
diff --git a/core/res/res/layout/app_language_picker_system_current.xml b/core/res/res/layout/app_language_picker_system_current.xml
index 341ee25..300da25 100644
--- a/core/res/res/layout/app_language_picker_system_current.xml
+++ b/core/res/res/layout/app_language_picker_system_current.xml
@@ -40,6 +40,6 @@
             android:layout_width="24dp"
             android:layout_height="24dp"
             android:src="@drawable/ic_check_24dp"
-            app:tint="#0F9D58"/>
+            app:tint="?attr/colorAccentPrimaryVariant"/>
     </LinearLayout>
 </LinearLayout>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index bf42da0..a60862b 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -894,6 +894,22 @@
     <!-- @hide Special theme for the default system Activity-based Alert dialogs. -->
     <style name="Theme.Dialog.Confirmation" parent="Theme.DeviceDefault.Dialog.Alert.DayNight" />
 
+    <!-- @hide Theme for GameSessionTrampolineActivity that prevents showing UI and activity
+         transitions. -->
+    <style name="Theme.GameSessionTrampoline">
+        <item name="backgroundDimEnabled">false</item>
+        <item name="colorBackgroundCacheHint">@null</item>
+        <item name="navigationBarColor">@color/transparent</item>
+        <item name="statusBarColor">@color/transparent</item>
+        <item name="windowAnimationStyle">@null</item>
+        <item name="windowBackground">@null</item>
+        <item name="windowContentOverlay">@null</item>
+        <item name="windowDrawsSystemBarBackgrounds">true</item>
+        <item name="windowIsFloating">true</item>
+        <item name="windowIsTranslucent">true</item>
+        <item name="windowNoTitle">true</item>
+    </style>
+
     <!-- Theme for a window that looks like a toast. -->
     <style name="Theme.Toast" parent="Theme.DeviceDefault.Dialog">
         <item name="windowBackground">?attr/toastFrameBackground</item>
diff --git a/core/tests/coretests/src/android/net/UriTest.java b/core/tests/coretests/src/android/net/UriTest.java
index e083b0d..3733bfa 100644
--- a/core/tests/coretests/src/android/net/UriTest.java
+++ b/core/tests/coretests/src/android/net/UriTest.java
@@ -48,6 +48,7 @@
     public void testParcelling() {
         parcelAndUnparcel(Uri.parse("foo:bob%20lee"));
         parcelAndUnparcel(Uri.fromParts("foo", "bob lee", "fragment"));
+        parcelAndUnparcel(Uri.fromParts("https", "www.google.com", null));
         parcelAndUnparcel(new Uri.Builder()
             .scheme("http")
             .authority("crazybob.org")
@@ -890,9 +891,62 @@
             Throwable targetException = expected.getTargetException();
             // Check that the exception was thrown for the correct reason.
             assertEquals("Unknown representation: 0", targetException.getMessage());
+        } finally {
+            parcel.recycle();
         }
     }
 
+    private Uri buildUriFromRawParcel(boolean argumentsEncoded,
+                                      String scheme,
+                                      String authority,
+                                      String path,
+                                      String query,
+                                      String fragment) {
+        // Representation value (from AbstractPart.REPRESENTATION_{ENCODED,DECODED}).
+        final int representation = argumentsEncoded ? 1 : 2;
+        Parcel parcel = Parcel.obtain();
+        try {
+            parcel.writeInt(3);  // hierarchical
+            parcel.writeString8(scheme);
+            parcel.writeInt(representation);
+            parcel.writeString8(authority);
+            parcel.writeInt(representation);
+            parcel.writeString8(path);
+            parcel.writeInt(representation);
+            parcel.writeString8(query);
+            parcel.writeInt(representation);
+            parcel.writeString8(fragment);
+            parcel.setDataPosition(0);
+            return Uri.CREATOR.createFromParcel(parcel);
+        } finally {
+            parcel.recycle();
+        }
+    }
+
+    public void testUnparcelMalformedPath() {
+        // Regression tests for b/171966843.
+
+        // Test cases with arguments encoded (covering testing `scheme` * `authority` options).
+        Uri uri0 = buildUriFromRawParcel(true, "https", "google.com", "@evil.com", null, null);
+        assertEquals("https://google.com/@evil.com", uri0.toString());
+        Uri uri1 = buildUriFromRawParcel(true, null, "google.com", "@evil.com", "name=spark", "x");
+        assertEquals("//google.com/@evil.com?name=spark#x", uri1.toString());
+        Uri uri2 = buildUriFromRawParcel(true, "http:", null, "@evil.com", null, null);
+        assertEquals("http::/@evil.com", uri2.toString());
+        Uri uri3 = buildUriFromRawParcel(true, null, null, "@evil.com", null, null);
+        assertEquals("@evil.com", uri3.toString());
+
+        // Test cases with arguments not encoded (covering testing `scheme` * `authority` options).
+        Uri uriA = buildUriFromRawParcel(false, "https", "google.com", "@evil.com", null, null);
+        assertEquals("https://google.com/%40evil.com", uriA.toString());
+        Uri uriB = buildUriFromRawParcel(false, null, "google.com", "@evil.com", null, null);
+        assertEquals("//google.com/%40evil.com", uriB.toString());
+        Uri uriC = buildUriFromRawParcel(false, "http:", null, "@evil.com", null, null);
+        assertEquals("http::/%40evil.com", uriC.toString());
+        Uri uriD = buildUriFromRawParcel(false, null, null, "@evil.com", "name=spark", "y");
+        assertEquals("%40evil.com?name%3Dspark#y", uriD.toString());
+    }
+
     public void testToSafeString() {
         checkToSafeString("tel:xxxxxx", "tel:Google");
         checkToSafeString("tel:xxxxxxxxxx", "tel:1234567890");
diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java
index b04b826..a76d74e 100644
--- a/graphics/java/android/graphics/drawable/Icon.java
+++ b/graphics/java/android/graphics/drawable/Icon.java
@@ -128,6 +128,7 @@
     // TYPE_RESOURCE: Resources
     // TYPE_DATA: DataBytes
     private Object          mObj1;
+    private boolean mCachedAshmem = false;
 
     // TYPE_RESOURCE: package name
     // TYPE_URI: uri string
@@ -156,6 +157,8 @@
     /**
      * @return The {@link android.graphics.Bitmap} held by this {@link #TYPE_BITMAP} or
      * {@link #TYPE_ADAPTIVE_BITMAP} Icon.
+     *
+     * Note that this will always return an immutable Bitmap.
      * @hide
      */
     @UnsupportedAppUsage
@@ -166,8 +169,20 @@
         return (Bitmap) mObj1;
     }
 
+    /**
+     * Sets the Icon's contents to a particular Bitmap. Note that this may make a copy of the Bitmap
+     * if the supplied Bitmap is mutable. In that case, the value returned by getBitmap() may not
+     * equal the Bitmap passed to setBitmap().
+     *
+     * @hide
+     */
     private void setBitmap(Bitmap b) {
-        mObj1 = b;
+        if (b.isMutable()) {
+            mObj1 = b.copy(b.getConfig(), false);
+        } else {
+            mObj1 = b;
+        }
+        mCachedAshmem = false;
     }
 
     /**
@@ -488,6 +503,7 @@
             getBitmap().getAllocationByteCount() >= MIN_ASHMEM_ICON_SIZE) {
             setBitmap(getBitmap().asShared());
         }
+        mCachedAshmem = true;
     }
 
     /**
@@ -913,7 +929,10 @@
         switch (mType) {
             case TYPE_BITMAP:
             case TYPE_ADAPTIVE_BITMAP:
-                final Bitmap bits = getBitmap();
+                if (!mCachedAshmem) {
+                    mObj1 = ((Bitmap) mObj1).asShared();
+                    mCachedAshmem = true;
+                }
                 getBitmap().writeToParcel(dest, flags);
                 break;
             case TYPE_RESOURCE:
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 e50b9a1..81caf77 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizer.java
@@ -16,7 +16,6 @@
 
 package androidx.window.extensions.embedding;
 
-import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 
 import android.app.Activity;
@@ -49,7 +48,8 @@
 class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
 
     /** Mapping from the client assigned unique token to the {@link TaskFragmentInfo}. */
-    private final Map<IBinder, TaskFragmentInfo> mFragmentInfos = new ArrayMap<>();
+    @VisibleForTesting
+    final Map<IBinder, TaskFragmentInfo> mFragmentInfos = new ArrayMap<>();
 
     /**
      * Mapping from the client assigned unique token to the TaskFragment parent
@@ -120,25 +120,29 @@
      * @param secondaryFragmentBounds   the initial bounds for the secondary TaskFragment
      * @param activityIntent    Intent to start the secondary Activity with.
      * @param activityOptions   ActivityOptions to start the secondary Activity with.
+     * @param windowingMode     the windowing mode to set for the TaskFragments.
      */
     void startActivityToSide(@NonNull WindowContainerTransaction wct,
             @NonNull IBinder launchingFragmentToken, @NonNull Rect launchingFragmentBounds,
             @NonNull Activity launchingActivity, @NonNull IBinder secondaryFragmentToken,
             @NonNull Rect secondaryFragmentBounds, @NonNull Intent activityIntent,
-            @Nullable Bundle activityOptions, @NonNull SplitRule rule) {
+            @Nullable Bundle activityOptions, @NonNull SplitRule rule,
+            @WindowingMode int windowingMode) {
         final IBinder ownerToken = launchingActivity.getActivityToken();
 
         // Create or resize the launching TaskFragment.
         if (mFragmentInfos.containsKey(launchingFragmentToken)) {
             resizeTaskFragment(wct, launchingFragmentToken, launchingFragmentBounds);
+            wct.setWindowingMode(mFragmentInfos.get(launchingFragmentToken).getToken(),
+                    windowingMode);
         } else {
             createTaskFragmentAndReparentActivity(wct, launchingFragmentToken, ownerToken,
-                    launchingFragmentBounds, WINDOWING_MODE_MULTI_WINDOW, launchingActivity);
+                    launchingFragmentBounds, windowingMode, launchingActivity);
         }
 
         // Create a TaskFragment for the secondary activity.
         createTaskFragmentAndStartActivity(wct, secondaryFragmentToken, ownerToken,
-                secondaryFragmentBounds, WINDOWING_MODE_MULTI_WINDOW, activityIntent,
+                secondaryFragmentBounds, windowingMode, activityIntent,
                 activityOptions);
 
         // Set adjacent to each other so that the containers below will be invisible.
@@ -153,6 +157,7 @@
     void expandTaskFragment(WindowContainerTransaction wct, IBinder fragmentToken) {
         resizeTaskFragment(wct, fragmentToken, new Rect());
         setAdjacentTaskFragments(wct, fragmentToken, null /* secondary */, null /* splitRule */);
+        setWindowingMode(wct, fragmentToken, WINDOWING_MODE_UNDEFINED);
     }
 
     /**
@@ -255,6 +260,15 @@
         wct.setBounds(mFragmentInfos.get(fragmentToken).getToken(), bounds);
     }
 
+    private void setWindowingMode(WindowContainerTransaction wct, IBinder fragmentToken,
+            @WindowingMode int windowingMode) {
+        if (!mFragmentInfos.containsKey(fragmentToken)) {
+            throw new IllegalArgumentException(
+                    "Can't find an existing TaskFragment with fragmentToken=" + fragmentToken);
+        }
+        wct.setWindowingMode(mFragmentInfos.get(fragmentToken).getToken(), windowingMode);
+    }
+
     void deleteTaskFragment(WindowContainerTransaction wct, IBinder fragmentToken) {
         if (!mFragmentInfos.containsKey(fragmentToken)) {
             throw new IllegalArgumentException(
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 2328f76..b370e59 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java
@@ -257,9 +257,9 @@
         if (taskContainer == null) {
             return;
         }
-        final boolean wasInPip = isInPictureInPicture(taskContainer.getConfiguration());
+        final boolean wasInPip = taskContainer.isInPictureInPicture();
         final boolean isInPIp = isInPictureInPicture(config);
-        taskContainer.setConfiguration(config);
+        taskContainer.setWindowingMode(config.windowConfiguration.getWindowingMode());
 
         // We need to check the animation override when enter/exit PIP or has bounds changed.
         boolean shouldUpdateAnimationOverride = wasInPip != isInPIp;
@@ -278,8 +278,9 @@
      * bounds is large enough for at least one split rule.
      */
     private void updateAnimationOverride(@NonNull TaskContainer taskContainer) {
-        if (!taskContainer.isTaskBoundsInitialized()) {
-            // We don't know about the Task bounds yet.
+        if (!taskContainer.isTaskBoundsInitialized()
+                || !taskContainer.isWindowingModeInitialized()) {
+            // We don't know about the Task bounds/windowingMode yet.
             return;
         }
 
@@ -293,7 +294,7 @@
 
     private boolean supportSplit(@NonNull TaskContainer taskContainer) {
         // No split inside PIP.
-        if (isInPictureInPicture(taskContainer.getConfiguration())) {
+        if (taskContainer.isInPictureInPicture()) {
             return false;
         }
         // Check if the parent container bounds can support any split rule.
@@ -461,8 +462,12 @@
             if (!taskContainer.setTaskBounds(taskBounds)) {
                 Log.w(TAG, "Can't find bounds from activity=" + activityInTask);
             }
-            updateAnimationOverride(taskContainer);
         }
+        if (!taskContainer.isWindowingModeInitialized()) {
+            taskContainer.setWindowingMode(activityInTask.getResources().getConfiguration()
+                    .windowConfiguration.getWindowingMode());
+        }
+        updateAnimationOverride(taskContainer);
         return container;
     }
 
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
index ee5a322..e64e5d1 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -16,10 +16,11 @@
 
 package androidx.window.extensions.embedding;
 
-import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
 
 import android.app.Activity;
 import android.app.WindowConfiguration;
+import android.app.WindowConfiguration.WindowingMode;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Rect;
@@ -111,13 +112,16 @@
                 primaryActivity, primaryRectBounds, null);
 
         // Create new empty task fragment
+        final int taskId = primaryContainer.getTaskId();
         final TaskFragmentContainer secondaryContainer = mController.newContainer(
-                null /* activity */, primaryActivity, primaryContainer.getTaskId());
+                null /* activity */, primaryActivity, taskId);
         final Rect secondaryRectBounds = getBoundsForPosition(POSITION_END, parentBounds,
                 rule, isLtr(primaryActivity, rule));
+        final int windowingMode = mController.getTaskContainer(taskId)
+                .getWindowingModeForSplitTaskFragment(secondaryRectBounds);
         createTaskFragment(wct, secondaryContainer.getTaskFragmentToken(),
                 primaryActivity.getActivityToken(), secondaryRectBounds,
-                WINDOWING_MODE_MULTI_WINDOW);
+                windowingMode);
         secondaryContainer.setLastRequestedBounds(secondaryRectBounds);
 
         // Set adjacent to each other so that the containers below will be invisible.
@@ -173,7 +177,7 @@
 
         final WindowContainerTransaction wct = new WindowContainerTransaction();
         createTaskFragment(wct, newContainer.getTaskFragmentToken(),
-                launchingActivity.getActivityToken(), new Rect(), WINDOWING_MODE_MULTI_WINDOW);
+                launchingActivity.getActivityToken(), new Rect(), WINDOWING_MODE_UNDEFINED);
 
         applyTransaction(wct);
         return newContainer;
@@ -189,15 +193,17 @@
             @NonNull Rect bounds, @Nullable TaskFragmentContainer containerToAvoid) {
         TaskFragmentContainer container = mController.getContainerWithActivity(
                 activity.getActivityToken());
+        final int taskId = container != null ? container.getTaskId() : activity.getTaskId();
+        final int windowingMode = mController.getTaskContainer(taskId)
+                .getWindowingModeForSplitTaskFragment(bounds);
         if (container == null || container == containerToAvoid) {
-            container = mController.newContainer(activity, activity.getTaskId());
-
+            container = mController.newContainer(activity, taskId);
             final TaskFragmentCreationParams fragmentOptions =
                     createFragmentOptions(
                             container.getTaskFragmentToken(),
                             activity.getActivityToken(),
                             bounds,
-                            WINDOWING_MODE_MULTI_WINDOW);
+                            windowingMode);
             wct.createTaskFragment(fragmentOptions);
 
             wct.reparentActivityToTaskFragment(container.getTaskFragmentToken(),
@@ -206,6 +212,7 @@
             container.setLastRequestedBounds(bounds);
         } else {
             resizeTaskFragmentIfRegistered(wct, container, bounds);
+            updateTaskFragmentWindowingModeIfRegistered(wct, container, windowingMode);
         }
 
         return container;
@@ -237,14 +244,17 @@
                     launchingActivity.getTaskId());
         }
 
+        final int taskId = primaryContainer.getTaskId();
         TaskFragmentContainer secondaryContainer = mController.newContainer(null /* activity */,
-                launchingActivity, primaryContainer.getTaskId());
+                launchingActivity, taskId);
+        final int windowingMode = mController.getTaskContainer(taskId)
+                .getWindowingModeForSplitTaskFragment(primaryRectBounds);
         final WindowContainerTransaction wct = new WindowContainerTransaction();
         mController.registerSplit(wct, primaryContainer, launchingActivity, secondaryContainer,
                 rule);
         startActivityToSide(wct, primaryContainer.getTaskFragmentToken(), primaryRectBounds,
                 launchingActivity, secondaryContainer.getTaskFragmentToken(), secondaryRectBounds,
-                activityIntent, activityOptions, rule);
+                activityIntent, activityOptions, rule, windowingMode);
         if (isPlaceholder) {
             // When placeholder is launched in split, we should keep the focus on the primary.
             wct.requestFocusOnTaskFragment(primaryContainer.getTaskFragmentToken());
@@ -292,6 +302,12 @@
             // When placeholder is shown in split, we should keep the focus on the primary.
             wct.requestFocusOnTaskFragment(primaryContainer.getTaskFragmentToken());
         }
+        final TaskContainer taskContainer = mController.getTaskContainer(
+                updatedContainer.getTaskId());
+        final int windowingMode = taskContainer.getWindowingModeForSplitTaskFragment(
+                primaryRectBounds);
+        updateTaskFragmentWindowingModeIfRegistered(wct, primaryContainer, windowingMode);
+        updateTaskFragmentWindowingModeIfRegistered(wct, secondaryContainer, windowingMode);
     }
 
     private void setAdjacentTaskFragments(@NonNull WindowContainerTransaction wct,
@@ -323,6 +339,15 @@
         resizeTaskFragment(wct, container.getTaskFragmentToken(), bounds);
     }
 
+    private void updateTaskFragmentWindowingModeIfRegistered(
+            @NonNull WindowContainerTransaction wct,
+            @NonNull TaskFragmentContainer container,
+            @WindowingMode int windowingMode) {
+        if (container.getInfo() != null) {
+            wct.setWindowingMode(container.getInfo().getToken(), windowingMode);
+        }
+    }
+
     @Override
     void resizeTaskFragment(@NonNull WindowContainerTransaction wct, @NonNull IBinder fragmentToken,
             @Nullable Rect bounds) {
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
index be79301..3c0762d 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskContainer.java
@@ -16,9 +16,14 @@
 
 package androidx.window.extensions.embedding;
 
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.content.res.Configuration;
+import android.app.WindowConfiguration;
+import android.app.WindowConfiguration.WindowingMode;
 import android.graphics.Rect;
 import android.os.IBinder;
 import android.util.ArraySet;
@@ -37,9 +42,9 @@
     /** Available window bounds of this Task. */
     private final Rect mTaskBounds = new Rect();
 
-    /** Configuration of the Task. */
-    @Nullable
-    private Configuration mConfiguration;
+    /** Windowing mode of this Task. */
+    @WindowingMode
+    private int mWindowingMode = WINDOWING_MODE_UNDEFINED;
 
     /** Active TaskFragments in this Task. */
     final List<TaskFragmentContainer> mContainers = new ArrayList<>();
@@ -81,13 +86,42 @@
         return !mTaskBounds.isEmpty();
     }
 
-    @Nullable
-    Configuration getConfiguration() {
-        return mConfiguration;
+    void setWindowingMode(int windowingMode) {
+        mWindowingMode = windowingMode;
     }
 
-    void setConfiguration(@Nullable Configuration configuration) {
-        mConfiguration = configuration;
+    /** Whether the Task windowing mode has been initialized. */
+    boolean isWindowingModeInitialized() {
+        return mWindowingMode != WINDOWING_MODE_UNDEFINED;
+    }
+
+    /**
+     * Returns the windowing mode for the TaskFragments below this Task, which should be split with
+     * other TaskFragments.
+     *
+     * @param taskFragmentBounds    Requested bounds for the TaskFragment. It will be empty when
+     *                              the pair of TaskFragments are stacked due to the limited space.
+     */
+    @WindowingMode
+    int getWindowingModeForSplitTaskFragment(@Nullable Rect taskFragmentBounds) {
+        // Only set to multi-windowing mode if the pair are showing side-by-side. Otherwise, it
+        // will be set to UNDEFINED which will then inherit the Task windowing mode.
+        if (taskFragmentBounds == null || taskFragmentBounds.isEmpty()) {
+            return WINDOWING_MODE_UNDEFINED;
+        }
+        // We use WINDOWING_MODE_MULTI_WINDOW when the Task is fullscreen.
+        // However, when the Task is in other multi windowing mode, such as Freeform, we need to
+        // have the activity windowing mode to match the Task, otherwise things like
+        // DecorCaptionView won't work correctly. As a result, have the TaskFragment to be in the
+        // Task windowing mode if the Task is in multi window.
+        // TODO we won't need this anymore after we migrate Freeform caption to WM Shell.
+        return WindowConfiguration.inMultiWindowMode(mWindowingMode)
+                ? mWindowingMode
+                : WINDOWING_MODE_MULTI_WINDOW;
+    }
+
+    boolean isInPictureInPicture() {
+        return mWindowingMode == WINDOWING_MODE_PINNED;
     }
 
     /** Whether there is any {@link TaskFragmentContainer} below this Task. */
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
index b06ce4c..1f12c448 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/JetpackTaskFragmentOrganizerTest.java
@@ -16,15 +16,23 @@
 
 package androidx.window.extensions.embedding;
 
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+
 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.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 
+import android.content.res.Configuration;
+import android.graphics.Point;
 import android.platform.test.annotations.Presubmit;
+import android.window.TaskFragmentInfo;
+import android.window.WindowContainerToken;
+import android.window.WindowContainerTransaction;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
@@ -35,6 +43,8 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.util.ArrayList;
+
 /**
  * Test class for {@link JetpackTaskFragmentOrganizer}.
  *
@@ -48,6 +58,8 @@
     private static final int TASK_ID = 10;
 
     @Mock
+    private WindowContainerTransaction mTransaction;
+    @Mock
     private JetpackTaskFragmentOrganizer.TaskFragmentCallback mCallback;
     private JetpackTaskFragmentOrganizer mOrganizer;
 
@@ -91,4 +103,24 @@
 
         verify(mOrganizer).unregisterRemoteAnimations(TASK_ID);
     }
+
+    @Test
+    public void testExpandTaskFragment() {
+        final TaskFragmentContainer container = new TaskFragmentContainer(null, TASK_ID);
+        final TaskFragmentInfo info = createMockInfo(container);
+        mOrganizer.mFragmentInfos.put(container.getTaskFragmentToken(), info);
+        container.setInfo(info);
+
+        mOrganizer.expandTaskFragment(mTransaction, container.getTaskFragmentToken());
+
+        verify(mTransaction).setWindowingMode(container.getInfo().getToken(),
+                WINDOWING_MODE_UNDEFINED);
+    }
+
+    private TaskFragmentInfo createMockInfo(TaskFragmentContainer container) {
+        return new TaskFragmentInfo(container.getTaskFragmentToken(),
+                mock(WindowContainerToken.class), new Configuration(), 0 /* runningActivityCount */,
+                false /* isVisible */, new ArrayList<>(), new Point(),
+                false /* isTaskClearedForReuse */, false /* isTaskFragmentClearedForPip */);
+    }
 }
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java
index 9fb08df..c7feb7e 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/TaskContainerTest.java
@@ -16,6 +16,13 @@
 
 package androidx.window.extensions.embedding;
 
+import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
+import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+
+import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
 
@@ -64,6 +71,56 @@
     }
 
     @Test
+    public void testIsWindowingModeInitialized() {
+        final TaskContainer taskContainer = new TaskContainer(TASK_ID);
+
+        assertFalse(taskContainer.isWindowingModeInitialized());
+
+        taskContainer.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+
+        assertTrue(taskContainer.isWindowingModeInitialized());
+    }
+
+    @Test
+    public void testGetWindowingModeForSplitTaskFragment() {
+        final TaskContainer taskContainer = new TaskContainer(TASK_ID);
+        final Rect splitBounds = new Rect(0, 0, 500, 1000);
+
+        assertEquals(WINDOWING_MODE_MULTI_WINDOW,
+                taskContainer.getWindowingModeForSplitTaskFragment(splitBounds));
+
+        taskContainer.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+
+        assertEquals(WINDOWING_MODE_MULTI_WINDOW,
+                taskContainer.getWindowingModeForSplitTaskFragment(splitBounds));
+
+        taskContainer.setWindowingMode(WINDOWING_MODE_FREEFORM);
+
+        assertEquals(WINDOWING_MODE_FREEFORM,
+                taskContainer.getWindowingModeForSplitTaskFragment(splitBounds));
+
+        // Empty bounds means the split pair are stacked, so it should be UNDEFINED which will then
+        // inherit the Task windowing mode
+        assertEquals(WINDOWING_MODE_UNDEFINED,
+                taskContainer.getWindowingModeForSplitTaskFragment(new Rect()));
+    }
+
+    @Test
+    public void testIsInPictureInPicture() {
+        final TaskContainer taskContainer = new TaskContainer(TASK_ID);
+
+        assertFalse(taskContainer.isInPictureInPicture());
+
+        taskContainer.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
+
+        assertFalse(taskContainer.isInPictureInPicture());
+
+        taskContainer.setWindowingMode(WINDOWING_MODE_PINNED);
+
+        assertTrue(taskContainer.isInPictureInPicture());
+    }
+
+    @Test
     public void testIsEmpty() {
         final TaskContainer taskContainer = new TaskContainer(TASK_ID);
 
diff --git a/libs/WindowManager/Shell/res/layout/split_decor.xml b/libs/WindowManager/Shell/res/layout/split_decor.xml
index dfb90af..443ecb2 100644
--- a/libs/WindowManager/Shell/res/layout/split_decor.xml
+++ b/libs/WindowManager/Shell/res/layout/split_decor.xml
@@ -20,8 +20,8 @@
     android:layout_width="match_parent">
 
     <ImageView android:id="@+id/split_resizing_icon"
-               android:layout_height="@*android:dimen/starting_surface_icon_size"
-               android:layout_width="@*android:dimen/starting_surface_icon_size"
+               android:layout_height="@dimen/split_icon_size"
+               android:layout_width="@dimen/split_icon_size"
                android:layout_gravity="center"
                android:scaleType="fitCenter"
                android:padding="0dp"
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index c21381d..1dac9ca 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -87,6 +87,8 @@
     <!-- How high we lift the divider when touching -->
     <dimen name="docked_stack_divider_lift_elevation">4dp</dimen>
 
+    <!-- Icon size for split screen -->
+    <dimen name="split_icon_size">72dp</dimen>
     <!-- Divider handle size for legacy split screen -->
     <dimen name="docked_divider_handle_width">16dp</dimen>
     <dimen name="docked_divider_handle_height">2dp</dimen>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
index 5dc6bd1..de30dbb 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
@@ -73,6 +73,8 @@
     private Rect mBounds = new Rect();
     private ValueAnimator mFadeAnimator;
 
+    private int mIconSize;
+
     public SplitDecorManager(Configuration configuration, IconProvider iconProvider,
             SurfaceSession surfaceSession) {
         super(configuration, null /* rootSurface */, null /* hostInputToken */);
@@ -104,6 +106,7 @@
         mHostLeash = rootLeash;
         mViewHost = new SurfaceControlViewHost(context, context.getDisplay(), this);
 
+        mIconSize = context.getResources().getDimensionPixelSize(R.dimen.split_icon_size);
         final FrameLayout rootLayout = (FrameLayout) LayoutInflater.from(context)
                 .inflate(R.layout.split_decor, null);
         mResizingIconView = rootLayout.findViewById(R.id.split_resizing_icon);
@@ -171,14 +174,14 @@
 
             WindowManager.LayoutParams lp =
                     (WindowManager.LayoutParams) mViewHost.getView().getLayoutParams();
-            lp.width = mIcon.getIntrinsicWidth();
-            lp.height = mIcon.getIntrinsicHeight();
+            lp.width = mIconSize;
+            lp.height = mIconSize;
             mViewHost.relayout(lp);
             t.setLayer(mIconLeash, Integer.MAX_VALUE);
         }
         t.setPosition(mIconLeash,
-                newBounds.width() / 2 - mIcon.getIntrinsicWidth() / 2,
-                newBounds.height() / 2 - mIcon.getIntrinsicWidth() / 2);
+                newBounds.width() / 2 - mIconSize / 2,
+                newBounds.height() / 2 - mIconSize / 2);
 
         boolean show = newBounds.width() > mBounds.width() || newBounds.height() > mBounds.height();
         if (show != mShown) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DropZoneView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DropZoneView.java
index 0cea36e..28f59b5 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DropZoneView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/draganddrop/DropZoneView.java
@@ -111,8 +111,7 @@
         mColorDrawable = new ColorDrawable();
         setBackgroundDrawable(mColorDrawable);
 
-        final int iconSize = context.getResources().getDimensionPixelSize(
-                com.android.internal.R.dimen.starting_surface_icon_size);
+        final int iconSize = context.getResources().getDimensionPixelSize(R.dimen.split_icon_size);
         mSplashScreenView = new ImageView(context);
         mSplashScreenView.setScaleType(ImageView.ScaleType.FIT_CENTER);
         addView(mSplashScreenView,
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
index 5d17f85b..195923c 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
@@ -225,6 +225,12 @@
         // For transition that we don't animate, but contains the PIP leash, we need to update the
         // PIP surface, otherwise it will be reset after the transition.
         if (currentPipTaskChange != null) {
+            // Set the "end" bounds of pip. The default setup uses the start bounds. Since this is
+            // changing the *finish*Transaction, we need to use the end bounds. This will also
+            // make sure that the fade-in animation (below) uses the end bounds as well.
+            if (!currentPipTaskChange.getEndAbsBounds().isEmpty()) {
+                mPipBoundsState.setBounds(currentPipTaskChange.getEndAbsBounds());
+            }
             updatePipForUnhandledTransition(currentPipTaskChange, startTransaction,
                     finishTransaction);
         }
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 272331b..cc387ed 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
@@ -524,24 +524,44 @@
             mMenuController.attachPipMenuView();
             // Calculate the snap fraction of the current stack along the old movement bounds
             final PipSnapAlgorithm pipSnapAlgorithm = mPipBoundsAlgorithm.getSnapAlgorithm();
-            final Rect postChangeStackBounds = new Rect(mPipBoundsState.getBounds());
-            final float snapFraction = pipSnapAlgorithm.getSnapFraction(postChangeStackBounds,
-                    mPipBoundsAlgorithm.getMovementBounds(postChangeStackBounds),
+            final Rect postChangeBounds = new Rect(mPipBoundsState.getBounds());
+            final float snapFraction = pipSnapAlgorithm.getSnapFraction(postChangeBounds,
+                    mPipBoundsAlgorithm.getMovementBounds(postChangeBounds),
                     mPipBoundsState.getStashedState());
 
+            // Scale PiP on density dpi change, so it appears to be the same size physically.
+            final boolean densityDpiChanged = mPipBoundsState.getDisplayLayout().densityDpi() != 0
+                    && (mPipBoundsState.getDisplayLayout().densityDpi() != layout.densityDpi());
+            if (densityDpiChanged) {
+                final float scale = (float) layout.densityDpi()
+                        / mPipBoundsState.getDisplayLayout().densityDpi();
+                postChangeBounds.set(0, 0,
+                        (int) (postChangeBounds.width() * scale),
+                        (int) (postChangeBounds.height() * scale));
+            }
+
             updateDisplayLayout.run();
 
-            // Calculate the stack bounds in the new orientation based on same fraction along the
+            // Calculate the PiP bounds in the new orientation based on same fraction along the
             // rotated movement bounds.
             final Rect postChangeMovementBounds = mPipBoundsAlgorithm.getMovementBounds(
-                    postChangeStackBounds, false /* adjustForIme */);
-            pipSnapAlgorithm.applySnapFraction(postChangeStackBounds, postChangeMovementBounds,
+                    postChangeBounds, false /* adjustForIme */);
+            pipSnapAlgorithm.applySnapFraction(postChangeBounds, postChangeMovementBounds,
                     snapFraction, mPipBoundsState.getStashedState(),
                     mPipBoundsState.getStashOffset(),
                     mPipBoundsState.getDisplayBounds(),
                     mPipBoundsState.getDisplayLayout().stableInsets());
 
-            mTouchHandler.getMotionHelper().movePip(postChangeStackBounds);
+            if (densityDpiChanged) {
+                // Using PipMotionHelper#movePip directly here may cause race condition since
+                // the app content in PiP mode may or may not be updated for the new density dpi.
+                final int duration = mContext.getResources().getInteger(
+                        R.integer.config_pipEnterAnimationDuration);
+                mPipTaskOrganizer.scheduleAnimateResizePip(
+                        postChangeBounds, duration, null /* updateBoundsCallback */);
+            } else {
+                mTouchHandler.getMotionHelper().movePip(postChangeBounds);
+            }
         } else {
             updateDisplayLayout.run();
         }
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 05a240a..06f7eda 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
@@ -1827,15 +1827,17 @@
         @Override
         public void onNoLongerSupportMultiWindow() {
             if (mMainStage.isActive()) {
+                final boolean isMainStage = mMainStageListener == this;
                 if (!ENABLE_SHELL_TRANSITIONS) {
-                    StageCoordinator.this.exitSplitScreen(null /* childrenToTop */,
+                    StageCoordinator.this.exitSplitScreen(isMainStage ? mMainStage : mSideStage,
                             EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW);
+                    return;
                 }
 
+                final int stageType = isMainStage ? STAGE_TYPE_MAIN : STAGE_TYPE_SIDE;
                 final WindowContainerTransaction wct = new WindowContainerTransaction();
-                prepareExitSplitScreen(STAGE_TYPE_UNDEFINED, wct);
-                mSplitTransitions.startDismissTransition(wct,
-                        StageCoordinator.this, STAGE_TYPE_UNDEFINED,
+                prepareExitSplitScreen(stageType, wct);
+                mSplitTransitions.startDismissTransition(wct,StageCoordinator.this, stageType,
                         EXIT_REASON_APP_DOES_NOT_SUPPORT_MULTIWINDOW);
             }
         }
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 37e93443..c6a705d 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
@@ -80,7 +80,17 @@
     /** {@inheritDoc}  */
     @FlakyTest(bugId = 206753786)
     @Test
-    override fun statusBarLayerRotatesScales() = super.statusBarLayerRotatesScales()
+    override fun statusBarLayerRotatesScales() {
+        Assume.assumeFalse(isShellTransitionsEnabled)
+        super.statusBarLayerRotatesScales()
+    }
+
+    @Presubmit
+    @Test
+    fun statusBarLayerRotatesScales_ShellTransit() {
+        Assume.assumeTrue(isShellTransitionsEnabled)
+        super.statusBarLayerRotatesScales()
+    }
 
     /** {@inheritDoc}  */
     @FlakyTest(bugId = 197726610)
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTestShellTransit.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTestShellTransit.kt
index 1a21d32..fe51228 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTestShellTransit.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/pip/PipKeyboardTestShellTransit.kt
@@ -16,7 +16,7 @@
 
 package com.android.wm.shell.flicker.pip
 
-import androidx.test.filters.FlakyTest
+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
@@ -35,7 +35,6 @@
 @Parameterized.UseParametersRunnerFactory(FlickerParametersRunnerFactory::class)
 @FixMethodOrder(MethodSorters.NAME_ASCENDING)
 @Group4
-@FlakyTest(bugId = 217777115)
 class PipKeyboardTestShellTransit(testSpec: FlickerTestParameter) : PipKeyboardTest(testSpec) {
 
     @Before
@@ -43,7 +42,7 @@
         Assume.assumeTrue(isShellTransitionsEnabled)
     }
 
-    @FlakyTest(bugId = 214452854)
+    @Presubmit
     @Test
     override fun statusBarLayerRotatesScales() = super.statusBarLayerRotatesScales()
 }
\ No newline at end of file
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 c1ee1a7..4618fb3 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,12 +27,10 @@
 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
 import org.junit.FixMethodOrder
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -141,14 +139,6 @@
     @Presubmit
     @Test
     fun pipLayerRotates_StartingBounds() {
-        Assume.assumeFalse(isShellTransitionsEnabled)
-        pipLayerRotates_StartingBounds_internal()
-    }
-
-    @FlakyTest(bugId = 228024285)
-    @Test
-    fun pipLayerRotates_StartingBounds_ShellTransit() {
-        Assume.assumeTrue(isShellTransitionsEnabled)
         pipLayerRotates_StartingBounds_internal()
     }
 
diff --git a/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchPreference.java b/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchPreference.java
index 7c9a045..fc0e05f 100644
--- a/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchPreference.java
+++ b/packages/SettingsLib/MainSwitchPreference/src/com/android/settingslib/widget/MainSwitchPreference.java
@@ -122,9 +122,10 @@
      * Adds a listener for switch changes
      */
     public void addOnSwitchChangeListener(OnMainSwitchChangeListener listener) {
-        if (mMainSwitchBar == null) {
+        if (!mSwitchChangeListeners.contains(listener)) {
             mSwitchChangeListeners.add(listener);
-        } else {
+        }
+        if (mMainSwitchBar != null) {
             mMainSwitchBar.addOnSwitchChangeListener(listener);
         }
     }
@@ -133,9 +134,8 @@
      * Remove a listener for switch changes
      */
     public void removeOnSwitchChangeListener(OnMainSwitchChangeListener listener) {
-        if (mMainSwitchBar == null) {
-            mSwitchChangeListeners.remove(listener);
-        } else {
+        mSwitchChangeListeners.remove(listener);
+        if (mMainSwitchBar != null) {
             mMainSwitchBar.removeOnSwitchChangeListener(listener);
         }
     }
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt
index ca55779..093589f 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/ViewHierarchyAnimator.kt
@@ -20,6 +20,7 @@
 import android.animation.AnimatorListenerAdapter
 import android.animation.ObjectAnimator
 import android.animation.PropertyValuesHolder
+import android.animation.ValueAnimator
 import android.util.IntProperty
 import android.view.View
 import android.view.ViewGroup
@@ -37,6 +38,7 @@
         private const val DEFAULT_DURATION = 500L
         private val DEFAULT_INTERPOLATOR = Interpolators.STANDARD
         private val DEFAULT_ADDITION_INTERPOLATOR = Interpolators.STANDARD_DECELERATE
+        private val DEFAULT_REMOVAL_INTERPOLATOR = Interpolators.STANDARD_ACCELERATE
 
         /** The properties used to animate the view bounds. */
         private val PROPERTIES = mapOf(
@@ -113,7 +115,7 @@
             }
 
             val listener = createUpdateListener(interpolator, duration, ephemeral)
-            recursivelyAddListener(rootView, listener)
+            addListener(rootView, listener, recursive = true)
             return true
         }
 
@@ -183,7 +185,7 @@
             val listener = createAdditionListener(
                 origin, interpolator, duration, ignorePreviousValues = !includeMargins
             )
-            recursivelyAddListener(rootView, listener)
+            addListener(rootView, listener, recursive = true)
             return true
         }
 
@@ -298,6 +300,183 @@
         }
 
         /**
+         * Animates the removal of [rootView] and its children from the hierarchy. It uses the given
+         * [interpolator] and [duration].
+         *
+         * The end state of the animation is controlled by [destination]. This value can be any of
+         * the four corners, any of the four edges, or the center of the view.
+         */
+        @JvmOverloads
+        fun animateRemoval(
+            rootView: View,
+            destination: Hotspot = Hotspot.CENTER,
+            interpolator: Interpolator = DEFAULT_REMOVAL_INTERPOLATOR,
+            duration: Long = DEFAULT_DURATION
+        ): Boolean {
+            if (!isVisible(
+                    rootView.visibility,
+                    rootView.left,
+                    rootView.top,
+                    rootView.right,
+                    rootView.bottom
+                )
+            ) {
+                return false
+            }
+
+            val parent = rootView.parent as ViewGroup
+
+            // Ensure that rootView's siblings animate nicely around the removal.
+            val listener = createUpdateListener(
+                interpolator,
+                duration,
+                ephemeral = true
+            )
+            for (i in 0 until parent.childCount) {
+                val child = parent.getChildAt(i)
+                if (child == rootView) continue
+                addListener(child, listener, recursive = false)
+            }
+
+            // Remove the view so that a layout update is triggered for the siblings and they
+            // animate to their next position while the view's removal is also animating.
+            parent.removeView(rootView)
+            // By adding the view to the overlay, we can animate it while it isn't part of the view
+            // hierarchy. It is correctly positioned because we have its previous bounds, and we set
+            // them manually during the animation.
+            parent.overlay.add(rootView)
+
+            val startValues = mapOf(
+                Bound.LEFT to rootView.left,
+                Bound.TOP to rootView.top,
+                Bound.RIGHT to rootView.right,
+                Bound.BOTTOM to rootView.bottom
+            )
+            val endValues = processEndValuesForRemoval(
+                destination,
+                rootView.left,
+                rootView.top,
+                rootView.right,
+                rootView.bottom
+            )
+
+            val boundsToAnimate = mutableSetOf<Bound>()
+            if (rootView.left != endValues.getValue(Bound.LEFT)) boundsToAnimate.add(Bound.LEFT)
+            if (rootView.top != endValues.getValue(Bound.TOP)) boundsToAnimate.add(Bound.TOP)
+            if (rootView.right != endValues.getValue(Bound.RIGHT)) boundsToAnimate.add(Bound.RIGHT)
+            if (rootView.bottom != endValues.getValue(Bound.BOTTOM)) {
+                boundsToAnimate.add(Bound.BOTTOM)
+            }
+
+            startAnimation(
+                rootView,
+                boundsToAnimate,
+                startValues,
+                endValues,
+                interpolator,
+                duration,
+                ephemeral = true
+            )
+
+            if (rootView is ViewGroup) {
+                // Shift the children so they maintain a consistent position within the shrinking
+                // view.
+                shiftChildrenForRemoval(rootView, destination, endValues, interpolator, duration)
+
+                // Fade out the children during the first half of the removal, so they don't clutter
+                // too much once the view becomes very small. Then we fade out the view itself, in
+                // case it has its own content and/or background.
+                val startAlphas = FloatArray(rootView.childCount)
+                for (i in 0 until rootView.childCount) {
+                    startAlphas[i] = rootView.getChildAt(i).alpha
+                }
+
+                val animator = ValueAnimator.ofFloat(1f, 0f)
+                animator.interpolator = Interpolators.ALPHA_OUT
+                animator.duration = duration / 2
+                animator.addUpdateListener { animation ->
+                    for (i in 0 until rootView.childCount) {
+                        rootView.getChildAt(i).alpha =
+                            (animation.animatedValue as Float) * startAlphas[i]
+                    }
+                }
+                animator.addListener(object : AnimatorListenerAdapter() {
+                    override fun onAnimationEnd(animation: Animator) {
+                        rootView.animate()
+                            .alpha(0f)
+                            .setInterpolator(Interpolators.ALPHA_OUT)
+                            .setDuration(duration / 2)
+                            .withEndAction { parent.overlay.remove(rootView) }
+                            .start()
+                    }
+                })
+                animator.start()
+            } else {
+                // Fade out the view during the second half of the removal.
+                rootView.animate()
+                    .alpha(0f)
+                    .setInterpolator(Interpolators.ALPHA_OUT)
+                    .setDuration(duration / 2)
+                    .setStartDelay(duration / 2)
+                    .withEndAction { parent.overlay.remove(rootView) }
+                    .start()
+            }
+
+            return true
+        }
+
+        /**
+         * Animates the children of [rootView] so that its layout remains internally consistent as
+         * it shrinks towards [destination] and changes its bounds to [endValues].
+         *
+         * Uses [interpolator] and [duration], which should match those of the removal animation.
+         */
+        private fun shiftChildrenForRemoval(
+            rootView: ViewGroup,
+            destination: Hotspot,
+            endValues: Map<Bound, Int>,
+            interpolator: Interpolator,
+            duration: Long
+        ) {
+            for (i in 0 until rootView.childCount) {
+                val child = rootView.getChildAt(i)
+                val childStartValues = mapOf(
+                    Bound.LEFT to child.left,
+                    Bound.TOP to child.top,
+                    Bound.RIGHT to child.right,
+                    Bound.BOTTOM to child.bottom
+                )
+                val childEndValues = processChildEndValuesForRemoval(
+                    destination,
+                    child.left,
+                    child.top,
+                    child.right,
+                    child.bottom,
+                    endValues.getValue(Bound.RIGHT) - endValues.getValue(Bound.LEFT),
+                    endValues.getValue(Bound.BOTTOM) - endValues.getValue(Bound.TOP)
+                )
+
+                val boundsToAnimate = mutableSetOf<Bound>()
+                if (child.left != endValues.getValue(Bound.LEFT)) boundsToAnimate.add(Bound.LEFT)
+                if (child.top != endValues.getValue(Bound.TOP)) boundsToAnimate.add(Bound.TOP)
+                if (child.right != endValues.getValue(Bound.RIGHT)) boundsToAnimate.add(Bound.RIGHT)
+                if (child.bottom != endValues.getValue(Bound.BOTTOM)) {
+                    boundsToAnimate.add(Bound.BOTTOM)
+                }
+
+                startAnimation(
+                    child,
+                    boundsToAnimate,
+                    childStartValues,
+                    childEndValues,
+                    interpolator,
+                    duration,
+                    ephemeral = true
+                )
+            }
+        }
+
+        /**
          * Returns whether the given [visibility] and bounds are consistent with a view being
          * currently visible on screen.
          */
@@ -312,7 +491,7 @@
         }
 
         /**
-         * Compute the actual starting values based on the requested [origin] and on
+         * Computes the actual starting values based on the requested [origin] and on
          * [ignorePreviousValues].
          *
          * If [origin] is null, the resolved start values will be the same as those passed in, or
@@ -422,7 +601,140 @@
             )
         }
 
-        private fun recursivelyAddListener(view: View, listener: View.OnLayoutChangeListener) {
+        /**
+         * Computes a removal animation's end values based on the requested [destination] and the
+         * view's starting bounds.
+         *
+         * Examples:
+         *     1) destination=TOP
+         *         x---------x    x---------x    x---------x    x---------x    x---------x
+         *         |         |    |         |    |         |    x---------x
+         *         |         | -> |         | -> x---------x ->             ->
+         *         |         |    x---------x
+         *         x---------x
+         *      2) destination=BOTTOM_LEFT
+         *         x---------x
+         *         |         |    x-------x
+         *         |         | -> |       |   -> x----x      ->             ->
+         *         |         |    |       |      |    |         x--x
+         *         x---------x    x-------x      x----x         x--x           x
+         *     3) destination=CENTER
+         *         x---------x
+         *         |         |     x-------x       x-----x
+         *         |         | ->  |       |  ->   |     |   ->    x---x    ->      x
+         *         |         |     x-------x       x-----x
+         *         x---------x
+         */
+        private fun processEndValuesForRemoval(
+            destination: Hotspot,
+            left: Int,
+            top: Int,
+            right: Int,
+            bottom: Int
+        ): Map<Bound, Int> {
+            val endLeft = when (destination) {
+                Hotspot.CENTER -> (left + right) / 2
+                Hotspot.BOTTOM, Hotspot.BOTTOM_LEFT, Hotspot.LEFT, Hotspot.TOP_LEFT, Hotspot.TOP ->
+                    left
+                Hotspot.TOP_RIGHT, Hotspot.RIGHT, Hotspot.BOTTOM_RIGHT -> right
+            }
+            val endTop = when (destination) {
+                Hotspot.CENTER -> (top + bottom) / 2
+                Hotspot.LEFT, Hotspot.TOP_LEFT, Hotspot.TOP, Hotspot.TOP_RIGHT, Hotspot.RIGHT ->
+                    top
+                Hotspot.BOTTOM_RIGHT, Hotspot.BOTTOM, Hotspot.BOTTOM_LEFT -> bottom
+            }
+            val endRight = when (destination) {
+                Hotspot.CENTER -> (left + right) / 2
+                Hotspot.TOP, Hotspot.TOP_RIGHT, Hotspot.RIGHT,
+                Hotspot.BOTTOM_RIGHT, Hotspot.BOTTOM ->
+                    right
+                Hotspot.BOTTOM_LEFT, Hotspot.LEFT, Hotspot.TOP_LEFT -> left
+            }
+            val endBottom = when (destination) {
+                Hotspot.CENTER -> (top + bottom) / 2
+                Hotspot.RIGHT, Hotspot.BOTTOM_RIGHT, Hotspot.BOTTOM,
+                Hotspot.BOTTOM_LEFT, Hotspot.LEFT ->
+                    bottom
+                Hotspot.TOP_LEFT, Hotspot.TOP, Hotspot.TOP_RIGHT -> top
+            }
+
+            return mapOf(
+                Bound.LEFT to endLeft,
+                Bound.TOP to endTop,
+                Bound.RIGHT to endRight,
+                Bound.BOTTOM to endBottom
+            )
+        }
+
+        /**
+         * Computes the end values for the child of a view being removed, based on the child's
+         * starting bounds, the removal's [destination], and the [parentWidth] and [parentHeight].
+         *
+         * The end values always represent the child's position after it has been translated so that
+         * its center is at the [destination].
+         *
+         * Examples:
+         *     1) destination=TOP
+         *         The child maintains its left and right positions, but is shifted up so that its
+         *         center is on the parent's end top edge.
+         *     2) destination=BOTTOM_LEFT
+         *         The child shifts so that its center is on the parent's end bottom left corner.
+         *     3) destination=CENTER
+         *         The child shifts so that its own center is on the parent's end center.
+         */
+        private fun processChildEndValuesForRemoval(
+            destination: Hotspot,
+            left: Int,
+            top: Int,
+            right: Int,
+            bottom: Int,
+            parentWidth: Int,
+            parentHeight: Int
+        ): Map<Bound, Int> {
+            val halfWidth = (right - left) / 2
+            val halfHeight = (bottom - top) / 2
+
+            val endLeft = when (destination) {
+                Hotspot.CENTER -> (parentWidth / 2) - halfWidth
+                Hotspot.BOTTOM_LEFT, Hotspot.LEFT, Hotspot.TOP_LEFT -> -halfWidth
+                Hotspot.TOP_RIGHT, Hotspot.RIGHT, Hotspot.BOTTOM_RIGHT -> parentWidth - halfWidth
+                Hotspot.TOP, Hotspot.BOTTOM -> left
+            }
+            val endTop = when (destination) {
+                Hotspot.CENTER -> (parentHeight / 2) - halfHeight
+                Hotspot.TOP_LEFT, Hotspot.TOP, Hotspot.TOP_RIGHT -> -halfHeight
+                Hotspot.BOTTOM_RIGHT, Hotspot.BOTTOM, Hotspot.BOTTOM_LEFT ->
+                    parentHeight - halfHeight
+                Hotspot.LEFT, Hotspot.RIGHT -> top
+            }
+            val endRight = when (destination) {
+                Hotspot.CENTER -> (parentWidth / 2) + halfWidth
+                Hotspot.TOP_RIGHT, Hotspot.RIGHT, Hotspot.BOTTOM_RIGHT -> parentWidth + halfWidth
+                Hotspot.BOTTOM_LEFT, Hotspot.LEFT, Hotspot.TOP_LEFT -> halfWidth
+                Hotspot.TOP, Hotspot.BOTTOM -> right
+            }
+            val endBottom = when (destination) {
+                Hotspot.CENTER -> (parentHeight / 2) + halfHeight
+                Hotspot.BOTTOM_RIGHT, Hotspot.BOTTOM, Hotspot.BOTTOM_LEFT ->
+                    parentHeight + halfHeight
+                Hotspot.TOP_LEFT, Hotspot.TOP, Hotspot.TOP_RIGHT -> halfHeight
+                Hotspot.LEFT, Hotspot.RIGHT -> bottom
+            }
+
+            return mapOf(
+                Bound.LEFT to endLeft,
+                Bound.TOP to endTop,
+                Bound.RIGHT to endRight,
+                Bound.BOTTOM to endBottom
+            )
+        }
+
+        private fun addListener(
+            view: View,
+            listener: View.OnLayoutChangeListener,
+            recursive: Boolean = false
+        ) {
             // Make sure that only one listener is active at a time.
             val previousListener = view.getTag(R.id.tag_layout_listener)
             if (previousListener != null && previousListener is View.OnLayoutChangeListener) {
@@ -431,9 +743,9 @@
 
             view.addOnLayoutChangeListener(listener)
             view.setTag(R.id.tag_layout_listener, listener)
-            if (view is ViewGroup) {
+            if (view is ViewGroup && recursive) {
                 for (i in 0 until view.childCount) {
-                    recursivelyAddListener(view.getChildAt(i), listener)
+                    addListener(view.getChildAt(i), listener, recursive = true)
                 }
             }
         }
@@ -490,6 +802,8 @@
                 }
             }.toTypedArray()
 
+            (view.getTag(R.id.tag_animator) as? ObjectAnimator)?.cancel()
+
             val animator = ObjectAnimator.ofPropertyValuesHolder(view, *propertyValuesHolders)
             animator.interpolator = interpolator
             animator.duration = duration
diff --git a/packages/SystemUI/res/drawable/keyguard_framed_avatar_background.xml b/packages/SystemUI/res/drawable/keyguard_framed_avatar_background.xml
new file mode 100644
index 0000000..a461bf8
--- /dev/null
+++ b/packages/SystemUI/res/drawable/keyguard_framed_avatar_background.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2022 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<shape
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <corners android:radius="@dimen/kg_framed_avatar_size"/>
+    <solid android:color="@color/kg_user_avatar_frame"/>
+</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/keyguard_qs_user_switch.xml b/packages/SystemUI/res/layout/keyguard_qs_user_switch.xml
index 9cf09ff..6f33623 100644
--- a/packages/SystemUI/res/layout/keyguard_qs_user_switch.xml
+++ b/packages/SystemUI/res/layout/keyguard_qs_user_switch.xml
@@ -22,18 +22,25 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:layout_gravity="end">
-    <com.android.systemui.statusbar.phone.UserAvatarView
-        android:id="@+id/kg_multi_user_avatar"
-        android:layout_width="@dimen/kg_framed_avatar_size"
-        android:layout_height="@dimen/kg_framed_avatar_size"
-        android:layout_centerHorizontal="true"
+    <!-- We add a background behind the UserAvatarView with the same color and with a circular shape
+         so that this view can be expanded into a Dialog or an Activity. -->
+    <FrameLayout
+        android:id="@+id/kg_multi_user_avatar_with_background"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
         android:layout_gravity="top|end"
         android:layout_marginEnd="16dp"
-        systemui:avatarPadding="0dp"
-        systemui:badgeDiameter="18dp"
-        systemui:badgeMargin="1dp"
-        systemui:frameColor="@color/kg_user_avatar_frame"
-        systemui:framePadding="0dp"
-        systemui:frameWidth="0dp">
-    </com.android.systemui.statusbar.phone.UserAvatarView>
+        android:background="@drawable/keyguard_framed_avatar_background">
+        <com.android.systemui.statusbar.phone.UserAvatarView
+            android:id="@+id/kg_multi_user_avatar"
+            android:layout_width="@dimen/kg_framed_avatar_size"
+            android:layout_height="@dimen/kg_framed_avatar_size"
+            systemui:avatarPadding="0dp"
+            systemui:badgeDiameter="18dp"
+            systemui:badgeMargin="1dp"
+            systemui:frameColor="@color/kg_user_avatar_frame"
+            systemui:framePadding="0dp"
+            systemui:frameWidth="0dp">
+        </com.android.systemui.statusbar.phone.UserAvatarView>
+    </FrameLayout>
 </FrameLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 21e5697..008299b 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -60,6 +60,8 @@
 
     <dimen name="global_actions_grid_item_layout_height">80dp</dimen>
 
+    <dimen name="qs_brightness_margin_bottom">16dp</dimen>
+
     <!--  For large screens the security footer appears below the footer,
     same as phones in portrait  -->
     <dimen name="qs_security_footer_single_line_height">48dp</dimen>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 9e6b277..4b6c0dc 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -714,4 +714,10 @@
         <item>@*android:string/status_bar_alarm_clock</item>
         <item>@*android:string/status_bar_call_strength</item>
     </string-array>
+
+    <!-- Packages of SystemUI -->
+    <string-array name="system_ui_packages" translatable="false">
+        <item>com.android.keyguard</item>
+        <item>com.android.systemui</item>
+    </string-array>
 </resources>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index d46a404..3015400 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -213,6 +213,8 @@
     <!-- Notification text displayed when we fail to take a screenshot. [CHAR LIMIT=100] -->
     <string name="screenshot_failed_to_capture_text">Taking screenshots isn\'t allowed by the app or
         your organization</string>
+    <!-- Notification text displayed when screenshots are blocked by an IT admin. [CHAR LIMIT=100] -->
+    <string name="screenshot_blocked_by_admin">Taking screenshots is blocked by your IT admin</string>
     <!-- Label for UI element which allows editing the screenshot [CHAR LIMIT=30] -->
     <string name="screenshot_edit_label">Edit</string>
     <!-- Content description indicating that tapping the element will allow editing the screenshot [CHAR LIMIT=NONE] -->
@@ -2018,7 +2020,8 @@
          app for debugging. Will not be seen by users. [CHAR LIMIT=20] -->
     <string name="heap_dump_tile_name">Dump SysUI Heap</string>
 
-    <!-- Content description for ongoing privacy chip. Use with a single app [CHAR LIMIT=NONE]-->
+    <!-- Title for the privacy indicators dialog, only appears as part of a11y descriptions [CHAR LIMIT=NONE] -->
+    <string name="ongoing_privacy_dialog_a11y_title">In use</string>
 
     <!-- Content description for ongoing privacy chip. Use with multiple apps [CHAR LIMIT=NONE]-->
     <string name="ongoing_privacy_chip_content_multiple_apps">Applications are using your <xliff:g id="types_list" example="camera, location">%s</xliff:g>.</string>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index a6feedb5..3f8c4b3 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -1512,6 +1512,20 @@
                 handleFingerprintAuthenticated(userId, isStrongBiometric);
             };
 
+    /**
+     * Propagates a pointer down event to keyguard.
+     */
+    public void onUdfpsPointerDown(int sensorId) {
+        mFingerprintAuthenticationCallback.onUdfpsPointerDown(sensorId);
+    }
+
+    /**
+     * Propagates a pointer up event to keyguard.
+     */
+    public void onUdfpsPointerUp(int sensorId) {
+        mFingerprintAuthenticationCallback.onUdfpsPointerUp(sensorId);
+    }
+
     @VisibleForTesting
     final FingerprintManager.AuthenticationCallback mFingerprintAuthenticationCallback
             = new AuthenticationCallback() {
@@ -1553,6 +1567,9 @@
                     Trace.endSection();
                 }
 
+                /**
+                 * Note, this is currently called from UdfpsController.
+                 */
                 @Override
                 public void onUdfpsPointerDown(int sensorId) {
                     Log.d(TAG, "onUdfpsPointerDown, sensorId: " + sensorId);
@@ -1562,6 +1579,9 @@
                     }
                 }
 
+                /**
+                 * Note, this is currently called from UdfpsController.
+                 */
                 @Override
                 public void onUdfpsPointerUp(int sensorId) {
                     Log.d(TAG, "onUdfpsPointerUp, sensorId: " + sensorId);
diff --git a/packages/SystemUI/src/com/android/systemui/FontSizeUtils.java b/packages/SystemUI/src/com/android/systemui/FontSizeUtils.java
index 35a70a5..0d1dc9d 100644
--- a/packages/SystemUI/src/com/android/systemui/FontSizeUtils.java
+++ b/packages/SystemUI/src/com/android/systemui/FontSizeUtils.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui;
 
+import android.annotation.StyleRes;
+import android.content.res.TypedArray;
 import android.util.TypedValue;
 import android.view.View;
 import android.widget.TextView;
@@ -23,9 +25,9 @@
 /**
  * Utility class to update the font size when the configuration has changed.
  */
-public class FontSizeUtils {
+public final class FontSizeUtils {
 
-    public static final float LARGE_TEXT_SCALE = 1.3f;
+    private FontSizeUtils() {}
 
     public static void updateFontSize(View parent, int viewId, int dimensId) {
         updateFontSize((TextView) parent.findViewById(viewId), dimensId);
@@ -37,4 +39,20 @@
                     v.getResources().getDimensionPixelSize(dimensId));
         }
     }
+
+    /**
+     * Updates the font size according to the style given.
+     *
+     * @param v     Text to update.
+     * @param resId Style applying to the text.
+     */
+    public static void updateFontSizeFromStyle(TextView v, @StyleRes int resId) {
+        int[] attrs = {android.R.attr.textSize};
+        int indexOfAttrTextSize = 0;
+        TypedArray ta = v.getContext().obtainStyledAttributes(resId, attrs);
+        int updatedTextPixelSize = ta.getDimensionPixelSize(indexOfAttrTextSize,
+                (int) v.getTextSize());
+        v.setTextSize(TypedValue.COMPLEX_UNIT_PX, updatedTextPixelSize);
+        ta.recycle();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt b/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt
index 3641e1d..0df2730 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorHwcLayer.kt
@@ -380,7 +380,7 @@
     ) {
         if (hasTopRoundedCorner == hasTop &&
                 hasBottomRoundedCorner == hasBottom &&
-                roundedCornerBottomSize == bottomSize &&
+                roundedCornerTopSize == topSize &&
                 roundedCornerBottomSize == bottomSize) {
             return
         }
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index b98fc03..8d65098 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -348,7 +348,8 @@
             @Override
             public void onDisplayChanged(int displayId) {
                 final int newRotation = mContext.getDisplay().getRotation();
-                if (mOverlays != null && mRotation != newRotation) {
+                if ((mOverlays != null || mScreenDecorHwcWindow != null)
+                        && mRotation != newRotation) {
                     // We cannot immediately update the orientation. Otherwise
                     // WindowManager is still deferring layout until it has finished dispatching
                     // the config changes, which may cause divergence between what we draw
@@ -362,11 +363,13 @@
                                 + mRotation);
                     }
 
-                    for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
-                        if (mOverlays[i] != null) {
-                            final ViewGroup overlayView = mOverlays[i].getRootView();
-                            overlayView.getViewTreeObserver().addOnPreDrawListener(
-                                    new RestartingPreDrawListener(overlayView, i, newRotation));
+                    if (mOverlays != null) {
+                        for (int i = 0; i < BOUNDS_POSITION_LENGTH; i++) {
+                            if (mOverlays[i] != null) {
+                                final ViewGroup overlayView = mOverlays[i].getRootView();
+                                overlayView.getViewTreeObserver().addOnPreDrawListener(
+                                        new RestartingPreDrawListener(overlayView, i, newRotation));
+                            }
                         }
                     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
index 9d5b93c..7c2673c 100644
--- a/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
+++ b/packages/SystemUI/src/com/android/systemui/assist/AssistManager.java
@@ -187,6 +187,14 @@
                     }
 
                     @Override
+                    public void onVoiceSessionWindowVisibilityChanged(boolean visible)
+                            throws RemoteException {
+                        if (VERBOSE) {
+                            Log.v(TAG, "Window visibility changed: " + visible);
+                        }
+                    }
+
+                    @Override
                     public void onSetUiHints(Bundle hints) {
                         if (VERBOSE) {
                             Log.v(TAG, "UI hints received");
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 0096032..09d9792 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -796,6 +796,11 @@
         mOnFingerDown = true;
         if (mAlternateTouchProvider != null) {
             mAlternateTouchProvider.onPointerDown(requestId, x, y, minor, major);
+            mFgExecutor.execute(() -> {
+                if (mKeyguardUpdateMonitor.isFingerprintDetectionRunning()) {
+                    mKeyguardUpdateMonitor.onUdfpsPointerDown((int) requestId);
+                }
+            });
         } else {
             mFingerprintManager.onPointerDown(requestId, mSensorId, x, y, minor, major);
         }
@@ -821,6 +826,11 @@
         if (mOnFingerDown) {
             if (mAlternateTouchProvider != null) {
                 mAlternateTouchProvider.onPointerUp(requestId);
+                mFgExecutor.execute(() -> {
+                    if (mKeyguardUpdateMonitor.isFingerprintDetectionRunning()) {
+                        mKeyguardUpdateMonitor.onUdfpsPointerUp((int) requestId);
+                    }
+                });
             } else {
                 mFingerprintManager.onPointerUp(requestId, mSensorId);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
index 842791f..937b813 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardView.java
@@ -127,17 +127,19 @@
         mBurnInProgress = MathUtils.lerp(0f, getBurnInProgressOffset(), darkAmountForAnimation);
 
         if (mAnimatingBetweenAodAndLockscreen && !mPauseAuth) {
+            mLockScreenFp.setTranslationX(mBurnInOffsetX);
+            mLockScreenFp.setTranslationY(mBurnInOffsetY);
             mBgProtection.setAlpha(1f - mInterpolatedDarkAmount);
             mLockScreenFp.setAlpha(1f - mInterpolatedDarkAmount);
         } else if (mInterpolatedDarkAmount == 0f) {
+            mLockScreenFp.setTranslationX(0);
+            mLockScreenFp.setTranslationY(0);
             mBgProtection.setAlpha(mAlpha / 255f);
             mLockScreenFp.setAlpha(mAlpha / 255f);
         } else {
             mBgProtection.setAlpha(0f);
             mLockScreenFp.setAlpha(0f);
         }
-        mLockScreenFp.setTranslationX(mBurnInOffsetX);
-        mLockScreenFp.setTranslationY(mBurnInOffsetY);
         mLockScreenFp.setProgress(1f - mInterpolatedDarkAmount);
 
         mAodFp.setTranslationX(mBurnInOffsetX);
diff --git a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt
index 9dbeb77..e316722 100644
--- a/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/decor/RoundedCornerDecorProviderImpl.kt
@@ -105,7 +105,7 @@
         DisplayCutout.BOUNDS_POSITION_LEFT -> Gravity.BOTTOM
         DisplayCutout.BOUNDS_POSITION_TOP -> Gravity.LEFT
         DisplayCutout.BOUNDS_POSITION_RIGHT -> Gravity.TOP
-        else /* DisplayCutout.BOUNDS_POSITION_BOTTOM */ -> Gravity.LEFT
+        else /* DisplayCutout.BOUNDS_POSITION_BOTTOM */ -> Gravity.RIGHT
     }
     Surface.ROTATION_270 -> when (this) {
         DisplayCutout.BOUNDS_POSITION_LEFT -> Gravity.TOP
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/SmartSpaceComplication.java b/packages/SystemUI/src/com/android/systemui/dreams/SmartSpaceComplication.java
index a83e006..7666eb8 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/SmartSpaceComplication.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/SmartSpaceComplication.java
@@ -26,7 +26,7 @@
 import com.android.systemui.dreams.complication.Complication;
 import com.android.systemui.dreams.complication.ComplicationLayoutParams;
 import com.android.systemui.dreams.complication.ComplicationViewModel;
-import com.android.systemui.dreams.smartspace.DreamsSmartspaceController;
+import com.android.systemui.dreams.smartspace.DreamSmartspaceController;
 import com.android.systemui.plugins.BcSmartspaceDataPlugin;
 
 import java.util.List;
@@ -43,7 +43,7 @@
      * SystemUI.
      */
     public static class Registrant extends CoreStartable {
-        private final DreamsSmartspaceController mSmartSpaceController;
+        private final DreamSmartspaceController mSmartSpaceController;
         private final DreamOverlayStateController mDreamOverlayStateController;
         private final SmartSpaceComplication mComplication;
 
@@ -66,7 +66,7 @@
         public Registrant(Context context,
                 DreamOverlayStateController dreamOverlayStateController,
                 SmartSpaceComplication smartSpaceComplication,
-                DreamsSmartspaceController smartSpaceController) {
+                DreamSmartspaceController smartSpaceController) {
             super(context);
             mDreamOverlayStateController = dreamOverlayStateController;
             mComplication = smartSpaceComplication;
@@ -90,12 +90,12 @@
 
     private static class SmartSpaceComplicationViewHolder implements ViewHolder {
         private static final int SMARTSPACE_COMPLICATION_WEIGHT = 10;
-        private final DreamsSmartspaceController mSmartSpaceController;
+        private final DreamSmartspaceController mSmartSpaceController;
         private final Context mContext;
 
         protected SmartSpaceComplicationViewHolder(
                 Context context,
-                DreamsSmartspaceController smartSpaceController) {
+                DreamSmartspaceController smartSpaceController) {
             mSmartSpaceController = smartSpaceController;
             mContext = context;
         }
@@ -120,12 +120,12 @@
         }
     }
 
-    private final DreamsSmartspaceController mSmartSpaceController;
+    private final DreamSmartspaceController mSmartSpaceController;
     private final Context mContext;
 
     @Inject
     public SmartSpaceComplication(Context context,
-            DreamsSmartspaceController smartSpaceController) {
+            DreamSmartspaceController smartSpaceController) {
         mContext = context;
         mSmartSpaceController = smartSpaceController;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/smartspace/DreamsSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/dreams/smartspace/DreamSmartspaceController.kt
similarity index 98%
rename from packages/SystemUI/src/com/android/systemui/dreams/smartspace/DreamsSmartspaceController.kt
rename to packages/SystemUI/src/com/android/systemui/dreams/smartspace/DreamSmartspaceController.kt
index a309547..da2cf84 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/smartspace/DreamsSmartspaceController.kt
+++ b/packages/SystemUI/src/com/android/systemui/dreams/smartspace/DreamSmartspaceController.kt
@@ -46,7 +46,7 @@
  * Controller for managing the smartspace view on the dream
  */
 @SysUISingleton
-class DreamsSmartspaceController @Inject constructor(
+class DreamSmartspaceController @Inject constructor(
     private val context: Context,
     private val smartspaceManager: SmartspaceManager,
     private val execution: Execution,
@@ -58,7 +58,7 @@
     @Named(DREAM_SMARTSPACE_DATA_PLUGIN) optionalPlugin: Optional<BcSmartspaceDataPlugin>
 ) {
     companion object {
-        private const val TAG = "DreamsSmartspaceCtrlr"
+        private const val TAG = "DreamSmartspaceCtrlr"
     }
 
     private var session: SmartspaceSession? = null
diff --git a/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java b/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java
index f5575a2..f769a23 100644
--- a/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandler.java
@@ -44,6 +44,7 @@
 import com.android.wm.shell.animation.FlingAnimationUtils;
 
 import java.util.Optional;
+
 import javax.inject.Inject;
 import javax.inject.Named;
 
@@ -153,8 +154,6 @@
 
     private void setPanelExpansion(float expansion, float dragDownAmount) {
         mCurrentExpansion = expansion;
-        mCentralSurfaces.ifPresent(centralSurfaces -> centralSurfaces.setBouncerShowingOverDream(
-                mCurrentExpansion != KeyguardBouncer.EXPANSION_HIDDEN));
         PanelExpansionChangeEvent event =
                 new PanelExpansionChangeEvent(
                         /* fraction= */ mCurrentExpansion,
diff --git a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
index 3ae11ff..9c7411b 100644
--- a/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
+++ b/packages/SystemUI/src/com/android/systemui/fragments/FragmentHostManager.java
@@ -54,7 +54,7 @@
     private final View mRootView;
     private final InterestingConfigChanges mConfigChanges = new InterestingConfigChanges(
             ActivityInfo.CONFIG_FONT_SCALE | ActivityInfo.CONFIG_LOCALE
-                    | ActivityInfo.CONFIG_LAYOUT_DIRECTION | ActivityInfo.CONFIG_ASSETS_PATHS);
+                    | ActivityInfo.CONFIG_ASSETS_PATHS);
     private final FragmentService mManager;
     private final ExtensionFragmentManager mPlugins = new ExtensionFragmentManager();
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 2e13732..29e940f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -849,7 +849,8 @@
 
                 @Override
                 public void onLaunchAnimationCancelled() {
-                    setOccluded(true /* occluded */, false /* animate */);
+                    Log.d(TAG, "Occlude launch animation cancelled. "
+                            + "Occluded state is now: " + mOccluded);
                 }
 
                 @NonNull
@@ -894,7 +895,7 @@
             };
 
     private IRemoteAnimationRunner mOccludeAnimationRunner =
-            new ActivityLaunchRemoteAnimationRunner(mOccludeAnimationController);
+            new OccludeActivityLaunchRemoteAnimationRunner(mOccludeAnimationController);
 
     /**
      * Animation controller for activities that unocclude the keyguard. This does not use the
@@ -919,13 +920,17 @@
                         RemoteAnimationTarget[] wallpapers,
                         RemoteAnimationTarget[] nonApps,
                         IRemoteAnimationFinishedCallback finishedCallback) throws RemoteException {
-                    final RemoteAnimationTarget primary = apps[0];
+                    if (apps == null || apps.length == 0 || apps[0] == null) {
+                        Log.d(TAG, "No apps provided to unocclude runner; "
+                                + "skipping animation and unoccluding.");
 
-                    if (primary == null) {
                         finishedCallback.onAnimationFinished();
+                        setOccluded(false /* isOccluded */, true /* animate */);
                         return;
                     }
 
+                    final RemoteAnimationTarget primary = apps[0];
+
                     final SyncRtSurfaceTransactionApplier applier =
                             new SyncRtSurfaceTransactionApplier(
                                     mKeyguardViewControllerLazy.get().getViewRootImpl().getView());
@@ -965,6 +970,7 @@
                             @Override
                             public void onAnimationEnd(Animator animation) {
                                 try {
+                                    setOccluded(false /* isOccluded */, true /* animate */);
                                     finishedCallback.onAnimationFinished();
                                     mUnoccludeAnimator = null;
                                 } catch (RemoteException e) {
@@ -3125,4 +3131,36 @@
             mRunner.onAnimationStart(transit, apps, wallpapers, nonApps, finishedCallback);
         }
     }
+
+    /**
+     * Subclass of {@link ActivityLaunchRemoteAnimationRunner} that calls {@link #setOccluded} when
+     * onAnimationStart is called.
+     */
+    private class OccludeActivityLaunchRemoteAnimationRunner
+            extends ActivityLaunchRemoteAnimationRunner {
+
+        OccludeActivityLaunchRemoteAnimationRunner(
+                ActivityLaunchAnimator.Controller controller) {
+            super(controller);
+        }
+
+        @Override
+        public void onAnimationStart(int transit, RemoteAnimationTarget[] apps,
+                RemoteAnimationTarget[] wallpapers, RemoteAnimationTarget[] nonApps,
+                IRemoteAnimationFinishedCallback finishedCallback) throws RemoteException {
+            super.onAnimationStart(transit, apps, wallpapers, nonApps, finishedCallback);
+
+            // This is the first signal we have from WM that we're going to be occluded. Set our
+            // internal state to reflect that immediately, vs. waiting for the launch animator to
+            // begin. Otherwise, calls to setShowingLocked, etc. will not know that we're about to
+            // be occluded and might re-show the keyguard.
+            setOccluded(true /* isOccluded */, false /* animate */);
+        }
+
+        @Override
+        public void onAnimationCancelled() throws RemoteException {
+            super.onAnimationCancelled();
+            Log.d(TAG, "Occlude launch animation cancelled. Occluded state is now: " + mOccluded);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index d2c35bd..d9ee8f3 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -30,10 +30,12 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.res.ColorStateList;
+import android.graphics.Color;
 import android.graphics.ColorMatrix;
 import android.graphics.ColorMatrixColorFilter;
 import android.graphics.Rect;
 import android.graphics.drawable.Animatable;
+import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.Icon;
 import android.graphics.drawable.TransitionDrawable;
@@ -159,6 +161,7 @@
     private MetadataAnimationHandler mMetadataAnimationHandler;
     private ColorSchemeTransition mColorSchemeTransition;
     private Drawable mPrevArtwork = null;
+    private boolean mIsArtworkBound = false;
     private int mArtworkBoundId = 0;
     private int mArtworkNextBindRequestId = 0;
 
@@ -586,6 +589,9 @@
 
     private void bindArtworkAndColors(MediaData data, boolean updateBackground) {
         final int reqId = mArtworkNextBindRequestId++;
+        if (updateBackground) {
+            mIsArtworkBound = false;
+        }
 
         // Capture width & height from views in foreground for artwork scaling in background
         int width = mMediaViewHolder.getPlayer().getWidth();
@@ -597,15 +603,18 @@
             // Album art
             ColorScheme mutableColorScheme = null;
             Drawable artwork;
+            boolean isArtworkBound;
             Icon artworkIcon = data.getArtwork();
             if (artworkIcon != null) {
                 WallpaperColors wallpaperColors = WallpaperColors
                         .fromBitmap(artworkIcon.getBitmap());
                 mutableColorScheme = new ColorScheme(wallpaperColors, true);
                 artwork = getScaledBackground(artworkIcon, width, height);
+                isArtworkBound = true;
             } else {
                 // If there's no artwork, use colors from the app icon
-                artwork = null;
+                artwork = new ColorDrawable(Color.TRANSPARENT);
+                isArtworkBound = false;
                 try {
                     Drawable icon = mContext.getPackageManager()
                             .getApplicationIcon(data.getPackageName());
@@ -625,16 +634,20 @@
                 ImageView albumView = mMediaViewHolder.getAlbumView();
                 albumView.setPadding(0, 0, 0, 0);
                 albumView.setClipToOutline(true);
-                if (updateBackground) {
-                    if (mPrevArtwork == null || artwork == null) {
+                if (updateBackground || (!mIsArtworkBound && isArtworkBound)) {
+                    if (mPrevArtwork == null) {
                         albumView.setImageDrawable(artwork);
                     } else {
+                        // Since we throw away the last transition, this'll pop if you backgrounds
+                        // are cycled too fast (or the correct background arrives very soon after
+                        // the metadata changes).
                         TransitionDrawable transitionDrawable = new TransitionDrawable(
-                                new Drawable[] { mPrevArtwork, artwork });
+                                new Drawable[]{mPrevArtwork, artwork});
                         albumView.setImageDrawable(transitionDrawable);
-                        transitionDrawable.startTransition(333);
+                        transitionDrawable.startTransition(isArtworkBound ? 333 : 80);
                     }
                     mPrevArtwork = artwork;
+                    mIsArtworkBound = isArtworkBound;
                 }
 
                 // Transition Colors to current color scheme
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt
index fe4cb71..d4e1642 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt
@@ -67,7 +67,7 @@
             attributes.receiveInsetsIgnoringZOrder = true
             setGravity(Gravity.TOP or Gravity.CENTER_HORIZONTAL)
         }
-
+        setTitle(R.string.ongoing_privacy_dialog_a11y_title)
         setContentView(R.layout.privacy_dialog)
         rootView = requireViewById<ViewGroup>(R.id.root)
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index 34f771c..ce50ddf 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -39,6 +39,7 @@
 
     private static final boolean DEBUG = false;
     private static final String CURRENT_PAGE = "current_page";
+    private static final int NO_PAGE = -1;
 
     private static final String TAG = "PagedTileLayout";
     private static final int REVEAL_SCROLL_DURATION_MILLIS = 750;
@@ -109,13 +110,14 @@
     }
 
     public void saveInstanceState(Bundle outState) {
-        outState.putInt(CURRENT_PAGE, getCurrentItem());
+        int resolvedPage = mPageToRestore != NO_PAGE ? mPageToRestore : getCurrentPageNumber();
+        outState.putInt(CURRENT_PAGE, resolvedPage);
     }
 
     public void restoreInstanceState(Bundle savedInstanceState) {
         // There's only 1 page at this point. We want to restore the correct page once the
         // pages have been inflated
-        mPageToRestore = savedInstanceState.getInt(CURRENT_PAGE, -1);
+        mPageToRestore = savedInstanceState.getInt(CURRENT_PAGE, NO_PAGE);
     }
 
     @Override
@@ -151,12 +153,15 @@
 
     @Override
     public void onRtlPropertiesChanged(int layoutDirection) {
+        // The configuration change will change the flag in the view (that's returned in
+        // isLayoutRtl). As we detect the change, we use the cached direction to store the page
+        // before setting it.
+        final int page = getPageNumberForDirection(mLayoutDirection == LAYOUT_DIRECTION_RTL);
         super.onRtlPropertiesChanged(layoutDirection);
         if (mLayoutDirection != layoutDirection) {
             mLayoutDirection = layoutDirection;
             setAdapter(mAdapter);
-            setCurrentItem(0, false);
-            mPageToRestore = 0;
+            setCurrentItem(page, false);
         }
     }
 
@@ -172,8 +177,12 @@
      * Obtains the current page number respecting RTL
      */
     private int getCurrentPageNumber() {
+        return getPageNumberForDirection(isLayoutRtl());
+    }
+
+    private int getPageNumberForDirection(boolean isLayoutRTL) {
         int page = getCurrentItem();
-        if (mLayoutDirection == LAYOUT_DIRECTION_RTL) {
+        if (isLayoutRTL) {
             page = mPages.size() - 1 - page;
         }
         return page;
@@ -388,9 +397,9 @@
         mPageIndicator.setNumPages(mPages.size());
         setAdapter(mAdapter);
         mAdapter.notifyDataSetChanged();
-        if (mPageToRestore != -1) {
+        if (mPageToRestore != NO_PAGE) {
             setCurrentItem(mPageToRestore, false);
-            mPageToRestore = -1;
+            mPageToRestore = NO_PAGE;
         }
     }
 
@@ -479,9 +488,27 @@
                 maxHeight = height;
             }
         }
+        if (mPages.get(0).getParent() == null) {
+            // Measure page 0 so we know how tall it is if it's not attached to the pager.
+            mPages.get(0).measure(widthMeasureSpec, heightMeasureSpec);
+            int height = mPages.get(0).getMeasuredHeight();
+            if (height > maxHeight) {
+                maxHeight = height;
+            }
+        }
         setMeasuredDimension(getMeasuredWidth(), maxHeight + getPaddingBottom());
     }
 
+    @Override
+    protected void onLayout(boolean changed, int l, int t, int r, int b) {
+        super.onLayout(changed, l, t, r, b);
+        if (mPages.get(0).getParent() == null) {
+            // Layout page 0, so we can get the bottom of the tiles. We only do this if the page
+            // is not attached.
+            mPages.get(0).layout(l, t, r, b);
+        }
+    }
+
     public int getColumnCount() {
         if (mPages.size() == 0) return 0;
         return mPages.get(0).mColumns;
@@ -625,8 +652,7 @@
                     if (mPageIndicator == null) return;
                     if (mPageListener != null) {
                         int pageNumber = isLayoutRtl() ? mPages.size() - 1 - position : position;
-                        mPageListener.onPageChanged(isLayoutRtl() ? position == mPages.size() - 1
-                                : position == 0, pageNumber);
+                        mPageListener.onPageChanged(pageNumber == 0, pageNumber);
                     }
                 }
 
@@ -645,8 +671,8 @@
                     mPageIndicator.setLocation(mPageIndicatorPosition);
                     if (mPageListener != null) {
                         int pageNumber = isLayoutRtl() ? mPages.size() - 1 - position : position;
-                        mPageListener.onPageChanged(positionOffsetPixels == 0 &&
-                                (isLayoutRtl() ? position == mPages.size() - 1 : position == 0),
+                        mPageListener.onPageChanged(
+                                positionOffsetPixels == 0 && pageNumber == 0,
                                 // Send only valid page number on integer pages
                                 positionOffsetPixels == 0 ? pageNumber : PageListener.INVALID_PAGE
                         );
diff --git a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java
index 2959c3b..592da65 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrier.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.qs.carrier;
 
+import android.annotation.StyleRes;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.text.TextUtils;
@@ -30,6 +31,7 @@
 
 import com.android.settingslib.Utils;
 import com.android.settingslib.graph.SignalDrawable;
+import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
 
 import java.util.Objects;
@@ -146,4 +148,8 @@
     public void setCarrierText(CharSequence text) {
         mCarrierText.setText(text);
     }
+
+    public void updateTextAppearance(@StyleRes int resId) {
+        FontSizeUtils.updateFontSizeFromStyle(mCarrierText, resId);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroup.java b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroup.java
index d03563f..a36035b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroup.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/carrier/QSCarrierGroup.java
@@ -16,12 +16,14 @@
 
 package com.android.systemui.qs.carrier;
 
+import android.annotation.StyleRes;
 import android.content.Context;
 import android.util.AttributeSet;
 import android.view.View;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
+import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
 
 /**
@@ -55,4 +57,11 @@
     View getCarrierDivider2() {
         return findViewById(R.id.qs_carrier_divider2);
     }
+
+    public void updateTextAppearance(@StyleRes int resId) {
+        FontSizeUtils.updateFontSizeFromStyle(getNoSimTextView(), resId);
+        getCarrier1View().updateTextAppearance(resId);
+        getCarrier2View().updateTextAppearance(resId);
+        getCarrier3View().updateTextAppearance(resId);
+    }
 }
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 8ca095d..6eb54f7 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
@@ -24,7 +24,6 @@
 import android.graphics.drawable.Drawable;
 import android.net.Network;
 import android.net.NetworkCapabilities;
-import android.net.wifi.WifiManager;
 import android.os.Bundle;
 import android.os.Handler;
 import android.telephony.ServiceState;
@@ -90,8 +89,6 @@
     @VisibleForTesting
     protected InternetAdapter mAdapter;
     @VisibleForTesting
-    protected WifiManager mWifiManager;
-    @VisibleForTesting
     protected View mDialogView;
     @VisibleForTesting
     protected boolean mCanConfigWifi;
@@ -179,7 +176,6 @@
         mSubscriptionManager = mInternetDialogController.getSubscriptionManager();
         mDefaultDataSubId = mInternetDialogController.getDefaultDataSubscriptionId();
         mTelephonyManager = mInternetDialogController.getTelephonyManager();
-        mWifiManager = mInternetDialogController.getWifiManager();
         mCanConfigMobileData = canConfigMobileData;
         mCanConfigWifi = canConfigWifi;
         mCanChangeWifiState = WifiEnterpriseRestrictionUtils.isChangeWifiStateAllowed(context);
@@ -332,7 +328,7 @@
 
         showProgressBar();
         final boolean isDeviceLocked = mInternetDialogController.isDeviceLocked();
-        final boolean isWifiEnabled = mWifiManager != null && mWifiManager.isWifiEnabled();
+        final boolean isWifiEnabled = mInternetDialogController.isWifiEnabled();
         final boolean isWifiScanEnabled = mInternetDialogController.isWifiScanEnabled();
         updateWifiToggle(isWifiEnabled, isDeviceLocked);
         updateConnectedWifi(isWifiEnabled, isDeviceLocked);
@@ -362,9 +358,8 @@
         mSeeAllLayout.setOnClickListener(this::onClickSeeMoreButton);
         mWiFiToggle.setOnCheckedChangeListener(
                 (buttonView, isChecked) -> {
-                    if (mWifiManager == null) return;
-                    buttonView.setChecked(isChecked);
-                    mWifiManager.setWifiEnabled(isChecked);
+                    if (mInternetDialogController.isWifiEnabled() == isChecked) return;
+                    mInternetDialogController.setWifiEnabled(isChecked);
                 });
         mDoneButton.setOnClickListener(v -> dismiss());
         mAirplaneModeButton.setOnClickListener(v -> {
@@ -388,7 +383,7 @@
             Log.d(TAG, "setMobileDataLayout, isCarrierNetworkActive = " + isCarrierNetworkActive);
         }
 
-        boolean isWifiEnabled = mWifiManager != null && mWifiManager.isWifiEnabled();
+        boolean isWifiEnabled = mInternetDialogController.isWifiEnabled();
         if (!mInternetDialogController.hasActiveSubId()
                 && (!isWifiEnabled || !isCarrierNetworkActive)) {
             mMobileNetworkLayout.setVisibility(View.GONE);
@@ -444,7 +439,9 @@
 
     @MainThread
     private void updateWifiToggle(boolean isWifiEnabled, boolean isDeviceLocked) {
-        mWiFiToggle.setChecked(isWifiEnabled);
+        if (mWiFiToggle.isChecked() != isWifiEnabled) {
+            mWiFiToggle.setChecked(isWifiEnabled);
+        }
         if (isDeviceLocked) {
             mWifiToggleTitleText.setTextAppearance((mConnectedWifiEntry != null)
                     ? R.style.TextAppearance_InternetDialog_Active
@@ -572,7 +569,7 @@
     }
 
     protected void showProgressBar() {
-        if (mWifiManager == null || !mWifiManager.isWifiEnabled()
+        if (!mInternetDialogController.isWifiEnabled()
                 || mInternetDialogController.isDeviceLocked()) {
             setProgressBarVisible(false);
             return;
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 d97ce77..90a3d45 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
@@ -22,6 +22,7 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
+import android.annotation.AnyThread;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -157,6 +158,7 @@
     private LocationController mLocationController;
     private DialogLaunchAnimator mDialogLaunchAnimator;
     private boolean mHasWifiEntries;
+    private WifiStateWorker mWifiStateWorker;
 
     @VisibleForTesting
     static final float TOAST_PARAMS_HORIZONTAL_WEIGHT = 1.0f;
@@ -210,7 +212,9 @@
             @Background Handler workerHandler,
             CarrierConfigTracker carrierConfigTracker,
             LocationController locationController,
-            DialogLaunchAnimator dialogLaunchAnimator) {
+            DialogLaunchAnimator dialogLaunchAnimator,
+            WifiStateWorker wifiStateWorker
+    ) {
         if (DEBUG) {
             Log.d(TAG, "Init InternetDialogController");
         }
@@ -241,6 +245,7 @@
         mLocationController = locationController;
         mDialogLaunchAnimator = dialogLaunchAnimator;
         mConnectedWifiInternetMonitor = new ConnectedWifiInternetMonitor();
+        mWifiStateWorker = wifiStateWorker;
     }
 
     void onStart(@NonNull InternetDialogCallback callback, boolean canConfigWifi) {
@@ -323,7 +328,7 @@
 
     @Nullable
     CharSequence getSubtitleText(boolean isProgressBarVisible) {
-        if (mCanConfigWifi && !mWifiManager.isWifiEnabled()) {
+        if (mCanConfigWifi && !isWifiEnabled()) {
             // When Wi-Fi is disabled.
             //   Sub-Title: Wi-Fi is off
             if (DEBUG) {
@@ -648,6 +653,27 @@
         startActivity(intent, view);
     }
 
+    /**
+     * Enable or disable Wi-Fi.
+     *
+     * @param enabled {@code true} to enable, {@code false} to disable.
+     */
+    @AnyThread
+    public void setWifiEnabled(boolean enabled) {
+        mWifiStateWorker.setWifiEnabled(enabled);
+    }
+
+    /**
+     * Return whether Wi-Fi is enabled or disabled.
+     *
+     * @return {@code true} if Wi-Fi is enabled or enabling
+     * @see WifiManager#getWifiState()
+     */
+    @AnyThread
+    public boolean isWifiEnabled() {
+        return mWifiStateWorker.isWifiEnabled();
+    }
+
     void connectCarrierNetwork() {
         final MergedCarrierEntry mergedCarrierEntry =
                 mAccessPointController.getMergedCarrierEntry();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/WifiStateWorker.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/WifiStateWorker.java
new file mode 100644
index 0000000..a7ea50e
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/WifiStateWorker.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2022 The Android Open 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.dialog;
+
+import static android.net.wifi.WifiManager.EXTRA_WIFI_STATE;
+import static android.net.wifi.WifiManager.WIFI_STATE_CHANGED_ACTION;
+import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED;
+import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING;
+import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
+import static android.net.wifi.WifiManager.WIFI_STATE_ENABLING;
+import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.net.wifi.WifiManager;
+import android.util.Log;
+
+import androidx.annotation.AnyThread;
+import androidx.annotation.Nullable;
+
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Background;
+import com.android.systemui.util.concurrency.DelayableExecutor;
+
+import javax.inject.Inject;
+
+/**
+ * Worker for the Wi-Fi enabled state cache.
+ */
+@SysUISingleton
+public class WifiStateWorker extends BroadcastReceiver {
+
+    private static final String TAG = "WifiStateWorker";
+
+    private DelayableExecutor mBackgroundExecutor;
+    private WifiManager mWifiManager;
+    private int mWifiState = WIFI_STATE_DISABLED;
+
+    @Inject
+    public WifiStateWorker(
+            BroadcastDispatcher broadcastDispatcher,
+            @Background DelayableExecutor backgroundExecutor,
+            @Nullable WifiManager wifiManager) {
+        mWifiManager = wifiManager;
+        mBackgroundExecutor = backgroundExecutor;
+
+        broadcastDispatcher.registerReceiver(this, new IntentFilter(WIFI_STATE_CHANGED_ACTION));
+        mBackgroundExecutor.execute(() -> {
+            if (mWifiManager == null) return;
+
+            mWifiState = mWifiManager.getWifiState();
+            Log.i(TAG, "WifiManager.getWifiState():" + mWifiState);
+        });
+    }
+
+    /**
+     * Enable or disable Wi-Fi.
+     *
+     * @param enabled {@code true} to enable, {@code false} to disable.
+     */
+    @AnyThread
+    public void setWifiEnabled(boolean enabled) {
+        mBackgroundExecutor.execute(() -> {
+            if (mWifiManager == null) return;
+
+            mWifiState = (enabled) ? WIFI_STATE_ENABLING : WIFI_STATE_DISABLING;
+            if (!mWifiManager.setWifiEnabled(enabled)) {
+                Log.e(TAG, "Failed to WifiManager.setWifiEnabled(" + enabled + ");");
+            }
+        });
+    }
+
+    /**
+     * Gets the Wi-Fi enabled state.
+     *
+     * @return One of {@link WifiManager#WIFI_STATE_DISABLED},
+     *         {@link WifiManager#WIFI_STATE_DISABLING}, {@link WifiManager#WIFI_STATE_ENABLED},
+     *         {@link WifiManager#WIFI_STATE_ENABLING}
+     */
+    @AnyThread
+    public int getWifiState() {
+        return mWifiState;
+    }
+
+    /**
+     * Return whether Wi-Fi is enabled or disabled.
+     *
+     * @return {@code true} if Wi-Fi is enabled or enabling
+     * @see WifiManager#getWifiState()
+     */
+    @AnyThread
+    public boolean isWifiEnabled() {
+        return (mWifiState == WIFI_STATE_ENABLED || mWifiState == WIFI_STATE_ENABLING);
+    }
+
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        if (intent == null) return;
+
+        if (WIFI_STATE_CHANGED_ACTION.equals(intent.getAction())) {
+            final int wifiState = intent.getIntExtra(EXTRA_WIFI_STATE, WIFI_STATE_DISABLED);
+            if (wifiState == WIFI_STATE_UNKNOWN) return;
+
+            mWifiState = wifiState;
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
index 924351d..7f3758e 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/TakeScreenshotService.java
@@ -27,6 +27,7 @@
 
 import android.annotation.MainThread;
 import android.app.Service;
+import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.Context;
@@ -42,9 +43,11 @@
 import android.os.Message;
 import android.os.Messenger;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.os.UserManager;
 import android.util.Log;
 import android.view.WindowManager;
+import android.widget.Toast;
 
 import androidx.annotation.NonNull;
 
@@ -62,9 +65,11 @@
     private ScreenshotController mScreenshot;
 
     private final UserManager mUserManager;
+    private final DevicePolicyManager mDevicePolicyManager;
     private final UiEventLogger mUiEventLogger;
     private final ScreenshotNotificationsController mNotificationsController;
     private final Handler mHandler;
+    private final Context mContext;
 
     private final BroadcastReceiver mCloseSystemDialogs = new BroadcastReceiver() {
         @Override
@@ -91,16 +96,18 @@
 
     @Inject
     public TakeScreenshotService(ScreenshotController screenshotController, UserManager userManager,
-            UiEventLogger uiEventLogger,
-            ScreenshotNotificationsController notificationsController) {
+            DevicePolicyManager devicePolicyManager, UiEventLogger uiEventLogger,
+            ScreenshotNotificationsController notificationsController, Context context) {
         if (DEBUG_SERVICE) {
             Log.d(TAG, "new " + this);
         }
         mHandler = new Handler(Looper.getMainLooper(), this::handleMessage);
         mScreenshot = screenshotController;
         mUserManager = userManager;
+        mDevicePolicyManager = devicePolicyManager;
         mUiEventLogger = uiEventLogger;
         mNotificationsController = notificationsController;
+        mContext = context;
     }
 
     @Override
@@ -182,6 +189,14 @@
             requestCallback.reportError();
             return true;
         }
+        if(mDevicePolicyManager.getScreenCaptureDisabled(null, UserHandle.USER_ALL)) {
+            Log.w(TAG, "Skipping screenshot because an IT admin has disabled "
+                    + "screenshots on the device");
+            Toast.makeText(mContext, R.string.screenshot_blocked_by_admin,
+                    Toast.LENGTH_SHORT).show();
+            requestCallback.reportError();
+            return true;
+        }
 
         ScreenshotHelper.ScreenshotRequest screenshotRequest =
                 (ScreenshotHelper.ScreenshotRequest) msg.obj;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 5585cde..aa80b73 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -23,7 +23,7 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
 
-import static com.android.systemui.statusbar.phone.CentralSurfaces.ONLY_CORE_APPS;
+import static com.android.systemui.statusbar.phone.CentralSurfacesImpl.ONLY_CORE_APPS;
 
 import android.annotation.Nullable;
 import android.app.ITransientNotificationCallback;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
index 83290af..29411e6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/CentralSurfacesDependenciesModule.java
@@ -61,6 +61,7 @@
 import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection;
 import com.android.systemui.statusbar.notification.collection.render.NotificationVisibilityProvider;
 import com.android.systemui.statusbar.phone.CentralSurfaces;
+import com.android.systemui.statusbar.phone.CentralSurfacesImpl;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.ManagedProfileController;
 import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
@@ -87,7 +88,7 @@
 import dagger.Provides;
 
 /**
- * This module provides instances needed to construct {@link CentralSurfaces}. These are moved to
+ * This module provides instances needed to construct {@link CentralSurfacesImpl}. These are moved to
  * this separate from {@link CentralSurfacesModule} module so that components that wish to build
  * their own version of CentralSurfaces can include just dependencies, without injecting
  * CentralSurfaces itself.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StartCentralSurfacesModule.kt b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StartCentralSurfacesModule.kt
index fe55dea7..e84d31d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StartCentralSurfacesModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/dagger/StartCentralSurfacesModule.kt
@@ -18,6 +18,7 @@
 
 import com.android.systemui.CoreStartable
 import com.android.systemui.statusbar.phone.CentralSurfaces
+import com.android.systemui.statusbar.phone.CentralSurfacesImpl
 import dagger.Binds
 import dagger.Module
 import dagger.multibindings.ClassKey
@@ -29,5 +30,5 @@
     @Binds
     @IntoMap
     @ClassKey(CentralSurfaces::class)
-    abstract fun bindsCentralSurfaces(centralSurfaces: CentralSurfaces): CoreStartable
+    abstract fun bindsCentralSurfaces(centralSurfaces: CentralSurfacesImpl): CoreStartable
 }
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 bf27550..36cd173 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
@@ -415,6 +415,10 @@
     private boolean mForwardScrollable;
     private boolean mBackwardScrollable;
     private NotificationShelf mShelf;
+    /**
+     * Limits the number of visible notifications. The remaining are collapsed in the notification
+     * shelf. -1 when there is no limit.
+     */
     private int mMaxDisplayedNotifications = -1;
     private float mKeyguardBottomPadding = -1;
     @VisibleForTesting int mStatusBarHeight;
@@ -1323,7 +1327,14 @@
     }
 
     private float updateStackEndHeight(float height, float bottomMargin, float topPadding) {
-        final float stackEndHeight = Math.max(0f, height - bottomMargin - topPadding);
+        final float stackEndHeight;
+        if (mMaxDisplayedNotifications != -1) {
+            // The stack intrinsic height already contains the correct value when there is a limit
+            // in the max number of notifications (e.g. as in keyguard).
+            stackEndHeight = mIntrinsicContentHeight;
+        } else {
+            stackEndHeight = Math.max(0f, height - bottomMargin - topPadding);
+        }
         mAmbientState.setStackEndHeight(stackEndHeight);
         return stackEndHeight;
     }
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 ae1fd2b..c2750c2 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
@@ -1207,7 +1207,7 @@
      */
     public void updateShowEmptyShadeView() {
         Trace.beginSection("NSSLC.updateShowEmptyShadeView");
-        mShowEmptyShadeView = mBarState != KEYGUARD
+        mShowEmptyShadeView = mStatusBarStateController.getCurrentOrUpcomingState() != KEYGUARD
                 && !mView.isQsFullScreen()
                 && getVisibleNotificationCount() == 0;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
index 159ebd9..d1f586e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfaces.java
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2022 The Android Open 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,2372 +16,89 @@
 
 package com.android.systemui.statusbar.phone;
 
-import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN;
-import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
-import static android.app.StatusBarManager.WindowVisibleState;
-import static android.app.StatusBarManager.windowStateToString;
-import static android.view.InsetsState.ITYPE_STATUS_BAR;
-import static android.view.InsetsState.containsType;
-import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
-import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_STATUS_BARS;
-import static android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS;
-
-import static androidx.core.view.ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_AUTO;
-import static androidx.core.view.ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
-import static androidx.lifecycle.Lifecycle.State.RESUMED;
-
-import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME;
-import static com.android.systemui.charging.WirelessChargingLayout.UNKNOWN_BATTERY_LEVEL;
-import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP;
-import static com.android.systemui.statusbar.NotificationLockscreenUserManager.PERMISSION_SELF;
-import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
-import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
-import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
-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.transition.Transitions.ENABLE_SHELL_TRANSITIONS;
 
 import android.annotation.Nullable;
-import android.app.ActivityManager;
 import android.app.ActivityOptions;
-import android.app.ActivityTaskManager;
-import android.app.IWallpaperManager;
-import android.app.KeyguardManager;
-import android.app.Notification;
-import android.app.NotificationManager;
 import android.app.PendingIntent;
-import android.app.StatusBarManager;
-import android.app.TaskInfo;
-import android.app.TaskStackBuilder;
-import android.app.UiModeManager;
-import android.app.WallpaperInfo;
-import android.app.WallpaperManager;
-import android.app.admin.DevicePolicyManager;
-import android.content.BroadcastReceiver;
-import android.content.ComponentCallbacks2;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
-import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.ResolveInfo;
-import android.content.res.Configuration;
-import android.graphics.Point;
-import android.graphics.PointF;
-import android.hardware.devicestate.DeviceStateManager;
-import android.metrics.LogMaker;
-import android.net.Uri;
 import android.os.Bundle;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.PowerManager;
-import android.os.RemoteException;
-import android.os.ServiceManager;
-import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.os.Trace;
 import android.os.UserHandle;
-import android.provider.Settings;
-import android.service.dreams.DreamService;
-import android.service.dreams.IDreamManager;
 import android.service.notification.StatusBarNotification;
-import android.text.TextUtils;
-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;
-import android.view.Display;
-import android.view.IRemoteAnimationRunner;
-import android.view.IWindowManager;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.RemoteAnimationAdapter;
-import android.view.ThreadedRenderer;
 import android.view.View;
 import android.view.ViewGroup;
-import android.view.WindowInsetsController.Appearance;
-import android.view.WindowManager;
-import android.view.WindowManagerGlobal;
-import android.view.accessibility.AccessibilityManager;
-import android.widget.DateTimeView;
 import android.window.SplashScreen;
 
 import androidx.annotation.NonNull;
 import androidx.lifecycle.Lifecycle;
 import androidx.lifecycle.LifecycleOwner;
-import androidx.lifecycle.LifecycleRegistry;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.colorextraction.ColorExtractor;
-import com.android.internal.jank.InteractionJankMonitor;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.logging.UiEvent;
-import com.android.internal.logging.UiEventLogger;
-import com.android.internal.logging.UiEventLoggerImpl;
-import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.statusbar.RegisterStatusBarResult;
-import com.android.keyguard.KeyguardUpdateMonitor;
-import com.android.keyguard.KeyguardUpdateMonitorCallback;
-import com.android.keyguard.ViewMediatorCallback;
-import com.android.systemui.ActivityIntentHelper;
-import com.android.systemui.AutoReinflateContainer;
-import com.android.systemui.CoreStartable;
-import com.android.systemui.DejankUtils;
-import com.android.systemui.EventLogTags;
-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.Dumpable;
 import com.android.systemui.animation.ActivityLaunchAnimator;
-import com.android.systemui.animation.DelegateLaunchAnimatorController;
 import com.android.systemui.animation.RemoteTransitionAdapter;
-import com.android.systemui.assist.AssistManager;
-import com.android.systemui.biometrics.AuthRippleController;
-import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.camera.CameraIntents;
-import com.android.systemui.charging.WirelessChargingAnimation;
-import com.android.systemui.classifier.FalsingCollector;
-import com.android.systemui.colorextraction.SysuiColorExtractor;
-import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.dagger.qualifiers.UiBackground;
-import com.android.systemui.demomode.DemoMode;
-import com.android.systemui.demomode.DemoModeController;
-import com.android.systemui.dreams.DreamOverlayStateController;
-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;
-import com.android.systemui.keyguard.ScreenLifecycle;
-import com.android.systemui.keyguard.WakefulnessLifecycle;
-import com.android.systemui.navigationbar.NavigationBarController;
 import com.android.systemui.navigationbar.NavigationBarView;
 import com.android.systemui.plugins.ActivityStarter;
-import com.android.systemui.plugins.DarkIconDispatcher;
-import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.plugins.OverlayPlugin;
-import com.android.systemui.plugins.PluginDependencyProvider;
-import com.android.systemui.plugins.PluginListener;
-import com.android.systemui.plugins.qs.QS;
-import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
-import com.android.systemui.plugins.statusbar.StatusBarStateController;
-import com.android.systemui.qs.QSFragment;
+import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper;
 import com.android.systemui.qs.QSPanelController;
-import com.android.systemui.recents.ScreenPinningRequest;
-import com.android.systemui.scrim.ScrimView;
-import com.android.systemui.settings.brightness.BrightnessSliderController;
-import com.android.systemui.shared.plugins.PluginManager;
-import com.android.systemui.statusbar.AutoHideUiElement;
-import com.android.systemui.statusbar.BackDropView;
-import com.android.systemui.statusbar.CircleReveal;
-import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.GestureRecorder;
-import com.android.systemui.statusbar.KeyboardShortcuts;
-import com.android.systemui.statusbar.KeyguardIndicationController;
-import com.android.systemui.statusbar.LiftReveal;
 import com.android.systemui.statusbar.LightRevealScrim;
-import com.android.systemui.statusbar.LockscreenShadeTransitionController;
-import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.NotificationMediaManager;
 import com.android.systemui.statusbar.NotificationPresenter;
-import com.android.systemui.statusbar.NotificationRemoteInputManager;
-import com.android.systemui.statusbar.NotificationShadeDepthController;
-import com.android.systemui.statusbar.NotificationShadeWindowController;
-import com.android.systemui.statusbar.NotificationShelfController;
-import com.android.systemui.statusbar.NotificationViewHierarchyManager;
-import com.android.systemui.statusbar.PowerButtonReveal;
-import com.android.systemui.statusbar.PulseExpansionHandler;
-import com.android.systemui.statusbar.StatusBarState;
-import com.android.systemui.statusbar.SysuiStatusBarStateController;
-import com.android.systemui.statusbar.charging.WiredChargingRippleController;
-import com.android.systemui.statusbar.connectivity.NetworkController;
-import com.android.systemui.statusbar.core.StatusBarInitializer;
-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;
-import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
-import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
-import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
-import com.android.systemui.statusbar.notification.init.NotificationsController;
-import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
-import com.android.systemui.statusbar.notification.logging.NotificationLogger;
-import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
-import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
-import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent;
-import com.android.systemui.statusbar.phone.dagger.StatusBarPhoneModule;
-import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
-import com.android.systemui.statusbar.phone.panelstate.PanelExpansionChangeEvent;
-import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
-import com.android.systemui.statusbar.policy.BatteryController;
-import com.android.systemui.statusbar.policy.BrightnessMirrorController;
-import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
-import com.android.systemui.statusbar.policy.ExtensionController;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
-import com.android.systemui.statusbar.policy.UserSwitcherController;
-import com.android.systemui.statusbar.window.StatusBarWindowController;
-import com.android.systemui.statusbar.window.StatusBarWindowStateController;
-import com.android.systemui.util.DumpUtilsKt;
-import com.android.systemui.util.WallpaperController;
-import com.android.systemui.util.concurrency.DelayableExecutor;
-import com.android.systemui.util.concurrency.MessageRouter;
-import com.android.systemui.volume.VolumeComponent;
-import com.android.systemui.wmshell.BubblesManager;
-import com.android.wm.shell.bubbles.Bubbles;
-import com.android.wm.shell.startingsurface.SplashscreenContentDrawer;
-import com.android.wm.shell.startingsurface.StartingSurface;
 
 import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.concurrent.Executor;
 
-import javax.inject.Named;
-
-import dagger.Lazy;
-
-/**
- * A class handling initialization and coordination between some of the key central surfaces in
- * System UI: The notification shade, the keyguard (lockscreen), and the status bar.
- *
- * This class is not our ideal architecture because it doesn't enforce much isolation between these
- * three mostly disparate surfaces. In an ideal world, this class would not exist. Instead, we would
- * break it up into three modules -- one for each of those three surfaces -- and we would define any
- * APIs that are needed for these surfaces to communicate with each other when necessary.
- *
- * <b>If at all possible, please avoid adding additional code to this monstrous class! Our goal is
- * to break up this class into many small classes, and any code added here will slow down that goal.
- * </b>
- */
-public class CentralSurfaces extends CoreStartable implements
-        ActivityStarter,
-        LifecycleOwner {
-    public static final boolean MULTIUSER_DEBUG = false;
-
-    protected static final int MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU = 1027;
-
+public interface CentralSurfaces extends Dumpable, ActivityStarter, LifecycleOwner {
+    boolean MULTIUSER_DEBUG = false;
     // Should match the values in PhoneWindowManager
-    public static final String SYSTEM_DIALOG_REASON_KEY = "reason";
-    public static final String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
-    public static final String SYSTEM_DIALOG_REASON_DREAM = "dream";
-    static public final String SYSTEM_DIALOG_REASON_SCREENSHOT = "screenshot";
-
-    private static final String BANNER_ACTION_CANCEL =
-            "com.android.systemui.statusbar.banner_action_cancel";
-    private static final String BANNER_ACTION_SETUP =
-            "com.android.systemui.statusbar.banner_action_setup";
-    public static final String TAG = "CentralSurfaces";
-    public static final boolean DEBUG = false;
-    public static final boolean SPEW = false;
-    public static final boolean DUMPTRUCK = true; // extra dumpsys info
-    public static final boolean DEBUG_GESTURES = false;
-    public static final boolean DEBUG_MEDIA_FAKE_ARTWORK = false;
-    public static final boolean DEBUG_CAMERA_LIFT = false;
-
-    public static final boolean DEBUG_WINDOW_STATE = false;
-
+    String SYSTEM_DIALOG_REASON_KEY = "reason";
+    String SYSTEM_DIALOG_REASON_RECENT_APPS = "recentapps";
+    String SYSTEM_DIALOG_REASON_DREAM = "dream";
+    String SYSTEM_DIALOG_REASON_SCREENSHOT = "screenshot";
+    String TAG = "CentralSurfaces";
+    boolean DEBUG = false;
+    boolean SPEW = false;
+    boolean DUMPTRUCK = true; // extra dumpsys info
+    boolean DEBUG_GESTURES = false;
+    boolean DEBUG_MEDIA_FAKE_ARTWORK = false;
+    boolean DEBUG_CAMERA_LIFT = false;
+    boolean DEBUG_WINDOW_STATE = false;
     // additional instrumentation for testing purposes; intended to be left on during development
-    public static final boolean CHATTY = DEBUG;
-
-    public static final boolean SHOW_LOCKSCREEN_MEDIA_ARTWORK = true;
-
-    public static final String ACTION_FAKE_ARTWORK = "fake_artwork";
-
-    private static final int MSG_OPEN_SETTINGS_PANEL = 1002;
-    private static final int MSG_LAUNCH_TRANSITION_TIMEOUT = 1003;
-    // 1020-1040 reserved for BaseStatusBar
-
-    // Time after we abort the launch transition.
-    static final long LAUNCH_TRANSITION_TIMEOUT_MS = 5000;
-
-    protected static final boolean CLOSE_PANEL_WHEN_EMPTIED = true;
-
-    /**
-     * The delay to reset the hint text when the hint animation is finished running.
-     */
-    private static final int HINT_RESET_DELAY_MS = 1200;
-
-    public static final int FADE_KEYGUARD_START_DELAY = 100;
-    public static final int FADE_KEYGUARD_DURATION = 300;
-    public static final int FADE_KEYGUARD_DURATION_PULSING = 96;
-
-    public static final long[] CAMERA_LAUNCH_GESTURE_VIBRATION_TIMINGS =
+    boolean CHATTY = DEBUG;
+    boolean SHOW_LOCKSCREEN_MEDIA_ARTWORK = true;
+    String ACTION_FAKE_ARTWORK = "fake_artwork";
+    int FADE_KEYGUARD_START_DELAY = 100;
+    int FADE_KEYGUARD_DURATION = 300;
+    int FADE_KEYGUARD_DURATION_PULSING = 96;
+    long[] CAMERA_LAUNCH_GESTURE_VIBRATION_TIMINGS =
             new long[]{20, 20, 20, 20, 100, 20};
-    public static final int[] CAMERA_LAUNCH_GESTURE_VIBRATION_AMPLITUDES =
+    int[] CAMERA_LAUNCH_GESTURE_VIBRATION_AMPLITUDES =
             new int[]{39, 82, 139, 213, 0, 127};
 
-    /**
-     * If true, the system is in the half-boot-to-decryption-screen state.
-     * Prudently disable QS and notifications.
-     */
-    public static final boolean ONLY_CORE_APPS;
-
     /** If true, the lockscreen will show a distinct wallpaper */
-    public static final boolean ENABLE_LOCKSCREEN_WALLPAPER = true;
+    boolean ENABLE_LOCKSCREEN_WALLPAPER = true;
+    // Time after we abort the launch transition.
+    long LAUNCH_TRANSITION_TIMEOUT_MS = 5000;
+    int MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU = 1027;
 
-    private static final UiEventLogger sUiEventLogger = new UiEventLoggerImpl();
+    static final boolean CLOSE_PANEL_WHEN_EMPTIED = true;
 
-    static {
-        boolean onlyCoreApps;
-        try {
-            IPackageManager packageManager =
-                    IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
-            onlyCoreApps = packageManager != null && packageManager.isOnlyCoreApps();
-        } catch (RemoteException e) {
-            onlyCoreApps = false;
-        }
-        ONLY_CORE_APPS = onlyCoreApps;
-    }
-
-    private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
-    private final DreamOverlayStateController mDreamOverlayStateController;
-    private CentralSurfacesCommandQueueCallbacks mCommandQueueCallbacks;
-    private float mTransitionToFullShadeProgress = 0f;
-    private NotificationListContainer mNotifListContainer;
-
-    private final KeyguardStateController.Callback mKeyguardStateControllerCallback =
-            new KeyguardStateController.Callback() {
-                @Override
-                public void onKeyguardShowingChanged() {
-                    boolean occluded = mKeyguardStateController.isOccluded();
-                    mStatusBarHideIconsForBouncerManager.setIsOccludedAndTriggerUpdate(occluded);
-                    mScrimController.setKeyguardOccluded(occluded);
-                }
-            };
-
-    void onStatusBarWindowStateChanged(@WindowVisibleState int state) {
-        updateBubblesVisibility();
-        mStatusBarWindowState = state;
-    }
-
-    void acquireGestureWakeLock(long time) {
-        mGestureWakeLock.acquire(time);
-    }
-
-    boolean setAppearance(int appearance) {
-        if (mAppearance != appearance) {
-            mAppearance = appearance;
-            return updateBarMode(barMode(isTransientShown(), appearance));
-        }
-
-        return false;
-    }
-
-    int getBarMode() {
-        return mStatusBarMode;
-    }
-
-    void resendMessage(int msg) {
-        mMessageRouter.cancelMessages(msg);
-        mMessageRouter.sendMessage(msg);
-    }
-
-    void resendMessage(Object msg) {
-        mMessageRouter.cancelMessages(msg.getClass());
-        mMessageRouter.sendMessage(msg);
-    }
-
-    int getDisabled1() {
-        return mDisabled1;
-    }
-
-    void setDisabled1(int disabled) {
-        mDisabled1 = disabled;
-    }
-
-    int getDisabled2() {
-        return mDisabled2;
-    }
-
-    void setDisabled2(int disabled) {
-        mDisabled2 = disabled;
-    }
-
-    void setLastCameraLaunchSource(int source) {
-        mLastCameraLaunchSource = source;
-    }
-
-    void setLaunchCameraOnFinishedGoingToSleep(boolean launch) {
-        mLaunchCameraOnFinishedGoingToSleep = launch;
-    }
-
-    void setLaunchCameraOnFinishedWaking(boolean launch) {
-        mLaunchCameraWhenFinishedWaking = launch;
-    }
-
-    void setLaunchEmergencyActionOnFinishedGoingToSleep(boolean launch) {
-        mLaunchEmergencyActionOnFinishedGoingToSleep = launch;
-    }
-
-    void setLaunchEmergencyActionOnFinishedWaking(boolean launch) {
-        mLaunchEmergencyActionWhenFinishedWaking = launch;
-    }
-
-    void setTopHidesStatusBar(boolean hides) {
-        mTopHidesStatusBar = hides;
-    }
-
-    QSPanelController getQSPanelController() {
-        return mQSPanelController;
-    }
-
-    /** */
-    public void animateExpandNotificationsPanel() {
-        mCommandQueueCallbacks.animateExpandNotificationsPanel();
-    }
-
-    /** */
-    public void animateExpandSettingsPanel(@Nullable String subpanel) {
-        mCommandQueueCallbacks.animateExpandSettingsPanel(subpanel);
-    }
-
-    /** */
-    public void animateCollapsePanels(int flags, boolean force) {
-        mCommandQueueCallbacks.animateCollapsePanels(flags, force);
-    }
-
-    /** */
-    public void togglePanel() {
-        mCommandQueueCallbacks.togglePanel();
-    }
-    /**
-     * The {@link StatusBarState} of the status bar.
-     */
-    protected int mState; // TODO: remove this. Just use StatusBarStateController
-    protected boolean mBouncerShowing;
-    private boolean mBouncerShowingOverDream;
-
-    private final PhoneStatusBarPolicy mIconPolicy;
-
-    private final VolumeComponent mVolumeComponent;
-    private BrightnessMirrorController mBrightnessMirrorController;
-    private boolean mBrightnessMirrorVisible;
-    private BiometricUnlockController mBiometricUnlockController;
-    private final LightBarController mLightBarController;
-    private final Lazy<LockscreenWallpaper> mLockscreenWallpaperLazy;
-    private final LockscreenGestureLogger mLockscreenGestureLogger;
-    @Nullable
-    protected LockscreenWallpaper mLockscreenWallpaper;
-    private final AutoHideController mAutoHideController;
-
-    private final Point mCurrentDisplaySize = new Point();
-
-    protected NotificationShadeWindowView mNotificationShadeWindowView;
-    protected PhoneStatusBarView mStatusBarView;
-    private PhoneStatusBarViewController mPhoneStatusBarViewController;
-    private PhoneStatusBarTransitions mStatusBarTransitions;
-    private AuthRippleController mAuthRippleController;
-    @WindowVisibleState private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
-    protected final NotificationShadeWindowController mNotificationShadeWindowController;
-    private final StatusBarWindowController mStatusBarWindowController;
-    private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
-    @VisibleForTesting
-    DozeServiceHost mDozeServiceHost;
-    private boolean mWakeUpComingFromTouch;
-    private PointF mWakeUpTouchLocation;
-    private LightRevealScrim mLightRevealScrim;
-    private PowerButtonReveal mPowerButtonReveal;
-
-    private final Object mQueueLock = new Object();
-
-    private final PulseExpansionHandler mPulseExpansionHandler;
-    private final NotificationWakeUpCoordinator mWakeUpCoordinator;
-    private final KeyguardBypassController mKeyguardBypassController;
-    private final KeyguardStateController mKeyguardStateController;
-    private final HeadsUpManagerPhone mHeadsUpManager;
-    private final StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
-    private final DynamicPrivacyController mDynamicPrivacyController;
-    private final FalsingCollector mFalsingCollector;
-    private final FalsingManager mFalsingManager;
-    private final BroadcastDispatcher mBroadcastDispatcher;
-    private final ConfigurationController mConfigurationController;
-    protected NotificationShadeWindowViewController mNotificationShadeWindowViewController;
-    private final DozeParameters mDozeParameters;
-    private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
-    private final CentralSurfacesComponent.Factory mCentralSurfacesComponentFactory;
-    private final PluginManager mPluginManager;
-    private final ShadeController mShadeController;
-    private final InitController mInitController;
-
-    private final PluginDependencyProvider mPluginDependencyProvider;
-    private final KeyguardDismissUtil mKeyguardDismissUtil;
-    private final ExtensionController mExtensionController;
-    private final UserInfoControllerImpl mUserInfoControllerImpl;
-    private final DemoModeController mDemoModeController;
-    private final NotificationsController mNotificationsController;
-    private final OngoingCallController mOngoingCallController;
-    private final StatusBarSignalPolicy mStatusBarSignalPolicy;
-    private final StatusBarHideIconsForBouncerManager mStatusBarHideIconsForBouncerManager;
-
-    // expanded notifications
-    // the sliding/resizing panel within the notification window
-    protected NotificationPanelViewController mNotificationPanelViewController;
-
-    // settings
-    private QSPanelController mQSPanelController;
-
-    KeyguardIndicationController mKeyguardIndicationController;
-
-    private View mReportRejectedTouch;
-
-    private boolean mExpandedVisible;
-
-    private final int[] mAbsPos = new int[2];
-
-    private final NotifShadeEventSource mNotifShadeEventSource;
-    protected final NotificationEntryManager mEntryManager;
-    private final NotificationGutsManager mGutsManager;
-    private final NotificationLogger mNotificationLogger;
-    private final NotificationViewHierarchyManager mViewHierarchyManager;
-    private final PanelExpansionStateManager mPanelExpansionStateManager;
-    private final KeyguardViewMediator mKeyguardViewMediator;
-    protected final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
-    private final BrightnessSliderController.Factory mBrightnessSliderFactory;
-    private final FeatureFlags mFeatureFlags;
-    private final FragmentService mFragmentService;
-    private final ScreenOffAnimationController mScreenOffAnimationController;
-    private final WallpaperController mWallpaperController;
-    private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
-    private final MessageRouter mMessageRouter;
-    private final WallpaperManager mWallpaperManager;
-
-    private CentralSurfacesComponent mCentralSurfacesComponent;
-
-    // Flags for disabling the status bar
-    // Two variables becaseu the first one evidently ran out of room for new flags.
-    private int mDisabled1 = 0;
-    private int mDisabled2 = 0;
-
-    /** @see android.view.WindowInsetsController#setSystemBarsAppearance(int, int) */
-    private @Appearance int mAppearance;
-
-    private boolean mTransientShown;
-
-    private final DisplayMetrics mDisplayMetrics;
-
-    // XXX: gesture research
-    private final GestureRecorder mGestureRec = DEBUG_GESTURES
-        ? new GestureRecorder("/sdcard/statusbar_gestures.dat")
-        : null;
-
-    private final ScreenPinningRequest mScreenPinningRequest;
-
-    private final MetricsLogger mMetricsLogger;
-
-    // ensure quick settings is disabled until the current user makes it through the setup wizard
-    @VisibleForTesting
-    protected boolean mUserSetup = false;
-
-    @VisibleForTesting
-    public enum StatusBarUiEvent implements UiEventLogger.UiEventEnum {
-        @UiEvent(doc = "Secured lockscreen is opened.")
-        LOCKSCREEN_OPEN_SECURE(405),
-
-        @UiEvent(doc = "Lockscreen without security is opened.")
-        LOCKSCREEN_OPEN_INSECURE(406),
-
-        @UiEvent(doc = "Secured lockscreen is closed.")
-        LOCKSCREEN_CLOSE_SECURE(407),
-
-        @UiEvent(doc = "Lockscreen without security is closed.")
-        LOCKSCREEN_CLOSE_INSECURE(408),
-
-        @UiEvent(doc = "Secured bouncer is opened.")
-        BOUNCER_OPEN_SECURE(409),
-
-        @UiEvent(doc = "Bouncer without security is opened.")
-        BOUNCER_OPEN_INSECURE(410),
-
-        @UiEvent(doc = "Secured bouncer is closed.")
-        BOUNCER_CLOSE_SECURE(411),
-
-        @UiEvent(doc = "Bouncer without security is closed.")
-        BOUNCER_CLOSE_INSECURE(412);
-
-        private final int mId;
-
-        StatusBarUiEvent(int id) {
-            mId = id;
-        }
-
-        @Override
-        public int getId() {
-            return mId;
-        }
-    }
-
-    private Handler mMainHandler;
-    private final DelayableExecutor mMainExecutor;
-
-    private int mInteractingWindows;
-    private @TransitionMode int mStatusBarMode;
-
-    private final ViewMediatorCallback mKeyguardViewMediatorCallback;
-    private final ScrimController mScrimController;
-    protected DozeScrimController mDozeScrimController;
-    private final Executor mUiBgExecutor;
-
-    protected boolean mDozing;
-    private boolean mIsFullscreen;
-
-    boolean mCloseQsBeforeScreenOff;
-
-    private final NotificationMediaManager mMediaManager;
-    private final NotificationLockscreenUserManager mLockscreenUserManager;
-    private final NotificationRemoteInputManager mRemoteInputManager;
-    private boolean mWallpaperSupported;
-
-    private Runnable mLaunchTransitionEndRunnable;
-    private Runnable mLaunchTransitionCancelRunnable;
-    private boolean mLaunchCameraWhenFinishedWaking;
-    private boolean mLaunchCameraOnFinishedGoingToSleep;
-    private boolean mLaunchEmergencyActionWhenFinishedWaking;
-    private boolean mLaunchEmergencyActionOnFinishedGoingToSleep;
-    private int mLastCameraLaunchSource;
-    protected PowerManager.WakeLock mGestureWakeLock;
-
-    private final int[] mTmpInt2 = new int[2];
-
-    // Fingerprint (as computed by getLoggingFingerprint() of the last logged state.
-    private int mLastLoggedStateFingerprint;
-    private boolean mTopHidesStatusBar;
-    private boolean mStatusBarWindowHidden;
-    private boolean mIsLaunchingActivityOverLockscreen;
-
-    private final UserSwitcherController mUserSwitcherController;
-    private final NetworkController mNetworkController;
-    private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this);
-    protected final BatteryController mBatteryController;
-    protected boolean mPanelExpanded;
-    private UiModeManager mUiModeManager;
-    private LogMaker mStatusBarStateLog;
-    protected final NotificationIconAreaController mNotificationIconAreaController;
-    @Nullable private View mAmbientIndicationContainer;
-    private final SysuiColorExtractor mColorExtractor;
-    private final ScreenLifecycle mScreenLifecycle;
-    private final WakefulnessLifecycle mWakefulnessLifecycle;
-
-    private boolean mNoAnimationOnNextBarModeChange;
-    private final SysuiStatusBarStateController mStatusBarStateController;
-
-    private final ActivityLaunchAnimator mActivityLaunchAnimator;
-    private NotificationLaunchAnimatorControllerProvider mNotificationAnimationProvider;
-    protected NotificationPresenter mPresenter;
-    private NotificationActivityStarter mNotificationActivityStarter;
-    private final Lazy<NotificationShadeDepthController> mNotificationShadeDepthControllerLazy;
-    private final Optional<BubblesManager> mBubblesManagerOptional;
-    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 final ColorExtractor.OnColorsChangedListener mOnColorsChangedListener =
-            (extractor, which) -> updateTheme();
-
-    private final InteractionJankMonitor mJankMonitor;
-
-
-    /**
-     * Public constructor for CentralSurfaces.
-     *
-     * CentralSurfaces is considered optional, and therefore can not be marked as @Inject directly.
-     * Instead, an @Provide method is included. See {@link StatusBarPhoneModule}.
-     */
-    @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
-    public CentralSurfaces(
-            Context context,
-            NotificationsController notificationsController,
-            FragmentService fragmentService,
-            LightBarController lightBarController,
-            AutoHideController autoHideController,
-            StatusBarWindowController statusBarWindowController,
-            StatusBarWindowStateController statusBarWindowStateController,
-            KeyguardUpdateMonitor keyguardUpdateMonitor,
-            StatusBarSignalPolicy statusBarSignalPolicy,
-            PulseExpansionHandler pulseExpansionHandler,
-            NotificationWakeUpCoordinator notificationWakeUpCoordinator,
-            KeyguardBypassController keyguardBypassController,
-            KeyguardStateController keyguardStateController,
-            HeadsUpManagerPhone headsUpManagerPhone,
-            DynamicPrivacyController dynamicPrivacyController,
-            FalsingManager falsingManager,
-            FalsingCollector falsingCollector,
-            BroadcastDispatcher broadcastDispatcher,
-            NotifShadeEventSource notifShadeEventSource,
-            NotificationEntryManager notificationEntryManager,
-            NotificationGutsManager notificationGutsManager,
-            NotificationLogger notificationLogger,
-            NotificationInterruptStateProvider notificationInterruptStateProvider,
-            NotificationViewHierarchyManager notificationViewHierarchyManager,
-            PanelExpansionStateManager panelExpansionStateManager,
-            KeyguardViewMediator keyguardViewMediator,
-            DisplayMetrics displayMetrics,
-            MetricsLogger metricsLogger,
-            @UiBackground Executor uiBgExecutor,
-            NotificationMediaManager notificationMediaManager,
-            NotificationLockscreenUserManager lockScreenUserManager,
-            NotificationRemoteInputManager remoteInputManager,
-            UserSwitcherController userSwitcherController,
-            NetworkController networkController,
-            BatteryController batteryController,
-            SysuiColorExtractor colorExtractor,
-            ScreenLifecycle screenLifecycle,
-            WakefulnessLifecycle wakefulnessLifecycle,
-            SysuiStatusBarStateController statusBarStateController,
-            Optional<BubblesManager> bubblesManagerOptional,
-            Optional<Bubbles> bubblesOptional,
-            VisualStabilityManager visualStabilityManager,
-            DeviceProvisionedController deviceProvisionedController,
-            NavigationBarController navigationBarController,
-            AccessibilityFloatingMenuController accessibilityFloatingMenuController,
-            Lazy<AssistManager> assistManagerLazy,
-            ConfigurationController configurationController,
-            NotificationShadeWindowController notificationShadeWindowController,
-            DozeParameters dozeParameters,
-            ScrimController scrimController,
-            Lazy<LockscreenWallpaper> lockscreenWallpaperLazy,
-            LockscreenGestureLogger lockscreenGestureLogger,
-            Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
-            DozeServiceHost dozeServiceHost,
-            PowerManager powerManager,
-            ScreenPinningRequest screenPinningRequest,
-            DozeScrimController dozeScrimController,
-            VolumeComponent volumeComponent,
-            CommandQueue commandQueue,
-            CentralSurfacesComponent.Factory centralSurfacesComponentFactory,
-            PluginManager pluginManager,
-            ShadeController shadeController,
-            StatusBarKeyguardViewManager statusBarKeyguardViewManager,
-            ViewMediatorCallback viewMediatorCallback,
-            InitController initController,
-            @Named(TIME_TICK_HANDLER_NAME) Handler timeTickHandler,
-            PluginDependencyProvider pluginDependencyProvider,
-            KeyguardDismissUtil keyguardDismissUtil,
-            ExtensionController extensionController,
-            UserInfoControllerImpl userInfoControllerImpl,
-            PhoneStatusBarPolicy phoneStatusBarPolicy,
-            KeyguardIndicationController keyguardIndicationController,
-            DemoModeController demoModeController,
-            Lazy<NotificationShadeDepthController> notificationShadeDepthControllerLazy,
-            StatusBarTouchableRegionManager statusBarTouchableRegionManager,
-            NotificationIconAreaController notificationIconAreaController,
-            BrightnessSliderController.Factory brightnessSliderFactory,
-            ScreenOffAnimationController screenOffAnimationController,
-            WallpaperController wallpaperController,
-            OngoingCallController ongoingCallController,
-            StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager,
-            LockscreenShadeTransitionController lockscreenShadeTransitionController,
-            FeatureFlags featureFlags,
-            KeyguardUnlockAnimationController keyguardUnlockAnimationController,
-            @Main Handler mainHandler,
-            @Main DelayableExecutor delayableExecutor,
-            @Main MessageRouter messageRouter,
-            WallpaperManager wallpaperManager,
-            Optional<StartingSurface> startingSurfaceOptional,
-            ActivityLaunchAnimator activityLaunchAnimator,
-            NotifPipelineFlags notifPipelineFlags,
-            InteractionJankMonitor jankMonitor,
-            DeviceStateManager deviceStateManager,
-            DreamOverlayStateController dreamOverlayStateController,
-            WiredChargingRippleController wiredChargingRippleController) {
-        super(context);
-        mNotificationsController = notificationsController;
-        mFragmentService = fragmentService;
-        mLightBarController = lightBarController;
-        mAutoHideController = autoHideController;
-        mStatusBarWindowController = statusBarWindowController;
-        mKeyguardUpdateMonitor = keyguardUpdateMonitor;
-        mPulseExpansionHandler = pulseExpansionHandler;
-        mWakeUpCoordinator = notificationWakeUpCoordinator;
-        mKeyguardBypassController = keyguardBypassController;
-        mKeyguardStateController = keyguardStateController;
-        mHeadsUpManager = headsUpManagerPhone;
-        mKeyguardIndicationController = keyguardIndicationController;
-        mStatusBarTouchableRegionManager = statusBarTouchableRegionManager;
-        mDynamicPrivacyController = dynamicPrivacyController;
-        mFalsingCollector = falsingCollector;
-        mFalsingManager = falsingManager;
-        mBroadcastDispatcher = broadcastDispatcher;
-        mNotifShadeEventSource = notifShadeEventSource;
-        mEntryManager = notificationEntryManager;
-        mGutsManager = notificationGutsManager;
-        mNotificationLogger = notificationLogger;
-        mNotificationInterruptStateProvider = notificationInterruptStateProvider;
-        mViewHierarchyManager = notificationViewHierarchyManager;
-        mPanelExpansionStateManager = panelExpansionStateManager;
-        mKeyguardViewMediator = keyguardViewMediator;
-        mDisplayMetrics = displayMetrics;
-        mMetricsLogger = metricsLogger;
-        mUiBgExecutor = uiBgExecutor;
-        mMediaManager = notificationMediaManager;
-        mLockscreenUserManager = lockScreenUserManager;
-        mRemoteInputManager = remoteInputManager;
-        mUserSwitcherController = userSwitcherController;
-        mNetworkController = networkController;
-        mBatteryController = batteryController;
-        mColorExtractor = colorExtractor;
-        mScreenLifecycle = screenLifecycle;
-        mWakefulnessLifecycle = wakefulnessLifecycle;
-        mStatusBarStateController = statusBarStateController;
-        mBubblesManagerOptional = bubblesManagerOptional;
-        mBubblesOptional = bubblesOptional;
-        mVisualStabilityManager = visualStabilityManager;
-        mDeviceProvisionedController = deviceProvisionedController;
-        mNavigationBarController = navigationBarController;
-        mAccessibilityFloatingMenuController = accessibilityFloatingMenuController;
-        mAssistManagerLazy = assistManagerLazy;
-        mConfigurationController = configurationController;
-        mNotificationShadeWindowController = notificationShadeWindowController;
-        mDozeServiceHost = dozeServiceHost;
-        mPowerManager = powerManager;
-        mDozeParameters = dozeParameters;
-        mScrimController = scrimController;
-        mLockscreenWallpaperLazy = lockscreenWallpaperLazy;
-        mLockscreenGestureLogger = lockscreenGestureLogger;
-        mScreenPinningRequest = screenPinningRequest;
-        mDozeScrimController = dozeScrimController;
-        mBiometricUnlockControllerLazy = biometricUnlockControllerLazy;
-        mNotificationShadeDepthControllerLazy = notificationShadeDepthControllerLazy;
-        mVolumeComponent = volumeComponent;
-        mCommandQueue = commandQueue;
-        mCentralSurfacesComponentFactory = centralSurfacesComponentFactory;
-        mPluginManager = pluginManager;
-        mShadeController = shadeController;
-        mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
-        mKeyguardViewMediatorCallback = viewMediatorCallback;
-        mInitController = initController;
-        mPluginDependencyProvider = pluginDependencyProvider;
-        mKeyguardDismissUtil = keyguardDismissUtil;
-        mExtensionController = extensionController;
-        mUserInfoControllerImpl = userInfoControllerImpl;
-        mIconPolicy = phoneStatusBarPolicy;
-        mDemoModeController = demoModeController;
-        mNotificationIconAreaController = notificationIconAreaController;
-        mBrightnessSliderFactory = brightnessSliderFactory;
-        mWallpaperController = wallpaperController;
-        mOngoingCallController = ongoingCallController;
-        mStatusBarSignalPolicy = statusBarSignalPolicy;
-        mStatusBarHideIconsForBouncerManager = statusBarHideIconsForBouncerManager;
-        mFeatureFlags = featureFlags;
-        mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
-        mMainHandler = mainHandler;
-        mMainExecutor = delayableExecutor;
-        mMessageRouter = messageRouter;
-        mWallpaperManager = wallpaperManager;
-        mJankMonitor = jankMonitor;
-        mDreamOverlayStateController = dreamOverlayStateController;
-
-        mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
-        mStartingSurfaceOptional = startingSurfaceOptional;
-        mNotifPipelineFlags = notifPipelineFlags;
-        lockscreenShadeTransitionController.setCentralSurfaces(this);
-        statusBarWindowStateController.addListener(this::onStatusBarWindowStateChanged);
-
-        mScreenOffAnimationController = screenOffAnimationController;
-
-        mPanelExpansionStateManager.addExpansionListener(this::onPanelExpansionChanged);
-
-        mBubbleExpandListener =
-                (isExpanding, key) -> mContext.getMainExecutor().execute(() -> {
-                    mNotificationsController.requestNotificationUpdate("onBubbleExpandChanged");
-                    updateScrimController();
-                });
-
-        mActivityIntentHelper = new ActivityIntentHelper(mContext);
-        mActivityLaunchAnimator = activityLaunchAnimator;
-
-        // The status bar background may need updating when the ongoing call status changes.
-        mOngoingCallController.addCallback((animate) -> maybeUpdateBarMode());
-
-        // TODO(b/190746471): Find a better home for this.
-        DateTimeView.setReceiverHandler(timeTickHandler);
-
-        mMessageRouter.subscribeTo(KeyboardShortcutsMessage.class,
-                data -> toggleKeyboardShortcuts(data.mDeviceId));
-        mMessageRouter.subscribeTo(MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU,
-                id -> dismissKeyboardShortcuts());
-        mMessageRouter.subscribeTo(AnimateExpandSettingsPanelMessage.class,
-                data -> mCommandQueueCallbacks.animateExpandSettingsPanel(data.mSubpanel));
-        mMessageRouter.subscribeTo(MSG_LAUNCH_TRANSITION_TIMEOUT,
-                id -> onLaunchTransitionTimeout());
-
-        deviceStateManager.registerCallback(mMainExecutor,
-                new FoldStateListener(mContext, this::onFoldedStateChanged));
-        wiredChargingRippleController.registerCallbacks();
-    }
-
-    @Override
-    public void start() {
-        mScreenLifecycle.addObserver(mScreenObserver);
-        mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
-        mUiModeManager = mContext.getSystemService(UiModeManager.class);
-        if (mBubblesOptional.isPresent()) {
-            mBubblesOptional.get().setExpandListener(mBubbleExpandListener);
-        }
-
-        mStatusBarSignalPolicy.init();
-        mKeyguardIndicationController.init();
-
-        mColorExtractor.addOnColorsChangedListener(mOnColorsChangedListener);
-        mStatusBarStateController.addCallback(mStateListener,
-                SysuiStatusBarStateController.RANK_STATUS_BAR);
-
-        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
-        mDreamManager = IDreamManager.Stub.asInterface(
-                ServiceManager.checkService(DreamService.DREAM_SERVICE));
-
-        mDisplay = mContext.getDisplay();
-        mDisplayId = mDisplay.getDisplayId();
-        updateDisplaySize();
-        mStatusBarHideIconsForBouncerManager.setDisplayId(mDisplayId);
-
-        // start old BaseStatusBar.start().
-        mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
-        mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService(
-                Context.DEVICE_POLICY_SERVICE);
-
-        mAccessibilityManager = (AccessibilityManager)
-                mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
-
-        mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);
-        mBarService = IStatusBarService.Stub.asInterface(
-                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
-
-        mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
-        mWallpaperSupported = mWallpaperManager.isWallpaperSupported();
-
-        RegisterStatusBarResult result = null;
-        try {
-            result = mBarService.registerStatusBar(mCommandQueue);
-        } catch (RemoteException ex) {
-            ex.rethrowFromSystemServer();
-        }
-
-        createAndAddWindows(result);
-
-        if (mWallpaperSupported) {
-            // Make sure we always have the most current wallpaper info.
-            IntentFilter wallpaperChangedFilter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED);
-            mBroadcastDispatcher.registerReceiver(mWallpaperChangedReceiver, wallpaperChangedFilter,
-                    null /* handler */, UserHandle.ALL);
-            mWallpaperChangedReceiver.onReceive(mContext, null);
-        } else if (DEBUG) {
-            Log.v(TAG, "start(): no wallpaper service ");
-        }
-
-        // Set up the initial notification state. This needs to happen before CommandQueue.disable()
-        setUpPresenter();
-
-        if (containsType(result.mTransientBarTypes, ITYPE_STATUS_BAR)) {
-            showTransientUnchecked();
-        }
-        mCommandQueueCallbacks.onSystemBarAttributesChanged(mDisplayId, result.mAppearance,
-                result.mAppearanceRegions, result.mNavbarColorManagedByIme, result.mBehavior,
-                result.mRequestedVisibilities, result.mPackageName);
-
-        // StatusBarManagerService has a back up of IME token and it's restored here.
-        mCommandQueueCallbacks.setImeWindowStatus(mDisplayId, result.mImeToken,
-                result.mImeWindowVis, result.mImeBackDisposition, result.mShowImeSwitcher);
-
-        // Set up the initial icon state
-        int numIcons = result.mIcons.size();
-        for (int i = 0; i < numIcons; i++) {
-            mCommandQueue.setIcon(result.mIcons.keyAt(i), result.mIcons.valueAt(i));
-        }
-
-        if (DEBUG) {
-            Log.d(TAG, String.format(
-                    "init: icons=%d disabled=0x%08x lights=0x%08x imeButton=0x%08x",
-                    numIcons,
-                    result.mDisabledFlags1,
-                    result.mAppearance,
-                    result.mImeWindowVis));
-        }
-
-        IntentFilter internalFilter = new IntentFilter();
-        internalFilter.addAction(BANNER_ACTION_CANCEL);
-        internalFilter.addAction(BANNER_ACTION_SETUP);
-        mContext.registerReceiver(mBannerActionBroadcastReceiver, internalFilter, PERMISSION_SELF,
-                null, Context.RECEIVER_EXPORTED_UNAUDITED);
-
-        if (mWallpaperSupported) {
-            IWallpaperManager wallpaperManager = IWallpaperManager.Stub.asInterface(
-                    ServiceManager.getService(Context.WALLPAPER_SERVICE));
-            try {
-                wallpaperManager.setInAmbientMode(false /* ambientMode */, 0L /* duration */);
-            } catch (RemoteException e) {
-                // Just pass, nothing critical.
-            }
-        }
-
-        // end old BaseStatusBar.start().
-
-        // Lastly, call to the icon policy to install/update all the icons.
-        mIconPolicy.init();
-
-        mKeyguardStateController.addCallback(new KeyguardStateController.Callback() {
-            @Override
-            public void onUnlockedChanged() {
-                logStateToEventlog();
-            }
-        });
-        startKeyguard();
-
-        mKeyguardUpdateMonitor.registerCallback(mUpdateCallback);
-        mDozeServiceHost.initialize(
-                this,
-                mStatusBarKeyguardViewManager,
-                mNotificationShadeWindowViewController,
-                mNotificationPanelViewController,
-                mAmbientIndicationContainer);
-        updateLightRevealScrimVisibility();
-
-        mConfigurationController.addCallback(mConfigurationListener);
-
-        mBatteryController.observe(mLifecycle, mBatteryStateChangeCallback);
-        mLifecycle.setCurrentState(RESUMED);
-
-        mAccessibilityFloatingMenuController.init();
-
-        // set the initial view visibility
-        int disabledFlags1 = result.mDisabledFlags1;
-        int disabledFlags2 = result.mDisabledFlags2;
-        mInitController.addPostInitTask(
-                () -> setUpDisableFlags(disabledFlags1, disabledFlags2));
-
-        mFalsingManager.addFalsingBeliefListener(mFalsingBeliefListener);
-
-        mPluginManager.addPluginListener(
-                new PluginListener<OverlayPlugin>() {
-                    private final ArraySet<OverlayPlugin> mOverlays = new ArraySet<>();
-
-                    @Override
-                    public void onPluginConnected(OverlayPlugin plugin, Context pluginContext) {
-                        mMainExecutor.execute(
-                                () -> plugin.setup(getNotificationShadeWindowView(),
-                                        getNavigationBarView(),
-                                        new Callback(plugin), mDozeParameters));
-                    }
-
-                    @Override
-                    public void onPluginDisconnected(OverlayPlugin plugin) {
-                        mMainExecutor.execute(() -> {
-                            mOverlays.remove(plugin);
-                            mNotificationShadeWindowController
-                                    .setForcePluginOpen(mOverlays.size() != 0, this);
-                        });
-                    }
-
-                    class Callback implements OverlayPlugin.Callback {
-                        private final OverlayPlugin mPlugin;
-
-                        Callback(OverlayPlugin plugin) {
-                            mPlugin = plugin;
-                        }
-
-                        @Override
-                        public void onHoldStatusBarOpenChange() {
-                            if (mPlugin.holdStatusBarOpen()) {
-                                mOverlays.add(mPlugin);
-                            } else {
-                                mOverlays.remove(mPlugin);
-                            }
-                            mMainExecutor.execute(() -> {
-                                mNotificationShadeWindowController
-                                        .setStateListener(b -> mOverlays.forEach(
-                                                o -> o.setCollapseDesired(b)));
-                                mNotificationShadeWindowController
-                                        .setForcePluginOpen(mOverlays.size() != 0, this);
-                            });
-                        }
-                    }
-                }, OverlayPlugin.class, true /* Allow multiple plugins */);
-
-        mStartingSurfaceOptional.ifPresent(startingSurface -> startingSurface.setSysuiProxy(
-                (requestTopUi, componentTag) -> mMainExecutor.execute(() ->
-                        mNotificationShadeWindowController.setRequestTopUi(
-                                requestTopUi, componentTag))));
-    }
-
-    private void onFoldedStateChanged(boolean isFolded, boolean willGoToSleep) {
-        Trace.beginSection("CentralSurfaces#onFoldedStateChanged");
-        onFoldedStateChangedInternal(isFolded, willGoToSleep);
-        Trace.endSection();
-    }
-
-    private void onFoldedStateChangedInternal(boolean isFolded, boolean willGoToSleep) {
-        // Folded state changes are followed by a screen off event.
-        // By default turning off the screen also closes the shade.
-        // We want to make sure that the shade status is kept after
-        // folding/unfolding.
-        boolean isShadeOpen = mShadeController.isShadeOpen();
-        boolean leaveOpen = isShadeOpen && !willGoToSleep;
-        if (DEBUG) {
-            Log.d(TAG, String.format(
-                    "#onFoldedStateChanged(): "
-                            + "isFolded=%s, "
-                            + "willGoToSleep=%s, "
-                            + "isShadeOpen=%s, "
-                            + "leaveOpen=%s",
-                    isFolded, willGoToSleep, isShadeOpen, leaveOpen));
-        }
-        if (leaveOpen) {
-            mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
-            if (mKeyguardStateController.isShowing()) {
-                // When device state changes on keyguard we don't want to keep the state of
-                // the shade and instead we open clean state of keyguard with shade closed.
-                // Normally some parts of QS state (like expanded/collapsed) are persisted and
-                // that causes incorrect UI rendering, especially when changing state with QS
-                // expanded. To prevent that we can close QS which resets QS and some parts of
-                // the shade to its default state. Read more in b/201537421
-                mCloseQsBeforeScreenOff = true;
-            }
-        }
-    }
-
-    // ================================================================================
-    // Constructing the view
-    // ================================================================================
-    protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {
-        updateDisplaySize(); // populates mDisplayMetrics
-        updateResources();
-        updateTheme();
-
-        inflateStatusBarWindow();
-        mNotificationShadeWindowView.setOnTouchListener(getStatusBarWindowTouchListener());
-        mWallpaperController.setRootView(mNotificationShadeWindowView);
-
-        // TODO: Deal with the ugliness that comes from having some of the status bar broken out
-        // into fragments, but the rest here, it leaves some awkward lifecycle and whatnot.
-        mNotificationLogger.setUpWithContainer(mNotifListContainer);
-        mNotificationIconAreaController.setupShelf(mNotificationShelfController);
-        mPanelExpansionStateManager.addExpansionListener(mWakeUpCoordinator);
-        mUserSwitcherController.init(mNotificationShadeWindowView);
-
-        // Allow plugins to reference DarkIconDispatcher and StatusBarStateController
-        mPluginDependencyProvider.allowPluginDependency(DarkIconDispatcher.class);
-        mPluginDependencyProvider.allowPluginDependency(StatusBarStateController.class);
-
-        // Set up CollapsedStatusBarFragment and PhoneStatusBarView
-        StatusBarInitializer initializer = mCentralSurfacesComponent.getStatusBarInitializer();
-        initializer.setStatusBarViewUpdatedListener(
-                (statusBarView, statusBarViewController, statusBarTransitions) -> {
-                    mStatusBarView = statusBarView;
-                    mPhoneStatusBarViewController = statusBarViewController;
-                    mStatusBarTransitions = statusBarTransitions;
-                    mNotificationShadeWindowViewController
-                            .setStatusBarViewController(mPhoneStatusBarViewController);
-                    // 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
-                    // re-display the notification panel if necessary (for example, if
-                    // a heads-up notification was being displayed and should continue being
-                    // displayed).
-                    mNotificationPanelViewController.updatePanelExpansionAndVisibility();
-                    setBouncerShowingForStatusBarComponents(mBouncerShowing);
-                    checkBarModes();
-                });
-        initializer.initializeStatusBar(mCentralSurfacesComponent);
-
-        mStatusBarTouchableRegionManager.setup(this, mNotificationShadeWindowView);
-        mHeadsUpManager.addListener(mNotificationPanelViewController.getOnHeadsUpChangedListener());
-        if (!mNotifPipelineFlags.isNewPipelineEnabled()) {
-            mHeadsUpManager.addListener(mVisualStabilityManager);
-        }
-        mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager);
-
-        createNavigationBar(result);
-
-        if (ENABLE_LOCKSCREEN_WALLPAPER && mWallpaperSupported) {
-            mLockscreenWallpaper = mLockscreenWallpaperLazy.get();
-        }
-
-        mNotificationPanelViewController.setKeyguardIndicationController(
-                mKeyguardIndicationController);
-
-        mAmbientIndicationContainer = mNotificationShadeWindowView.findViewById(
-                R.id.ambient_indication_container);
-
-        mAutoHideController.setStatusBar(new AutoHideUiElement() {
-            @Override
-            public void synchronizeState() {
-                checkBarModes();
-            }
-
-            @Override
-            public boolean shouldHideOnTouch() {
-                return !mRemoteInputManager.isRemoteInputActive();
-            }
-
-            @Override
-            public boolean isVisible() {
-                return isTransientShown();
-            }
-
-            @Override
-            public void hide() {
-                clearTransient();
-            }
-        });
-
-        ScrimView scrimBehind = mNotificationShadeWindowView.findViewById(R.id.scrim_behind);
-        ScrimView notificationsScrim = mNotificationShadeWindowView
-                .findViewById(R.id.scrim_notifications);
-        ScrimView scrimInFront = mNotificationShadeWindowView.findViewById(R.id.scrim_in_front);
-
-        mScrimController.setScrimVisibleListener(scrimsVisible -> {
-            mNotificationShadeWindowController.setScrimsVisibility(scrimsVisible);
-        });
-        mScrimController.attachViews(scrimBehind, notificationsScrim, scrimInFront);
-
-        mLightRevealScrim = mNotificationShadeWindowView.findViewById(R.id.light_reveal_scrim);
-        mLightRevealScrim.setScrimOpaqueChangedListener((opaque) -> {
-            Runnable updateOpaqueness = () -> {
-                mNotificationShadeWindowController.setLightRevealScrimOpaque(
-                        mLightRevealScrim.isScrimOpaque());
-                mScreenOffAnimationController
-                        .onScrimOpaqueChanged(mLightRevealScrim.isScrimOpaque());
-            };
-            if (opaque) {
-                // Delay making the view opaque for a frame, because it needs some time to render
-                // otherwise this can lead to a flicker where the scrim doesn't cover the screen
-                mLightRevealScrim.post(updateOpaqueness);
-            } else {
-                updateOpaqueness.run();
-            }
-        });
-
-        mScreenOffAnimationController.initialize(this, mLightRevealScrim);
-        updateLightRevealScrimVisibility();
-
-        mNotificationPanelViewController.initDependencies(
-                this,
-                this::makeExpandedInvisible,
-                mNotificationShelfController);
-
-        BackDropView backdrop = mNotificationShadeWindowView.findViewById(R.id.backdrop);
-        mMediaManager.setup(backdrop, backdrop.findViewById(R.id.backdrop_front),
-                backdrop.findViewById(R.id.backdrop_back), mScrimController, mLockscreenWallpaper);
-        float maxWallpaperZoom = mContext.getResources().getFloat(
-                com.android.internal.R.dimen.config_wallpaperMaxScale);
-        mNotificationShadeDepthControllerLazy.get().addListener(depth -> {
-            float scale = MathUtils.lerp(maxWallpaperZoom, 1f, depth);
-            backdrop.setPivotX(backdrop.getWidth() / 2f);
-            backdrop.setPivotY(backdrop.getHeight() / 2f);
-            backdrop.setScaleX(scale);
-            backdrop.setScaleY(scale);
-        });
-
-        mNotificationPanelViewController.setUserSetupComplete(mUserSetup);
-
-        // Set up the quick settings tile panel
-        final View container = mNotificationShadeWindowView.findViewById(R.id.qs_frame);
-        if (container != null) {
-            FragmentHostManager fragmentHostManager = FragmentHostManager.get(container);
-            ExtensionFragmentListener.attachExtensonToFragment(container, QS.TAG, R.id.qs_frame,
-                    mExtensionController
-                            .newExtension(QS.class)
-                            .withPlugin(QS.class)
-                            .withDefault(this::createDefaultQSFragment)
-                            .build());
-            mBrightnessMirrorController = new BrightnessMirrorController(
-                    mNotificationShadeWindowView,
-                    mNotificationPanelViewController,
-                    mNotificationShadeDepthControllerLazy.get(),
-                    mBrightnessSliderFactory,
-                    (visible) -> {
-                        mBrightnessMirrorVisible = visible;
-                        updateScrimController();
-                    });
-            fragmentHostManager.addTagListener(QS.TAG, (tag, f) -> {
-                QS qs = (QS) f;
-                if (qs instanceof QSFragment) {
-                    mQSPanelController = ((QSFragment) qs).getQSPanelController();
-                    ((QSFragment) qs).setBrightnessMirrorController(mBrightnessMirrorController);
-                }
-            });
-        }
-
-        mReportRejectedTouch = mNotificationShadeWindowView
-                .findViewById(R.id.report_rejected_touch);
-        if (mReportRejectedTouch != null) {
-            updateReportRejectedTouchVisibility();
-            mReportRejectedTouch.setOnClickListener(v -> {
-                Uri session = mFalsingManager.reportRejectedTouch();
-                if (session == null) { return; }
-
-                StringWriter message = new StringWriter();
-                message.write("Build info: ");
-                message.write(SystemProperties.get("ro.build.description"));
-                message.write("\nSerial number: ");
-                message.write(SystemProperties.get("ro.serialno"));
-                message.write("\n");
-
-                startActivityDismissingKeyguard(Intent.createChooser(new Intent(Intent.ACTION_SEND)
-                                .setType("*/*")
-                                .putExtra(Intent.EXTRA_SUBJECT, "Rejected touch report")
-                                .putExtra(Intent.EXTRA_STREAM, session)
-                                .putExtra(Intent.EXTRA_TEXT, message.toString()),
-                        "Share rejected touch report")
-                                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
-                        true /* onlyProvisioned */, true /* dismissShade */);
-            });
-        }
-
-        if (!mPowerManager.isInteractive()) {
-            mBroadcastReceiver.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF));
-        }
-        mGestureWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
-                "sysui:GestureWakeLock");
-
-        // receive broadcasts
-        registerBroadcastReceiver();
-
-        IntentFilter demoFilter = new IntentFilter();
-        if (DEBUG_MEDIA_FAKE_ARTWORK) {
-            demoFilter.addAction(ACTION_FAKE_ARTWORK);
-        }
-        mContext.registerReceiverAsUser(mDemoReceiver, UserHandle.ALL, demoFilter,
-                android.Manifest.permission.DUMP, null,
-                Context.RECEIVER_EXPORTED_UNAUDITED);
-
-        // listen for USER_SETUP_COMPLETE setting (per-user)
-        mDeviceProvisionedController.addCallback(mUserSetupObserver);
-        mUserSetupObserver.onUserSetupChanged();
-
-        // disable profiling bars, since they overlap and clutter the output on app windows
-        ThreadedRenderer.overrideProperty("disableProfileBars", "true");
-
-        // Private API call to make the shadows look better for Recents
-        ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f));
-    }
-
-
-    /**
-     * When swiping up to dismiss the lock screen, the panel expansion fraction goes from 1f to 0f.
-     * This results in the clock/notifications/other content disappearing off the top of the screen.
-     *
-     * We also use the expansion fraction to animate in the app/launcher surface from the bottom of
-     * the screen, 'pushing' off the notifications and other content. To do this, we dispatch the
-     * expansion fraction to the KeyguardViewMediator if we're in the process of dismissing the
-     * keyguard.
-     */
-    private void dispatchPanelExpansionForKeyguardDismiss(float fraction, boolean trackingTouch) {
-        // Things that mean we're not swiping to dismiss the keyguard, and should ignore this
-        // expansion:
-        // - Keyguard isn't even visible.
-        // - Keyguard is occluded. Expansion changes here are the shade being expanded over the
-        //   occluding activity.
-        // - Keyguard is visible, but can't be dismissed (swiping up will show PIN/password prompt).
-        // - The SIM is locked, you can't swipe to unlock. If the SIM is locked but there is no
-        //   device lock set, canDismissLockScreen returns true even though you should not be able
-        //   to dismiss the lock screen until entering the SIM PIN.
-        // - QS is expanded and we're swiping - swiping up now will hide QS, not dismiss the
-        //   keyguard.
-        if (!isKeyguardShowing()
-                || isOccluded()
-                || !mKeyguardStateController.canDismissLockScreen()
-                || mKeyguardViewMediator.isAnySimPinSecure()
-                || (mNotificationPanelViewController.isQsExpanded() && trackingTouch)) {
-            return;
-        }
-
-        // Otherwise, we should let the keyguard know about this if we're tracking touch, or if we
-        // are already animating the keyguard dismiss (since we will need to either finish or cancel
-        // the animation).
-        if (trackingTouch
-                || mKeyguardViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehindOrWillBe()
-                || mKeyguardUnlockAnimationController.isUnlockingWithSmartSpaceTransition()) {
-            mKeyguardStateController.notifyKeyguardDismissAmountChanged(
-                    1f - fraction, trackingTouch);
-        }
-    }
-
-    private void onPanelExpansionChanged(PanelExpansionChangeEvent event) {
-        float fraction = event.getFraction();
-        boolean tracking = event.getTracking();
-        dispatchPanelExpansionForKeyguardDismiss(fraction, tracking);
-
-        if (fraction == 0 || fraction == 1) {
-            if (getNavigationBarView() != null) {
-                getNavigationBarView().onStatusBarPanelStateChanged();
-            }
-            if (getNotificationPanelViewController() != null) {
-                getNotificationPanelViewController().updateSystemUiStateFlags();
-            }
-        }
-    }
-
-    @NonNull
-    @Override
-    public Lifecycle getLifecycle() {
-        return mLifecycle;
-    }
-
-    @VisibleForTesting
-    protected void registerBroadcastReceiver() {
-        IntentFilter filter = new IntentFilter();
-        filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
-        filter.addAction(Intent.ACTION_SCREEN_OFF);
-        mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter, null, UserHandle.ALL);
-    }
-
-    protected QS createDefaultQSFragment() {
-        return FragmentHostManager.get(mNotificationShadeWindowView).create(QSFragment.class);
-    }
-
-    private void setUpPresenter() {
-        // Set up the initial notification state.
-        mActivityLaunchAnimator.setCallback(mActivityLaunchAnimatorCallback);
-        mActivityLaunchAnimator.addListener(mActivityLaunchAnimatorListener);
-        mNotificationAnimationProvider = new NotificationLaunchAnimatorControllerProvider(
-                mNotificationShadeWindowViewController,
-                mNotifListContainer,
-                mHeadsUpManager,
-                mJankMonitor);
-        mNotificationShelfController.setOnActivatedListener(mPresenter);
-        mRemoteInputManager.addControllerCallback(mNotificationShadeWindowController);
-        mStackScrollerController.setNotificationActivityStarter(mNotificationActivityStarter);
-        mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter);
-        mNotificationsController.initialize(
-                mPresenter,
-                mNotifListContainer,
-                mStackScrollerController.getNotifStackController(),
-                mNotificationActivityStarter,
-                mCentralSurfacesComponent.getBindRowCallback());
-    }
-
-    /**
-     * Post-init task of {@link #start()}
-     * @param state1 disable1 flags
-     * @param state2 disable2 flags
-     */
-    protected void setUpDisableFlags(int state1, int state2) {
-        mCommandQueue.disable(mDisplayId, state1, state2, false /* animate */);
-    }
-
-    /**
-     * Ask the display to wake up if currently dozing, else do nothing
-     *
-     * @param time when to wake up
-     * @param where the view requesting the wakeup
-     * @param why the reason for the wake up
-     */
-    public void wakeUpIfDozing(long time, View where, String why) {
-        if (mDozing && mScreenOffAnimationController.allowWakeUpIfDozing()) {
-            mPowerManager.wakeUp(
-                    time, PowerManager.WAKE_REASON_GESTURE, "com.android.systemui:" + why);
-            mWakeUpComingFromTouch = true;
-            where.getLocationInWindow(mTmpInt2);
-
-            // NOTE, the incoming view can sometimes be the entire container... unsure if
-            // this location is valuable enough
-            mWakeUpTouchLocation = new PointF(mTmpInt2[0] + where.getWidth() / 2,
-                    mTmpInt2[1] + where.getHeight() / 2);
-            mFalsingCollector.onScreenOnFromTouch();
-        }
-    }
-
-    // TODO(b/117478341): This was left such that CarStatusBar can override this method.
-    // Try to remove this.
-    protected void createNavigationBar(@Nullable RegisterStatusBarResult result) {
-        mNavigationBarController.createNavigationBars(true /* includeDefaultDisplay */, result);
-    }
-
-    /**
-     * Returns the {@link android.view.View.OnTouchListener} that will be invoked when the
-     * background window of the status bar is clicked.
-     */
-    protected View.OnTouchListener getStatusBarWindowTouchListener() {
-        return (v, event) -> {
-            mAutoHideController.checkUserAutoHide(event);
-            mRemoteInputManager.checkRemoteInputOutside(event);
-            if (event.getAction() == MotionEvent.ACTION_UP) {
-                if (mExpandedVisible) {
-                    mShadeController.animateCollapsePanels();
-                }
-            }
-            return mNotificationShadeWindowView.onTouchEvent(event);
-        };
-    }
-
-    private void inflateStatusBarWindow() {
-        if (mCentralSurfacesComponent != null) {
-            // Tear down
-            for (CentralSurfacesComponent.Startable s : mCentralSurfacesComponent.getStartables()) {
-                s.stop();
-            }
-        }
-        mCentralSurfacesComponent = mCentralSurfacesComponentFactory.create();
-        mFragmentService.addFragmentInstantiationProvider(mCentralSurfacesComponent);
-
-        mNotificationShadeWindowView = mCentralSurfacesComponent.getNotificationShadeWindowView();
-        mNotificationShadeWindowViewController = mCentralSurfacesComponent
-                .getNotificationShadeWindowViewController();
-        mNotificationShadeWindowController.setNotificationShadeView(mNotificationShadeWindowView);
-        mNotificationShadeWindowViewController.setupExpandedStatusBar();
-        mNotificationPanelViewController =
-                mCentralSurfacesComponent.getNotificationPanelViewController();
-        mCentralSurfacesComponent.getLockIconViewController().init();
-        mStackScrollerController =
-                mCentralSurfacesComponent.getNotificationStackScrollLayoutController();
-        mStackScroller = mStackScrollerController.getView();
-        mNotifListContainer = mCentralSurfacesComponent.getNotificationListContainer();
-        mPresenter = mCentralSurfacesComponent.getNotificationPresenter();
-        mNotificationActivityStarter = mCentralSurfacesComponent.getNotificationActivityStarter();
-        mNotificationShelfController = mCentralSurfacesComponent.getNotificationShelfController();
-        mAuthRippleController = mCentralSurfacesComponent.getAuthRippleController();
-        mAuthRippleController.init();
-
-        mHeadsUpManager.addListener(mCentralSurfacesComponent.getStatusBarHeadsUpChangeListener());
-
-        // Listen for demo mode changes
-        mDemoModeController.addCallback(mDemoModeCallback);
-
-        if (mCommandQueueCallbacks != null) {
-            mCommandQueue.removeCallback(mCommandQueueCallbacks);
-        }
-        mCommandQueueCallbacks =
-                mCentralSurfacesComponent.getCentralSurfacesCommandQueueCallbacks();
-        // Connect in to the status bar manager service
-        mCommandQueue.addCallback(mCommandQueueCallbacks);
-
-        // Perform all other initialization for CentralSurfacesScope
-        for (CentralSurfacesComponent.Startable s : mCentralSurfacesComponent.getStartables()) {
-            s.start();
-        }
-    }
-
-    protected void startKeyguard() {
-        Trace.beginSection("CentralSurfaces#startKeyguard");
-        mBiometricUnlockController = mBiometricUnlockControllerLazy.get();
-        mBiometricUnlockController.setBiometricModeListener(
-                new BiometricUnlockController.BiometricModeListener() {
-                    @Override
-                    public void onResetMode() {
-                        setWakeAndUnlocking(false);
-                    }
-
-                    @Override
-                    public void onModeChanged(int mode) {
-                        switch (mode) {
-                            case BiometricUnlockController.MODE_WAKE_AND_UNLOCK_FROM_DREAM:
-                            case BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING:
-                            case BiometricUnlockController.MODE_WAKE_AND_UNLOCK:
-                                setWakeAndUnlocking(true);
-                        }
-                    }
-
-                    @Override
-                    public void notifyBiometricAuthModeChanged() {
-                        CentralSurfaces.this.notifyBiometricAuthModeChanged();
-                    }
-
-                    private void setWakeAndUnlocking(boolean wakeAndUnlocking) {
-                        if (getNavigationBarView() != null) {
-                            getNavigationBarView().setWakeAndUnlocking(wakeAndUnlocking);
-                        }
-                    }
-                });
-        mStatusBarKeyguardViewManager.registerCentralSurfaces(
-                /* statusBar= */ this,
-                mNotificationPanelViewController,
-                mPanelExpansionStateManager,
-                mBiometricUnlockController,
-                mStackScroller,
-                mKeyguardBypassController);
-        mKeyguardStateController.addCallback(mKeyguardStateControllerCallback);
-        mKeyguardIndicationController
-                .setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
-        mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager);
-        mRemoteInputManager.addControllerCallback(mStatusBarKeyguardViewManager);
-        mDynamicPrivacyController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
-
-        mLightBarController.setBiometricUnlockController(mBiometricUnlockController);
-        mMediaManager.setBiometricUnlockController(mBiometricUnlockController);
-        mKeyguardDismissUtil.setDismissHandler(this::executeWhenUnlocked);
-        Trace.endSection();
-    }
-
-    public NotificationShadeWindowView getNotificationShadeWindowView() {
-        return mNotificationShadeWindowView;
-    }
-
-    public NotificationShadeWindowViewController getNotificationShadeWindowViewController() {
-        return mNotificationShadeWindowViewController;
-    }
-
-    public NotificationPanelViewController getNotificationPanelViewController() {
-        return mNotificationPanelViewController;
-    }
-
-    public ViewGroup getBouncerContainer() {
-        return mNotificationShadeWindowViewController.getBouncerContainer();
-    }
-
-    public int getStatusBarHeight() {
-        return mStatusBarWindowController.getStatusBarHeight();
-    }
-
-    /**
-     * Disable QS if device not provisioned.
-     * If the user switcher is simple then disable QS during setup because
-     * the user intends to use the lock screen user switcher, QS in not needed.
-     */
-    void updateQsExpansionEnabled() {
-        final boolean expandEnabled = mDeviceProvisionedController.isDeviceProvisioned()
-                && (mUserSetup || mUserSwitcherController == null
-                        || !mUserSwitcherController.isSimpleUserSwitcher())
-                && !isShadeDisabled()
-                && ((mDisabled2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) == 0)
-                && !mDozing
-                && !ONLY_CORE_APPS;
-        mNotificationPanelViewController.setQsExpansionEnabledPolicy(expandEnabled);
-        Log.d(TAG, "updateQsExpansionEnabled - QS Expand enabled: " + expandEnabled);
-    }
-
-    public boolean isShadeDisabled() {
-        return (mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0;
-    }
-
-    /**
-     * Request a notification update
-     * @param reason why we're requesting a notification update
-     */
-    public void requestNotificationUpdate(String reason) {
-        mNotificationsController.requestNotificationUpdate(reason);
-    }
-
-    /**
-     * Asks {@link KeyguardUpdateMonitor} to run face auth.
-     */
-    public void requestFaceAuth(boolean userInitiatedRequest) {
-        if (!mKeyguardStateController.canDismissLockScreen()) {
-            mKeyguardUpdateMonitor.requestFaceAuth(userInitiatedRequest);
-        }
-    }
-
-    private void updateReportRejectedTouchVisibility() {
-        if (mReportRejectedTouch == null) {
-            return;
-        }
-        mReportRejectedTouch.setVisibility(mState == StatusBarState.KEYGUARD && !mDozing
-                && mFalsingCollector.isReportingEnabled() ? View.VISIBLE : View.INVISIBLE);
-    }
-
-    boolean areNotificationAlertsDisabled() {
-        return (mDisabled1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0;
-    }
-
-    @Override
-    public void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade,
-            int flags) {
-        startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, flags);
-    }
-
-    @Override
-    public void startActivity(Intent intent, boolean dismissShade) {
-        startActivityDismissingKeyguard(intent, false /* onlyProvisioned */, dismissShade);
-    }
-
-    @Override
-    public void startActivity(Intent intent, boolean dismissShade,
-            @Nullable ActivityLaunchAnimator.Controller animationController,
-            boolean showOverLockscreenWhenLocked) {
-        startActivity(intent, dismissShade, animationController, showOverLockscreenWhenLocked,
-                getActivityUserHandle(intent));
-    }
-
-    @Override
-    public void startActivity(Intent intent, boolean dismissShade,
-            @Nullable ActivityLaunchAnimator.Controller animationController,
-            boolean showOverLockscreenWhenLocked, UserHandle userHandle) {
-        // Make sure that we dismiss the keyguard if it is directly dismissable or when we don't
-        // want to show the activity above it.
-        if (mKeyguardStateController.isUnlocked() || !showOverLockscreenWhenLocked) {
-            startActivityDismissingKeyguard(intent, false, dismissShade,
-                    false /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */,
-                    0 /* flags */, animationController, userHandle);
-            return;
-        }
-
-        boolean animate =
-                animationController != null && shouldAnimateLaunch(true /* isActivityIntent */,
-                        showOverLockscreenWhenLocked);
-
-        ActivityLaunchAnimator.Controller controller = null;
-        if (animate) {
-            // Wrap the animation controller to dismiss the shade and set
-            // mIsLaunchingActivityOverLockscreen during the animation.
-            ActivityLaunchAnimator.Controller delegate = wrapAnimationController(
-                    animationController, dismissShade);
-            controller = new DelegateLaunchAnimatorController(delegate) {
-                @Override
-                public void onIntentStarted(boolean willAnimate) {
-                    getDelegate().onIntentStarted(willAnimate);
-
-                    if (willAnimate) {
-                        CentralSurfaces.this.mIsLaunchingActivityOverLockscreen = true;
-                    }
-                }
-
-                @Override
-                public void onLaunchAnimationEnd(boolean isExpandingFullyAbove) {
-                    // Set mIsLaunchingActivityOverLockscreen to false before actually finishing the
-                    // animation so that we can assume that mIsLaunchingActivityOverLockscreen
-                    // being true means that we will collapse the shade (or at least run the
-                    // post collapse runnables) later on.
-                    CentralSurfaces.this.mIsLaunchingActivityOverLockscreen = false;
-                    getDelegate().onLaunchAnimationEnd(isExpandingFullyAbove);
-                }
-
-                @Override
-                public void onLaunchAnimationCancelled() {
-                    // Set mIsLaunchingActivityOverLockscreen to false before actually finishing the
-                    // animation so that we can assume that mIsLaunchingActivityOverLockscreen
-                    // being true means that we will collapse the shade (or at least run the
-                    // post collapse runnables) later on.
-                    CentralSurfaces.this.mIsLaunchingActivityOverLockscreen = false;
-                    getDelegate().onLaunchAnimationCancelled();
-                }
-            };
-        } else if (dismissShade) {
-            // The animation will take care of dismissing the shade at the end of the animation. If
-            // we don't animate, collapse it directly.
-            collapseShade();
-        }
-
-        mActivityLaunchAnimator.startIntentWithAnimation(controller, animate,
-                intent.getPackage(), showOverLockscreenWhenLocked, (adapter) -> TaskStackBuilder
-                        .create(mContext)
-                        .addNextIntent(intent)
-                        .startActivities(getActivityOptions(getDisplayId(), adapter),
-                                userHandle));
-    }
-
-    /**
-     * Whether we are currently animating an activity launch above the lockscreen (occluding
-     * activity).
-     */
-    public boolean isLaunchingActivityOverLockscreen() {
-        return mIsLaunchingActivityOverLockscreen;
-    }
-
-    @Override
-    public void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade) {
-        startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade);
-    }
-
-    @Override
-    public void startActivity(Intent intent, boolean dismissShade, Callback callback) {
-        startActivityDismissingKeyguard(intent, false, dismissShade,
-                false /* disallowEnterPictureInPictureWhileLaunching */, callback, 0,
-                null /* animationController */, getActivityUserHandle(intent));
-    }
-
-    public void setQsExpanded(boolean expanded) {
-        mNotificationShadeWindowController.setQsExpanded(expanded);
-        mNotificationPanelViewController.setStatusAccessibilityImportance(expanded
-                ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
-                : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
-        mNotificationPanelViewController.updateSystemUiStateFlags();
-        if (getNavigationBarView() != null) {
-            getNavigationBarView().onStatusBarPanelStateChanged();
-        }
-    }
-
-    public boolean isWakeUpComingFromTouch() {
-        return mWakeUpComingFromTouch;
-    }
-
-    public boolean isFalsingThresholdNeeded() {
-        return true;
-    }
-
-    /**
-     * To be called when there's a state change in StatusBarKeyguardViewManager.
-     */
-    public void onKeyguardViewManagerStatesUpdated() {
-        logStateToEventlog();
-    }
-
-    public void setPanelExpanded(boolean isExpanded) {
-        if (mPanelExpanded != isExpanded) {
-            mNotificationLogger.onPanelExpandedChanged(isExpanded);
-        }
-        mPanelExpanded = isExpanded;
-        mStatusBarHideIconsForBouncerManager.setPanelExpandedAndTriggerUpdate(isExpanded);
-        mNotificationShadeWindowController.setPanelExpanded(isExpanded);
-        mStatusBarStateController.setPanelExpanded(isExpanded);
-        if (isExpanded && mStatusBarStateController.getState() != StatusBarState.KEYGUARD) {
-            if (DEBUG) {
-                Log.v(TAG, "clearing notification effects from Height");
-            }
-            clearNotificationEffects();
-        }
-
-        if (!isExpanded) {
-            mRemoteInputManager.onPanelCollapsed();
-        }
-    }
-
-    public ViewGroup getNotificationScrollLayout() {
-        return mStackScroller;
-    }
-
-    public boolean isPulsing() {
-        return mDozeServiceHost.isPulsing();
-    }
-
-    @Nullable
-    public View getAmbientIndicationContainer() {
-        return mAmbientIndicationContainer;
-    }
-
-    /**
-     * When the keyguard is showing and covered by a "showWhenLocked" activity it
-     * is occluded. This is controlled by {@link com.android.server.policy.PhoneWindowManager}
-     *
-     * @return whether the keyguard is currently occluded
-     */
-    public boolean isOccluded() {
-        return mKeyguardStateController.isOccluded();
-    }
-
-    /** A launch animation was cancelled. */
-    //TODO: These can / should probably be moved to NotificationPresenter or ShadeController
-    public void onLaunchAnimationCancelled(boolean isLaunchForActivity) {
-        if (mPresenter.isPresenterFullyCollapsed() && !mPresenter.isCollapsing()
-                && isLaunchForActivity) {
-            onClosingFinished();
-        } else {
-            mShadeController.collapsePanel(true /* animate */);
-        }
-    }
-
-    /** A launch animation ended. */
-    public void onLaunchAnimationEnd(boolean launchIsFullScreen) {
-        if (!mPresenter.isCollapsing()) {
-            onClosingFinished();
-        }
-        if (launchIsFullScreen) {
-            instantCollapseNotificationPanel();
-        }
-    }
-
-    /**
-     * Whether we should animate an activity launch.
-     *
-     * Note: This method must be called *before* dismissing the keyguard.
-     */
-    public boolean shouldAnimateLaunch(boolean isActivityIntent, boolean showOverLockscreen) {
-        // TODO(b/184121838): Support launch animations when occluded.
-        if (isOccluded()) {
-            return false;
-        }
-
-        // Always animate if we are not showing the keyguard or if we animate over the lockscreen
-        // (without unlocking it).
-        if (showOverLockscreen || !mKeyguardStateController.isShowing()) {
-            return true;
-        }
-
-        // If we are locked and have to dismiss the keyguard, only animate if remote unlock
-        // animations are enabled. We also don't animate non-activity launches as they can break the
-        // animation.
-        // TODO(b/184121838): Support non activity launches on the lockscreen.
-        return isActivityIntent && KeyguardService.sEnableRemoteKeyguardGoingAwayAnimation;
-    }
-
-    /** Whether we should animate an activity launch. */
-    public boolean shouldAnimateLaunch(boolean isActivityIntent) {
-        return shouldAnimateLaunch(isActivityIntent, false /* showOverLockscreen */);
-    }
-
-    public boolean isDeviceInVrMode() {
-        return mPresenter.isDeviceInVrMode();
-    }
-
-    public NotificationPresenter getPresenter() {
-        return mPresenter;
-    }
-
-    @VisibleForTesting
-    void setBarStateForTest(int state) {
-        mState = state;
-    }
-
-    static class KeyboardShortcutsMessage {
-        final int mDeviceId;
-
-        KeyboardShortcutsMessage(int deviceId) {
-            mDeviceId = deviceId;
-        }
-    }
-
-    static class AnimateExpandSettingsPanelMessage {
-        final String mSubpanel;
-
-        AnimateExpandSettingsPanelMessage(String subpanel) {
-            mSubpanel = subpanel;
-        }
-    }
-
-    private void maybeEscalateHeadsUp() {
-        mHeadsUpManager.getAllEntries().forEach(entry -> {
-            final StatusBarNotification sbn = entry.getSbn();
-            final Notification notification = sbn.getNotification();
-            if (notification.fullScreenIntent != null) {
-                if (DEBUG) {
-                    Log.d(TAG, "converting a heads up to fullScreen");
-                }
-                try {
-                    EventLog.writeEvent(EventLogTags.SYSUI_HEADS_UP_ESCALATION,
-                            sbn.getKey());
-                    wakeUpForFullScreenIntent();
-                    notification.fullScreenIntent.send();
-                    entry.notifyFullScreenIntentLaunched();
-                } catch (PendingIntent.CanceledException e) {
-                }
-            }
-        });
-        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())) {
-            return;
-        }
-
-        mExpandedVisible = true;
-
-        // Expand the window to encompass the full screen in anticipation of the drag.
-        // This is only possible to do atomically because the status bar is at the top of the screen!
-        mNotificationShadeWindowController.setPanelVisible(true);
-
-        visibilityChanged(true);
-        mCommandQueue.recomputeDisableFlags(mDisplayId, !force /* animate */);
-        setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true);
-    }
-
-    public void postAnimateCollapsePanels() {
-        mMainExecutor.execute(mShadeController::animateCollapsePanels);
-    }
-
-    public void postAnimateForceCollapsePanels() {
-        mMainExecutor.execute(
-                () -> mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE,
-                true /* force */));
-    }
-
-    public void postAnimateOpenPanels() {
-        mMessageRouter.sendMessage(MSG_OPEN_SETTINGS_PANEL);
-    }
-
-    public boolean isExpandedVisible() {
-        return mExpandedVisible;
-    }
-
-    public boolean isPanelExpanded() {
-        return mPanelExpanded;
-    }
-
-    /**
-     * Called when another window is about to transfer it's input focus.
-     */
-    public void onInputFocusTransfer(boolean start, boolean cancel, float velocity) {
-        if (!mCommandQueue.panelsEnabled()) {
-            return;
-        }
-
-        if (start) {
-            mNotificationPanelViewController.startWaitingForOpenPanelGesture();
-        } else {
-            mNotificationPanelViewController.stopWaitingForOpenPanelGesture(cancel, velocity);
-        }
-    }
-
-    public void animateCollapseQuickSettings() {
-        if (mState == StatusBarState.SHADE) {
-            mNotificationPanelViewController.collapsePanel(
-                    true, false /* delayed */, 1.0f /* speedUpFactor */);
-        }
-    }
-
-    void makeExpandedInvisible() {
-        if (SPEW) Log.d(TAG, "makeExpandedInvisible: mExpandedVisible=" + mExpandedVisible
-                + " mExpandedVisible=" + mExpandedVisible);
-
-        if (!mExpandedVisible || mNotificationShadeWindowView == null) {
-            return;
-        }
-
-        // Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868)
-        mNotificationPanelViewController.collapsePanel(/*animate=*/ false, false /* delayed*/,
-                1.0f /* speedUpFactor */);
-
-        mNotificationPanelViewController.closeQs();
-
-        mExpandedVisible = false;
-        visibilityChanged(false);
-
-        // Update the visibility of notification shade and status bar window.
-        mNotificationShadeWindowController.setPanelVisible(false);
-        mStatusBarWindowController.setForceStatusBarVisible(false);
-
-        // Close any guts that might be visible
-        mGutsManager.closeAndSaveGuts(true /* removeLeavebehind */, true /* force */,
-                true /* removeControls */, -1 /* x */, -1 /* y */, true /* resetMenu */);
-
-        mShadeController.runPostCollapseRunnables();
-        setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
-        if (!mNotificationActivityStarter.isCollapsingToShowActivityOverLockscreen()) {
-            showBouncerOrLockScreenIfKeyguard();
-        } else if (DEBUG) {
-            Log.d(TAG, "Not showing bouncer due to activity showing over lockscreen");
-        }
-        mCommandQueue.recomputeDisableFlags(
-                mDisplayId,
-                mNotificationPanelViewController.hideStatusBarIconsWhenExpanded() /* animate */);
-
-        // Trimming will happen later if Keyguard is showing - doing it here might cause a jank in
-        // the bouncer appear animation.
-        if (!mStatusBarKeyguardViewManager.isShowing()) {
-            WindowManagerGlobal.getInstance().trimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
-        }
-    }
-
-    /** Called when a touch event occurred on {@link PhoneStatusBarView}. */
-    public void onTouchEvent(MotionEvent event) {
-        // TODO(b/202981994): Move this touch debugging to a central location. (Right now, it's
-        //   split between NotificationPanelViewController and here.)
-        if (DEBUG_GESTURES) {
-            if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {
-                EventLog.writeEvent(EventLogTags.SYSUI_STATUSBAR_TOUCH,
-                        event.getActionMasked(), (int) event.getX(), (int) event.getY(),
-                        mDisabled1, mDisabled2);
-            }
-
-        }
-
-        if (SPEW) {
-            Log.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled1="
-                    + mDisabled1 + " mDisabled2=" + mDisabled2);
-        } else if (CHATTY) {
-            if (event.getAction() != MotionEvent.ACTION_MOVE) {
-                Log.d(TAG, String.format(
-                            "panel: %s at (%f, %f) mDisabled1=0x%08x mDisabled2=0x%08x",
-                            MotionEvent.actionToString(event.getAction()),
-                            event.getRawX(), event.getRawY(), mDisabled1, mDisabled2));
-            }
-        }
-
-        if (DEBUG_GESTURES) {
-            mGestureRec.add(event);
-        }
-
-        if (mStatusBarWindowState == WINDOW_STATE_SHOWING) {
-            final boolean upOrCancel =
-                    event.getAction() == MotionEvent.ACTION_UP ||
-                    event.getAction() == MotionEvent.ACTION_CANCEL;
-            setInteracting(StatusBarManager.WINDOW_STATUS_BAR, !upOrCancel || mExpandedVisible);
-        }
-    }
-
-    public GestureRecorder getGestureRecorder() {
-        return mGestureRec;
-    }
-
-    public BiometricUnlockController getBiometricUnlockController() {
-        return mBiometricUnlockController;
-    }
-
-    void showTransientUnchecked() {
-        if (!mTransientShown) {
-            mTransientShown = true;
-            mNoAnimationOnNextBarModeChange = true;
-            maybeUpdateBarMode();
-        }
-    }
-
-
-    void clearTransient() {
-        if (mTransientShown) {
-            mTransientShown = false;
-            maybeUpdateBarMode();
-        }
-    }
-
-    private void maybeUpdateBarMode() {
-        final int barMode = barMode(mTransientShown, mAppearance);
-        if (updateBarMode(barMode)) {
-            mLightBarController.onStatusBarModeChanged(barMode);
-            updateBubblesVisibility();
-        }
-    }
-
-    private boolean updateBarMode(int barMode) {
-        if (mStatusBarMode != barMode) {
-            mStatusBarMode = barMode;
-            checkBarModes();
-            mAutoHideController.touchAutoHide();
-            return true;
-        }
-        return false;
-    }
-
-    private @TransitionMode int barMode(boolean isTransient, int appearance) {
-        final int lightsOutOpaque = APPEARANCE_LOW_PROFILE_BARS | APPEARANCE_OPAQUE_STATUS_BARS;
-        if (mOngoingCallController.hasOngoingCall() && mIsFullscreen) {
-            return MODE_SEMI_TRANSPARENT;
-        } else if (isTransient) {
-            return MODE_SEMI_TRANSPARENT;
-        } else if ((appearance & lightsOutOpaque) == lightsOutOpaque) {
-            return MODE_LIGHTS_OUT;
-        } else if ((appearance & APPEARANCE_LOW_PROFILE_BARS) != 0) {
-            return MODE_LIGHTS_OUT_TRANSPARENT;
-        } else if ((appearance & APPEARANCE_OPAQUE_STATUS_BARS) != 0) {
-            return MODE_OPAQUE;
-        } else if ((appearance & APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS) != 0) {
-            return MODE_SEMI_TRANSPARENT;
-        } else {
-            return MODE_TRANSPARENT;
-        }
-    }
-
-    protected void showWirelessChargingAnimation(int batteryLevel) {
-        showChargingAnimation(batteryLevel, UNKNOWN_BATTERY_LEVEL, 0);
-    }
-
-    protected void showChargingAnimation(int batteryLevel, int transmittingBatteryLevel,
-            long animationDelay) {
-        WirelessChargingAnimation.makeWirelessChargingAnimation(mContext, null,
-                transmittingBatteryLevel, batteryLevel,
-                new WirelessChargingAnimation.Callback() {
-                    @Override
-                    public void onAnimationStarting() {
-                        mNotificationShadeWindowController.setRequestTopUi(true, TAG);
-                    }
-
-                    @Override
-                    public void onAnimationEnded() {
-                        mNotificationShadeWindowController.setRequestTopUi(false, TAG);
-                    }
-                }, false, sUiEventLogger).show(animationDelay);
-    }
-
-    public void checkBarModes() {
-        if (mDemoModeController.isInDemoMode()) return;
-        if (mStatusBarTransitions != null) {
-            checkBarMode(mStatusBarMode, mStatusBarWindowState, mStatusBarTransitions);
-        }
-        mNavigationBarController.checkNavBarModes(mDisplayId);
-        mNoAnimationOnNextBarModeChange = false;
-    }
-
-    // Called by NavigationBarFragment
-    public void setQsScrimEnabled(boolean scrimEnabled) {
-        mNotificationPanelViewController.setQsScrimEnabled(scrimEnabled);
-    }
-
-    /** Temporarily hides Bubbles if the status bar is hidden. */
-    void updateBubblesVisibility() {
-        mBubblesOptional.ifPresent(bubbles -> bubbles.onStatusBarVisibilityChanged(
-                mStatusBarMode != MODE_LIGHTS_OUT
-                        && mStatusBarMode != MODE_LIGHTS_OUT_TRANSPARENT
-                        && !mStatusBarWindowHidden));
-    }
-
-    void checkBarMode(@TransitionMode int mode, @WindowVisibleState int windowState,
-            BarTransitions transitions) {
-        final boolean anim = !mNoAnimationOnNextBarModeChange && mDeviceInteractive
-                && windowState != WINDOW_STATE_HIDDEN;
-        transitions.transitionTo(mode, anim);
-    }
-
-    private void finishBarAnimations() {
-        if (mStatusBarTransitions != null) {
-            mStatusBarTransitions.finishAnimations();
-        }
-        mNavigationBarController.finishBarAnimations(mDisplayId);
-    }
-
-    private final Runnable mCheckBarModes = this::checkBarModes;
-
-    public void setInteracting(int barWindow, boolean interacting) {
-        mInteractingWindows = interacting
-                ? (mInteractingWindows | barWindow)
-                : (mInteractingWindows & ~barWindow);
-        if (mInteractingWindows != 0) {
-            mAutoHideController.suspendAutoHide();
-        } else {
-            mAutoHideController.resumeSuspendedAutoHide();
-        }
-        checkBarModes();
-    }
-
-    private void dismissVolumeDialog() {
-        if (mVolumeComponent != null) {
-            mVolumeComponent.dismissNow();
-        }
-    }
-
-    public static String viewInfo(View v) {
+    static String viewInfo(View v) {
         return "[(" + v.getLeft() + "," + v.getTop() + ")(" + v.getRight() + "," + v.getBottom()
                 + ") " + v.getWidth() + "x" + v.getHeight() + "]";
     }
 
-    @Override
-    public void dump(PrintWriter pwOriginal, String[] args) {
-        IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal);
-        synchronized (mQueueLock) {
-            pw.println("Current Status Bar state:");
-            pw.println("  mExpandedVisible=" + mExpandedVisible);
-            pw.println("  mDisplayMetrics=" + mDisplayMetrics);
-            pw.println("  mStackScroller: " + viewInfo(mStackScroller));
-            pw.println("  mStackScroller: " + viewInfo(mStackScroller)
-                    + " scroll " + mStackScroller.getScrollX()
-                    + "," + mStackScroller.getScrollY());
-        }
-
-        pw.print("  mInteractingWindows="); pw.println(mInteractingWindows);
-        pw.print("  mStatusBarWindowState=");
-        pw.println(windowStateToString(mStatusBarWindowState));
-        pw.print("  mStatusBarMode=");
-        pw.println(BarTransitions.modeToString(mStatusBarMode));
-        pw.print("  mDozing="); pw.println(mDozing);
-        pw.print("  mWallpaperSupported= "); pw.println(mWallpaperSupported);
-
-        pw.println("  ShadeWindowView: ");
-        if (mNotificationShadeWindowViewController != null) {
-            mNotificationShadeWindowViewController.dump(pw, args);
-            dumpBarTransitions(pw, "PhoneStatusBarTransitions", mStatusBarTransitions);
-        }
-
-        pw.println("  mMediaManager: ");
-        if (mMediaManager != null) {
-            mMediaManager.dump(pw, args);
-        }
-
-        pw.println("  Panels: ");
-        if (mNotificationPanelViewController != null) {
-            pw.println("    mNotificationPanel="
-                    + mNotificationPanelViewController.getView() + " params="
-                    + mNotificationPanelViewController.getView().getLayoutParams().debug(""));
-            pw.print  ("      ");
-            mNotificationPanelViewController.dump(pw, args);
-        }
-        pw.println("  mStackScroller: ");
-        if (mStackScroller != null) {
-            // Double indent until we rewrite the rest of this dump()
-            pw.increaseIndent();
-            pw.increaseIndent();
-            mStackScroller.dump(pw, args);
-            pw.decreaseIndent();
-            pw.decreaseIndent();
-        }
-        pw.println("  Theme:");
-        String nightMode = mUiModeManager == null ? "null" : mUiModeManager.getNightMode() + "";
-        pw.println("    dark theme: " + nightMode +
-                " (auto: " + UiModeManager.MODE_NIGHT_AUTO +
-                ", yes: " + UiModeManager.MODE_NIGHT_YES +
-                ", no: " + UiModeManager.MODE_NIGHT_NO + ")");
-        final boolean lightWpTheme = mContext.getThemeResId()
-                == R.style.Theme_SystemUI_LightWallpaper;
-        pw.println("    light wallpaper theme: " + lightWpTheme);
-
-        if (mKeyguardIndicationController != null) {
-            mKeyguardIndicationController.dump(pw, args);
-        }
-
-        if (mScrimController != null) {
-            mScrimController.dump(pw, args);
-        }
-
-        if (mLightRevealScrim != null) {
-            pw.println(
-                    "mLightRevealScrim.getRevealEffect(): " + mLightRevealScrim.getRevealEffect());
-            pw.println(
-                    "mLightRevealScrim.getRevealAmount(): " + mLightRevealScrim.getRevealAmount());
-        }
-
-        if (mStatusBarKeyguardViewManager != null) {
-            mStatusBarKeyguardViewManager.dump(pw);
-        }
-
-        mNotificationsController.dump(pw, args, DUMPTRUCK);
-
-        if (DEBUG_GESTURES) {
-            pw.print("  status bar gestures: ");
-            mGestureRec.dump(pw, args);
-        }
-
-        if (mHeadsUpManager != null) {
-            mHeadsUpManager.dump(pw, args);
-        } else {
-            pw.println("  mHeadsUpManager: null");
-        }
-
-        if (mStatusBarTouchableRegionManager != null) {
-            mStatusBarTouchableRegionManager.dump(pw, args);
-        } else {
-            pw.println("  mStatusBarTouchableRegionManager: null");
-        }
-
-        if (mLightBarController != null) {
-            mLightBarController.dump(pw, args);
-        }
-
-        pw.println("SharedPreferences:");
-        for (Map.Entry<String, ?> entry : Prefs.getAll(mContext).entrySet()) {
-            pw.print("  "); pw.print(entry.getKey()); pw.print("="); pw.println(entry.getValue());
-        }
-
-        pw.println("Camera gesture intents:");
-        pw.println("   Insecure camera: " + CameraIntents.getInsecureCameraIntent(mContext));
-        pw.println("   Secure camera: " + CameraIntents.getSecureCameraIntent(mContext));
-        pw.println("   Override package: "
-                + CameraIntents.getOverrideCameraPackage(mContext));
-    }
-
-    public static void dumpBarTransitions(
+    static void dumpBarTransitions(
             PrintWriter pw, String var, @Nullable BarTransitions transitions) {
-        pw.print("  "); pw.print(var); pw.print(".BarTransitions.mMode=");
+        pw.print("  ");
+        pw.print(var);
+        pw.print(".BarTransitions.mMode=");
         if (transitions != null) {
             pw.println(BarTransitions.modeToString(transitions.getMode()));
         } else {
@@ -2389,1691 +106,15 @@
         }
     }
 
-    public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {
-        makeStatusBarView(result);
-        mNotificationShadeWindowController.attach();
-        mStatusBarWindowController.attach();
-    }
-
-    // called by makeStatusbar and also by PhoneStatusBarView
-    void updateDisplaySize() {
-        mDisplay.getMetrics(mDisplayMetrics);
-        mDisplay.getSize(mCurrentDisplaySize);
-        if (DEBUG_GESTURES) {
-            mGestureRec.tag("display",
-                    String.format("%dx%d", mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels));
-        }
-    }
-
-    float getDisplayDensity() {
-        return mDisplayMetrics.density;
-    }
-
-    public float getDisplayWidth() {
-        return mDisplayMetrics.widthPixels;
-    }
-
-    public float getDisplayHeight() {
-        return mDisplayMetrics.heightPixels;
-    }
-
-    int getRotation() {
-        return mDisplay.getRotation();
-    }
-
-    int getDisplayId() {
-        return mDisplayId;
-    }
-
-    public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
-            boolean dismissShade, int flags) {
-        startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade,
-                false /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */,
-                flags, null /* animationController */, getActivityUserHandle(intent));
-    }
-
-    public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
-            boolean dismissShade) {
-        startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, 0);
-    }
-
-    void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
-            final boolean dismissShade, final boolean disallowEnterPictureInPictureWhileLaunching,
-            final Callback callback, int flags,
-            @Nullable ActivityLaunchAnimator.Controller animationController,
-            final UserHandle userHandle) {
-        if (onlyProvisioned && !mDeviceProvisionedController.isDeviceProvisioned()) return;
-
-        final boolean willLaunchResolverActivity =
-                mActivityIntentHelper.wouldLaunchResolverActivity(intent,
-                        mLockscreenUserManager.getCurrentUserId());
-
-        boolean animate =
-                animationController != null && !willLaunchResolverActivity && shouldAnimateLaunch(
-                        true /* isActivityIntent */);
-        ActivityLaunchAnimator.Controller animController =
-                animationController != null ? wrapAnimationController(animationController,
-                        dismissShade) : null;
-
-        // If we animate, we will dismiss the shade only once the animation is done. This is taken
-        // care of by the StatusBarLaunchAnimationController.
-        boolean dismissShadeDirectly = dismissShade && animController == null;
-
-        Runnable runnable = () -> {
-            mAssistManagerLazy.get().hideAssist();
-            intent.setFlags(
-                    Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
-            intent.addFlags(flags);
-            int[] result = new int[]{ActivityManager.START_CANCELED};
-
-            mActivityLaunchAnimator.startIntentWithAnimation(animController,
-                    animate, intent.getPackage(), (adapter) -> {
-                        ActivityOptions options = new ActivityOptions(
-                                getActivityOptions(mDisplayId, adapter));
-                        options.setDisallowEnterPictureInPictureWhileLaunching(
-                                disallowEnterPictureInPictureWhileLaunching);
-                        if (CameraIntents.isInsecureCameraIntent(intent)) {
-                            // Normally an activity will set it's requested rotation
-                            // animation on its window. However when launching an activity
-                            // causes the orientation to change this is too late. In these cases
-                            // the default animation is used. This doesn't look good for
-                            // the camera (as it rotates the camera contents out of sync
-                            // with physical reality). So, we ask the WindowManager to
-                            // force the crossfade animation if an orientation change
-                            // happens to occur during the launch.
-                            options.setRotationAnimationHint(
-                                    WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS);
-                        }
-                        if (Settings.Panel.ACTION_VOLUME.equals(intent.getAction())) {
-                            // Settings Panel is implemented as activity(not a dialog), so
-                            // underlying app is paused and may enter picture-in-picture mode
-                            // as a result.
-                            // So we need to disable picture-in-picture mode here
-                            // if it is volume panel.
-                            options.setDisallowEnterPictureInPictureWhileLaunching(true);
-                        }
-
-                        try {
-                            result[0] = ActivityTaskManager.getService().startActivityAsUser(
-                                    null, mContext.getBasePackageName(),
-                                    mContext.getAttributionTag(),
-                                    intent,
-                                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
-                                    null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null,
-                                    options.toBundle(), userHandle.getIdentifier());
-                        } catch (RemoteException e) {
-                            Log.w(TAG, "Unable to start activity", e);
-                        }
-                        return result[0];
-                    });
-
-            if (callback != null) {
-                callback.onActivityStarted(result[0]);
-            }
-        };
-        Runnable cancelRunnable = () -> {
-            if (callback != null) {
-                callback.onActivityStarted(ActivityManager.START_CANCELED);
-            }
-        };
-        executeRunnableDismissingKeyguard(runnable, cancelRunnable, dismissShadeDirectly,
-                willLaunchResolverActivity, true /* deferred */, animate);
-    }
-
-    @Nullable
-    private ActivityLaunchAnimator.Controller wrapAnimationController(
-            ActivityLaunchAnimator.Controller animationController, boolean dismissShade) {
-        View rootView = animationController.getLaunchContainer().getRootView();
-
-        Optional<ActivityLaunchAnimator.Controller> controllerFromStatusBar =
-                mStatusBarWindowController.wrapAnimationControllerIfInStatusBar(
-                        rootView, animationController);
-        if (controllerFromStatusBar.isPresent()) {
-            return controllerFromStatusBar.get();
-        }
-
-        if (dismissShade) {
-            // If the view is not in the status bar, then we are animating a view in the shade.
-            // We have to make sure that we collapse it when the animation ends or is cancelled.
-            return new StatusBarLaunchAnimatorController(animationController, this,
-                    true /* isLaunchForActivity */);
-        }
-
-        return animationController;
-    }
-
-    public void readyForKeyguardDone() {
-        mStatusBarKeyguardViewManager.readyForKeyguardDone();
-    }
-
-    public void executeRunnableDismissingKeyguard(final Runnable runnable,
-            final Runnable cancelAction,
-            final boolean dismissShade,
-            final boolean afterKeyguardGone,
-            final boolean deferred) {
-        executeRunnableDismissingKeyguard(runnable, cancelAction, dismissShade, afterKeyguardGone,
-                deferred, false /* willAnimateOnKeyguard */);
-    }
-
-    public void executeRunnableDismissingKeyguard(final Runnable runnable,
-            final Runnable cancelAction,
-            final boolean dismissShade,
-            final boolean afterKeyguardGone,
-            final boolean deferred,
-            final boolean willAnimateOnKeyguard) {
-        OnDismissAction onDismissAction = new OnDismissAction() {
-            @Override
-            public boolean onDismiss() {
-                if (runnable != null) {
-                    if (mStatusBarKeyguardViewManager.isShowing()
-                            && mStatusBarKeyguardViewManager.isOccluded()) {
-                        mStatusBarKeyguardViewManager.addAfterKeyguardGoneRunnable(runnable);
-                    } else {
-                        mMainExecutor.execute(runnable);
-                    }
-                }
-                if (dismissShade) {
-                    if (mExpandedVisible && !mBouncerShowing) {
-                        mShadeController.animateCollapsePanels(
-                                CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
-                                true /* force */, true /* delayed*/);
-                    } else {
-
-                        // Do it after DismissAction has been processed to conserve the needed
-                        // ordering.
-                        mMainExecutor.execute(mShadeController::runPostCollapseRunnables);
-                    }
-                } else if (CentralSurfaces.this.isInLaunchTransition()
-                        && mNotificationPanelViewController.isLaunchTransitionFinished()) {
-
-                    // We are not dismissing the shade, but the launch transition is already
-                    // finished,
-                    // so nobody will call readyForKeyguardDone anymore. Post it such that
-                    // keyguardDonePending gets called first.
-                    mMainExecutor.execute(mStatusBarKeyguardViewManager::readyForKeyguardDone);
-                }
-                return deferred;
-            }
-
-            @Override
-            public boolean willRunAnimationOnKeyguard() {
-                return willAnimateOnKeyguard;
-            }
-        };
-        dismissKeyguardThenExecute(onDismissAction, cancelAction, afterKeyguardGone);
-    }
-
-    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            Trace.beginSection("CentralSurfaces#onReceive");
-            if (DEBUG) Log.v(TAG, "onReceive: " + intent);
-            String action = intent.getAction();
-            String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
-            if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
-                KeyboardShortcuts.dismiss();
-                mRemoteInputManager.closeRemoteInputs();
-                if (mLockscreenUserManager.isCurrentProfile(getSendingUserId())) {
-                    int flags = CommandQueue.FLAG_EXCLUDE_NONE;
-                    if (reason != null) {
-                        if (reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) {
-                            flags |= CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL;
-                        }
-                        // Do not collapse notifications when starting dreaming if the notifications
-                        // shade is used for the screen off animation. It might require expanded
-                        // state for the scrims to be visible
-                        if (reason.equals(SYSTEM_DIALOG_REASON_DREAM)
-                                && mScreenOffAnimationController.shouldExpandNotifications()) {
-                            flags |= CommandQueue.FLAG_EXCLUDE_NOTIFICATION_PANEL;
-                        }
-                    }
-                    mShadeController.animateCollapsePanels(flags);
-                }
-            } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
-                if (mNotificationShadeWindowController != null) {
-                    mNotificationShadeWindowController.setNotTouchable(false);
-                }
-                finishBarAnimations();
-                resetUserExpandedStates();
-            }
-            Trace.endSection();
-        }
-    };
-
-    private final BroadcastReceiver mDemoReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (DEBUG) Log.v(TAG, "onReceive: " + intent);
-            String action = intent.getAction();
-            if (ACTION_FAKE_ARTWORK.equals(action)) {
-                if (DEBUG_MEDIA_FAKE_ARTWORK) {
-                    mPresenter.updateMediaMetaData(true, true);
-                }
-            }
-        }
-    };
-
-    public void resetUserExpandedStates() {
-        mNotificationsController.resetUserExpandedStates();
-    }
-
-    private void executeWhenUnlocked(OnDismissAction action, boolean requiresShadeOpen,
-            boolean afterKeyguardGone) {
-        if (mStatusBarKeyguardViewManager.isShowing() && requiresShadeOpen) {
-            mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
-        }
-        dismissKeyguardThenExecute(action, null /* cancelAction */,
-                afterKeyguardGone /* afterKeyguardGone */);
-    }
-
-    protected void dismissKeyguardThenExecute(OnDismissAction action, boolean afterKeyguardGone) {
-        dismissKeyguardThenExecute(action, null /* cancelRunnable */, afterKeyguardGone);
-    }
-
-    @Override
-    public void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction,
-            boolean afterKeyguardGone) {
-        if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_ASLEEP
-                && mKeyguardStateController.canDismissLockScreen()
-                && !mStatusBarStateController.leaveOpenOnKeyguardHide()
-                && mDozeServiceHost.isPulsing()) {
-            // Reuse the biometric wake-and-unlock transition if we dismiss keyguard from a pulse.
-            // TODO: Factor this transition out of BiometricUnlockController.
-            mBiometricUnlockController.startWakeAndUnlock(
-                    BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING);
-        }
-        if (mStatusBarKeyguardViewManager.isShowing()) {
-            mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction,
-                    afterKeyguardGone);
-        } else {
-            action.onDismiss();
-        }
-    }
-    /**
-     * Notify the shade controller that the current user changed
-     *
-     * @param newUserId userId of the new user
-     */
-    public void setLockscreenUser(int newUserId) {
-        if (mLockscreenWallpaper != null) {
-            mLockscreenWallpaper.setCurrentUser(newUserId);
-        }
-        mScrimController.setCurrentUser(newUserId);
-        if (mWallpaperSupported) {
-            mWallpaperChangedReceiver.onReceive(mContext, null);
-        }
-    }
-
-    /**
-     * Reload some of our resources when the configuration changes.
-     *
-     * We don't reload everything when the configuration changes -- we probably
-     * should, but getting that smooth is tough.  Someday we'll fix that.  In the
-     * meantime, just update the things that we know change.
-     */
-    void updateResources() {
-        // Update the quick setting tiles
-        if (mQSPanelController != null) {
-            mQSPanelController.updateResources();
-        }
-
-        if (mStatusBarWindowController != null) {
-            mStatusBarWindowController.refreshStatusBarHeight();
-        }
-
-        if (mNotificationPanelViewController != null) {
-            mNotificationPanelViewController.updateResources();
-        }
-        if (mBrightnessMirrorController != null) {
-            mBrightnessMirrorController.updateResources();
-        }
-        if (mStatusBarKeyguardViewManager != null) {
-            mStatusBarKeyguardViewManager.updateResources();
-        }
-
-        mPowerButtonReveal = new PowerButtonReveal(mContext.getResources().getDimensionPixelSize(
-                com.android.systemui.R.dimen.physical_power_button_center_screen_location_y));
-    }
-
-    // Visibility reporting
-    protected void handleVisibleToUserChanged(boolean visibleToUser) {
-        if (visibleToUser) {
-            handleVisibleToUserChangedImpl(visibleToUser);
-            mNotificationLogger.startNotificationLogging();
-        } else {
-            mNotificationLogger.stopNotificationLogging();
-            handleVisibleToUserChangedImpl(visibleToUser);
-        }
-    }
-
-    // Visibility reporting
-    void handleVisibleToUserChangedImpl(boolean visibleToUser) {
-        if (visibleToUser) {
-            /* The LEDs are turned off when the notification panel is shown, even just a little bit.
-             * See also CentralSurfaces.setPanelExpanded for another place where we attempt to do
-             * this.
-             */
-            boolean pinnedHeadsUp = mHeadsUpManager.hasPinnedHeadsUp();
-            boolean clearNotificationEffects =
-                    !mPresenter.isPresenterFullyCollapsed() &&
-                            (mState == StatusBarState.SHADE
-                                    || mState == StatusBarState.SHADE_LOCKED);
-            int notificationLoad = mNotificationsController.getActiveNotificationsCount();
-            if (pinnedHeadsUp && mPresenter.isPresenterFullyCollapsed()) {
-                notificationLoad = 1;
-            }
-            final int finalNotificationLoad = notificationLoad;
-            mUiBgExecutor.execute(() -> {
-                try {
-                    mBarService.onPanelRevealed(clearNotificationEffects,
-                            finalNotificationLoad);
-                } catch (RemoteException ex) {
-                    // Won't fail unless the world has ended.
-                }
-            });
-        } else {
-            mUiBgExecutor.execute(() -> {
-                try {
-                    mBarService.onPanelHidden();
-                } catch (RemoteException ex) {
-                    // Won't fail unless the world has ended.
-                }
-            });
-        }
-
-    }
-
-    private void logStateToEventlog() {
-        boolean isShowing = mStatusBarKeyguardViewManager.isShowing();
-        boolean isOccluded = mStatusBarKeyguardViewManager.isOccluded();
-        boolean isBouncerShowing = mStatusBarKeyguardViewManager.isBouncerShowing();
-        boolean isSecure = mKeyguardStateController.isMethodSecure();
-        boolean unlocked = mKeyguardStateController.canDismissLockScreen();
-        int stateFingerprint = getLoggingFingerprint(mState,
-                isShowing,
-                isOccluded,
-                isBouncerShowing,
-                isSecure,
-                unlocked);
-        if (stateFingerprint != mLastLoggedStateFingerprint) {
-            if (mStatusBarStateLog == null) {
-                mStatusBarStateLog = new LogMaker(MetricsEvent.VIEW_UNKNOWN);
-            }
-            mMetricsLogger.write(mStatusBarStateLog
-                    .setCategory(isBouncerShowing ? MetricsEvent.BOUNCER : MetricsEvent.LOCKSCREEN)
-                    .setType(isShowing ? MetricsEvent.TYPE_OPEN : MetricsEvent.TYPE_CLOSE)
-                    .setSubtype(isSecure ? 1 : 0));
-            EventLogTags.writeSysuiStatusBarState(mState,
-                    isShowing ? 1 : 0,
-                    isOccluded ? 1 : 0,
-                    isBouncerShowing ? 1 : 0,
-                    isSecure ? 1 : 0,
-                    unlocked ? 1 : 0);
-            mLastLoggedStateFingerprint = stateFingerprint;
-
-            StringBuilder uiEventValueBuilder = new StringBuilder();
-            uiEventValueBuilder.append(isBouncerShowing ? "BOUNCER" : "LOCKSCREEN");
-            uiEventValueBuilder.append(isShowing ? "_OPEN" : "_CLOSE");
-            uiEventValueBuilder.append(isSecure ? "_SECURE" : "_INSECURE");
-            sUiEventLogger.log(StatusBarUiEvent.valueOf(uiEventValueBuilder.toString()));
-        }
-    }
-
-    /**
-     * Returns a fingerprint of fields logged to eventlog
-     */
-    private static int getLoggingFingerprint(int statusBarState, boolean keyguardShowing,
-            boolean keyguardOccluded, boolean bouncerShowing, boolean secure,
-            boolean currentlyInsecure) {
-        // Reserve 8 bits for statusBarState. We'll never go higher than
-        // that, right? Riiiight.
-        return (statusBarState & 0xFF)
-                | ((keyguardShowing   ? 1 : 0) <<  8)
-                | ((keyguardOccluded  ? 1 : 0) <<  9)
-                | ((bouncerShowing    ? 1 : 0) << 10)
-                | ((secure            ? 1 : 0) << 11)
-                | ((currentlyInsecure ? 1 : 0) << 12);
-    }
-
-    @Override
-    public void postQSRunnableDismissingKeyguard(final Runnable runnable) {
-        mMainExecutor.execute(() -> {
-            mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
-            executeRunnableDismissingKeyguard(
-                    () -> mMainExecutor.execute(runnable), null, false, false, false);
-        });
-    }
-
-    @Override
-    public void postStartActivityDismissingKeyguard(PendingIntent intent) {
-        postStartActivityDismissingKeyguard(intent, null /* animationController */);
-    }
-
-    @Override
-    public void postStartActivityDismissingKeyguard(final PendingIntent intent,
-            @Nullable ActivityLaunchAnimator.Controller animationController) {
-        mMainExecutor.execute(() -> startPendingIntentDismissingKeyguard(intent,
-                null /* intentSentUiThreadCallback */, animationController));
-    }
-
-    @Override
-    public void postStartActivityDismissingKeyguard(final Intent intent, int delay) {
-        postStartActivityDismissingKeyguard(intent, delay, null /* animationController */);
-    }
-
-    @Override
-    public void postStartActivityDismissingKeyguard(Intent intent, int delay,
-            @Nullable ActivityLaunchAnimator.Controller animationController) {
-        mMainExecutor.executeDelayed(
-                () ->
-                        startActivityDismissingKeyguard(intent, true /* onlyProvisioned */,
-                                true /* dismissShade */,
-                                false /* disallowEnterPictureInPictureWhileLaunching */,
-                                null /* callback */,
-                                0 /* flags */,
-                                animationController,
-                                getActivityUserHandle(intent)),
-                delay);
-    }
-
-    public void showKeyguard() {
-        mStatusBarStateController.setKeyguardRequested(true);
-        mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
-        updateIsKeyguard();
-        mAssistManagerLazy.get().onLockscreenShown();
-    }
-
-    public boolean hideKeyguard() {
-        mStatusBarStateController.setKeyguardRequested(false);
-        return updateIsKeyguard();
-    }
-
-    boolean updateIsKeyguard() {
-        return updateIsKeyguard(false /* forceStateChange */);
-    }
-
-    boolean updateIsKeyguard(boolean forceStateChange) {
-        boolean wakeAndUnlocking = mBiometricUnlockController.isWakeAndUnlock();
-
-        // For dozing, keyguard needs to be shown whenever the device is non-interactive. Otherwise
-        // there's no surface we can show to the user. Note that the device goes fully interactive
-        // late in the transition, so we also allow the device to start dozing once the screen has
-        // turned off fully.
-        boolean keyguardForDozing = mDozeServiceHost.getDozingRequested()
-                && (!mDeviceInteractive || (isGoingToSleep()
-                    && (isScreenFullyOff()
-                        || (mKeyguardStateController.isShowing() && !isOccluded()))));
-        boolean isWakingAndOccluded = isOccluded() && isWakingOrAwake();
-        boolean shouldBeKeyguard = (mStatusBarStateController.isKeyguardRequested()
-                || keyguardForDozing) && !wakeAndUnlocking && !isWakingAndOccluded;
-        if (keyguardForDozing) {
-            updatePanelExpansionForKeyguard();
-        }
-        if (shouldBeKeyguard) {
-            if (mScreenOffAnimationController.isKeyguardShowDelayed()
-                    || (isGoingToSleep()
-                    && mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_TURNING_OFF)) {
-                // Delay showing the keyguard until screen turned off.
-            } else {
-                showKeyguardImpl();
-            }
-        } else {
-            // During folding a foldable device this might be called as a result of
-            // 'onScreenTurnedOff' call for the inner display.
-            // In this case:
-            //  * When phone is locked on folding: it doesn't make sense to hide keyguard as it
-            //    will be immediately locked again
-            //  * When phone is unlocked: we still don't want to execute hiding of the keyguard
-            //    as the animation could prepare 'fake AOD' interface (without actually
-            //    transitioning to keyguard state) and this might reset the view states
-            if (!mScreenOffAnimationController.isKeyguardHideDelayed()) {
-                return hideKeyguardImpl(forceStateChange);
-            }
-        }
-        return false;
-    }
-
-    public void showKeyguardImpl() {
-        Trace.beginSection("CentralSurfaces#showKeyguard");
-        // In case we're locking while a smartspace transition is in progress, reset it.
-        mKeyguardUnlockAnimationController.resetSmartspaceTransition();
-        if (mKeyguardStateController.isLaunchTransitionFadingAway()) {
-            mNotificationPanelViewController.cancelAnimation();
-            onLaunchTransitionFadingEnded();
-        }
-        mMessageRouter.cancelMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
-        if (!mLockscreenShadeTransitionController.isWakingToShadeLocked()) {
-            mStatusBarStateController.setState(StatusBarState.KEYGUARD);
-        }
-        updatePanelExpansionForKeyguard();
-        Trace.endSection();
-    }
-
-    private void updatePanelExpansionForKeyguard() {
-        if (mState == StatusBarState.KEYGUARD && mBiometricUnlockController.getMode()
-                != BiometricUnlockController.MODE_WAKE_AND_UNLOCK && !mBouncerShowing) {
-            mShadeController.instantExpandNotificationsPanel();
-        }
-    }
-
-    private void onLaunchTransitionFadingEnded() {
-        mNotificationPanelViewController.resetAlpha();
-        mNotificationPanelViewController.onAffordanceLaunchEnded();
-        releaseGestureWakeLock();
-        runLaunchTransitionEndRunnable();
-        mKeyguardStateController.setLaunchTransitionFadingAway(false);
-        mPresenter.updateMediaMetaData(true /* metaDataChanged */, true);
-    }
-
-    public boolean isInLaunchTransition() {
-        return mNotificationPanelViewController.isLaunchTransitionRunning()
-                || mNotificationPanelViewController.isLaunchTransitionFinished();
-    }
-
-    /**
-     * Fades the content of the keyguard away after the launch transition is done.
-     *
-     * @param beforeFading the runnable to be run when the circle is fully expanded and the fading
-     *                     starts
-     * @param endRunnable the runnable to be run when the transition is done. Will not run
-     *                    if the transition is cancelled, instead cancelRunnable will run
-     * @param cancelRunnable the runnable to be run if the transition is cancelled
-     */
-    public void fadeKeyguardAfterLaunchTransition(final Runnable beforeFading,
-            Runnable endRunnable, Runnable cancelRunnable) {
-        mMessageRouter.cancelMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
-        mLaunchTransitionEndRunnable = endRunnable;
-        mLaunchTransitionCancelRunnable = cancelRunnable;
-        Runnable hideRunnable = () -> {
-            mKeyguardStateController.setLaunchTransitionFadingAway(true);
-            if (beforeFading != null) {
-                beforeFading.run();
-            }
-            updateScrimController();
-            mPresenter.updateMediaMetaData(false, true);
-            mNotificationPanelViewController.resetAlpha();
-            mNotificationPanelViewController.fadeOut(
-                    FADE_KEYGUARD_START_DELAY, FADE_KEYGUARD_DURATION,
-                    this::onLaunchTransitionFadingEnded);
-            mCommandQueue.appTransitionStarting(mDisplayId, SystemClock.uptimeMillis(),
-                    LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true);
-        };
-        if (mNotificationPanelViewController.isLaunchTransitionRunning()) {
-            mNotificationPanelViewController.setLaunchTransitionEndRunnable(hideRunnable);
-        } else {
-            hideRunnable.run();
-        }
-    }
-
-    private void cancelAfterLaunchTransitionRunnables() {
-        if (mLaunchTransitionCancelRunnable != null) {
-            mLaunchTransitionCancelRunnable.run();
-        }
-        mLaunchTransitionEndRunnable = null;
-        mLaunchTransitionCancelRunnable = null;
-        mNotificationPanelViewController.setLaunchTransitionEndRunnable(null);
-    }
-
-    /**
-     * Fades the content of the Keyguard while we are dozing and makes it invisible when finished
-     * fading.
-     */
-    public void fadeKeyguardWhilePulsing() {
-        mNotificationPanelViewController.fadeOut(0, FADE_KEYGUARD_DURATION_PULSING,
-                ()-> {
-                hideKeyguard();
-                mStatusBarKeyguardViewManager.onKeyguardFadedAway();
-            }).start();
-    }
-
-    /**
-     * Plays the animation when an activity that was occluding Keyguard goes away.
-     */
-    public void animateKeyguardUnoccluding() {
-        mNotificationPanelViewController.setExpandedFraction(0f);
-        mCommandQueueCallbacks.animateExpandNotificationsPanel();
-        mScrimController.setUnocclusionAnimationRunning(true);
-    }
-
-    /**
-     * Starts the timeout when we try to start the affordances on Keyguard. We usually rely that
-     * Keyguard goes away via fadeKeyguardAfterLaunchTransition, however, that might not happen
-     * because the launched app crashed or something else went wrong.
-     */
-    public void startLaunchTransitionTimeout() {
-        mMessageRouter.sendMessageDelayed(
-                MSG_LAUNCH_TRANSITION_TIMEOUT, LAUNCH_TRANSITION_TIMEOUT_MS);
-    }
-
-    private void onLaunchTransitionTimeout() {
-        Log.w(TAG, "Launch transition: Timeout!");
-        mNotificationPanelViewController.onAffordanceLaunchEnded();
-        releaseGestureWakeLock();
-        mNotificationPanelViewController.resetViews(false /* animate */);
-    }
-
-    private void runLaunchTransitionEndRunnable() {
-        mLaunchTransitionCancelRunnable = null;
-        if (mLaunchTransitionEndRunnable != null) {
-            Runnable r = mLaunchTransitionEndRunnable;
-
-            // mLaunchTransitionEndRunnable might call showKeyguard, which would execute it again,
-            // which would lead to infinite recursion. Protect against it.
-            mLaunchTransitionEndRunnable = null;
-            r.run();
-        }
-    }
-
-    /**
-     * @return true if we would like to stay in the shade, false if it should go away entirely
-     */
-    public boolean hideKeyguardImpl(boolean forceStateChange) {
-        Trace.beginSection("CentralSurfaces#hideKeyguard");
-        boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide();
-        int previousState = mStatusBarStateController.getState();
-        if (!(mStatusBarStateController.setState(StatusBarState.SHADE, forceStateChange))) {
-            //TODO: StatusBarStateController should probably know about hiding the keyguard and
-            // notify listeners.
-
-            // If the state didn't change, we may still need to update public mode
-            mLockscreenUserManager.updatePublicMode();
-        }
-        if (mStatusBarStateController.leaveOpenOnKeyguardHide()) {
-            if (!mStatusBarStateController.isKeyguardRequested()) {
-                mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
-            }
-            long delay = mKeyguardStateController.calculateGoingToFullShadeDelay();
-            mLockscreenShadeTransitionController.onHideKeyguard(delay, previousState);
-
-            // Disable layout transitions in navbar for this transition because the load is just
-            // too heavy for the CPU and GPU on any device.
-            mNavigationBarController.disableAnimationsDuringHide(mDisplayId, delay);
-        } else if (!mNotificationPanelViewController.isCollapsing()) {
-            instantCollapseNotificationPanel();
-        }
-
-        // Keyguard state has changed, but QS is not listening anymore. Make sure to update the tile
-        // visibilities so next time we open the panel we know the correct height already.
-        if (mQSPanelController != null) {
-            mQSPanelController.refreshAllTiles();
-        }
-        mMessageRouter.cancelMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
-        releaseGestureWakeLock();
-        mNotificationPanelViewController.onAffordanceLaunchEnded();
-        mNotificationPanelViewController.resetAlpha();
-        mNotificationPanelViewController.resetTranslation();
-        mNotificationPanelViewController.resetViewGroupFade();
-        updateDozingState();
-        updateScrimController();
-        Trace.endSection();
-        return staying;
-    }
-
-    private void releaseGestureWakeLock() {
-        if (mGestureWakeLock.isHeld()) {
-            mGestureWakeLock.release();
-        }
-    }
-
-    /**
-     * Notifies the status bar that Keyguard is going away very soon.
-     */
-    public void keyguardGoingAway() {
-        // Treat Keyguard exit animation as an app transition to achieve nice transition for status
-        // bar.
-        mKeyguardStateController.notifyKeyguardGoingAway(true);
-        mCommandQueue.appTransitionPending(mDisplayId, true /* forced */);
-        updateScrimController();
-    }
-
-    /**
-     * Notifies the status bar the Keyguard is fading away with the specified timings.
-     *  @param startTime the start time of the animations in uptime millis
-     * @param delay the precalculated animation delay in milliseconds
-     * @param fadeoutDuration the duration of the exit animation, in milliseconds
-     * @param isBypassFading is this a fading away animation while bypassing
-     */
-    public void setKeyguardFadingAway(long startTime, long delay, long fadeoutDuration,
-            boolean isBypassFading) {
-        mCommandQueue.appTransitionStarting(mDisplayId, startTime + fadeoutDuration
-                        - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION,
-                LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true);
-        mCommandQueue.recomputeDisableFlags(mDisplayId, fadeoutDuration > 0 /* animate */);
-        mCommandQueue.appTransitionStarting(mDisplayId,
-                    startTime - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION,
-                    LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true);
-        mKeyguardStateController.notifyKeyguardFadingAway(delay, fadeoutDuration, isBypassFading);
-    }
-
-    /**
-     * Notifies that the Keyguard fading away animation is done.
-     */
-    public void finishKeyguardFadingAway() {
-        mKeyguardStateController.notifyKeyguardDoneFading();
-        mScrimController.setExpansionAffectsAlpha(true);
-
-        // If the device was re-locked while unlocking, we might have a pending lock that was
-        // delayed because the keyguard was in the middle of going away.
-        mKeyguardViewMediator.maybeHandlePendingLock();
-    }
-
-    /**
-     * Switches theme from light to dark and vice-versa.
-     */
-    protected void updateTheme() {
-        // Set additional scrim only if the lock and system wallpaper are different to prevent
-        // applying the dimming effect twice.
-        mUiBgExecutor.execute(() -> {
-            float dimAmount = 0f;
-            if (mWallpaperManager.lockScreenWallpaperExists()) {
-                dimAmount = mWallpaperManager.getWallpaperDimAmount();
-            }
-            final float scrimDimAmount = dimAmount;
-            mMainExecutor.execute(() -> {
-                mScrimController.setAdditionalScrimBehindAlphaKeyguard(scrimDimAmount);
-                mScrimController.applyCompositeAlphaOnScrimBehindKeyguard();
-            });
-        });
-
-        // Lock wallpaper defines the color of the majority of the views, hence we'll use it
-        // to set our default theme.
-        final boolean lockDarkText = mColorExtractor.getNeutralColors().supportsDarkText();
-        final int themeResId = lockDarkText ? R.style.Theme_SystemUI_LightWallpaper
-                : R.style.Theme_SystemUI;
-        if (mContext.getThemeResId() != themeResId) {
-            mContext.setTheme(themeResId);
-            mConfigurationController.notifyThemeChanged();
-        }
-    }
-
-    private void updateDozingState() {
-        Trace.traceCounter(Trace.TRACE_TAG_APP, "dozing", mDozing ? 1 : 0);
-        Trace.beginSection("CentralSurfaces#updateDozingState");
-
-        boolean visibleNotOccluded = mStatusBarKeyguardViewManager.isShowing()
-                && !mStatusBarKeyguardViewManager.isOccluded();
-        // If we're dozing and we'll be animating the screen off, the keyguard isn't currently
-        // visible but will be shortly for the animation, so we should proceed as if it's visible.
-        boolean visibleNotOccludedOrWillBe =
-                visibleNotOccluded || (mDozing && mDozeParameters.shouldDelayKeyguardShow());
-
-        boolean wakeAndUnlock = mBiometricUnlockController.getMode()
-                == BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
-        boolean animate = (!mDozing && mDozeServiceHost.shouldAnimateWakeup() && !wakeAndUnlock)
-                || (mDozing && mDozeParameters.shouldControlScreenOff()
-                && visibleNotOccludedOrWillBe);
-
-        mNotificationPanelViewController.setDozing(mDozing, animate, mWakeUpTouchLocation);
-        updateQsExpansionEnabled();
-        Trace.endSection();
-    }
-
-    public void userActivity() {
-        if (mState == StatusBarState.KEYGUARD) {
-            mKeyguardViewMediatorCallback.userActivity();
-        }
-    }
-
-    public boolean interceptMediaKey(KeyEvent event) {
-        return mState == StatusBarState.KEYGUARD
-                && mStatusBarKeyguardViewManager.interceptMediaKey(event);
-    }
-
-    /**
-     * While IME is active and a BACK event is detected, check with
-     * {@link StatusBarKeyguardViewManager#dispatchBackKeyEventPreIme()} to see if the event
-     * should be handled before routing to IME, in order to prevent the user having to hit back
-     * twice to exit bouncer.
-     */
-    public boolean dispatchKeyEventPreIme(KeyEvent event) {
-        switch (event.getKeyCode()) {
-            case KeyEvent.KEYCODE_BACK:
-                if (mState == StatusBarState.KEYGUARD
-                        && mStatusBarKeyguardViewManager.dispatchBackKeyEventPreIme()) {
-                    return onBackPressed();
-                }
-        }
-        return false;
-    }
-
-    protected boolean shouldUnlockOnMenuPressed() {
-        return mDeviceInteractive && mState != StatusBarState.SHADE
-            && mStatusBarKeyguardViewManager.shouldDismissOnMenuPressed();
-    }
-
-    public boolean onMenuPressed() {
-        if (shouldUnlockOnMenuPressed()) {
-            mShadeController.animateCollapsePanels(
-                    CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL /* flags */, true /* force */);
-            return true;
-        }
-        return false;
-    }
-
-    public void endAffordanceLaunch() {
-        releaseGestureWakeLock();
-        mNotificationPanelViewController.onAffordanceLaunchEnded();
-    }
-
-    public boolean onBackPressed() {
-        final boolean isScrimmedBouncer =
-                mScrimController.getState() == ScrimState.BOUNCER_SCRIMMED;
-        final boolean isBouncerOverDream = isBouncerShowingOverDream();
-
-        if (mStatusBarKeyguardViewManager.onBackPressed(
-                isScrimmedBouncer || isBouncerOverDream /* hideImmediately */)) {
-            if (isScrimmedBouncer || isBouncerOverDream) {
-                mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
-            } else {
-                mNotificationPanelViewController.expandWithoutQs();
-            }
-            return true;
-        }
-        if (mNotificationPanelViewController.isQsCustomizing()) {
-            mNotificationPanelViewController.closeQsCustomizer();
-            return true;
-        }
-        if (mNotificationPanelViewController.isQsExpanded()) {
-            if (mNotificationPanelViewController.isQsDetailShowing()) {
-                mNotificationPanelViewController.closeQsDetail();
-            } else {
-                mNotificationPanelViewController.animateCloseQs(false /* animateAway */);
-            }
-            return true;
-        }
-        if (mNotificationPanelViewController.closeUserSwitcherIfOpen()) {
-            return true;
-        }
-        if (mState != StatusBarState.KEYGUARD && mState != StatusBarState.SHADE_LOCKED
-                && !isBouncerOverDream) {
-            if (mNotificationPanelViewController.canPanelBeCollapsed()) {
-                mShadeController.animateCollapsePanels();
-            }
-            return true;
-        }
-        return false;
-    }
-
-    public boolean onSpacePressed() {
-        if (mDeviceInteractive && mState != StatusBarState.SHADE) {
-            mShadeController.animateCollapsePanels(
-                    CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL /* flags */, true /* force */);
-            return true;
-        }
-        return false;
-    }
-
-    private void showBouncerOrLockScreenIfKeyguard() {
-        // If the keyguard is animating away, we aren't really the keyguard anymore and should not
-        // show the bouncer/lockscreen.
-        if (!mKeyguardViewMediator.isHiding()
-                && !mKeyguardUnlockAnimationController.isPlayingCannedUnlockAnimation()) {
-            if (mState == StatusBarState.SHADE_LOCKED
-                    && mKeyguardUpdateMonitor.isUdfpsEnrolled()) {
-                // shade is showing while locked on the keyguard, so go back to showing the
-                // lock screen where users can use the UDFPS affordance to enter the device
-                mStatusBarKeyguardViewManager.reset(true);
-            } else if ((mState == StatusBarState.KEYGUARD
-                    && !mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing())
-                    || mState == StatusBarState.SHADE_LOCKED) {
-                mStatusBarKeyguardViewManager.showGenericBouncer(true /* scrimmed */);
-            }
-        }
-    }
-
-    /**
-     * Show the bouncer if we're currently on the keyguard or shade locked and aren't hiding.
-     * @param performAction the action to perform when the bouncer is dismissed.
-     * @param cancelAction the action to perform when unlock is aborted.
-     */
-    public void showBouncerWithDimissAndCancelIfKeyguard(OnDismissAction performAction,
-            Runnable cancelAction) {
-        if ((mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)
-                && !mKeyguardViewMediator.isHiding()) {
-            mStatusBarKeyguardViewManager.dismissWithAction(performAction, cancelAction,
-                    false /* afterKeyguardGone */);
-        } else if (cancelAction != null) {
-            cancelAction.run();
-        }
-    }
-
-    void instantCollapseNotificationPanel() {
-        mNotificationPanelViewController.instantCollapse();
-        mShadeController.runPostCollapseRunnables();
-    }
-
-    /**
-     * Collapse the panel directly if we are on the main thread, post the collapsing on the main
-     * thread if we are not.
-     */
-    void collapsePanelOnMainThread() {
-        if (Looper.getMainLooper().isCurrentThread()) {
-            mShadeController.collapsePanel();
-        } else {
-            mContext.getMainExecutor().execute(mShadeController::collapsePanel);
-        }
-    }
-
-    /** Collapse the panel. The collapsing will be animated for the given {@code duration}. */
-    void collapsePanelWithDuration(int duration) {
-        mNotificationPanelViewController.collapseWithDuration(duration);
-    }
-
-    /**
-     * Updates the light reveal effect to reflect the reason we're waking or sleeping (for example,
-     * from the power button).
-     * @param wakingUp Whether we're updating because we're waking up (true) or going to sleep
-     *                 (false).
-     */
-    private void updateRevealEffect(boolean wakingUp) {
-        if (mLightRevealScrim == null) {
-            return;
-        }
-
-        final boolean wakingUpFromPowerButton = wakingUp
-                && !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)
-                && mWakefulnessLifecycle.getLastWakeReason()
-                == PowerManager.WAKE_REASON_POWER_BUTTON;
-        final boolean sleepingFromPowerButton = !wakingUp
-                && mWakefulnessLifecycle.getLastSleepReason()
-                == PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON;
-
-        if (wakingUpFromPowerButton || sleepingFromPowerButton) {
-            mLightRevealScrim.setRevealEffect(mPowerButtonReveal);
-            mLightRevealScrim.setRevealAmount(1f - mStatusBarStateController.getDozeAmount());
-        } else if (!wakingUp || !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)) {
-            // If we're going to sleep, but it's not from the power button, use the default reveal.
-            // If we're waking up, only use the default reveal if the biometric controller didn't
-            // already set it to the circular reveal because we're waking up from a fingerprint/face
-            // auth.
-            mLightRevealScrim.setRevealEffect(LiftReveal.INSTANCE);
-            mLightRevealScrim.setRevealAmount(1f - mStatusBarStateController.getDozeAmount());
-        }
-    }
-
-    public LightRevealScrim getLightRevealScrim() {
-        return mLightRevealScrim;
-    }
-
-    public void onTrackingStarted() {
-        mShadeController.runPostCollapseRunnables();
-    }
-
-    public void onClosingFinished() {
-        mShadeController.runPostCollapseRunnables();
-        if (!mPresenter.isPresenterFullyCollapsed()) {
-            // if we set it not to be focusable when collapsing, we have to undo it when we aborted
-            // the closing
-            mNotificationShadeWindowController.setNotificationShadeFocusable(true);
-        }
-    }
-
-    public void onUnlockHintStarted() {
-        mFalsingCollector.onUnlockHintStarted();
-        mKeyguardIndicationController.showActionToUnlock();
-    }
-
-    public void onHintFinished() {
-        // Delay the reset a bit so the user can read the text.
-        mKeyguardIndicationController.hideTransientIndicationDelayed(HINT_RESET_DELAY_MS);
-    }
-
-    public void onCameraHintStarted() {
-        mFalsingCollector.onCameraHintStarted();
-        mKeyguardIndicationController.showTransientIndication(R.string.camera_hint);
-    }
-
-    public void onVoiceAssistHintStarted() {
-        mFalsingCollector.onLeftAffordanceHintStarted();
-        mKeyguardIndicationController.showTransientIndication(R.string.voice_hint);
-    }
-
-    public void onPhoneHintStarted() {
-        mFalsingCollector.onLeftAffordanceHintStarted();
-        mKeyguardIndicationController.showTransientIndication(R.string.phone_hint);
-    }
-
-    public void onTrackingStopped(boolean expand) {
-        if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
-            if (!expand && !mKeyguardStateController.canDismissLockScreen()) {
-                mStatusBarKeyguardViewManager.showBouncer(false /* scrimmed */);
-            }
-        }
-    }
-
-    // TODO: Figure out way to remove these.
-    public NavigationBarView getNavigationBarView() {
-        return mNavigationBarController.getNavigationBarView(mDisplayId);
-    }
-
-    public boolean isOverviewEnabled() {
-        return mNavigationBarController.isOverviewEnabled(mDisplayId);
-    }
-
-    public void showPinningEnterExitToast(boolean entering) {
-        mNavigationBarController.showPinningEnterExitToast(mDisplayId, entering);
-    }
-
-    public void showPinningEscapeToast() {
-        mNavigationBarController.showPinningEscapeToast(mDisplayId);
-    }
-
-    /**
-     * TODO: Remove this method. Views should not be passed forward. Will cause theme issues.
-     * @return bottom area view
-     */
-    public KeyguardBottomAreaView getKeyguardBottomAreaView() {
-        return mNotificationPanelViewController.getKeyguardBottomAreaView();
-    }
-
-    /**
-     * Propagation of the bouncer state, indicating that it's fully visible.
-     */
-    public void setBouncerShowing(boolean bouncerShowing) {
-        mBouncerShowing = bouncerShowing;
-        mKeyguardBypassController.setBouncerShowing(bouncerShowing);
-        mPulseExpansionHandler.setBouncerShowing(bouncerShowing);
-        setBouncerShowingForStatusBarComponents(bouncerShowing);
-        mStatusBarHideIconsForBouncerManager.setBouncerShowingAndTriggerUpdate(bouncerShowing);
-        mCommandQueue.recomputeDisableFlags(mDisplayId, true /* animate */);
-        updateScrimController();
-        if (!mBouncerShowing) {
-            updatePanelExpansionForKeyguard();
-        }
-    }
-
-    /**
-     * Sets whether the bouncer over dream is showing. Note that the bouncer over dream is handled
-     * independently of the rest of the notification panel. As a result, setting this state via
-     * {@link #setBouncerShowing(boolean)} leads to unintended side effects from states modified
-     * behind the dream.
-     */
-    public void setBouncerShowingOverDream(boolean bouncerShowingOverDream) {
-        mBouncerShowingOverDream = bouncerShowingOverDream;
-    }
-
-    /**
-     * Propagate the bouncer state to status bar components.
-     *
-     * Separate from {@link #setBouncerShowing} because we sometimes re-create the status bar and
-     * should update only the status bar components.
-     */
-    private void setBouncerShowingForStatusBarComponents(boolean bouncerShowing) {
-        int importance = bouncerShowing
-                ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
-                : IMPORTANT_FOR_ACCESSIBILITY_AUTO;
-        if (mPhoneStatusBarViewController != null) {
-            mPhoneStatusBarViewController.setImportantForAccessibility(importance);
-        }
-        mNotificationPanelViewController.setImportantForAccessibility(importance);
-        mNotificationPanelViewController.setBouncerShowing(bouncerShowing);
-    }
-
-    /**
-     * Collapses the notification shade if it is tracking or expanded.
-     */
-    public void collapseShade() {
-        if (mNotificationPanelViewController.isTracking()) {
-            mNotificationShadeWindowViewController.cancelCurrentTouch();
-        }
-        if (mPanelExpanded && mState == StatusBarState.SHADE) {
-            mShadeController.animateCollapsePanels();
-        }
-    }
-
-    @VisibleForTesting
-    final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() {
-        @Override
-        public void onFinishedGoingToSleep() {
-            mNotificationPanelViewController.onAffordanceLaunchEnded();
-            releaseGestureWakeLock();
-            mLaunchCameraWhenFinishedWaking = false;
-            mDeviceInteractive = false;
-            mWakeUpComingFromTouch = false;
-            mWakeUpTouchLocation = null;
-            updateVisibleToUser();
-
-            updateNotificationPanelTouchState();
-            mNotificationShadeWindowViewController.cancelCurrentTouch();
-            if (mLaunchCameraOnFinishedGoingToSleep) {
-                mLaunchCameraOnFinishedGoingToSleep = false;
-
-                // This gets executed before we will show Keyguard, so post it in order that the state
-                // is correct.
-                mMainExecutor.execute(() -> mCommandQueueCallbacks.onCameraLaunchGestureDetected(
-                        mLastCameraLaunchSource));
-            }
-
-            if (mLaunchEmergencyActionOnFinishedGoingToSleep) {
-                mLaunchEmergencyActionOnFinishedGoingToSleep = false;
-
-                // This gets executed before we will show Keyguard, so post it in order that the
-                // state is correct.
-                mMainExecutor.execute(
-                        () -> mCommandQueueCallbacks.onEmergencyActionLaunchGestureDetected());
-            }
-            updateIsKeyguard();
-        }
-
-        @Override
-        public void onStartedGoingToSleep() {
-            String tag = "CentralSurfaces#onStartedGoingToSleep";
-            DejankUtils.startDetectingBlockingIpcs(tag);
-
-            //  cancel stale runnables that could put the device in the wrong state
-            cancelAfterLaunchTransitionRunnables();
-
-            updateRevealEffect(false /* wakingUp */);
-            updateNotificationPanelTouchState();
-            maybeEscalateHeadsUp();
-            dismissVolumeDialog();
-            mWakeUpCoordinator.setFullyAwake(false);
-            mKeyguardBypassController.onStartedGoingToSleep();
-
-            // The unlocked screen off and fold to aod animations might use our LightRevealScrim -
-            // we need to be expanded for it to be visible.
-            if (mDozeParameters.shouldShowLightRevealScrim()) {
-                makeExpandedVisible(true);
-            }
-
-            DejankUtils.stopDetectingBlockingIpcs(tag);
-        }
-
-        @Override
-        public void onStartedWakingUp() {
-            String tag = "CentralSurfaces#onStartedWakingUp";
-            DejankUtils.startDetectingBlockingIpcs(tag);
-            mNotificationShadeWindowController.batchApplyWindowLayoutParams(()-> {
-                mDeviceInteractive = true;
-                mWakeUpCoordinator.setWakingUp(true);
-                if (!mKeyguardBypassController.getBypassEnabled()) {
-                    mHeadsUpManager.releaseAllImmediately();
-                }
-                updateVisibleToUser();
-                updateIsKeyguard();
-                mDozeServiceHost.stopDozing();
-                // This is intentionally below the stopDozing call above, since it avoids that we're
-                // unnecessarily animating the wakeUp transition. Animations should only be enabled
-                // once we fully woke up.
-                updateRevealEffect(true /* wakingUp */);
-                updateNotificationPanelTouchState();
-
-                // If we are waking up during the screen off animation, we should undo making the
-                // expanded visible (we did that so the LightRevealScrim would be visible).
-                if (mScreenOffAnimationController.shouldHideLightRevealScrimOnWakeUp()) {
-                    makeExpandedInvisible();
-                }
-
-            });
-            DejankUtils.stopDetectingBlockingIpcs(tag);
-        }
-
-        @Override
-        public void onFinishedWakingUp() {
-            mWakeUpCoordinator.setFullyAwake(true);
-            mWakeUpCoordinator.setWakingUp(false);
-            if (mLaunchCameraWhenFinishedWaking) {
-                mNotificationPanelViewController.launchCamera(
-                        false /* animate */, mLastCameraLaunchSource);
-                mLaunchCameraWhenFinishedWaking = false;
-            }
-            if (mLaunchEmergencyActionWhenFinishedWaking) {
-                mLaunchEmergencyActionWhenFinishedWaking = false;
-                Intent emergencyIntent = getEmergencyActionIntent();
-                if (emergencyIntent != null) {
-                    mContext.startActivityAsUser(emergencyIntent,
-                            getActivityUserHandle(emergencyIntent));
-                }
-            }
-            updateScrimController();
-        }
-    };
-
-    /**
-     * We need to disable touch events because these might
-     * collapse the panel after we expanded it, and thus we would end up with a blank
-     * Keyguard.
-     */
-    void updateNotificationPanelTouchState() {
-        boolean goingToSleepWithoutAnimation = isGoingToSleep()
-                && !mDozeParameters.shouldControlScreenOff();
-        boolean disabled = (!mDeviceInteractive && !mDozeServiceHost.isPulsing())
-                || goingToSleepWithoutAnimation;
-        mNotificationPanelViewController.setTouchAndAnimationDisabled(disabled);
-        mNotificationIconAreaController.setAnimationsEnabled(!disabled);
-    }
-
-    final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() {
-        @Override
-        public void onScreenTurningOn(Runnable onDrawn) {
-            mFalsingCollector.onScreenTurningOn();
-            mNotificationPanelViewController.onScreenTurningOn();
-        }
-
-        @Override
-        public void onScreenTurnedOn() {
-            mScrimController.onScreenTurnedOn();
-        }
-
-        @Override
-        public void onScreenTurnedOff() {
-            Trace.beginSection("CentralSurfaces#onScreenTurnedOff");
-            mFalsingCollector.onScreenOff();
-            mScrimController.onScreenTurnedOff();
-            if (mCloseQsBeforeScreenOff) {
-                mNotificationPanelViewController.closeQs();
-                mCloseQsBeforeScreenOff = false;
-            }
-            updateIsKeyguard();
-            Trace.endSection();
-        }
-    };
-
-    public int getWakefulnessState() {
-        return mWakefulnessLifecycle.getWakefulness();
-    }
-
-    /**
-     * @return true if the screen is currently fully off, i.e. has finished turning off and has
-     * since not started turning on.
-     */
-    public boolean isScreenFullyOff() {
-        return mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_OFF;
-    }
-
-    public void showScreenPinningRequest(int taskId, boolean allowCancel) {
-        mScreenPinningRequest.showPrompt(taskId, allowCancel);
-    }
-
-    @Nullable Intent getEmergencyActionIntent() {
-        Intent emergencyIntent = new Intent(EmergencyGesture.ACTION_LAUNCH_EMERGENCY);
-        PackageManager pm = mContext.getPackageManager();
-        List<ResolveInfo> emergencyActivities = pm.queryIntentActivities(emergencyIntent,
-                PackageManager.MATCH_SYSTEM_ONLY);
-        ResolveInfo resolveInfo = getTopEmergencySosInfo(emergencyActivities);
-        if (resolveInfo == null) {
-            Log.wtf(TAG, "Couldn't find an app to process the emergency intent.");
-            return null;
-        }
-        emergencyIntent.setComponent(new ComponentName(resolveInfo.activityInfo.packageName,
-                resolveInfo.activityInfo.name));
-        emergencyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-        return emergencyIntent;
-    }
-
-    /**
-     * Select and return the "best" ResolveInfo for Emergency SOS Activity.
-     */
-    private @Nullable ResolveInfo getTopEmergencySosInfo(List<ResolveInfo> emergencyActivities) {
-        // No matched activity.
-        if (emergencyActivities == null || emergencyActivities.isEmpty()) {
-            return null;
-        }
-
-        // Of multiple matched Activities, give preference to the pre-set package name.
-        String preferredAppPackageName =
-                mContext.getString(R.string.config_preferredEmergencySosPackage);
-
-        // If there is no preferred app, then return first match.
-        if (TextUtils.isEmpty(preferredAppPackageName)) {
-            return emergencyActivities.get(0);
-        }
-
-        for (ResolveInfo emergencyInfo: emergencyActivities) {
-            // If activity is from the preferred app, use it.
-            if (TextUtils.equals(emergencyInfo.activityInfo.packageName, preferredAppPackageName)) {
-                return emergencyInfo;
-            }
-        }
-        // No matching activity: return first match
-        return emergencyActivities.get(0);
-    }
-
-    boolean isCameraAllowedByAdmin() {
-        if (mDevicePolicyManager.getCameraDisabled(null,
-                mLockscreenUserManager.getCurrentUserId())) {
-            return false;
-        } else if (mStatusBarKeyguardViewManager == null
-                || (isKeyguardShowing() && isKeyguardSecure())) {
-            // Check if the admin has disabled the camera specifically for the keyguard
-            return (mDevicePolicyManager.getKeyguardDisabledFeatures(null,
-                    mLockscreenUserManager.getCurrentUserId())
-                    & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) == 0;
-        }
-        return true;
-    }
-
-    boolean isGoingToSleep() {
-        return mWakefulnessLifecycle.getWakefulness()
-                == WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP;
-    }
-
-    boolean isWakingOrAwake() {
-        return mWakefulnessLifecycle.getWakefulness() == WakefulnessLifecycle.WAKEFULNESS_WAKING
-                || mWakefulnessLifecycle.getWakefulness() == WakefulnessLifecycle.WAKEFULNESS_AWAKE;
-    }
-
-    public void notifyBiometricAuthModeChanged() {
-        mDozeServiceHost.updateDozing();
-        updateScrimController();
-    }
-
-    /**
-     * Set the amount of progress we are currently in if we're transitioning to the full shade.
-     * 0.0f means we're not transitioning yet, while 1 means we're all the way in the full
-     * shade.
-     */
-    public void setTransitionToFullShadeProgress(float transitionToFullShadeProgress) {
-        mTransitionToFullShadeProgress = transitionToFullShadeProgress;
-    }
-
-    /**
-     * Sets the amount of progress to the bouncer being fully hidden/visible. 1 means the bouncer
-     * is fully hidden, while 0 means the bouncer is visible.
-     */
-    public void setBouncerHiddenFraction(float expansion) {
-        mScrimController.setBouncerHiddenFraction(expansion);
-    }
-
-    @VisibleForTesting
-    public void updateScrimController() {
-        Trace.beginSection("CentralSurfaces#updateScrimController");
-
-        boolean unlocking = mKeyguardStateController.isShowing() && (
-                mBiometricUnlockController.isWakeAndUnlock()
-                        || mKeyguardStateController.isKeyguardFadingAway()
-                        || mKeyguardStateController.isKeyguardGoingAway()
-                        || mKeyguardViewMediator.requestedShowSurfaceBehindKeyguard()
-                        || mKeyguardViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehind());
-
-        mScrimController.setExpansionAffectsAlpha(!unlocking);
-
-        boolean launchingAffordanceWithPreview =
-                mNotificationPanelViewController.isLaunchingAffordanceWithPreview();
-        mScrimController.setLaunchingAffordanceWithPreview(launchingAffordanceWithPreview);
-
-        if (mStatusBarKeyguardViewManager.isShowingAlternateAuth()) {
-            if (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED
-                    || mTransitionToFullShadeProgress > 0f) {
-                mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED_SHADE);
-            } else {
-                mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED);
-            }
-        } else if (mBouncerShowing && !unlocking) {
-            // Bouncer needs the front scrim when it's on top of an activity,
-            // tapping on a notification, editing QS or being dismissed by
-            // FLAG_DISMISS_KEYGUARD_ACTIVITY.
-            ScrimState state = mStatusBarKeyguardViewManager.bouncerNeedsScrimming()
-                    ? ScrimState.BOUNCER_SCRIMMED : ScrimState.BOUNCER;
-            mScrimController.transitionTo(state);
-        } else if (launchingAffordanceWithPreview) {
-            // We want to avoid animating when launching with a preview.
-            mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
-        } else if (mBrightnessMirrorVisible) {
-            mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
-        } else if (mState == StatusBarState.SHADE_LOCKED) {
-            mScrimController.transitionTo(ScrimState.SHADE_LOCKED);
-        } else if (mDozeServiceHost.isPulsing()) {
-            mScrimController.transitionTo(ScrimState.PULSING,
-                    mDozeScrimController.getScrimCallback());
-        } else if (mDozeServiceHost.hasPendingScreenOffCallback()) {
-            mScrimController.transitionTo(ScrimState.OFF, new ScrimController.Callback() {
-                @Override
-                public void onFinished() {
-                    mDozeServiceHost.executePendingScreenOffCallback();
-                }
-            });
-        } else if (mDozing && !unlocking) {
-            mScrimController.transitionTo(ScrimState.AOD);
-        } else if (mKeyguardStateController.isShowing() && !isOccluded() && !unlocking) {
-            mScrimController.transitionTo(ScrimState.KEYGUARD);
-        } else if (mKeyguardStateController.isShowing() && mKeyguardUpdateMonitor.isDreaming()) {
-            mScrimController.transitionTo(ScrimState.DREAMING);
-        } else {
-            mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
-        }
-        updateLightRevealScrimVisibility();
-
-        Trace.endSection();
-    }
-
-    public boolean isKeyguardShowing() {
-        if (mStatusBarKeyguardViewManager == null) {
-            Slog.i(TAG, "isKeyguardShowing() called before startKeyguard(), returning true");
-            return true;
-        }
-        return mStatusBarKeyguardViewManager.isShowing();
-    }
-
-    public boolean shouldIgnoreTouch() {
-        return (mStatusBarStateController.isDozing()
-                && mDozeServiceHost.getIgnoreTouchWhilePulsing())
-                || mScreenOffAnimationController.shouldIgnoreKeyguardTouches();
-    }
-
-    // Begin Extra BaseStatusBar methods.
-
-    protected final CommandQueue mCommandQueue;
-    protected IStatusBarService mBarService;
-
-    // all notifications
-    protected NotificationStackScrollLayout mStackScroller;
-
-    // handling reordering
-    private final VisualStabilityManager mVisualStabilityManager;
-
-    protected AccessibilityManager mAccessibilityManager;
-
-    protected boolean mDeviceInteractive;
-
-    protected boolean mVisible;
-
-    // mScreenOnFromKeyguard && mVisible.
-    private boolean mVisibleToUser;
-
-    protected DevicePolicyManager mDevicePolicyManager;
-    private final PowerManager mPowerManager;
-    protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
-
-    protected KeyguardManager mKeyguardManager;
-    private final DeviceProvisionedController mDeviceProvisionedController;
-
-    private final NavigationBarController mNavigationBarController;
-    private final AccessibilityFloatingMenuController mAccessibilityFloatingMenuController;
-
-    // UI-specific methods
-
-    protected WindowManager mWindowManager;
-    protected IWindowManager mWindowManagerService;
-    private IDreamManager mDreamManager;
-
-    protected Display mDisplay;
-    private int mDisplayId;
-
-    protected NotificationShelfController mNotificationShelfController;
-
-    private final Lazy<AssistManager> mAssistManagerLazy;
-
-    public boolean isDeviceInteractive() {
-        return mDeviceInteractive;
-    }
-
-    private final BroadcastReceiver mBannerActionBroadcastReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            String action = intent.getAction();
-            if (BANNER_ACTION_CANCEL.equals(action) || BANNER_ACTION_SETUP.equals(action)) {
-                NotificationManager noMan = (NotificationManager)
-                        mContext.getSystemService(Context.NOTIFICATION_SERVICE);
-                noMan.cancel(com.android.internal.messages.nano.SystemMessageProto.SystemMessage.
-                        NOTE_HIDDEN_NOTIFICATIONS);
-
-                Settings.Secure.putInt(mContext.getContentResolver(),
-                        Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 0);
-                if (BANNER_ACTION_SETUP.equals(action)) {
-                    mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
-                            true /* force */);
-                    mContext.startActivity(new Intent(Settings.ACTION_APP_NOTIFICATION_REDACTION)
-                            .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
-
-                    );
-                }
-            }
-        }
-    };
-
-    public void setNotificationSnoozed(StatusBarNotification sbn, SnoozeOption snoozeOption) {
-        mNotificationsController.setNotificationSnoozed(sbn, snoozeOption);
-    }
-
-
-    public void awakenDreams() {
-        mUiBgExecutor.execute(() -> {
-            try {
-                mDreamManager.awaken();
-            } catch (RemoteException e) {
-                e.printStackTrace();
-            }
-        });
-    }
-
-    protected void toggleKeyboardShortcuts(int deviceId) {
-        KeyboardShortcuts.toggle(mContext, deviceId);
-    }
-
-    protected void dismissKeyboardShortcuts() {
-        KeyboardShortcuts.dismiss();
-    }
-
-    /**
-     * Dismiss the keyguard then execute an action.
-     *
-     * @param action The action to execute after dismissing the keyguard.
-     * @param collapsePanel Whether we should collapse the panel after dismissing the keyguard.
-     * @param willAnimateOnKeyguard Whether {@param action} will run an animation on the keyguard if
-     *                              we are locked.
-     */
-    private void executeActionDismissingKeyguard(Runnable action, boolean afterKeyguardGone,
-            boolean collapsePanel, boolean willAnimateOnKeyguard) {
-        if (!mDeviceProvisionedController.isDeviceProvisioned()) return;
-
-        OnDismissAction onDismissAction = new OnDismissAction() {
-            @Override
-            public boolean onDismiss() {
-                new Thread(() -> {
-                    try {
-                        // The intent we are sending is for the application, which
-                        // won't have permission to immediately start an activity after
-                        // the user switches to home.  We know it is safe to do at this
-                        // point, so make sure new activity switches are now allowed.
-                        ActivityManager.getService().resumeAppSwitches();
-                    } catch (RemoteException e) {
-                    }
-                    action.run();
-                }).start();
-
-                return collapsePanel ? mShadeController.collapsePanel() : willAnimateOnKeyguard;
-            }
-
-            @Override
-            public boolean willRunAnimationOnKeyguard() {
-                return willAnimateOnKeyguard;
-            }
-        };
-        dismissKeyguardThenExecute(onDismissAction, afterKeyguardGone);
-    }
-
-    @Override
-    public void startPendingIntentDismissingKeyguard(final PendingIntent intent) {
-        startPendingIntentDismissingKeyguard(intent, null);
-    }
-
-    @Override
-    public void startPendingIntentDismissingKeyguard(
-            final PendingIntent intent, @Nullable final Runnable intentSentUiThreadCallback) {
-        startPendingIntentDismissingKeyguard(intent, intentSentUiThreadCallback,
-                (ActivityLaunchAnimator.Controller) null);
-    }
-
-    @Override
-    public void startPendingIntentDismissingKeyguard(PendingIntent intent,
-            Runnable intentSentUiThreadCallback, View associatedView) {
-        ActivityLaunchAnimator.Controller animationController = null;
-        if (associatedView instanceof ExpandableNotificationRow) {
-            animationController = mNotificationAnimationProvider.getAnimatorController(
-                    ((ExpandableNotificationRow) associatedView));
-        }
-
-        startPendingIntentDismissingKeyguard(intent, intentSentUiThreadCallback,
-                animationController);
-    }
-
-    @Override
-    public void startPendingIntentDismissingKeyguard(
-            final PendingIntent intent, @Nullable final Runnable intentSentUiThreadCallback,
-            @Nullable ActivityLaunchAnimator.Controller animationController) {
-        final boolean willLaunchResolverActivity = intent.isActivity()
-                && mActivityIntentHelper.wouldLaunchResolverActivity(intent.getIntent(),
-                mLockscreenUserManager.getCurrentUserId());
-
-        boolean animate = !willLaunchResolverActivity
-                && animationController != null
-                && shouldAnimateLaunch(intent.isActivity());
-
-        // If we animate, don't collapse the shade and defer the keyguard dismiss (in case we run
-        // the animation on the keyguard). The animation will take care of (instantly) collapsing
-        // the shade and hiding the keyguard once it is done.
-        boolean collapse = !animate;
-        executeActionDismissingKeyguard(() -> {
-            try {
-                // We wrap animationCallback with a StatusBarLaunchAnimatorController so that the
-                // shade is collapsed after the animation (or when it is cancelled, aborted, etc).
-                ActivityLaunchAnimator.Controller controller =
-                        animationController != null ? new StatusBarLaunchAnimatorController(
-                                animationController, this, intent.isActivity()) : null;
-
-                mActivityLaunchAnimator.startPendingIntentWithAnimation(
-                        controller, animate, intent.getCreatorPackage(),
-                        (animationAdapter) -> {
-                            ActivityOptions options = new ActivityOptions(
-                                    getActivityOptions(mDisplayId, animationAdapter));
-                            // TODO b/221255671: restrict this to only be set for notifications
-                            options.setEligibleForLegacyPermissionPrompt(true);
-                            return intent.sendAndReturnResult(null, 0, null, null, null,
-                                    null, options.toBundle());
-                        });
-            } catch (PendingIntent.CanceledException e) {
-                // the stack trace isn't very helpful here.
-                // Just log the exception message.
-                Log.w(TAG, "Sending intent failed: " + e);
-                if (!collapse) {
-                    // executeActionDismissingKeyguard did not collapse for us already.
-                    collapsePanelOnMainThread();
-                }
-                // TODO: Dismiss Keyguard.
-            }
-            if (intent.isActivity()) {
-                mAssistManagerLazy.get().hideAssist();
-            }
-            if (intentSentUiThreadCallback != null) {
-                postOnUiThread(intentSentUiThreadCallback);
-            }
-        }, willLaunchResolverActivity, collapse, animate);
-    }
-
-    private void postOnUiThread(Runnable runnable) {
-        mMainExecutor.execute(runnable);
-    }
-
     /**
      * Returns an ActivityOptions bundle created using the given parameters.
      *
-     * @param displayId The ID of the display to launch the activity in. Typically this would be the
-     *                  display the status bar is on.
+     * @param displayId The ID of the display to launch the activity in. Typically this would
+     *                  be the display the status bar is on.
      * @param animationAdapter The animation adapter used to start this activity, or {@code null}
      *                         for the default animation.
      */
-    public static Bundle getActivityOptions(int displayId,
+    static Bundle getActivityOptions(int displayId,
             @Nullable RemoteAnimationAdapter animationAdapter) {
         ActivityOptions options = getDefaultActivityOptions(animationAdapter);
         options.setLaunchDisplayId(displayId);
@@ -4084,15 +125,16 @@
     /**
      * Returns an ActivityOptions bundle created using the given parameters.
      *
-     * @param displayId The ID of the display to launch the activity in. Typically this would be the
-     *                  display the status bar is on.
-     * @param animationAdapter The animation adapter used to start this activity, or {@code null}
-     *                         for the default animation.
+     * @param displayId         The ID of the display to launch the activity in. Typically this
+     *                          would be the
+     *                          display the status bar is on.
+     * @param animationAdapter  The animation adapter used to start this activity, or {@code null}
+     *                          for the default animation.
      * @param isKeyguardShowing Whether keyguard is currently showing.
-     * @param eventTime The event time in milliseconds since boot, not including sleep. See
-     *                  {@link ActivityOptions#setSourceInfo}.
+     * @param eventTime         The event time in milliseconds since boot, not including sleep. See
+     *                          {@link ActivityOptions#setSourceInfo}.
      */
-    public static Bundle getActivityOptions(int displayId,
+    static Bundle getActivityOptions(int displayId,
             @Nullable RemoteAnimationAdapter animationAdapter, boolean isKeyguardShowing,
             long eventTime) {
         ActivityOptions options = getDefaultActivityOptions(animationAdapter);
@@ -4103,7 +145,7 @@
         return options.toBundle();
     }
 
-    public static ActivityOptions getDefaultActivityOptions(
+    static ActivityOptions getDefaultActivityOptions(
             @Nullable RemoteAnimationAdapter animationAdapter) {
         ActivityOptions options;
         if (animationAdapter != null) {
@@ -4120,68 +162,11 @@
         return options;
     }
 
-    void visibilityChanged(boolean visible) {
-        if (mVisible != visible) {
-            mVisible = visible;
-            if (!visible) {
-                mGutsManager.closeAndSaveGuts(true /* removeLeavebehind */, true /* force */,
-                        true /* removeControls */, -1 /* x */, -1 /* y */, true /* resetMenu */);
-            }
-        }
-        updateVisibleToUser();
-    }
-
-    protected void updateVisibleToUser() {
-        boolean oldVisibleToUser = mVisibleToUser;
-        mVisibleToUser = mVisible && mDeviceInteractive;
-
-        if (oldVisibleToUser != mVisibleToUser) {
-            handleVisibleToUserChanged(mVisibleToUser);
-        }
-    }
-
     /**
-     * Clear Buzz/Beep/Blink.
+     * @return a PackageManager for userId or if userId is < 0 (USER_ALL etc) then
+     * return PackageManager for mContext
      */
-    public void clearNotificationEffects() {
-        try {
-            mBarService.clearNotificationEffects();
-        } catch (RemoteException e) {
-            // Won't fail unless the world has ended.
-        }
-    }
-
-    /**
-     * @return Whether the security bouncer from Keyguard is showing.
-     */
-    public boolean isBouncerShowing() {
-        return mBouncerShowing;
-    }
-
-    /**
-     * @return Whether the security bouncer from Keyguard is showing.
-     */
-    public boolean isBouncerShowingScrimmed() {
-        return isBouncerShowing() && mStatusBarKeyguardViewManager.bouncerNeedsScrimming();
-    }
-
-    public boolean isBouncerShowingOverDream() {
-        return mBouncerShowingOverDream;
-    }
-
-    /**
-     * When {@link KeyguardBouncer} starts to be dismissed, playing its animation.
-     */
-    public void onBouncerPreHideAnimation() {
-        mNotificationPanelViewController.onBouncerPreHideAnimation();
-
-    }
-
-    /**
-     * @return a PackageManger for userId or if userId is < 0 (USER_ALL etc) then
-     *         return PackageManager for mContext
-     */
-    public static PackageManager getPackageManagerForUser(Context context, int userId) {
+    static PackageManager getPackageManagerForUser(Context context, int userId) {
         Context contextForUser = context;
         // UserHandle defines special userId as negative values, e.g. USER_ALL
         if (userId >= 0) {
@@ -4190,350 +175,413 @@
                 // for user 0 we can still load information about the package.
                 contextForUser =
                         context.createPackageContextAsUser(context.getPackageName(),
-                        Context.CONTEXT_RESTRICTED,
-                        new UserHandle(userId));
-            } catch (NameNotFoundException e) {
+                                Context.CONTEXT_RESTRICTED,
+                                new UserHandle(userId));
+            } catch (PackageManager.NameNotFoundException e) {
                 // Shouldn't fail to find the package name for system ui.
             }
         }
         return contextForUser.getPackageManager();
     }
 
-    public boolean isKeyguardSecure() {
-        if (mStatusBarKeyguardViewManager == null) {
-            // startKeyguard() hasn't been called yet, so we don't know.
-            // Make sure anything that needs to know isKeyguardSecure() checks and re-checks this
-            // value onVisibilityChanged().
-            Slog.w(TAG, "isKeyguardSecure() called before startKeyguard(), returning false",
-                    new Throwable());
-            return false;
+    void animateExpandNotificationsPanel();
+
+    void animateExpandSettingsPanel(@Nullable String subpanel);
+
+    void animateCollapsePanels(int flags, boolean force);
+
+    void collapsePanelOnMainThread();
+
+    void collapsePanelWithDuration(int duration);
+
+    void togglePanel();
+
+    void start();
+
+    boolean updateIsKeyguard();
+
+    boolean updateIsKeyguard(boolean forceStateChange);
+
+    @NonNull
+    @Override
+    Lifecycle getLifecycle();
+
+    void wakeUpIfDozing(long time, View where, String why);
+
+    NotificationShadeWindowView getNotificationShadeWindowView();
+
+    NotificationShadeWindowViewController getNotificationShadeWindowViewController();
+
+    NotificationPanelViewController getNotificationPanelViewController();
+
+    ViewGroup getBouncerContainer();
+
+    int getStatusBarHeight();
+
+    void updateQsExpansionEnabled();
+
+    boolean isShadeDisabled();
+
+    void requestNotificationUpdate(String reason);
+
+    void requestFaceAuth(boolean userInitiatedRequest);
+
+    @Override
+    void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade,
+            int flags);
+
+    @Override
+    void startActivity(Intent intent, boolean dismissShade);
+
+    @Override
+    void startActivity(Intent intent, boolean dismissShade,
+            @Nullable ActivityLaunchAnimator.Controller animationController,
+            boolean showOverLockscreenWhenLocked);
+
+    @Override
+    void startActivity(Intent intent, boolean dismissShade,
+            @Nullable ActivityLaunchAnimator.Controller animationController,
+            boolean showOverLockscreenWhenLocked, UserHandle userHandle);
+
+    boolean isLaunchingActivityOverLockscreen();
+
+    @Override
+    void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade);
+
+    @Override
+    void startActivity(Intent intent, boolean dismissShade, Callback callback);
+
+    void setQsExpanded(boolean expanded);
+
+    boolean isWakeUpComingFromTouch();
+
+    boolean isFalsingThresholdNeeded();
+
+    void onKeyguardViewManagerStatesUpdated();
+
+    void setPanelExpanded(boolean isExpanded);
+
+    ViewGroup getNotificationScrollLayout();
+
+    boolean isPulsing();
+
+    @Nullable
+    View getAmbientIndicationContainer();
+
+    boolean isOccluded();
+
+    //TODO: These can / should probably be moved to NotificationPresenter or ShadeController
+    void onLaunchAnimationCancelled(boolean isLaunchForActivity);
+
+    void onLaunchAnimationEnd(boolean launchIsFullScreen);
+
+    boolean shouldAnimateLaunch(boolean isActivityIntent, boolean showOverLockscreen);
+
+    boolean shouldAnimateLaunch(boolean isActivityIntent);
+
+    boolean isDeviceInVrMode();
+
+    NotificationPresenter getPresenter();
+
+    void postAnimateCollapsePanels();
+
+    void postAnimateForceCollapsePanels();
+
+    void postAnimateOpenPanels();
+
+    boolean isExpandedVisible();
+
+    boolean isPanelExpanded();
+
+    void onInputFocusTransfer(boolean start, boolean cancel, float velocity);
+
+    void animateCollapseQuickSettings();
+
+    void onTouchEvent(MotionEvent event);
+
+    GestureRecorder getGestureRecorder();
+
+    BiometricUnlockController getBiometricUnlockController();
+
+    void showWirelessChargingAnimation(int batteryLevel);
+
+    void checkBarModes();
+
+    // Called by NavigationBarFragment
+    void setQsScrimEnabled(boolean scrimEnabled);
+
+    void updateBubblesVisibility();
+
+    void setInteracting(int barWindow, boolean interacting);
+
+    @Override
+    void dump(PrintWriter pwOriginal, String[] args);
+
+    void createAndAddWindows(@Nullable RegisterStatusBarResult result);
+
+    float getDisplayWidth();
+
+    float getDisplayHeight();
+
+    void startActivityDismissingKeyguard(Intent intent, boolean onlyProvisioned,
+            boolean dismissShade, int flags);
+
+    void startActivityDismissingKeyguard(Intent intent, boolean onlyProvisioned,
+            boolean dismissShade);
+
+    void startActivityDismissingKeyguard(Intent intent, boolean onlyProvisioned,
+            boolean dismissShade, boolean disallowEnterPictureInPictureWhileLaunching,
+            Callback callback, int flags,
+            @Nullable ActivityLaunchAnimator.Controller animationController,
+            UserHandle userHandle);
+
+    void readyForKeyguardDone();
+
+    void executeRunnableDismissingKeyguard(Runnable runnable,
+            Runnable cancelAction,
+            boolean dismissShade,
+            boolean afterKeyguardGone,
+            boolean deferred);
+
+    void executeRunnableDismissingKeyguard(Runnable runnable,
+            Runnable cancelAction,
+            boolean dismissShade,
+            boolean afterKeyguardGone,
+            boolean deferred,
+            boolean willAnimateOnKeyguard);
+
+    void resetUserExpandedStates();
+
+    @Override
+    void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction,
+            boolean afterKeyguardGone);
+
+    void setLockscreenUser(int newUserId);
+
+    @Override
+    void postQSRunnableDismissingKeyguard(Runnable runnable);
+
+    @Override
+    void postStartActivityDismissingKeyguard(PendingIntent intent);
+
+    @Override
+    void postStartActivityDismissingKeyguard(PendingIntent intent,
+            @Nullable ActivityLaunchAnimator.Controller animationController);
+
+    @Override
+    void postStartActivityDismissingKeyguard(Intent intent, int delay);
+
+    @Override
+    void postStartActivityDismissingKeyguard(Intent intent, int delay,
+            @Nullable ActivityLaunchAnimator.Controller animationController);
+
+    void showKeyguard();
+
+    boolean hideKeyguard();
+
+    void showKeyguardImpl();
+
+    boolean isInLaunchTransition();
+
+    void fadeKeyguardAfterLaunchTransition(Runnable beforeFading,
+            Runnable endRunnable, Runnable cancelRunnable);
+
+    void fadeKeyguardWhilePulsing();
+
+    void animateKeyguardUnoccluding();
+
+    void startLaunchTransitionTimeout();
+
+    boolean hideKeyguardImpl(boolean forceStateChange);
+
+    void keyguardGoingAway();
+
+    void setKeyguardFadingAway(long startTime, long delay, long fadeoutDuration,
+            boolean isBypassFading);
+
+    void finishKeyguardFadingAway();
+
+    void userActivity();
+
+    boolean interceptMediaKey(KeyEvent event);
+
+    boolean dispatchKeyEventPreIme(KeyEvent event);
+
+    boolean onMenuPressed();
+
+    void endAffordanceLaunch();
+
+    boolean onBackPressed();
+
+    boolean onSpacePressed();
+
+    void showBouncerWithDimissAndCancelIfKeyguard(OnDismissAction performAction,
+            Runnable cancelAction);
+
+    LightRevealScrim getLightRevealScrim();
+
+    void onTrackingStarted();
+
+    void onClosingFinished();
+
+    void onUnlockHintStarted();
+
+    void onHintFinished();
+
+    void onCameraHintStarted();
+
+    void onVoiceAssistHintStarted();
+
+    void onPhoneHintStarted();
+
+    void onTrackingStopped(boolean expand);
+
+    // TODO: Figure out way to remove these.
+    NavigationBarView getNavigationBarView();
+
+    boolean isOverviewEnabled();
+
+    void showPinningEnterExitToast(boolean entering);
+
+    void showPinningEscapeToast();
+
+    KeyguardBottomAreaView getKeyguardBottomAreaView();
+
+    void setBouncerShowing(boolean bouncerShowing);
+
+  void setBouncerShowingOverDream(boolean bouncerShowingOverDream);
+
+    void collapseShade();
+
+    int getWakefulnessState();
+
+    boolean isScreenFullyOff();
+
+    void showScreenPinningRequest(int taskId, boolean allowCancel);
+
+    @Nullable
+    Intent getEmergencyActionIntent();
+
+    boolean isCameraAllowedByAdmin();
+
+    boolean isGoingToSleep();
+
+    void notifyBiometricAuthModeChanged();
+
+    void setTransitionToFullShadeProgress(float transitionToFullShadeProgress);
+
+    void setBouncerHiddenFraction(float expansion);
+
+    @VisibleForTesting
+    void updateScrimController();
+
+    boolean isKeyguardShowing();
+
+    boolean shouldIgnoreTouch();
+
+    boolean isDeviceInteractive();
+
+    void setNotificationSnoozed(StatusBarNotification sbn,
+            NotificationSwipeActionHelper.SnoozeOption snoozeOption);
+
+    void awakenDreams();
+
+    @Override
+    void startPendingIntentDismissingKeyguard(PendingIntent intent);
+
+    @Override
+    void startPendingIntentDismissingKeyguard(
+            PendingIntent intent, @Nullable Runnable intentSentUiThreadCallback);
+
+    @Override
+    void startPendingIntentDismissingKeyguard(PendingIntent intent,
+            Runnable intentSentUiThreadCallback, View associatedView);
+
+    @Override
+    void startPendingIntentDismissingKeyguard(
+            PendingIntent intent, @Nullable Runnable intentSentUiThreadCallback,
+            @Nullable ActivityLaunchAnimator.Controller animationController);
+
+    void clearNotificationEffects();
+
+    boolean isBouncerShowing();
+
+    boolean isBouncerShowingScrimmed();
+
+    boolean isBouncerShowingOverDream();
+
+    void onBouncerPreHideAnimation();
+
+    boolean isKeyguardSecure();
+
+    NotificationPanelViewController getPanelController();
+
+    NotificationGutsManager getGutsManager();
+
+    void updateNotificationPanelTouchState();
+
+    void makeExpandedVisible(boolean force);
+
+    void instantCollapseNotificationPanel();
+
+    void visibilityChanged(boolean visible);
+
+    int getDisplayId();
+
+    int getRotation();
+
+    @VisibleForTesting
+    void setBarStateForTest(int state);
+
+    void wakeUpForFullScreenIntent();
+
+    void showTransientUnchecked();
+
+    void clearTransient();
+
+    void acquireGestureWakeLock(long time);
+
+    boolean setAppearance(int appearance);
+
+    int getBarMode();
+
+    void resendMessage(int msg);
+
+    void resendMessage(Object msg);
+
+    int getDisabled1();
+
+    void setDisabled1(int disabled);
+
+    int getDisabled2();
+
+    void setDisabled2(int disabled);
+
+    void setLastCameraLaunchSource(int source);
+
+    void setLaunchCameraOnFinishedGoingToSleep(boolean launch);
+
+    void setLaunchCameraOnFinishedWaking(boolean launch);
+
+    void setLaunchEmergencyActionOnFinishedGoingToSleep(boolean launch);
+
+    void setLaunchEmergencyActionOnFinishedWaking(boolean launch);
+
+    void setTopHidesStatusBar(boolean hides);
+
+    QSPanelController getQSPanelController();
+
+    boolean areNotificationAlertsDisabled();
+
+    float getDisplayDensity();
+
+    void extendDozePulse();
+
+    public static class KeyboardShortcutsMessage {
+        final int mDeviceId;
+
+        KeyboardShortcutsMessage(int deviceId) {
+            mDeviceId = deviceId;
         }
-        return mStatusBarKeyguardViewManager.isSecure();
-    }
-    public NotificationPanelViewController getPanelController() {
-        return mNotificationPanelViewController;
-    }
-    // End Extra BaseStatusBarMethods.
-
-    public NotificationGutsManager getGutsManager() {
-        return mGutsManager;
-    }
-
-    boolean isTransientShown() {
-        return mTransientShown;
-    }
-
-    private void updateLightRevealScrimVisibility() {
-        if (mLightRevealScrim == null) {
-            // status bar may not be inflated yet
-            return;
-        }
-
-        mLightRevealScrim.setAlpha(mScrimController.getState().getMaxLightRevealScrimAlpha());
-    }
-
-    private final KeyguardUpdateMonitorCallback mUpdateCallback =
-            new KeyguardUpdateMonitorCallback() {
-                @Override
-                public void onDreamingStateChanged(boolean dreaming) {
-                    updateScrimController();
-                    if (dreaming) {
-                        maybeEscalateHeadsUp();
-                    }
-                }
-
-                // TODO: (b/145659174) remove when moving to NewNotifPipeline. Replaced by
-                //  KeyguardCoordinator
-                @Override
-                public void onStrongAuthStateChanged(int userId) {
-                    super.onStrongAuthStateChanged(userId);
-                    mNotificationsController.requestNotificationUpdate("onStrongAuthStateChanged");
-                }
-            };
-
-
-    private final FalsingManager.FalsingBeliefListener mFalsingBeliefListener =
-            new FalsingManager.FalsingBeliefListener() {
-                @Override
-                public void onFalse() {
-                    // Hides quick settings, bouncer, and quick-quick settings.
-                    mStatusBarKeyguardViewManager.reset(true);
-                }
-            };
-
-    // Notifies StatusBarKeyguardViewManager every time the keyguard transition is over,
-    // this animation is tied to the scrim for historic reasons.
-    // TODO: notify when keyguard has faded away instead of the scrim.
-    private final ScrimController.Callback mUnlockScrimCallback = new ScrimController
-            .Callback() {
-        @Override
-        public void onFinished() {
-            if (mStatusBarKeyguardViewManager == null) {
-                Log.w(TAG, "Tried to notify keyguard visibility when "
-                        + "mStatusBarKeyguardViewManager was null");
-                return;
-            }
-            if (mKeyguardStateController.isKeyguardFadingAway()) {
-                mStatusBarKeyguardViewManager.onKeyguardFadedAway();
-            }
-        }
-
-        @Override
-        public void onCancelled() {
-            onFinished();
-        }
-    };
-
-    private final DeviceProvisionedListener mUserSetupObserver = new DeviceProvisionedListener() {
-        @Override
-        public void onUserSetupChanged() {
-            final boolean userSetup = mDeviceProvisionedController.isCurrentUserSetup();
-            Log.d(TAG, "mUserSetupObserver - DeviceProvisionedListener called for "
-                    + "current user");
-            if (MULTIUSER_DEBUG) {
-                Log.d(TAG, String.format("User setup changed: userSetup=%s mUserSetup=%s",
-                        userSetup, mUserSetup));
-            }
-
-            if (userSetup != mUserSetup) {
-                mUserSetup = userSetup;
-                if (!mUserSetup) {
-                    animateCollapseQuickSettings();
-                }
-                if (mNotificationPanelViewController != null) {
-                    mNotificationPanelViewController.setUserSetupComplete(mUserSetup);
-                }
-                updateQsExpansionEnabled();
-            }
-        }
-    };
-
-    private final BroadcastReceiver mWallpaperChangedReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (!mWallpaperSupported) {
-                // Receiver should not have been registered at all...
-                Log.wtf(TAG, "WallpaperManager not supported");
-                return;
-            }
-            WallpaperInfo info = mWallpaperManager.getWallpaperInfo(UserHandle.USER_CURRENT);
-            mWallpaperController.onWallpaperInfoUpdated(info);
-
-            final boolean deviceSupportsAodWallpaper = mContext.getResources().getBoolean(
-                    com.android.internal.R.bool.config_dozeSupportsAodWallpaper);
-            // If WallpaperInfo is null, it must be ImageWallpaper.
-            final boolean supportsAmbientMode = deviceSupportsAodWallpaper
-                    && (info != null && info.supportsAmbientMode());
-
-            mNotificationShadeWindowController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
-            mScrimController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
-            mKeyguardViewMediator.setWallpaperSupportsAmbientMode(supportsAmbientMode);
-        }
-    };
-
-    private final ConfigurationListener mConfigurationListener = new ConfigurationListener() {
-        @Override
-        public void onConfigChanged(Configuration newConfig) {
-            updateResources();
-            updateDisplaySize(); // populates mDisplayMetrics
-
-            if (DEBUG) {
-                Log.v(TAG, "configuration changed: " + mContext.getResources().getConfiguration());
-            }
-
-            if (!mNotifPipelineFlags.isNewPipelineEnabled()) {
-                mViewHierarchyManager.updateRowStates();
-            }
-            mScreenPinningRequest.onConfigurationChanged();
-        }
-
-        @Override
-        public void onDensityOrFontScaleChanged() {
-            // TODO: Remove this.
-            if (mBrightnessMirrorController != null) {
-                mBrightnessMirrorController.onDensityOrFontScaleChanged();
-            }
-            // TODO: Bring these out of CentralSurfaces.
-            mUserInfoControllerImpl.onDensityOrFontScaleChanged();
-            mUserSwitcherController.onDensityOrFontScaleChanged();
-            mNotificationIconAreaController.onDensityOrFontScaleChanged(mContext);
-            mHeadsUpManager.onDensityOrFontScaleChanged();
-        }
-
-        @Override
-        public void onThemeChanged() {
-            if (mBrightnessMirrorController != null) {
-                mBrightnessMirrorController.onOverlayChanged();
-            }
-            // We need the new R.id.keyguard_indication_area before recreating
-            // mKeyguardIndicationController
-            mNotificationPanelViewController.onThemeChanged();
-
-            if (mStatusBarKeyguardViewManager != null) {
-                mStatusBarKeyguardViewManager.onThemeChanged();
-            }
-            if (mAmbientIndicationContainer instanceof AutoReinflateContainer) {
-                ((AutoReinflateContainer) mAmbientIndicationContainer).inflateLayout();
-            }
-            mNotificationIconAreaController.onThemeChanged();
-        }
-
-        @Override
-        public void onUiModeChanged() {
-            if (mBrightnessMirrorController != null) {
-                mBrightnessMirrorController.onUiModeChanged();
-            }
-        }
-    };
-
-    private StatusBarStateController.StateListener mStateListener =
-            new StatusBarStateController.StateListener() {
-                @Override
-                public void onStatePreChange(int oldState, int newState) {
-                    // If we're visible and switched to SHADE_LOCKED (the user dragged
-                    // down on the lockscreen), clear notification LED, vibration,
-                    // ringing.
-                    // Other transitions are covered in handleVisibleToUserChanged().
-                    if (mVisible && (newState == StatusBarState.SHADE_LOCKED
-                            || mStatusBarStateController.goingToFullShade())) {
-                        clearNotificationEffects();
-                    }
-                    if (newState == StatusBarState.KEYGUARD) {
-                        mRemoteInputManager.onPanelCollapsed();
-                        maybeEscalateHeadsUp();
-                    }
-                }
-
-                @Override
-                public void onStateChanged(int newState) {
-                    mState = newState;
-                    updateReportRejectedTouchVisibility();
-                    mDozeServiceHost.updateDozing();
-                    updateTheme();
-                    mNavigationBarController.touchAutoDim(mDisplayId);
-                    Trace.beginSection("CentralSurfaces#updateKeyguardState");
-                    if (mState == StatusBarState.KEYGUARD) {
-                        mNotificationPanelViewController.cancelPendingPanelCollapse();
-                    }
-                    updateDozingState();
-                    checkBarModes();
-                    updateScrimController();
-                    mPresenter.updateMediaMetaData(false, mState != StatusBarState.KEYGUARD);
-                    Trace.endSection();
-                }
-
-                @Override
-                public void onDozeAmountChanged(float linear, float eased) {
-                    if (mFeatureFlags.isEnabled(Flags.LOCKSCREEN_ANIMATIONS)
-                            && !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)) {
-                        mLightRevealScrim.setRevealAmount(1f - linear);
-                    }
-                }
-
-                @Override
-                public void onDozingChanged(boolean isDozing) {
-                    Trace.beginSection("CentralSurfaces#updateDozing");
-                    mDozing = isDozing;
-
-                    // Collapse the notification panel if open
-                    boolean dozingAnimated = mDozeServiceHost.getDozingRequested()
-                            && mDozeParameters.shouldControlScreenOff();
-                    mNotificationPanelViewController.resetViews(dozingAnimated);
-
-                    updateQsExpansionEnabled();
-                    mKeyguardViewMediator.setDozing(mDozing);
-
-                    mNotificationsController.requestNotificationUpdate("onDozingChanged");
-                    updateDozingState();
-                    mDozeServiceHost.updateDozing();
-                    updateScrimController();
-                    updateReportRejectedTouchVisibility();
-                    Trace.endSection();
-                }
-
-                @Override
-                public void onFullscreenStateChanged(boolean isFullscreen) {
-                    mIsFullscreen = isFullscreen;
-                    maybeUpdateBarMode();
-                }
-            };
-
-    private final BatteryController.BatteryStateChangeCallback mBatteryStateChangeCallback =
-            new BatteryController.BatteryStateChangeCallback() {
-                @Override
-                public void onPowerSaveChanged(boolean isPowerSave) {
-                    mMainExecutor.execute(mCheckBarModes);
-                    if (mDozeServiceHost != null) {
-                        mDozeServiceHost.firePowerSaveChanged(isPowerSave);
-                    }
-                }
-            };
-
-    private final ActivityLaunchAnimator.Callback mActivityLaunchAnimatorCallback =
-            new ActivityLaunchAnimator.Callback() {
-                @Override
-                public boolean isOnKeyguard() {
-                    return mKeyguardStateController.isShowing();
-                }
-
-                @Override
-                public void hideKeyguardWithAnimation(IRemoteAnimationRunner runner) {
-                    // We post to the main thread for 2 reasons:
-                    //   1. KeyguardViewMediator is not thread-safe.
-                    //   2. To ensure that ViewMediatorCallback#keyguardDonePending is called before
-                    //      ViewMediatorCallback#readyForKeyguardDone. The wrong order could occur
-                    //      when doing
-                    //      dismissKeyguardThenExecute { hideKeyguardWithAnimation(runner) }.
-                    mMainExecutor.execute(() -> mKeyguardViewMediator.hideWithAnimation(runner));
-                }
-
-                @Override
-                public int getBackgroundColor(TaskInfo task) {
-                    if (!mStartingSurfaceOptional.isPresent()) {
-                        Log.w(TAG, "No starting surface, defaulting to SystemBGColor");
-                        return SplashscreenContentDrawer.getSystemBGColor();
-                    }
-
-                    return mStartingSurfaceOptional.get().getBackgroundColor(task);
-                }
-            };
-
-    private final ActivityLaunchAnimator.Listener mActivityLaunchAnimatorListener =
-            new ActivityLaunchAnimator.Listener() {
-                @Override
-                public void onLaunchAnimationStart() {
-                    mKeyguardViewMediator.setBlursDisabledForAppLaunch(true);
-                }
-
-                @Override
-                public void onLaunchAnimationEnd() {
-                    mKeyguardViewMediator.setBlursDisabledForAppLaunch(false);
-                }
-            };
-
-    private final DemoMode mDemoModeCallback = new DemoMode() {
-        @Override
-        public void onDemoModeFinished() {
-            checkBarModes();
-        }
-
-        @Override
-        public void dispatchDemoCommand(String command, Bundle args) { }
-    };
-
-    /**
-     *  Determines what UserHandle to use when launching an activity.
-     *
-     *  We want to ensure that activities that are launched within the systemui process should be
-     *  launched as user of the current process.
-     * @param intent
-     * @return UserHandle
-     */
-    private UserHandle getActivityUserHandle(Intent intent) {
-        if (intent.getComponent() != null
-                && mContext.getPackageName().equals(intent.getComponent().getPackageName())) {
-            return new UserHandle(UserHandle.myUserId());
-        }
-        return UserHandle.CURRENT;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
new file mode 100644
index 0000000..8f3e696
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/CentralSurfacesImpl.java
@@ -0,0 +1,4570 @@
+/*
+ * 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.
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static android.app.StatusBarManager.WINDOW_STATE_HIDDEN;
+import static android.app.StatusBarManager.WINDOW_STATE_SHOWING;
+import static android.app.StatusBarManager.WindowVisibleState;
+import static android.app.StatusBarManager.windowStateToString;
+import static android.view.InsetsState.ITYPE_STATUS_BAR;
+import static android.view.InsetsState.containsType;
+import static android.view.WindowInsetsController.APPEARANCE_LOW_PROFILE_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_OPAQUE_STATUS_BARS;
+import static android.view.WindowInsetsController.APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS;
+
+import static androidx.core.view.ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_AUTO;
+import static androidx.core.view.ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS;
+import static androidx.lifecycle.Lifecycle.State.RESUMED;
+
+import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME;
+import static com.android.systemui.charging.WirelessChargingLayout.UNKNOWN_BATTERY_LEVEL;
+import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP;
+import static com.android.systemui.statusbar.NotificationLockscreenUserManager.PERMISSION_SELF;
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
+import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
+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 android.annotation.Nullable;
+import android.app.ActivityManager;
+import android.app.ActivityOptions;
+import android.app.ActivityTaskManager;
+import android.app.IWallpaperManager;
+import android.app.KeyguardManager;
+import android.app.Notification;
+import android.app.NotificationManager;
+import android.app.PendingIntent;
+import android.app.StatusBarManager;
+import android.app.TaskInfo;
+import android.app.TaskStackBuilder;
+import android.app.UiModeManager;
+import android.app.WallpaperInfo;
+import android.app.WallpaperManager;
+import android.app.admin.DevicePolicyManager;
+import android.content.BroadcastReceiver;
+import android.content.ComponentCallbacks2;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.content.res.Configuration;
+import android.graphics.Point;
+import android.graphics.PointF;
+import android.hardware.devicestate.DeviceStateManager;
+import android.metrics.LogMaker;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.PowerManager;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.os.SystemClock;
+import android.os.SystemProperties;
+import android.os.Trace;
+import android.os.UserHandle;
+import android.provider.Settings;
+import android.service.dreams.DreamService;
+import android.service.dreams.IDreamManager;
+import android.service.notification.StatusBarNotification;
+import android.text.TextUtils;
+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;
+import android.view.Display;
+import android.view.IRemoteAnimationRunner;
+import android.view.IWindowManager;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.ThreadedRenderer;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowInsetsController.Appearance;
+import android.view.WindowManager;
+import android.view.WindowManagerGlobal;
+import android.view.accessibility.AccessibilityManager;
+import android.widget.DateTimeView;
+import android.window.SplashScreen;
+
+import androidx.annotation.NonNull;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleRegistry;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.colorextraction.ColorExtractor;
+import com.android.internal.jank.InteractionJankMonitor;
+import com.android.internal.logging.MetricsLogger;
+import com.android.internal.logging.UiEvent;
+import com.android.internal.logging.UiEventLogger;
+import com.android.internal.logging.UiEventLoggerImpl;
+import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
+import com.android.internal.statusbar.IStatusBarService;
+import com.android.internal.statusbar.RegisterStatusBarResult;
+import com.android.keyguard.KeyguardUpdateMonitor;
+import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.keyguard.ViewMediatorCallback;
+import com.android.systemui.ActivityIntentHelper;
+import com.android.systemui.AutoReinflateContainer;
+import com.android.systemui.CoreStartable;
+import com.android.systemui.DejankUtils;
+import com.android.systemui.EventLogTags;
+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.biometrics.AuthRippleController;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.camera.CameraIntents;
+import com.android.systemui.charging.WirelessChargingAnimation;
+import com.android.systemui.classifier.FalsingCollector;
+import com.android.systemui.colorextraction.SysuiColorExtractor;
+import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.dagger.qualifiers.UiBackground;
+import com.android.systemui.demomode.DemoMode;
+import com.android.systemui.demomode.DemoModeController;
+import com.android.systemui.dreams.DreamOverlayStateController;
+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;
+import com.android.systemui.keyguard.ScreenLifecycle;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
+import com.android.systemui.navigationbar.NavigationBarController;
+import com.android.systemui.navigationbar.NavigationBarView;
+import com.android.systemui.plugins.DarkIconDispatcher;
+import com.android.systemui.plugins.FalsingManager;
+import com.android.systemui.plugins.OverlayPlugin;
+import com.android.systemui.plugins.PluginDependencyProvider;
+import com.android.systemui.plugins.PluginListener;
+import com.android.systemui.plugins.qs.QS;
+import com.android.systemui.plugins.statusbar.NotificationSwipeActionHelper.SnoozeOption;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.qs.QSFragment;
+import com.android.systemui.qs.QSPanelController;
+import com.android.systemui.recents.ScreenPinningRequest;
+import com.android.systemui.scrim.ScrimView;
+import com.android.systemui.settings.brightness.BrightnessSliderController;
+import com.android.systemui.shared.plugins.PluginManager;
+import com.android.systemui.statusbar.AutoHideUiElement;
+import com.android.systemui.statusbar.BackDropView;
+import com.android.systemui.statusbar.CircleReveal;
+import com.android.systemui.statusbar.CommandQueue;
+import com.android.systemui.statusbar.GestureRecorder;
+import com.android.systemui.statusbar.KeyboardShortcuts;
+import com.android.systemui.statusbar.KeyguardIndicationController;
+import com.android.systemui.statusbar.LiftReveal;
+import com.android.systemui.statusbar.LightRevealScrim;
+import com.android.systemui.statusbar.LockscreenShadeTransitionController;
+import com.android.systemui.statusbar.NotificationLockscreenUserManager;
+import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.NotificationPresenter;
+import com.android.systemui.statusbar.NotificationRemoteInputManager;
+import com.android.systemui.statusbar.NotificationShadeDepthController;
+import com.android.systemui.statusbar.NotificationShadeWindowController;
+import com.android.systemui.statusbar.NotificationShelfController;
+import com.android.systemui.statusbar.NotificationViewHierarchyManager;
+import com.android.systemui.statusbar.PowerButtonReveal;
+import com.android.systemui.statusbar.PulseExpansionHandler;
+import com.android.systemui.statusbar.StatusBarState;
+import com.android.systemui.statusbar.SysuiStatusBarStateController;
+import com.android.systemui.statusbar.charging.WiredChargingRippleController;
+import com.android.systemui.statusbar.connectivity.NetworkController;
+import com.android.systemui.statusbar.core.StatusBarInitializer;
+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;
+import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
+import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
+import com.android.systemui.statusbar.notification.init.NotificationsController;
+import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
+import com.android.systemui.statusbar.notification.logging.NotificationLogger;
+import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
+import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
+import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
+import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent;
+import com.android.systemui.statusbar.phone.dagger.StatusBarPhoneModule;
+import com.android.systemui.statusbar.phone.ongoingcall.OngoingCallController;
+import com.android.systemui.statusbar.phone.panelstate.PanelExpansionChangeEvent;
+import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
+import com.android.systemui.statusbar.policy.BatteryController;
+import com.android.systemui.statusbar.policy.BrightnessMirrorController;
+import com.android.systemui.statusbar.policy.ConfigurationController;
+import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
+import com.android.systemui.statusbar.policy.ExtensionController;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
+import com.android.systemui.statusbar.policy.UserSwitcherController;
+import com.android.systemui.statusbar.window.StatusBarWindowController;
+import com.android.systemui.statusbar.window.StatusBarWindowStateController;
+import com.android.systemui.util.DumpUtilsKt;
+import com.android.systemui.util.WallpaperController;
+import com.android.systemui.util.concurrency.DelayableExecutor;
+import com.android.systemui.util.concurrency.MessageRouter;
+import com.android.systemui.volume.VolumeComponent;
+import com.android.systemui.wmshell.BubblesManager;
+import com.android.wm.shell.bubbles.Bubbles;
+import com.android.wm.shell.startingsurface.SplashscreenContentDrawer;
+import com.android.wm.shell.startingsurface.StartingSurface;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.Executor;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+
+import dagger.Lazy;
+
+/**
+ * A class handling initialization and coordination between some of the key central surfaces in
+ * System UI: The notification shade, the keyguard (lockscreen), and the status bar.
+ *
+ * This class is not our ideal architecture because it doesn't enforce much isolation between these
+ * three mostly disparate surfaces. In an ideal world, this class would not exist. Instead, we would
+ * break it up into three modules -- one for each of those three surfaces -- and we would define any
+ * APIs that are needed for these surfaces to communicate with each other when necessary.
+ *
+ * <b>If at all possible, please avoid adding additional code to this monstrous class! Our goal is
+ * to break up this class into many small classes, and any code added here will slow down that goal.
+ * </b>
+ */
+@SysUISingleton
+public class CentralSurfacesImpl extends CoreStartable implements
+        CentralSurfaces {
+
+    private static final String BANNER_ACTION_CANCEL =
+            "com.android.systemui.statusbar.banner_action_cancel";
+    private static final String BANNER_ACTION_SETUP =
+            "com.android.systemui.statusbar.banner_action_setup";
+
+    private static final int MSG_OPEN_SETTINGS_PANEL = 1002;
+    private static final int MSG_LAUNCH_TRANSITION_TIMEOUT = 1003;
+    // 1020-1040 reserved for BaseStatusBar
+
+    /**
+     * The delay to reset the hint text when the hint animation is finished running.
+     */
+    private static final int HINT_RESET_DELAY_MS = 1200;
+
+    private static final UiEventLogger sUiEventLogger = new UiEventLoggerImpl();
+
+    /**
+     * If true, the system is in the half-boot-to-decryption-screen state.
+     * Prudently disable QS and notifications.
+     */
+    public static final boolean ONLY_CORE_APPS;
+
+    static {
+        boolean onlyCoreApps;
+        try {
+            IPackageManager packageManager =
+                    IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
+            onlyCoreApps = packageManager != null && packageManager.isOnlyCoreApps();
+        } catch (RemoteException e) {
+            onlyCoreApps = false;
+        }
+        ONLY_CORE_APPS = onlyCoreApps;
+    }
+
+    private final LockscreenShadeTransitionController mLockscreenShadeTransitionController;
+    private final DreamOverlayStateController mDreamOverlayStateController;
+    private CentralSurfacesCommandQueueCallbacks mCommandQueueCallbacks;
+    private float mTransitionToFullShadeProgress = 0f;
+    private NotificationListContainer mNotifListContainer;
+
+    private final KeyguardStateController.Callback mKeyguardStateControllerCallback =
+            new KeyguardStateController.Callback() {
+                @Override
+                public void onKeyguardShowingChanged() {
+                    boolean occluded = mKeyguardStateController.isOccluded();
+                    mStatusBarHideIconsForBouncerManager.setIsOccludedAndTriggerUpdate(occluded);
+                    mScrimController.setKeyguardOccluded(occluded);
+                }
+            };
+
+    void onStatusBarWindowStateChanged(@WindowVisibleState int state) {
+        updateBubblesVisibility();
+        mStatusBarWindowState = state;
+    }
+
+    @Override
+    public void acquireGestureWakeLock(long time) {
+        mGestureWakeLock.acquire(time);
+    }
+
+    @Override
+    public boolean setAppearance(int appearance) {
+        if (mAppearance != appearance) {
+            mAppearance = appearance;
+            return updateBarMode(barMode(isTransientShown(), appearance));
+        }
+
+        return false;
+    }
+
+    @Override
+    public int getBarMode() {
+        return mStatusBarMode;
+    }
+
+    @Override
+    public void resendMessage(int msg) {
+        mMessageRouter.cancelMessages(msg);
+        mMessageRouter.sendMessage(msg);
+    }
+
+    @Override
+    public void resendMessage(Object msg) {
+        mMessageRouter.cancelMessages(msg.getClass());
+        mMessageRouter.sendMessage(msg);
+    }
+
+    @Override
+    public int getDisabled1() {
+        return mDisabled1;
+    }
+
+    @Override
+    public void setDisabled1(int disabled) {
+        mDisabled1 = disabled;
+    }
+
+    @Override
+    public int getDisabled2() {
+        return mDisabled2;
+    }
+
+    @Override
+    public void setDisabled2(int disabled) {
+        mDisabled2 = disabled;
+    }
+
+    @Override
+    public void setLastCameraLaunchSource(int source) {
+        mLastCameraLaunchSource = source;
+    }
+
+    @Override
+    public void setLaunchCameraOnFinishedGoingToSleep(boolean launch) {
+        mLaunchCameraOnFinishedGoingToSleep = launch;
+    }
+
+    @Override
+    public void setLaunchCameraOnFinishedWaking(boolean launch) {
+        mLaunchCameraWhenFinishedWaking = launch;
+    }
+
+    @Override
+    public void setLaunchEmergencyActionOnFinishedGoingToSleep(boolean launch) {
+        mLaunchEmergencyActionOnFinishedGoingToSleep = launch;
+    }
+
+    @Override
+    public void setLaunchEmergencyActionOnFinishedWaking(boolean launch) {
+        mLaunchEmergencyActionWhenFinishedWaking = launch;
+    }
+
+    @Override
+    public void setTopHidesStatusBar(boolean hides) {
+        mTopHidesStatusBar = hides;
+    }
+
+    @Override
+    public QSPanelController getQSPanelController() {
+        return mQSPanelController;
+    }
+
+    /** */
+    @Override
+    public void animateExpandNotificationsPanel() {
+        mCommandQueueCallbacks.animateExpandNotificationsPanel();
+    }
+
+    /** */
+    @Override
+    public void animateExpandSettingsPanel(@Nullable String subpanel) {
+        mCommandQueueCallbacks.animateExpandSettingsPanel(subpanel);
+    }
+
+    /** */
+    @Override
+    public void animateCollapsePanels(int flags, boolean force) {
+        mCommandQueueCallbacks.animateCollapsePanels(flags, force);
+    }
+
+    /** */
+    @Override
+    public void togglePanel() {
+        mCommandQueueCallbacks.togglePanel();
+    }
+    /**
+     * The {@link StatusBarState} of the status bar.
+     */
+    protected int mState; // TODO: remove this. Just use StatusBarStateController
+    protected boolean mBouncerShowing;
+    private boolean mBouncerShowingOverDream;
+
+    private final PhoneStatusBarPolicy mIconPolicy;
+
+    private final VolumeComponent mVolumeComponent;
+    private BrightnessMirrorController mBrightnessMirrorController;
+    private boolean mBrightnessMirrorVisible;
+    private BiometricUnlockController mBiometricUnlockController;
+    private final LightBarController mLightBarController;
+    private final Lazy<LockscreenWallpaper> mLockscreenWallpaperLazy;
+    private final LockscreenGestureLogger mLockscreenGestureLogger;
+    @Nullable
+    protected LockscreenWallpaper mLockscreenWallpaper;
+    private final AutoHideController mAutoHideController;
+
+    private final Point mCurrentDisplaySize = new Point();
+
+    protected NotificationShadeWindowView mNotificationShadeWindowView;
+    protected PhoneStatusBarView mStatusBarView;
+    private PhoneStatusBarViewController mPhoneStatusBarViewController;
+    private PhoneStatusBarTransitions mStatusBarTransitions;
+    private AuthRippleController mAuthRippleController;
+    @WindowVisibleState private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
+    protected final NotificationShadeWindowController mNotificationShadeWindowController;
+    private final StatusBarWindowController mStatusBarWindowController;
+    private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+    @VisibleForTesting
+    DozeServiceHost mDozeServiceHost;
+    private boolean mWakeUpComingFromTouch;
+    private PointF mWakeUpTouchLocation;
+    private LightRevealScrim mLightRevealScrim;
+    private PowerButtonReveal mPowerButtonReveal;
+
+    private final Object mQueueLock = new Object();
+
+    private final PulseExpansionHandler mPulseExpansionHandler;
+    private final NotificationWakeUpCoordinator mWakeUpCoordinator;
+    private final KeyguardBypassController mKeyguardBypassController;
+    private final KeyguardStateController mKeyguardStateController;
+    private final HeadsUpManagerPhone mHeadsUpManager;
+    private final StatusBarTouchableRegionManager mStatusBarTouchableRegionManager;
+    private final DynamicPrivacyController mDynamicPrivacyController;
+    private final FalsingCollector mFalsingCollector;
+    private final FalsingManager mFalsingManager;
+    private final BroadcastDispatcher mBroadcastDispatcher;
+    private final ConfigurationController mConfigurationController;
+    protected NotificationShadeWindowViewController mNotificationShadeWindowViewController;
+    private final DozeParameters mDozeParameters;
+    private final Lazy<BiometricUnlockController> mBiometricUnlockControllerLazy;
+    private final CentralSurfacesComponent.Factory mCentralSurfacesComponentFactory;
+    private final PluginManager mPluginManager;
+    private final ShadeController mShadeController;
+    private final InitController mInitController;
+
+    private final PluginDependencyProvider mPluginDependencyProvider;
+    private final KeyguardDismissUtil mKeyguardDismissUtil;
+    private final ExtensionController mExtensionController;
+    private final UserInfoControllerImpl mUserInfoControllerImpl;
+    private final DemoModeController mDemoModeController;
+    private final NotificationsController mNotificationsController;
+    private final OngoingCallController mOngoingCallController;
+    private final StatusBarSignalPolicy mStatusBarSignalPolicy;
+    private final StatusBarHideIconsForBouncerManager mStatusBarHideIconsForBouncerManager;
+
+    // expanded notifications
+    // the sliding/resizing panel within the notification window
+    protected NotificationPanelViewController mNotificationPanelViewController;
+
+    // settings
+    private QSPanelController mQSPanelController;
+
+    KeyguardIndicationController mKeyguardIndicationController;
+
+    private View mReportRejectedTouch;
+
+    private boolean mExpandedVisible;
+
+    private final int[] mAbsPos = new int[2];
+
+    private final NotifShadeEventSource mNotifShadeEventSource;
+    protected final NotificationEntryManager mEntryManager;
+    private final NotificationGutsManager mGutsManager;
+    private final NotificationLogger mNotificationLogger;
+    private final NotificationViewHierarchyManager mViewHierarchyManager;
+    private final PanelExpansionStateManager mPanelExpansionStateManager;
+    private final KeyguardViewMediator mKeyguardViewMediator;
+    protected final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
+    private final BrightnessSliderController.Factory mBrightnessSliderFactory;
+    private final FeatureFlags mFeatureFlags;
+    private final FragmentService mFragmentService;
+    private final ScreenOffAnimationController mScreenOffAnimationController;
+    private final WallpaperController mWallpaperController;
+    private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
+    private final MessageRouter mMessageRouter;
+    private final WallpaperManager mWallpaperManager;
+
+    private CentralSurfacesComponent mCentralSurfacesComponent;
+
+    // Flags for disabling the status bar
+    // Two variables becaseu the first one evidently ran out of room for new flags.
+    private int mDisabled1 = 0;
+    private int mDisabled2 = 0;
+
+    /** @see android.view.WindowInsetsController#setSystemBarsAppearance(int, int) */
+    private @Appearance int mAppearance;
+
+    private boolean mTransientShown;
+
+    private final DisplayMetrics mDisplayMetrics;
+
+    // XXX: gesture research
+    private final GestureRecorder mGestureRec = DEBUG_GESTURES
+        ? new GestureRecorder("/sdcard/statusbar_gestures.dat")
+        : null;
+
+    private final ScreenPinningRequest mScreenPinningRequest;
+
+    private final MetricsLogger mMetricsLogger;
+
+    // ensure quick settings is disabled until the current user makes it through the setup wizard
+    @VisibleForTesting
+    protected boolean mUserSetup = false;
+
+    @VisibleForTesting
+    public enum StatusBarUiEvent implements UiEventLogger.UiEventEnum {
+        @UiEvent(doc = "Secured lockscreen is opened.")
+        LOCKSCREEN_OPEN_SECURE(405),
+
+        @UiEvent(doc = "Lockscreen without security is opened.")
+        LOCKSCREEN_OPEN_INSECURE(406),
+
+        @UiEvent(doc = "Secured lockscreen is closed.")
+        LOCKSCREEN_CLOSE_SECURE(407),
+
+        @UiEvent(doc = "Lockscreen without security is closed.")
+        LOCKSCREEN_CLOSE_INSECURE(408),
+
+        @UiEvent(doc = "Secured bouncer is opened.")
+        BOUNCER_OPEN_SECURE(409),
+
+        @UiEvent(doc = "Bouncer without security is opened.")
+        BOUNCER_OPEN_INSECURE(410),
+
+        @UiEvent(doc = "Secured bouncer is closed.")
+        BOUNCER_CLOSE_SECURE(411),
+
+        @UiEvent(doc = "Bouncer without security is closed.")
+        BOUNCER_CLOSE_INSECURE(412);
+
+        private final int mId;
+
+        StatusBarUiEvent(int id) {
+            mId = id;
+        }
+
+        @Override
+        public int getId() {
+            return mId;
+        }
+    }
+
+    private Handler mMainHandler;
+    private final DelayableExecutor mMainExecutor;
+
+    private int mInteractingWindows;
+    private @TransitionMode int mStatusBarMode;
+
+    private final ViewMediatorCallback mKeyguardViewMediatorCallback;
+    private final ScrimController mScrimController;
+    protected DozeScrimController mDozeScrimController;
+    private final Executor mUiBgExecutor;
+
+    protected boolean mDozing;
+    private boolean mIsFullscreen;
+
+    boolean mCloseQsBeforeScreenOff;
+
+    private final NotificationMediaManager mMediaManager;
+    private final NotificationLockscreenUserManager mLockscreenUserManager;
+    private final NotificationRemoteInputManager mRemoteInputManager;
+    private boolean mWallpaperSupported;
+
+    private Runnable mLaunchTransitionEndRunnable;
+    private Runnable mLaunchTransitionCancelRunnable;
+    private boolean mLaunchCameraWhenFinishedWaking;
+    private boolean mLaunchCameraOnFinishedGoingToSleep;
+    private boolean mLaunchEmergencyActionWhenFinishedWaking;
+    private boolean mLaunchEmergencyActionOnFinishedGoingToSleep;
+    private int mLastCameraLaunchSource;
+    protected PowerManager.WakeLock mGestureWakeLock;
+
+    private final int[] mTmpInt2 = new int[2];
+
+    // Fingerprint (as computed by getLoggingFingerprint() of the last logged state.
+    private int mLastLoggedStateFingerprint;
+    private boolean mTopHidesStatusBar;
+    private boolean mStatusBarWindowHidden;
+    private boolean mIsLaunchingActivityOverLockscreen;
+
+    private final UserSwitcherController mUserSwitcherController;
+    private final NetworkController mNetworkController;
+    private final LifecycleRegistry mLifecycle = new LifecycleRegistry(this);
+    protected final BatteryController mBatteryController;
+    protected boolean mPanelExpanded;
+    private UiModeManager mUiModeManager;
+    private LogMaker mStatusBarStateLog;
+    protected final NotificationIconAreaController mNotificationIconAreaController;
+    @Nullable private View mAmbientIndicationContainer;
+    private final SysuiColorExtractor mColorExtractor;
+    private final ScreenLifecycle mScreenLifecycle;
+    private final WakefulnessLifecycle mWakefulnessLifecycle;
+
+    private boolean mNoAnimationOnNextBarModeChange;
+    private final SysuiStatusBarStateController mStatusBarStateController;
+
+    private final ActivityLaunchAnimator mActivityLaunchAnimator;
+    private NotificationLaunchAnimatorControllerProvider mNotificationAnimationProvider;
+    protected NotificationPresenter mPresenter;
+    private NotificationActivityStarter mNotificationActivityStarter;
+    private final Lazy<NotificationShadeDepthController> mNotificationShadeDepthControllerLazy;
+    private final Optional<BubblesManager> mBubblesManagerOptional;
+    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 final ColorExtractor.OnColorsChangedListener mOnColorsChangedListener =
+            (extractor, which) -> updateTheme();
+
+    private final InteractionJankMonitor mJankMonitor;
+
+
+    /**
+     * Public constructor for CentralSurfaces.
+     *
+     * CentralSurfaces is considered optional, and therefore can not be marked as @Inject directly.
+     * Instead, an @Provide method is included. See {@link StatusBarPhoneModule}.
+     */
+    @SuppressWarnings("OptionalUsedAsFieldOrParameterType")
+    @Inject
+    public CentralSurfacesImpl(
+            Context context,
+            NotificationsController notificationsController,
+            FragmentService fragmentService,
+            LightBarController lightBarController,
+            AutoHideController autoHideController,
+            StatusBarWindowController statusBarWindowController,
+            StatusBarWindowStateController statusBarWindowStateController,
+            KeyguardUpdateMonitor keyguardUpdateMonitor,
+            StatusBarSignalPolicy statusBarSignalPolicy,
+            PulseExpansionHandler pulseExpansionHandler,
+            NotificationWakeUpCoordinator notificationWakeUpCoordinator,
+            KeyguardBypassController keyguardBypassController,
+            KeyguardStateController keyguardStateController,
+            HeadsUpManagerPhone headsUpManagerPhone,
+            DynamicPrivacyController dynamicPrivacyController,
+            FalsingManager falsingManager,
+            FalsingCollector falsingCollector,
+            BroadcastDispatcher broadcastDispatcher,
+            NotifShadeEventSource notifShadeEventSource,
+            NotificationEntryManager notificationEntryManager,
+            NotificationGutsManager notificationGutsManager,
+            NotificationLogger notificationLogger,
+            NotificationInterruptStateProvider notificationInterruptStateProvider,
+            NotificationViewHierarchyManager notificationViewHierarchyManager,
+            PanelExpansionStateManager panelExpansionStateManager,
+            KeyguardViewMediator keyguardViewMediator,
+            DisplayMetrics displayMetrics,
+            MetricsLogger metricsLogger,
+            @UiBackground Executor uiBgExecutor,
+            NotificationMediaManager notificationMediaManager,
+            NotificationLockscreenUserManager lockScreenUserManager,
+            NotificationRemoteInputManager remoteInputManager,
+            UserSwitcherController userSwitcherController,
+            NetworkController networkController,
+            BatteryController batteryController,
+            SysuiColorExtractor colorExtractor,
+            ScreenLifecycle screenLifecycle,
+            WakefulnessLifecycle wakefulnessLifecycle,
+            SysuiStatusBarStateController statusBarStateController,
+            Optional<BubblesManager> bubblesManagerOptional,
+            Optional<Bubbles> bubblesOptional,
+            VisualStabilityManager visualStabilityManager,
+            DeviceProvisionedController deviceProvisionedController,
+            NavigationBarController navigationBarController,
+            AccessibilityFloatingMenuController accessibilityFloatingMenuController,
+            Lazy<AssistManager> assistManagerLazy,
+            ConfigurationController configurationController,
+            NotificationShadeWindowController notificationShadeWindowController,
+            DozeParameters dozeParameters,
+            ScrimController scrimController,
+            Lazy<LockscreenWallpaper> lockscreenWallpaperLazy,
+            LockscreenGestureLogger lockscreenGestureLogger,
+            Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
+            DozeServiceHost dozeServiceHost,
+            PowerManager powerManager,
+            ScreenPinningRequest screenPinningRequest,
+            DozeScrimController dozeScrimController,
+            VolumeComponent volumeComponent,
+            CommandQueue commandQueue,
+            CentralSurfacesComponent.Factory centralSurfacesComponentFactory,
+            PluginManager pluginManager,
+            ShadeController shadeController,
+            StatusBarKeyguardViewManager statusBarKeyguardViewManager,
+            ViewMediatorCallback viewMediatorCallback,
+            InitController initController,
+            @Named(TIME_TICK_HANDLER_NAME) Handler timeTickHandler,
+            PluginDependencyProvider pluginDependencyProvider,
+            KeyguardDismissUtil keyguardDismissUtil,
+            ExtensionController extensionController,
+            UserInfoControllerImpl userInfoControllerImpl,
+            PhoneStatusBarPolicy phoneStatusBarPolicy,
+            KeyguardIndicationController keyguardIndicationController,
+            DemoModeController demoModeController,
+            Lazy<NotificationShadeDepthController> notificationShadeDepthControllerLazy,
+            StatusBarTouchableRegionManager statusBarTouchableRegionManager,
+            NotificationIconAreaController notificationIconAreaController,
+            BrightnessSliderController.Factory brightnessSliderFactory,
+            ScreenOffAnimationController screenOffAnimationController,
+            WallpaperController wallpaperController,
+            OngoingCallController ongoingCallController,
+            StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager,
+            LockscreenShadeTransitionController lockscreenShadeTransitionController,
+            FeatureFlags featureFlags,
+            KeyguardUnlockAnimationController keyguardUnlockAnimationController,
+            @Main Handler mainHandler,
+            @Main DelayableExecutor delayableExecutor,
+            @Main MessageRouter messageRouter,
+            WallpaperManager wallpaperManager,
+            Optional<StartingSurface> startingSurfaceOptional,
+            ActivityLaunchAnimator activityLaunchAnimator,
+            NotifPipelineFlags notifPipelineFlags,
+            InteractionJankMonitor jankMonitor,
+            DeviceStateManager deviceStateManager,
+            DreamOverlayStateController dreamOverlayStateController,
+            WiredChargingRippleController wiredChargingRippleController) {
+        super(context);
+        mNotificationsController = notificationsController;
+        mFragmentService = fragmentService;
+        mLightBarController = lightBarController;
+        mAutoHideController = autoHideController;
+        mStatusBarWindowController = statusBarWindowController;
+        mKeyguardUpdateMonitor = keyguardUpdateMonitor;
+        mPulseExpansionHandler = pulseExpansionHandler;
+        mWakeUpCoordinator = notificationWakeUpCoordinator;
+        mKeyguardBypassController = keyguardBypassController;
+        mKeyguardStateController = keyguardStateController;
+        mHeadsUpManager = headsUpManagerPhone;
+        mKeyguardIndicationController = keyguardIndicationController;
+        mStatusBarTouchableRegionManager = statusBarTouchableRegionManager;
+        mDynamicPrivacyController = dynamicPrivacyController;
+        mFalsingCollector = falsingCollector;
+        mFalsingManager = falsingManager;
+        mBroadcastDispatcher = broadcastDispatcher;
+        mNotifShadeEventSource = notifShadeEventSource;
+        mEntryManager = notificationEntryManager;
+        mGutsManager = notificationGutsManager;
+        mNotificationLogger = notificationLogger;
+        mNotificationInterruptStateProvider = notificationInterruptStateProvider;
+        mViewHierarchyManager = notificationViewHierarchyManager;
+        mPanelExpansionStateManager = panelExpansionStateManager;
+        mKeyguardViewMediator = keyguardViewMediator;
+        mDisplayMetrics = displayMetrics;
+        mMetricsLogger = metricsLogger;
+        mUiBgExecutor = uiBgExecutor;
+        mMediaManager = notificationMediaManager;
+        mLockscreenUserManager = lockScreenUserManager;
+        mRemoteInputManager = remoteInputManager;
+        mUserSwitcherController = userSwitcherController;
+        mNetworkController = networkController;
+        mBatteryController = batteryController;
+        mColorExtractor = colorExtractor;
+        mScreenLifecycle = screenLifecycle;
+        mWakefulnessLifecycle = wakefulnessLifecycle;
+        mStatusBarStateController = statusBarStateController;
+        mBubblesManagerOptional = bubblesManagerOptional;
+        mBubblesOptional = bubblesOptional;
+        mVisualStabilityManager = visualStabilityManager;
+        mDeviceProvisionedController = deviceProvisionedController;
+        mNavigationBarController = navigationBarController;
+        mAccessibilityFloatingMenuController = accessibilityFloatingMenuController;
+        mAssistManagerLazy = assistManagerLazy;
+        mConfigurationController = configurationController;
+        mNotificationShadeWindowController = notificationShadeWindowController;
+        mDozeServiceHost = dozeServiceHost;
+        mPowerManager = powerManager;
+        mDozeParameters = dozeParameters;
+        mScrimController = scrimController;
+        mLockscreenWallpaperLazy = lockscreenWallpaperLazy;
+        mLockscreenGestureLogger = lockscreenGestureLogger;
+        mScreenPinningRequest = screenPinningRequest;
+        mDozeScrimController = dozeScrimController;
+        mBiometricUnlockControllerLazy = biometricUnlockControllerLazy;
+        mNotificationShadeDepthControllerLazy = notificationShadeDepthControllerLazy;
+        mVolumeComponent = volumeComponent;
+        mCommandQueue = commandQueue;
+        mCentralSurfacesComponentFactory = centralSurfacesComponentFactory;
+        mPluginManager = pluginManager;
+        mShadeController = shadeController;
+        mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
+        mKeyguardViewMediatorCallback = viewMediatorCallback;
+        mInitController = initController;
+        mPluginDependencyProvider = pluginDependencyProvider;
+        mKeyguardDismissUtil = keyguardDismissUtil;
+        mExtensionController = extensionController;
+        mUserInfoControllerImpl = userInfoControllerImpl;
+        mIconPolicy = phoneStatusBarPolicy;
+        mDemoModeController = demoModeController;
+        mNotificationIconAreaController = notificationIconAreaController;
+        mBrightnessSliderFactory = brightnessSliderFactory;
+        mWallpaperController = wallpaperController;
+        mOngoingCallController = ongoingCallController;
+        mStatusBarSignalPolicy = statusBarSignalPolicy;
+        mStatusBarHideIconsForBouncerManager = statusBarHideIconsForBouncerManager;
+        mFeatureFlags = featureFlags;
+        mKeyguardUnlockAnimationController = keyguardUnlockAnimationController;
+        mMainHandler = mainHandler;
+        mMainExecutor = delayableExecutor;
+        mMessageRouter = messageRouter;
+        mWallpaperManager = wallpaperManager;
+        mJankMonitor = jankMonitor;
+        mDreamOverlayStateController = dreamOverlayStateController;
+
+        mLockscreenShadeTransitionController = lockscreenShadeTransitionController;
+        mStartingSurfaceOptional = startingSurfaceOptional;
+        mNotifPipelineFlags = notifPipelineFlags;
+        lockscreenShadeTransitionController.setCentralSurfaces(this);
+        statusBarWindowStateController.addListener(this::onStatusBarWindowStateChanged);
+
+        mScreenOffAnimationController = screenOffAnimationController;
+
+        mPanelExpansionStateManager.addExpansionListener(this::onPanelExpansionChanged);
+
+        mBubbleExpandListener =
+                (isExpanding, key) -> mContext.getMainExecutor().execute(() -> {
+                    mNotificationsController.requestNotificationUpdate("onBubbleExpandChanged");
+                    updateScrimController();
+                });
+
+        mActivityIntentHelper = new ActivityIntentHelper(mContext);
+        mActivityLaunchAnimator = activityLaunchAnimator;
+
+        // The status bar background may need updating when the ongoing call status changes.
+        mOngoingCallController.addCallback((animate) -> maybeUpdateBarMode());
+
+        // TODO(b/190746471): Find a better home for this.
+        DateTimeView.setReceiverHandler(timeTickHandler);
+
+        mMessageRouter.subscribeTo(KeyboardShortcutsMessage.class,
+                data -> toggleKeyboardShortcuts(data.mDeviceId));
+        mMessageRouter.subscribeTo(MSG_DISMISS_KEYBOARD_SHORTCUTS_MENU,
+                id -> dismissKeyboardShortcuts());
+        mMessageRouter.subscribeTo(AnimateExpandSettingsPanelMessage.class,
+                data -> mCommandQueueCallbacks.animateExpandSettingsPanel(data.mSubpanel));
+        mMessageRouter.subscribeTo(MSG_LAUNCH_TRANSITION_TIMEOUT,
+                id -> onLaunchTransitionTimeout());
+
+        deviceStateManager.registerCallback(mMainExecutor,
+                new FoldStateListener(mContext, this::onFoldedStateChanged));
+        wiredChargingRippleController.registerCallbacks();
+    }
+
+    @Override
+    public void start() {
+        mScreenLifecycle.addObserver(mScreenObserver);
+        mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
+        mUiModeManager = mContext.getSystemService(UiModeManager.class);
+        if (mBubblesOptional.isPresent()) {
+            mBubblesOptional.get().setExpandListener(mBubbleExpandListener);
+        }
+
+        mStatusBarSignalPolicy.init();
+        mKeyguardIndicationController.init();
+
+        mColorExtractor.addOnColorsChangedListener(mOnColorsChangedListener);
+        mStatusBarStateController.addCallback(mStateListener,
+                SysuiStatusBarStateController.RANK_STATUS_BAR);
+
+        mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
+        mDreamManager = IDreamManager.Stub.asInterface(
+                ServiceManager.checkService(DreamService.DREAM_SERVICE));
+
+        mDisplay = mContext.getDisplay();
+        mDisplayId = mDisplay.getDisplayId();
+        updateDisplaySize();
+        mStatusBarHideIconsForBouncerManager.setDisplayId(mDisplayId);
+
+        // start old BaseStatusBar.start().
+        mWindowManagerService = WindowManagerGlobal.getWindowManagerService();
+        mDevicePolicyManager = (DevicePolicyManager) mContext.getSystemService(
+                Context.DEVICE_POLICY_SERVICE);
+
+        mAccessibilityManager = (AccessibilityManager)
+                mContext.getSystemService(Context.ACCESSIBILITY_SERVICE);
+
+        mKeyguardUpdateMonitor.setKeyguardBypassController(mKeyguardBypassController);
+        mBarService = IStatusBarService.Stub.asInterface(
+                ServiceManager.getService(Context.STATUS_BAR_SERVICE));
+
+        mKeyguardManager = (KeyguardManager) mContext.getSystemService(Context.KEYGUARD_SERVICE);
+        mWallpaperSupported = mWallpaperManager.isWallpaperSupported();
+
+        RegisterStatusBarResult result = null;
+        try {
+            result = mBarService.registerStatusBar(mCommandQueue);
+        } catch (RemoteException ex) {
+            ex.rethrowFromSystemServer();
+        }
+
+        createAndAddWindows(result);
+
+        if (mWallpaperSupported) {
+            // Make sure we always have the most current wallpaper info.
+            IntentFilter wallpaperChangedFilter = new IntentFilter(Intent.ACTION_WALLPAPER_CHANGED);
+            mBroadcastDispatcher.registerReceiver(mWallpaperChangedReceiver, wallpaperChangedFilter,
+                    null /* handler */, UserHandle.ALL);
+            mWallpaperChangedReceiver.onReceive(mContext, null);
+        } else if (DEBUG) {
+            Log.v(TAG, "start(): no wallpaper service ");
+        }
+
+        // Set up the initial notification state. This needs to happen before CommandQueue.disable()
+        setUpPresenter();
+
+        if (containsType(result.mTransientBarTypes, ITYPE_STATUS_BAR)) {
+            showTransientUnchecked();
+        }
+        mCommandQueueCallbacks.onSystemBarAttributesChanged(mDisplayId, result.mAppearance,
+                result.mAppearanceRegions, result.mNavbarColorManagedByIme, result.mBehavior,
+                result.mRequestedVisibilities, result.mPackageName);
+
+        // StatusBarManagerService has a back up of IME token and it's restored here.
+        mCommandQueueCallbacks.setImeWindowStatus(mDisplayId, result.mImeToken,
+                result.mImeWindowVis, result.mImeBackDisposition, result.mShowImeSwitcher);
+
+        // Set up the initial icon state
+        int numIcons = result.mIcons.size();
+        for (int i = 0; i < numIcons; i++) {
+            mCommandQueue.setIcon(result.mIcons.keyAt(i), result.mIcons.valueAt(i));
+        }
+
+        if (DEBUG) {
+            Log.d(TAG, String.format(
+                    "init: icons=%d disabled=0x%08x lights=0x%08x imeButton=0x%08x",
+                    numIcons,
+                    result.mDisabledFlags1,
+                    result.mAppearance,
+                    result.mImeWindowVis));
+        }
+
+        IntentFilter internalFilter = new IntentFilter();
+        internalFilter.addAction(BANNER_ACTION_CANCEL);
+        internalFilter.addAction(BANNER_ACTION_SETUP);
+        mContext.registerReceiver(mBannerActionBroadcastReceiver, internalFilter, PERMISSION_SELF,
+                null, Context.RECEIVER_EXPORTED_UNAUDITED);
+
+        if (mWallpaperSupported) {
+            IWallpaperManager wallpaperManager = IWallpaperManager.Stub.asInterface(
+                    ServiceManager.getService(Context.WALLPAPER_SERVICE));
+            try {
+                wallpaperManager.setInAmbientMode(false /* ambientMode */, 0L /* duration */);
+            } catch (RemoteException e) {
+                // Just pass, nothing critical.
+            }
+        }
+
+        // end old BaseStatusBar.start().
+
+        // Lastly, call to the icon policy to install/update all the icons.
+        mIconPolicy.init();
+
+        mKeyguardStateController.addCallback(new KeyguardStateController.Callback() {
+            @Override
+            public void onUnlockedChanged() {
+                logStateToEventlog();
+            }
+        });
+        startKeyguard();
+
+        mKeyguardUpdateMonitor.registerCallback(mUpdateCallback);
+        mDozeServiceHost.initialize(
+                this,
+                mStatusBarKeyguardViewManager,
+                mNotificationShadeWindowViewController,
+                mNotificationPanelViewController,
+                mAmbientIndicationContainer);
+        updateLightRevealScrimVisibility();
+
+        mConfigurationController.addCallback(mConfigurationListener);
+
+        mBatteryController.observe(mLifecycle, mBatteryStateChangeCallback);
+        mLifecycle.setCurrentState(RESUMED);
+
+        mAccessibilityFloatingMenuController.init();
+
+        // set the initial view visibility
+        int disabledFlags1 = result.mDisabledFlags1;
+        int disabledFlags2 = result.mDisabledFlags2;
+        mInitController.addPostInitTask(
+                () -> setUpDisableFlags(disabledFlags1, disabledFlags2));
+
+        mFalsingManager.addFalsingBeliefListener(mFalsingBeliefListener);
+
+        mPluginManager.addPluginListener(
+                new PluginListener<OverlayPlugin>() {
+                    private final ArraySet<OverlayPlugin> mOverlays = new ArraySet<>();
+
+                    @Override
+                    public void onPluginConnected(OverlayPlugin plugin, Context pluginContext) {
+                        mMainExecutor.execute(
+                                () -> plugin.setup(getNotificationShadeWindowView(),
+                                        getNavigationBarView(),
+                                        new Callback(plugin), mDozeParameters));
+                    }
+
+                    @Override
+                    public void onPluginDisconnected(OverlayPlugin plugin) {
+                        mMainExecutor.execute(() -> {
+                            mOverlays.remove(plugin);
+                            mNotificationShadeWindowController
+                                    .setForcePluginOpen(mOverlays.size() != 0, this);
+                        });
+                    }
+
+                    class Callback implements OverlayPlugin.Callback {
+                        private final OverlayPlugin mPlugin;
+
+                        Callback(OverlayPlugin plugin) {
+                            mPlugin = plugin;
+                        }
+
+                        @Override
+                        public void onHoldStatusBarOpenChange() {
+                            if (mPlugin.holdStatusBarOpen()) {
+                                mOverlays.add(mPlugin);
+                            } else {
+                                mOverlays.remove(mPlugin);
+                            }
+                            mMainExecutor.execute(() -> {
+                                mNotificationShadeWindowController
+                                        .setStateListener(b -> mOverlays.forEach(
+                                                o -> o.setCollapseDesired(b)));
+                                mNotificationShadeWindowController
+                                        .setForcePluginOpen(mOverlays.size() != 0, this);
+                            });
+                        }
+                    }
+                }, OverlayPlugin.class, true /* Allow multiple plugins */);
+
+        mStartingSurfaceOptional.ifPresent(startingSurface -> startingSurface.setSysuiProxy(
+                (requestTopUi, componentTag) -> mMainExecutor.execute(() ->
+                        mNotificationShadeWindowController.setRequestTopUi(
+                                requestTopUi, componentTag))));
+    }
+
+    private void onFoldedStateChanged(boolean isFolded, boolean willGoToSleep) {
+        Trace.beginSection("CentralSurfaces#onFoldedStateChanged");
+        onFoldedStateChangedInternal(isFolded, willGoToSleep);
+        Trace.endSection();
+    }
+
+    private void onFoldedStateChangedInternal(boolean isFolded, boolean willGoToSleep) {
+        // Folded state changes are followed by a screen off event.
+        // By default turning off the screen also closes the shade.
+        // We want to make sure that the shade status is kept after
+        // folding/unfolding.
+        boolean isShadeOpen = mShadeController.isShadeOpen();
+        boolean leaveOpen = isShadeOpen && !willGoToSleep;
+        if (DEBUG) {
+            Log.d(TAG, String.format(
+                    "#onFoldedStateChanged(): "
+                            + "isFolded=%s, "
+                            + "willGoToSleep=%s, "
+                            + "isShadeOpen=%s, "
+                            + "leaveOpen=%s",
+                    isFolded, willGoToSleep, isShadeOpen, leaveOpen));
+        }
+        if (leaveOpen) {
+            mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
+            if (mKeyguardStateController.isShowing()) {
+                // When device state changes on keyguard we don't want to keep the state of
+                // the shade and instead we open clean state of keyguard with shade closed.
+                // Normally some parts of QS state (like expanded/collapsed) are persisted and
+                // that causes incorrect UI rendering, especially when changing state with QS
+                // expanded. To prevent that we can close QS which resets QS and some parts of
+                // the shade to its default state. Read more in b/201537421
+                mCloseQsBeforeScreenOff = true;
+            }
+        }
+    }
+
+    // ================================================================================
+    // Constructing the view
+    // ================================================================================
+    protected void makeStatusBarView(@Nullable RegisterStatusBarResult result) {
+        updateDisplaySize(); // populates mDisplayMetrics
+        updateResources();
+        updateTheme();
+
+        inflateStatusBarWindow();
+        mNotificationShadeWindowView.setOnTouchListener(getStatusBarWindowTouchListener());
+        mWallpaperController.setRootView(mNotificationShadeWindowView);
+
+        // TODO: Deal with the ugliness that comes from having some of the status bar broken out
+        // into fragments, but the rest here, it leaves some awkward lifecycle and whatnot.
+        mNotificationLogger.setUpWithContainer(mNotifListContainer);
+        mNotificationIconAreaController.setupShelf(mNotificationShelfController);
+        mPanelExpansionStateManager.addExpansionListener(mWakeUpCoordinator);
+        mUserSwitcherController.init(mNotificationShadeWindowView);
+
+        // Allow plugins to reference DarkIconDispatcher and StatusBarStateController
+        mPluginDependencyProvider.allowPluginDependency(DarkIconDispatcher.class);
+        mPluginDependencyProvider.allowPluginDependency(StatusBarStateController.class);
+
+        // Set up CollapsedStatusBarFragment and PhoneStatusBarView
+        StatusBarInitializer initializer = mCentralSurfacesComponent.getStatusBarInitializer();
+        initializer.setStatusBarViewUpdatedListener(
+                (statusBarView, statusBarViewController, statusBarTransitions) -> {
+                    mStatusBarView = statusBarView;
+                    mPhoneStatusBarViewController = statusBarViewController;
+                    mStatusBarTransitions = statusBarTransitions;
+                    mNotificationShadeWindowViewController
+                            .setStatusBarViewController(mPhoneStatusBarViewController);
+                    // 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
+                    // re-display the notification panel if necessary (for example, if
+                    // a heads-up notification was being displayed and should continue being
+                    // displayed).
+                    mNotificationPanelViewController.updatePanelExpansionAndVisibility();
+                    setBouncerShowingForStatusBarComponents(mBouncerShowing);
+                    checkBarModes();
+                });
+        initializer.initializeStatusBar(mCentralSurfacesComponent);
+
+        mStatusBarTouchableRegionManager.setup(this, mNotificationShadeWindowView);
+        mHeadsUpManager.addListener(mNotificationPanelViewController.getOnHeadsUpChangedListener());
+        if (!mNotifPipelineFlags.isNewPipelineEnabled()) {
+            mHeadsUpManager.addListener(mVisualStabilityManager);
+        }
+        mNotificationPanelViewController.setHeadsUpManager(mHeadsUpManager);
+
+        createNavigationBar(result);
+
+        if (ENABLE_LOCKSCREEN_WALLPAPER && mWallpaperSupported) {
+            mLockscreenWallpaper = mLockscreenWallpaperLazy.get();
+        }
+
+        mNotificationPanelViewController.setKeyguardIndicationController(
+                mKeyguardIndicationController);
+
+        mAmbientIndicationContainer = mNotificationShadeWindowView.findViewById(
+                R.id.ambient_indication_container);
+
+        mAutoHideController.setStatusBar(new AutoHideUiElement() {
+            @Override
+            public void synchronizeState() {
+                checkBarModes();
+            }
+
+            @Override
+            public boolean shouldHideOnTouch() {
+                return !mRemoteInputManager.isRemoteInputActive();
+            }
+
+            @Override
+            public boolean isVisible() {
+                return isTransientShown();
+            }
+
+            @Override
+            public void hide() {
+                clearTransient();
+            }
+        });
+
+        ScrimView scrimBehind = mNotificationShadeWindowView.findViewById(R.id.scrim_behind);
+        ScrimView notificationsScrim = mNotificationShadeWindowView
+                .findViewById(R.id.scrim_notifications);
+        ScrimView scrimInFront = mNotificationShadeWindowView.findViewById(R.id.scrim_in_front);
+
+        mScrimController.setScrimVisibleListener(scrimsVisible -> {
+            mNotificationShadeWindowController.setScrimsVisibility(scrimsVisible);
+        });
+        mScrimController.attachViews(scrimBehind, notificationsScrim, scrimInFront);
+
+        mLightRevealScrim = mNotificationShadeWindowView.findViewById(R.id.light_reveal_scrim);
+        mLightRevealScrim.setScrimOpaqueChangedListener((opaque) -> {
+            Runnable updateOpaqueness = () -> {
+                mNotificationShadeWindowController.setLightRevealScrimOpaque(
+                        mLightRevealScrim.isScrimOpaque());
+                mScreenOffAnimationController
+                        .onScrimOpaqueChanged(mLightRevealScrim.isScrimOpaque());
+            };
+            if (opaque) {
+                // Delay making the view opaque for a frame, because it needs some time to render
+                // otherwise this can lead to a flicker where the scrim doesn't cover the screen
+                mLightRevealScrim.post(updateOpaqueness);
+            } else {
+                updateOpaqueness.run();
+            }
+        });
+
+        mScreenOffAnimationController.initialize(this, mLightRevealScrim);
+        updateLightRevealScrimVisibility();
+
+        mNotificationPanelViewController.initDependencies(
+                this,
+                this::makeExpandedInvisible,
+                mNotificationShelfController);
+
+        BackDropView backdrop = mNotificationShadeWindowView.findViewById(R.id.backdrop);
+        mMediaManager.setup(backdrop, backdrop.findViewById(R.id.backdrop_front),
+                backdrop.findViewById(R.id.backdrop_back), mScrimController, mLockscreenWallpaper);
+        float maxWallpaperZoom = mContext.getResources().getFloat(
+                com.android.internal.R.dimen.config_wallpaperMaxScale);
+        mNotificationShadeDepthControllerLazy.get().addListener(depth -> {
+            float scale = MathUtils.lerp(maxWallpaperZoom, 1f, depth);
+            backdrop.setPivotX(backdrop.getWidth() / 2f);
+            backdrop.setPivotY(backdrop.getHeight() / 2f);
+            backdrop.setScaleX(scale);
+            backdrop.setScaleY(scale);
+        });
+
+        mNotificationPanelViewController.setUserSetupComplete(mUserSetup);
+
+        // Set up the quick settings tile panel
+        final View container = mNotificationShadeWindowView.findViewById(R.id.qs_frame);
+        if (container != null) {
+            FragmentHostManager fragmentHostManager = FragmentHostManager.get(container);
+            ExtensionFragmentListener.attachExtensonToFragment(container, QS.TAG, R.id.qs_frame,
+                    mExtensionController
+                            .newExtension(QS.class)
+                            .withPlugin(QS.class)
+                            .withDefault(this::createDefaultQSFragment)
+                            .build());
+            mBrightnessMirrorController = new BrightnessMirrorController(
+                    mNotificationShadeWindowView,
+                    mNotificationPanelViewController,
+                    mNotificationShadeDepthControllerLazy.get(),
+                    mBrightnessSliderFactory,
+                    (visible) -> {
+                        mBrightnessMirrorVisible = visible;
+                        updateScrimController();
+                    });
+            fragmentHostManager.addTagListener(QS.TAG, (tag, f) -> {
+                QS qs = (QS) f;
+                if (qs instanceof QSFragment) {
+                    mQSPanelController = ((QSFragment) qs).getQSPanelController();
+                    ((QSFragment) qs).setBrightnessMirrorController(mBrightnessMirrorController);
+                }
+            });
+        }
+
+        mReportRejectedTouch = mNotificationShadeWindowView
+                .findViewById(R.id.report_rejected_touch);
+        if (mReportRejectedTouch != null) {
+            updateReportRejectedTouchVisibility();
+            mReportRejectedTouch.setOnClickListener(v -> {
+                Uri session = mFalsingManager.reportRejectedTouch();
+                if (session == null) { return; }
+
+                StringWriter message = new StringWriter();
+                message.write("Build info: ");
+                message.write(SystemProperties.get("ro.build.description"));
+                message.write("\nSerial number: ");
+                message.write(SystemProperties.get("ro.serialno"));
+                message.write("\n");
+
+                startActivityDismissingKeyguard(Intent.createChooser(new Intent(Intent.ACTION_SEND)
+                                .setType("*/*")
+                                .putExtra(Intent.EXTRA_SUBJECT, "Rejected touch report")
+                                .putExtra(Intent.EXTRA_STREAM, session)
+                                .putExtra(Intent.EXTRA_TEXT, message.toString()),
+                        "Share rejected touch report")
+                                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK),
+                        true /* onlyProvisioned */, true /* dismissShade */);
+            });
+        }
+
+        if (!mPowerManager.isInteractive()) {
+            mBroadcastReceiver.onReceive(mContext, new Intent(Intent.ACTION_SCREEN_OFF));
+        }
+        mGestureWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK,
+                "sysui:GestureWakeLock");
+
+        // receive broadcasts
+        registerBroadcastReceiver();
+
+        IntentFilter demoFilter = new IntentFilter();
+        if (DEBUG_MEDIA_FAKE_ARTWORK) {
+            demoFilter.addAction(ACTION_FAKE_ARTWORK);
+        }
+        mContext.registerReceiverAsUser(mDemoReceiver, UserHandle.ALL, demoFilter,
+                android.Manifest.permission.DUMP, null,
+                Context.RECEIVER_EXPORTED_UNAUDITED);
+
+        // listen for USER_SETUP_COMPLETE setting (per-user)
+        mDeviceProvisionedController.addCallback(mUserSetupObserver);
+        mUserSetupObserver.onUserSetupChanged();
+
+        // disable profiling bars, since they overlap and clutter the output on app windows
+        ThreadedRenderer.overrideProperty("disableProfileBars", "true");
+
+        // Private API call to make the shadows look better for Recents
+        ThreadedRenderer.overrideProperty("ambientRatio", String.valueOf(1.5f));
+    }
+
+
+    /**
+     * When swiping up to dismiss the lock screen, the panel expansion fraction goes from 1f to 0f.
+     * This results in the clock/notifications/other content disappearing off the top of the screen.
+     *
+     * We also use the expansion fraction to animate in the app/launcher surface from the bottom of
+     * the screen, 'pushing' off the notifications and other content. To do this, we dispatch the
+     * expansion fraction to the KeyguardViewMediator if we're in the process of dismissing the
+     * keyguard.
+     */
+    private void dispatchPanelExpansionForKeyguardDismiss(float fraction, boolean trackingTouch) {
+        // Things that mean we're not swiping to dismiss the keyguard, and should ignore this
+        // expansion:
+        // - Keyguard isn't even visible.
+        // - Keyguard is occluded. Expansion changes here are the shade being expanded over the
+        //   occluding activity.
+        // - Keyguard is visible, but can't be dismissed (swiping up will show PIN/password prompt).
+        // - The SIM is locked, you can't swipe to unlock. If the SIM is locked but there is no
+        //   device lock set, canDismissLockScreen returns true even though you should not be able
+        //   to dismiss the lock screen until entering the SIM PIN.
+        // - QS is expanded and we're swiping - swiping up now will hide QS, not dismiss the
+        //   keyguard.
+        if (!isKeyguardShowing()
+                || isOccluded()
+                || !mKeyguardStateController.canDismissLockScreen()
+                || mKeyguardViewMediator.isAnySimPinSecure()
+                || (mNotificationPanelViewController.isQsExpanded() && trackingTouch)) {
+            return;
+        }
+
+        // Otherwise, we should let the keyguard know about this if we're tracking touch, or if we
+        // are already animating the keyguard dismiss (since we will need to either finish or cancel
+        // the animation).
+        if (trackingTouch
+                || mKeyguardViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehindOrWillBe()
+                || mKeyguardUnlockAnimationController.isUnlockingWithSmartSpaceTransition()) {
+            mKeyguardStateController.notifyKeyguardDismissAmountChanged(
+                    1f - fraction, trackingTouch);
+        }
+    }
+
+    private void onPanelExpansionChanged(PanelExpansionChangeEvent event) {
+        float fraction = event.getFraction();
+        boolean tracking = event.getTracking();
+        dispatchPanelExpansionForKeyguardDismiss(fraction, tracking);
+
+        if (fraction == 0 || fraction == 1) {
+            if (getNavigationBarView() != null) {
+                getNavigationBarView().onStatusBarPanelStateChanged();
+            }
+            if (getNotificationPanelViewController() != null) {
+                getNotificationPanelViewController().updateSystemUiStateFlags();
+            }
+        }
+    }
+
+    @NonNull
+    @Override
+    public Lifecycle getLifecycle() {
+        return mLifecycle;
+    }
+
+    @VisibleForTesting
+    protected void registerBroadcastReceiver() {
+        IntentFilter filter = new IntentFilter();
+        filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
+        filter.addAction(Intent.ACTION_SCREEN_OFF);
+        mBroadcastDispatcher.registerReceiver(mBroadcastReceiver, filter, null, UserHandle.ALL);
+    }
+
+    protected QS createDefaultQSFragment() {
+        return FragmentHostManager.get(mNotificationShadeWindowView).create(QSFragment.class);
+    }
+
+    private void setUpPresenter() {
+        // Set up the initial notification state.
+        mActivityLaunchAnimator.setCallback(mActivityLaunchAnimatorCallback);
+        mActivityLaunchAnimator.addListener(mActivityLaunchAnimatorListener);
+        mNotificationAnimationProvider = new NotificationLaunchAnimatorControllerProvider(
+                mNotificationShadeWindowViewController,
+                mNotifListContainer,
+                mHeadsUpManager,
+                mJankMonitor);
+        mNotificationShelfController.setOnActivatedListener(mPresenter);
+        mRemoteInputManager.addControllerCallback(mNotificationShadeWindowController);
+        mStackScrollerController.setNotificationActivityStarter(mNotificationActivityStarter);
+        mGutsManager.setNotificationActivityStarter(mNotificationActivityStarter);
+        mNotificationsController.initialize(
+                mPresenter,
+                mNotifListContainer,
+                mStackScrollerController.getNotifStackController(),
+                mNotificationActivityStarter,
+                mCentralSurfacesComponent.getBindRowCallback());
+    }
+
+    /**
+     * Post-init task of {@link #start()}
+     * @param state1 disable1 flags
+     * @param state2 disable2 flags
+     */
+    protected void setUpDisableFlags(int state1, int state2) {
+        mCommandQueue.disable(mDisplayId, state1, state2, false /* animate */);
+    }
+
+    /**
+     * Ask the display to wake up if currently dozing, else do nothing
+     *
+     * @param time when to wake up
+     * @param where the view requesting the wakeup
+     * @param why the reason for the wake up
+     */
+    @Override
+    public void wakeUpIfDozing(long time, View where, String why) {
+        if (mDozing && mScreenOffAnimationController.allowWakeUpIfDozing()) {
+            mPowerManager.wakeUp(
+                    time, PowerManager.WAKE_REASON_GESTURE, "com.android.systemui:" + why);
+            mWakeUpComingFromTouch = true;
+            where.getLocationInWindow(mTmpInt2);
+
+            // NOTE, the incoming view can sometimes be the entire container... unsure if
+            // this location is valuable enough
+            mWakeUpTouchLocation = new PointF(mTmpInt2[0] + where.getWidth() / 2,
+                    mTmpInt2[1] + where.getHeight() / 2);
+            mFalsingCollector.onScreenOnFromTouch();
+        }
+    }
+
+    // TODO(b/117478341): This was left such that CarStatusBar can override this method.
+    // Try to remove this.
+    protected void createNavigationBar(@Nullable RegisterStatusBarResult result) {
+        mNavigationBarController.createNavigationBars(true /* includeDefaultDisplay */, result);
+    }
+
+    /**
+     * Returns the {@link android.view.View.OnTouchListener} that will be invoked when the
+     * background window of the status bar is clicked.
+     */
+    protected View.OnTouchListener getStatusBarWindowTouchListener() {
+        return (v, event) -> {
+            mAutoHideController.checkUserAutoHide(event);
+            mRemoteInputManager.checkRemoteInputOutside(event);
+            if (event.getAction() == MotionEvent.ACTION_UP) {
+                if (mExpandedVisible) {
+                    mShadeController.animateCollapsePanels();
+                }
+            }
+            return mNotificationShadeWindowView.onTouchEvent(event);
+        };
+    }
+
+    private void inflateStatusBarWindow() {
+        if (mCentralSurfacesComponent != null) {
+            // Tear down
+            for (CentralSurfacesComponent.Startable s : mCentralSurfacesComponent.getStartables()) {
+                s.stop();
+            }
+        }
+        mCentralSurfacesComponent = mCentralSurfacesComponentFactory.create();
+        mFragmentService.addFragmentInstantiationProvider(mCentralSurfacesComponent);
+
+        mNotificationShadeWindowView = mCentralSurfacesComponent.getNotificationShadeWindowView();
+        mNotificationShadeWindowViewController = mCentralSurfacesComponent
+                .getNotificationShadeWindowViewController();
+        mNotificationShadeWindowController.setNotificationShadeView(mNotificationShadeWindowView);
+        mNotificationShadeWindowViewController.setupExpandedStatusBar();
+        mNotificationPanelViewController =
+                mCentralSurfacesComponent.getNotificationPanelViewController();
+        mCentralSurfacesComponent.getLockIconViewController().init();
+        mStackScrollerController =
+                mCentralSurfacesComponent.getNotificationStackScrollLayoutController();
+        mStackScroller = mStackScrollerController.getView();
+        mNotifListContainer = mCentralSurfacesComponent.getNotificationListContainer();
+        mPresenter = mCentralSurfacesComponent.getNotificationPresenter();
+        mNotificationActivityStarter = mCentralSurfacesComponent.getNotificationActivityStarter();
+        mNotificationShelfController = mCentralSurfacesComponent.getNotificationShelfController();
+        mAuthRippleController = mCentralSurfacesComponent.getAuthRippleController();
+        mAuthRippleController.init();
+
+        mHeadsUpManager.addListener(mCentralSurfacesComponent.getStatusBarHeadsUpChangeListener());
+
+        // Listen for demo mode changes
+        mDemoModeController.addCallback(mDemoModeCallback);
+
+        if (mCommandQueueCallbacks != null) {
+            mCommandQueue.removeCallback(mCommandQueueCallbacks);
+        }
+        mCommandQueueCallbacks =
+                mCentralSurfacesComponent.getCentralSurfacesCommandQueueCallbacks();
+        // Connect in to the status bar manager service
+        mCommandQueue.addCallback(mCommandQueueCallbacks);
+
+        // Perform all other initialization for CentralSurfacesScope
+        for (CentralSurfacesComponent.Startable s : mCentralSurfacesComponent.getStartables()) {
+            s.start();
+        }
+    }
+
+    protected void startKeyguard() {
+        Trace.beginSection("CentralSurfaces#startKeyguard");
+        mBiometricUnlockController = mBiometricUnlockControllerLazy.get();
+        mBiometricUnlockController.setBiometricModeListener(
+                new BiometricUnlockController.BiometricModeListener() {
+                    @Override
+                    public void onResetMode() {
+                        setWakeAndUnlocking(false);
+                    }
+
+                    @Override
+                    public void onModeChanged(int mode) {
+                        switch (mode) {
+                            case BiometricUnlockController.MODE_WAKE_AND_UNLOCK_FROM_DREAM:
+                            case BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING:
+                            case BiometricUnlockController.MODE_WAKE_AND_UNLOCK:
+                                setWakeAndUnlocking(true);
+                        }
+                    }
+
+                    @Override
+                    public void notifyBiometricAuthModeChanged() {
+                        CentralSurfacesImpl.this.notifyBiometricAuthModeChanged();
+                    }
+
+                    private void setWakeAndUnlocking(boolean wakeAndUnlocking) {
+                        if (getNavigationBarView() != null) {
+                            getNavigationBarView().setWakeAndUnlocking(wakeAndUnlocking);
+                        }
+                    }
+                });
+        mStatusBarKeyguardViewManager.registerCentralSurfaces(
+                /* statusBar= */ this,
+                mNotificationPanelViewController,
+                mPanelExpansionStateManager,
+                mBiometricUnlockController,
+                mStackScroller,
+                mKeyguardBypassController);
+        mKeyguardStateController.addCallback(mKeyguardStateControllerCallback);
+        mKeyguardIndicationController
+                .setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
+        mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager);
+        mRemoteInputManager.addControllerCallback(mStatusBarKeyguardViewManager);
+        mDynamicPrivacyController.setStatusBarKeyguardViewManager(mStatusBarKeyguardViewManager);
+
+        mLightBarController.setBiometricUnlockController(mBiometricUnlockController);
+        mMediaManager.setBiometricUnlockController(mBiometricUnlockController);
+        mKeyguardDismissUtil.setDismissHandler(this::executeWhenUnlocked);
+        Trace.endSection();
+    }
+
+    @Override
+    public NotificationShadeWindowView getNotificationShadeWindowView() {
+        return mNotificationShadeWindowView;
+    }
+
+    @Override
+    public NotificationShadeWindowViewController getNotificationShadeWindowViewController() {
+        return mNotificationShadeWindowViewController;
+    }
+
+    @Override
+    public NotificationPanelViewController getNotificationPanelViewController() {
+        return mNotificationPanelViewController;
+    }
+
+    @Override
+    public ViewGroup getBouncerContainer() {
+        return mNotificationShadeWindowViewController.getBouncerContainer();
+    }
+
+    @Override
+    public int getStatusBarHeight() {
+        return mStatusBarWindowController.getStatusBarHeight();
+    }
+
+    /**
+     * Disable QS if device not provisioned.
+     * If the user switcher is simple then disable QS during setup because
+     * the user intends to use the lock screen user switcher, QS in not needed.
+     */
+    @Override
+    public void updateQsExpansionEnabled() {
+        final boolean expandEnabled = mDeviceProvisionedController.isDeviceProvisioned()
+                && (mUserSetup || mUserSwitcherController == null
+                        || !mUserSwitcherController.isSimpleUserSwitcher())
+                && !isShadeDisabled()
+                && ((mDisabled2 & StatusBarManager.DISABLE2_QUICK_SETTINGS) == 0)
+                && !mDozing
+                && !ONLY_CORE_APPS;
+        mNotificationPanelViewController.setQsExpansionEnabledPolicy(expandEnabled);
+        Log.d(TAG, "updateQsExpansionEnabled - QS Expand enabled: " + expandEnabled);
+    }
+
+    @Override
+    public boolean isShadeDisabled() {
+        return (mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0;
+    }
+
+    /**
+     * Request a notification update
+     * @param reason why we're requesting a notification update
+     */
+    @Override
+    public void requestNotificationUpdate(String reason) {
+        mNotificationsController.requestNotificationUpdate(reason);
+    }
+
+    /**
+     * Asks {@link KeyguardUpdateMonitor} to run face auth.
+     */
+    @Override
+    public void requestFaceAuth(boolean userInitiatedRequest) {
+        if (!mKeyguardStateController.canDismissLockScreen()) {
+            mKeyguardUpdateMonitor.requestFaceAuth(userInitiatedRequest);
+        }
+    }
+
+    private void updateReportRejectedTouchVisibility() {
+        if (mReportRejectedTouch == null) {
+            return;
+        }
+        mReportRejectedTouch.setVisibility(mState == StatusBarState.KEYGUARD && !mDozing
+                && mFalsingCollector.isReportingEnabled() ? View.VISIBLE : View.INVISIBLE);
+    }
+
+    @Override
+    public boolean areNotificationAlertsDisabled() {
+        return (mDisabled1 & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0;
+    }
+
+    @Override
+    public void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade,
+            int flags) {
+        startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, flags);
+    }
+
+    @Override
+    public void startActivity(Intent intent, boolean dismissShade) {
+        startActivityDismissingKeyguard(intent, false /* onlyProvisioned */, dismissShade);
+    }
+
+    @Override
+    public void startActivity(Intent intent, boolean dismissShade,
+            @Nullable ActivityLaunchAnimator.Controller animationController,
+            boolean showOverLockscreenWhenLocked) {
+        startActivity(intent, dismissShade, animationController, showOverLockscreenWhenLocked,
+                getActivityUserHandle(intent));
+    }
+
+    @Override
+    public void startActivity(Intent intent, boolean dismissShade,
+            @Nullable ActivityLaunchAnimator.Controller animationController,
+            boolean showOverLockscreenWhenLocked, UserHandle userHandle) {
+        // Make sure that we dismiss the keyguard if it is directly dismissable or when we don't
+        // want to show the activity above it.
+        if (mKeyguardStateController.isUnlocked() || !showOverLockscreenWhenLocked) {
+            startActivityDismissingKeyguard(intent, false, dismissShade,
+                    false /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */,
+                    0 /* flags */, animationController, userHandle);
+            return;
+        }
+
+        boolean animate =
+                animationController != null && shouldAnimateLaunch(true /* isActivityIntent */,
+                        showOverLockscreenWhenLocked);
+
+        ActivityLaunchAnimator.Controller controller = null;
+        if (animate) {
+            // Wrap the animation controller to dismiss the shade and set
+            // mIsLaunchingActivityOverLockscreen during the animation.
+            ActivityLaunchAnimator.Controller delegate = wrapAnimationController(
+                    animationController, dismissShade);
+            controller = new DelegateLaunchAnimatorController(delegate) {
+                @Override
+                public void onIntentStarted(boolean willAnimate) {
+                    getDelegate().onIntentStarted(willAnimate);
+
+                    if (willAnimate) {
+                        CentralSurfacesImpl.this.mIsLaunchingActivityOverLockscreen = true;
+                    }
+                }
+
+                @Override
+                public void onLaunchAnimationStart(boolean isExpandingFullyAbove) {
+                    super.onLaunchAnimationStart(isExpandingFullyAbove);
+
+                    // Double check that the keyguard is still showing and not going away, but if so
+                    // set the keyguard occluded. Typically, WM will let KeyguardViewMediator know
+                    // directly, but we're overriding that to play the custom launch animation, so
+                    // we need to take care of that here. The unocclude animation is not overridden,
+                    // so WM will call KeyguardViewMediator's unocclude animation runner when the
+                    // activity is exited.
+                    if (mKeyguardStateController.isShowing()
+                            && !mKeyguardStateController.isKeyguardGoingAway()) {
+                        mKeyguardViewMediator.setOccluded(true /* isOccluded */,
+                                true /* animate */);
+                    }
+                }
+
+                @Override
+                public void onLaunchAnimationEnd(boolean isExpandingFullyAbove) {
+                    // Set mIsLaunchingActivityOverLockscreen to false before actually finishing the
+                    // animation so that we can assume that mIsLaunchingActivityOverLockscreen
+                    // being true means that we will collapse the shade (or at least run the
+                    // post collapse runnables) later on.
+                    CentralSurfacesImpl.this.mIsLaunchingActivityOverLockscreen = false;
+                    getDelegate().onLaunchAnimationEnd(isExpandingFullyAbove);
+                }
+
+                @Override
+                public void onLaunchAnimationCancelled() {
+                    // Set mIsLaunchingActivityOverLockscreen to false before actually finishing the
+                    // animation so that we can assume that mIsLaunchingActivityOverLockscreen
+                    // being true means that we will collapse the shade (or at least run the
+                    // post collapse runnables) later on.
+                    CentralSurfacesImpl.this.mIsLaunchingActivityOverLockscreen = false;
+                    getDelegate().onLaunchAnimationCancelled();
+                }
+            };
+        } else if (dismissShade) {
+            // The animation will take care of dismissing the shade at the end of the animation. If
+            // we don't animate, collapse it directly.
+            collapseShade();
+        }
+
+        mActivityLaunchAnimator.startIntentWithAnimation(controller, animate,
+                intent.getPackage(), showOverLockscreenWhenLocked, (adapter) -> TaskStackBuilder
+                        .create(mContext)
+                        .addNextIntent(intent)
+                        .startActivities(
+                                CentralSurfaces.getActivityOptions(getDisplayId(), adapter),
+                                userHandle));
+    }
+
+    /**
+     * Whether we are currently animating an activity launch above the lockscreen (occluding
+     * activity).
+     */
+    @Override
+    public boolean isLaunchingActivityOverLockscreen() {
+        return mIsLaunchingActivityOverLockscreen;
+    }
+
+    @Override
+    public void startActivity(Intent intent, boolean onlyProvisioned, boolean dismissShade) {
+        startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade);
+    }
+
+    @Override
+    public void startActivity(Intent intent, boolean dismissShade, Callback callback) {
+        startActivityDismissingKeyguard(intent, false, dismissShade,
+                false /* disallowEnterPictureInPictureWhileLaunching */, callback, 0,
+                null /* animationController */, getActivityUserHandle(intent));
+    }
+
+    @Override
+    public void setQsExpanded(boolean expanded) {
+        mNotificationShadeWindowController.setQsExpanded(expanded);
+        mNotificationPanelViewController.setStatusAccessibilityImportance(expanded
+                ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
+                : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
+        mNotificationPanelViewController.updateSystemUiStateFlags();
+        if (getNavigationBarView() != null) {
+            getNavigationBarView().onStatusBarPanelStateChanged();
+        }
+    }
+
+    @Override
+    public boolean isWakeUpComingFromTouch() {
+        return mWakeUpComingFromTouch;
+    }
+
+    @Override
+    public boolean isFalsingThresholdNeeded() {
+        return true;
+    }
+
+    /**
+     * To be called when there's a state change in StatusBarKeyguardViewManager.
+     */
+    @Override
+    public void onKeyguardViewManagerStatesUpdated() {
+        logStateToEventlog();
+    }
+
+    @Override
+    public void setPanelExpanded(boolean isExpanded) {
+        if (mPanelExpanded != isExpanded) {
+            mNotificationLogger.onPanelExpandedChanged(isExpanded);
+        }
+        mPanelExpanded = isExpanded;
+        mStatusBarHideIconsForBouncerManager.setPanelExpandedAndTriggerUpdate(isExpanded);
+        mNotificationShadeWindowController.setPanelExpanded(isExpanded);
+        mStatusBarStateController.setPanelExpanded(isExpanded);
+        if (isExpanded && mStatusBarStateController.getState() != StatusBarState.KEYGUARD) {
+            if (DEBUG) {
+                Log.v(TAG, "clearing notification effects from Height");
+            }
+            clearNotificationEffects();
+        }
+
+        if (!isExpanded) {
+            mRemoteInputManager.onPanelCollapsed();
+        }
+    }
+
+    @Override
+    public ViewGroup getNotificationScrollLayout() {
+        return mStackScroller;
+    }
+
+    @Override
+    public boolean isPulsing() {
+        return mDozeServiceHost.isPulsing();
+    }
+
+    @androidx.annotation.Nullable
+    @Override
+    public View getAmbientIndicationContainer() {
+        return mAmbientIndicationContainer;
+    }
+
+    /**
+     * When the keyguard is showing and covered by a "showWhenLocked" activity it
+     * is occluded. This is controlled by {@link com.android.server.policy.PhoneWindowManager}
+     *
+     * @return whether the keyguard is currently occluded
+     */
+    @Override
+    public boolean isOccluded() {
+        return mKeyguardStateController.isOccluded();
+    }
+
+    /** A launch animation was cancelled. */
+    //TODO: These can / should probably be moved to NotificationPresenter or ShadeController
+    @Override
+    public void onLaunchAnimationCancelled(boolean isLaunchForActivity) {
+        if (mPresenter.isPresenterFullyCollapsed() && !mPresenter.isCollapsing()
+                && isLaunchForActivity) {
+            onClosingFinished();
+        } else {
+            mShadeController.collapsePanel(true /* animate */);
+        }
+    }
+
+    /** A launch animation ended. */
+    @Override
+    public void onLaunchAnimationEnd(boolean launchIsFullScreen) {
+        if (!mPresenter.isCollapsing()) {
+            onClosingFinished();
+        }
+        if (launchIsFullScreen) {
+            instantCollapseNotificationPanel();
+        }
+    }
+
+    /**
+     * Whether we should animate an activity launch.
+     *
+     * Note: This method must be called *before* dismissing the keyguard.
+     */
+    @Override
+    public boolean shouldAnimateLaunch(boolean isActivityIntent, boolean showOverLockscreen) {
+        // TODO(b/184121838): Support launch animations when occluded.
+        if (isOccluded()) {
+            return false;
+        }
+
+        // Always animate if we are not showing the keyguard or if we animate over the lockscreen
+        // (without unlocking it).
+        if (showOverLockscreen || !mKeyguardStateController.isShowing()) {
+            return true;
+        }
+
+        // If we are locked and have to dismiss the keyguard, only animate if remote unlock
+        // animations are enabled. We also don't animate non-activity launches as they can break the
+        // animation.
+        // TODO(b/184121838): Support non activity launches on the lockscreen.
+        return isActivityIntent && KeyguardService.sEnableRemoteKeyguardGoingAwayAnimation;
+    }
+
+    /** Whether we should animate an activity launch. */
+    @Override
+    public boolean shouldAnimateLaunch(boolean isActivityIntent) {
+        return shouldAnimateLaunch(isActivityIntent, false /* showOverLockscreen */);
+    }
+
+    @Override
+    public boolean isDeviceInVrMode() {
+        return mPresenter.isDeviceInVrMode();
+    }
+
+    @Override
+    public NotificationPresenter getPresenter() {
+        return mPresenter;
+    }
+
+    @VisibleForTesting
+    @Override
+    public void setBarStateForTest(int state) {
+        mState = state;
+    }
+
+    static class AnimateExpandSettingsPanelMessage {
+        final String mSubpanel;
+
+        AnimateExpandSettingsPanelMessage(String subpanel) {
+            mSubpanel = subpanel;
+        }
+    }
+
+    private void maybeEscalateHeadsUp() {
+        mHeadsUpManager.getAllEntries().forEach(entry -> {
+            final StatusBarNotification sbn = entry.getSbn();
+            final Notification notification = sbn.getNotification();
+            if (notification.fullScreenIntent != null) {
+                if (DEBUG) {
+                    Log.d(TAG, "converting a heads up to fullScreen");
+                }
+                try {
+                    EventLog.writeEvent(EventLogTags.SYSUI_HEADS_UP_ESCALATION,
+                            sbn.getKey());
+                    wakeUpForFullScreenIntent();
+                    notification.fullScreenIntent.send();
+                    entry.notifyFullScreenIntentLaunched();
+                } catch (PendingIntent.CanceledException e) {
+                }
+            }
+        });
+        mHeadsUpManager.releaseAllImmediately();
+    }
+
+    @Override
+    public void wakeUpForFullScreenIntent() {
+        if (isGoingToSleep() || mDozing) {
+            mPowerManager.wakeUp(
+                    SystemClock.uptimeMillis(),
+                    PowerManager.WAKE_REASON_APPLICATION,
+                    "com.android.systemui:full_screen_intent");
+            mWakeUpComingFromTouch = false;
+            mWakeUpTouchLocation = null;
+        }
+    }
+
+    @Override
+    public void makeExpandedVisible(boolean force) {
+        if (SPEW) Log.d(TAG, "Make expanded visible: expanded visible=" + mExpandedVisible);
+        if (!force && (mExpandedVisible || !mCommandQueue.panelsEnabled())) {
+            return;
+        }
+
+        mExpandedVisible = true;
+
+        // Expand the window to encompass the full screen in anticipation of the drag.
+        // This is only possible to do atomically because the status bar is at the top of the screen!
+        mNotificationShadeWindowController.setPanelVisible(true);
+
+        visibilityChanged(true);
+        mCommandQueue.recomputeDisableFlags(mDisplayId, !force /* animate */);
+        setInteracting(StatusBarManager.WINDOW_STATUS_BAR, true);
+    }
+
+    @Override
+    public void postAnimateCollapsePanels() {
+        mMainExecutor.execute(mShadeController::animateCollapsePanels);
+    }
+
+    @Override
+    public void postAnimateForceCollapsePanels() {
+        mMainExecutor.execute(
+                () -> mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_NONE,
+                true /* force */));
+    }
+
+    @Override
+    public void postAnimateOpenPanels() {
+        mMessageRouter.sendMessage(MSG_OPEN_SETTINGS_PANEL);
+    }
+
+    @Override
+    public boolean isExpandedVisible() {
+        return mExpandedVisible;
+    }
+
+    @Override
+    public boolean isPanelExpanded() {
+        return mPanelExpanded;
+    }
+
+    /**
+     * Called when another window is about to transfer it's input focus.
+     */
+    @Override
+    public void onInputFocusTransfer(boolean start, boolean cancel, float velocity) {
+        if (!mCommandQueue.panelsEnabled()) {
+            return;
+        }
+
+        if (start) {
+            mNotificationPanelViewController.startWaitingForOpenPanelGesture();
+        } else {
+            mNotificationPanelViewController.stopWaitingForOpenPanelGesture(cancel, velocity);
+        }
+    }
+
+    @Override
+    public void animateCollapseQuickSettings() {
+        if (mState == StatusBarState.SHADE) {
+            mNotificationPanelViewController.collapsePanel(
+                    true, false /* delayed */, 1.0f /* speedUpFactor */);
+        }
+    }
+
+    void makeExpandedInvisible() {
+        if (SPEW) Log.d(TAG, "makeExpandedInvisible: mExpandedVisible=" + mExpandedVisible
+                + " mExpandedVisible=" + mExpandedVisible);
+
+        if (!mExpandedVisible || mNotificationShadeWindowView == null) {
+            return;
+        }
+
+        // Ensure the panel is fully collapsed (just in case; bug 6765842, 7260868)
+        mNotificationPanelViewController.collapsePanel(/*animate=*/ false, false /* delayed*/,
+                1.0f /* speedUpFactor */);
+
+        mNotificationPanelViewController.closeQs();
+
+        mExpandedVisible = false;
+        visibilityChanged(false);
+
+        // Update the visibility of notification shade and status bar window.
+        mNotificationShadeWindowController.setPanelVisible(false);
+        mStatusBarWindowController.setForceStatusBarVisible(false);
+
+        // Close any guts that might be visible
+        mGutsManager.closeAndSaveGuts(true /* removeLeavebehind */, true /* force */,
+                true /* removeControls */, -1 /* x */, -1 /* y */, true /* resetMenu */);
+
+        mShadeController.runPostCollapseRunnables();
+        setInteracting(StatusBarManager.WINDOW_STATUS_BAR, false);
+        if (!mNotificationActivityStarter.isCollapsingToShowActivityOverLockscreen()) {
+            showBouncerOrLockScreenIfKeyguard();
+        } else if (DEBUG) {
+            Log.d(TAG, "Not showing bouncer due to activity showing over lockscreen");
+        }
+        mCommandQueue.recomputeDisableFlags(
+                mDisplayId,
+                mNotificationPanelViewController.hideStatusBarIconsWhenExpanded() /* animate */);
+
+        // Trimming will happen later if Keyguard is showing - doing it here might cause a jank in
+        // the bouncer appear animation.
+        if (!mStatusBarKeyguardViewManager.isShowing()) {
+            WindowManagerGlobal.getInstance().trimMemory(ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN);
+        }
+    }
+
+    /** Called when a touch event occurred on {@link PhoneStatusBarView}. */
+    @Override
+    public void onTouchEvent(MotionEvent event) {
+        // TODO(b/202981994): Move this touch debugging to a central location. (Right now, it's
+        //   split between NotificationPanelViewController and here.)
+        if (DEBUG_GESTURES) {
+            if (event.getActionMasked() != MotionEvent.ACTION_MOVE) {
+                EventLog.writeEvent(EventLogTags.SYSUI_STATUSBAR_TOUCH,
+                        event.getActionMasked(), (int) event.getX(), (int) event.getY(),
+                        mDisabled1, mDisabled2);
+            }
+
+        }
+
+        if (SPEW) {
+            Log.d(TAG, "Touch: rawY=" + event.getRawY() + " event=" + event + " mDisabled1="
+                    + mDisabled1 + " mDisabled2=" + mDisabled2);
+        } else if (CHATTY) {
+            if (event.getAction() != MotionEvent.ACTION_MOVE) {
+                Log.d(TAG, String.format(
+                            "panel: %s at (%f, %f) mDisabled1=0x%08x mDisabled2=0x%08x",
+                            MotionEvent.actionToString(event.getAction()),
+                            event.getRawX(), event.getRawY(), mDisabled1, mDisabled2));
+            }
+        }
+
+        if (DEBUG_GESTURES) {
+            mGestureRec.add(event);
+        }
+
+        if (mStatusBarWindowState == WINDOW_STATE_SHOWING) {
+            final boolean upOrCancel =
+                    event.getAction() == MotionEvent.ACTION_UP ||
+                    event.getAction() == MotionEvent.ACTION_CANCEL;
+            setInteracting(StatusBarManager.WINDOW_STATUS_BAR, !upOrCancel || mExpandedVisible);
+        }
+    }
+
+    @Override
+    public GestureRecorder getGestureRecorder() {
+        return mGestureRec;
+    }
+
+    @Override
+    public BiometricUnlockController getBiometricUnlockController() {
+        return mBiometricUnlockController;
+    }
+
+    @Override
+    public void showTransientUnchecked() {
+        if (!mTransientShown) {
+            mTransientShown = true;
+            mNoAnimationOnNextBarModeChange = true;
+            maybeUpdateBarMode();
+        }
+    }
+
+    @Override
+    public void clearTransient() {
+        if (mTransientShown) {
+            mTransientShown = false;
+            maybeUpdateBarMode();
+        }
+    }
+
+    private void maybeUpdateBarMode() {
+        final int barMode = barMode(mTransientShown, mAppearance);
+        if (updateBarMode(barMode)) {
+            mLightBarController.onStatusBarModeChanged(barMode);
+            updateBubblesVisibility();
+        }
+    }
+
+    private boolean updateBarMode(int barMode) {
+        if (mStatusBarMode != barMode) {
+            mStatusBarMode = barMode;
+            checkBarModes();
+            mAutoHideController.touchAutoHide();
+            return true;
+        }
+        return false;
+    }
+
+    private @TransitionMode int barMode(boolean isTransient, int appearance) {
+        final int lightsOutOpaque = APPEARANCE_LOW_PROFILE_BARS | APPEARANCE_OPAQUE_STATUS_BARS;
+        if (mOngoingCallController.hasOngoingCall() && mIsFullscreen) {
+            return MODE_SEMI_TRANSPARENT;
+        } else if (isTransient) {
+            return MODE_SEMI_TRANSPARENT;
+        } else if ((appearance & lightsOutOpaque) == lightsOutOpaque) {
+            return MODE_LIGHTS_OUT;
+        } else if ((appearance & APPEARANCE_LOW_PROFILE_BARS) != 0) {
+            return MODE_LIGHTS_OUT_TRANSPARENT;
+        } else if ((appearance & APPEARANCE_OPAQUE_STATUS_BARS) != 0) {
+            return MODE_OPAQUE;
+        } else if ((appearance & APPEARANCE_SEMI_TRANSPARENT_STATUS_BARS) != 0) {
+            return MODE_SEMI_TRANSPARENT;
+        } else {
+            return MODE_TRANSPARENT;
+        }
+    }
+
+    @Override
+    public void showWirelessChargingAnimation(int batteryLevel) {
+        showChargingAnimation(batteryLevel, UNKNOWN_BATTERY_LEVEL, 0);
+    }
+
+    protected void showChargingAnimation(int batteryLevel, int transmittingBatteryLevel,
+            long animationDelay) {
+        WirelessChargingAnimation.makeWirelessChargingAnimation(mContext, null,
+                transmittingBatteryLevel, batteryLevel,
+                new WirelessChargingAnimation.Callback() {
+                    @Override
+                    public void onAnimationStarting() {
+                        mNotificationShadeWindowController.setRequestTopUi(true, TAG);
+                    }
+
+                    @Override
+                    public void onAnimationEnded() {
+                        mNotificationShadeWindowController.setRequestTopUi(false, TAG);
+                    }
+                }, false, sUiEventLogger).show(animationDelay);
+    }
+
+    @Override
+    public void checkBarModes() {
+        if (mDemoModeController.isInDemoMode()) return;
+        if (mStatusBarTransitions != null) {
+            checkBarMode(mStatusBarMode, mStatusBarWindowState, mStatusBarTransitions);
+        }
+        mNavigationBarController.checkNavBarModes(mDisplayId);
+        mNoAnimationOnNextBarModeChange = false;
+    }
+
+    // Called by NavigationBarFragment
+    @Override
+    public void setQsScrimEnabled(boolean scrimEnabled) {
+        mNotificationPanelViewController.setQsScrimEnabled(scrimEnabled);
+    }
+
+    /** Temporarily hides Bubbles if the status bar is hidden. */
+    @Override
+    public void updateBubblesVisibility() {
+        mBubblesOptional.ifPresent(bubbles -> bubbles.onStatusBarVisibilityChanged(
+                mStatusBarMode != MODE_LIGHTS_OUT
+                        && mStatusBarMode != MODE_LIGHTS_OUT_TRANSPARENT
+                        && !mStatusBarWindowHidden));
+    }
+
+    void checkBarMode(@TransitionMode int mode, @WindowVisibleState int windowState,
+            BarTransitions transitions) {
+        final boolean anim = !mNoAnimationOnNextBarModeChange && mDeviceInteractive
+                && windowState != WINDOW_STATE_HIDDEN;
+        transitions.transitionTo(mode, anim);
+    }
+
+    private void finishBarAnimations() {
+        if (mStatusBarTransitions != null) {
+            mStatusBarTransitions.finishAnimations();
+        }
+        mNavigationBarController.finishBarAnimations(mDisplayId);
+    }
+
+    private final Runnable mCheckBarModes = this::checkBarModes;
+
+    @Override
+    public void setInteracting(int barWindow, boolean interacting) {
+        mInteractingWindows = interacting
+                ? (mInteractingWindows | barWindow)
+                : (mInteractingWindows & ~barWindow);
+        if (mInteractingWindows != 0) {
+            mAutoHideController.suspendAutoHide();
+        } else {
+            mAutoHideController.resumeSuspendedAutoHide();
+        }
+        checkBarModes();
+    }
+
+    private void dismissVolumeDialog() {
+        if (mVolumeComponent != null) {
+            mVolumeComponent.dismissNow();
+        }
+    }
+
+    @Override
+    public void dump(PrintWriter pwOriginal, String[] args) {
+        IndentingPrintWriter pw = DumpUtilsKt.asIndenting(pwOriginal);
+        synchronized (mQueueLock) {
+            pw.println("Current Status Bar state:");
+            pw.println("  mExpandedVisible=" + mExpandedVisible);
+            pw.println("  mDisplayMetrics=" + mDisplayMetrics);
+            pw.println("  mStackScroller: " + CentralSurfaces.viewInfo(mStackScroller));
+            pw.println("  mStackScroller: " + CentralSurfaces.viewInfo(mStackScroller)
+                    + " scroll " + mStackScroller.getScrollX()
+                    + "," + mStackScroller.getScrollY());
+        }
+
+        pw.print("  mInteractingWindows="); pw.println(mInteractingWindows);
+        pw.print("  mStatusBarWindowState=");
+        pw.println(windowStateToString(mStatusBarWindowState));
+        pw.print("  mStatusBarMode=");
+        pw.println(BarTransitions.modeToString(mStatusBarMode));
+        pw.print("  mDozing="); pw.println(mDozing);
+        pw.print("  mWallpaperSupported= "); pw.println(mWallpaperSupported);
+
+        pw.println("  ShadeWindowView: ");
+        if (mNotificationShadeWindowViewController != null) {
+            mNotificationShadeWindowViewController.dump(pw, args);
+            CentralSurfaces.dumpBarTransitions(
+                    pw, "PhoneStatusBarTransitions", mStatusBarTransitions);
+        }
+
+        pw.println("  mMediaManager: ");
+        if (mMediaManager != null) {
+            mMediaManager.dump(pw, args);
+        }
+
+        pw.println("  Panels: ");
+        if (mNotificationPanelViewController != null) {
+            pw.println("    mNotificationPanel="
+                    + mNotificationPanelViewController.getView() + " params="
+                    + mNotificationPanelViewController.getView().getLayoutParams().debug(""));
+            pw.print  ("      ");
+            mNotificationPanelViewController.dump(pw, args);
+        }
+        pw.println("  mStackScroller: ");
+        if (mStackScroller != null) {
+            // Double indent until we rewrite the rest of this dump()
+            pw.increaseIndent();
+            pw.increaseIndent();
+            mStackScroller.dump(pw, args);
+            pw.decreaseIndent();
+            pw.decreaseIndent();
+        }
+        pw.println("  Theme:");
+        String nightMode = mUiModeManager == null ? "null" : mUiModeManager.getNightMode() + "";
+        pw.println("    dark theme: " + nightMode +
+                " (auto: " + UiModeManager.MODE_NIGHT_AUTO +
+                ", yes: " + UiModeManager.MODE_NIGHT_YES +
+                ", no: " + UiModeManager.MODE_NIGHT_NO + ")");
+        final boolean lightWpTheme = mContext.getThemeResId()
+                == R.style.Theme_SystemUI_LightWallpaper;
+        pw.println("    light wallpaper theme: " + lightWpTheme);
+
+        if (mKeyguardIndicationController != null) {
+            mKeyguardIndicationController.dump(pw, args);
+        }
+
+        if (mScrimController != null) {
+            mScrimController.dump(pw, args);
+        }
+
+        if (mLightRevealScrim != null) {
+            pw.println(
+                    "mLightRevealScrim.getRevealEffect(): " + mLightRevealScrim.getRevealEffect());
+            pw.println(
+                    "mLightRevealScrim.getRevealAmount(): " + mLightRevealScrim.getRevealAmount());
+        }
+
+        if (mStatusBarKeyguardViewManager != null) {
+            mStatusBarKeyguardViewManager.dump(pw);
+        }
+
+        mNotificationsController.dump(pw, args, DUMPTRUCK);
+
+        if (DEBUG_GESTURES) {
+            pw.print("  status bar gestures: ");
+            mGestureRec.dump(pw, args);
+        }
+
+        if (mHeadsUpManager != null) {
+            mHeadsUpManager.dump(pw, args);
+        } else {
+            pw.println("  mHeadsUpManager: null");
+        }
+
+        if (mStatusBarTouchableRegionManager != null) {
+            mStatusBarTouchableRegionManager.dump(pw, args);
+        } else {
+            pw.println("  mStatusBarTouchableRegionManager: null");
+        }
+
+        if (mLightBarController != null) {
+            mLightBarController.dump(pw, args);
+        }
+
+        pw.println("SharedPreferences:");
+        for (Map.Entry<String, ?> entry : Prefs.getAll(mContext).entrySet()) {
+            pw.print("  "); pw.print(entry.getKey()); pw.print("="); pw.println(entry.getValue());
+        }
+
+        pw.println("Camera gesture intents:");
+        pw.println("   Insecure camera: " + CameraIntents.getInsecureCameraIntent(mContext));
+        pw.println("   Secure camera: " + CameraIntents.getSecureCameraIntent(mContext));
+        pw.println("   Override package: "
+                + CameraIntents.getOverrideCameraPackage(mContext));
+    }
+
+    @Override
+    public void createAndAddWindows(@Nullable RegisterStatusBarResult result) {
+        makeStatusBarView(result);
+        mNotificationShadeWindowController.attach();
+        mStatusBarWindowController.attach();
+    }
+
+    // called by makeStatusbar and also by PhoneStatusBarView
+    void updateDisplaySize() {
+        mDisplay.getMetrics(mDisplayMetrics);
+        mDisplay.getSize(mCurrentDisplaySize);
+        if (DEBUG_GESTURES) {
+            mGestureRec.tag("display",
+                    String.format("%dx%d", mDisplayMetrics.widthPixels, mDisplayMetrics.heightPixels));
+        }
+    }
+
+    @Override
+    public float getDisplayDensity() {
+        return mDisplayMetrics.density;
+    }
+
+    @Override
+    public float getDisplayWidth() {
+        return mDisplayMetrics.widthPixels;
+    }
+
+    @Override
+    public float getDisplayHeight() {
+        return mDisplayMetrics.heightPixels;
+    }
+
+    @Override
+    public int getRotation() {
+        return mDisplay.getRotation();
+    }
+
+    @Override
+    public int getDisplayId() {
+        return mDisplayId;
+    }
+
+    @Override
+    public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
+            boolean dismissShade, int flags) {
+        startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade,
+                false /* disallowEnterPictureInPictureWhileLaunching */, null /* callback */,
+                flags, null /* animationController */, getActivityUserHandle(intent));
+    }
+
+    @Override
+    public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
+            boolean dismissShade) {
+        startActivityDismissingKeyguard(intent, onlyProvisioned, dismissShade, 0);
+    }
+
+    @Override
+    public void startActivityDismissingKeyguard(final Intent intent, boolean onlyProvisioned,
+            final boolean dismissShade, final boolean disallowEnterPictureInPictureWhileLaunching,
+            final Callback callback, int flags,
+            @Nullable ActivityLaunchAnimator.Controller animationController,
+            final UserHandle userHandle) {
+        if (onlyProvisioned && !mDeviceProvisionedController.isDeviceProvisioned()) return;
+
+        final boolean willLaunchResolverActivity =
+                mActivityIntentHelper.wouldLaunchResolverActivity(intent,
+                        mLockscreenUserManager.getCurrentUserId());
+
+        boolean animate =
+                animationController != null && !willLaunchResolverActivity && shouldAnimateLaunch(
+                        true /* isActivityIntent */);
+        ActivityLaunchAnimator.Controller animController =
+                animationController != null ? wrapAnimationController(animationController,
+                        dismissShade) : null;
+
+        // If we animate, we will dismiss the shade only once the animation is done. This is taken
+        // care of by the StatusBarLaunchAnimationController.
+        boolean dismissShadeDirectly = dismissShade && animController == null;
+
+        Runnable runnable = () -> {
+            mAssistManagerLazy.get().hideAssist();
+            intent.setFlags(
+                    Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
+            intent.addFlags(flags);
+            int[] result = new int[]{ActivityManager.START_CANCELED};
+
+            mActivityLaunchAnimator.startIntentWithAnimation(animController,
+                    animate, intent.getPackage(), (adapter) -> {
+                        ActivityOptions options = new ActivityOptions(
+                                CentralSurfaces.getActivityOptions(mDisplayId, adapter));
+                        options.setDisallowEnterPictureInPictureWhileLaunching(
+                                disallowEnterPictureInPictureWhileLaunching);
+                        if (CameraIntents.isInsecureCameraIntent(intent)) {
+                            // Normally an activity will set it's requested rotation
+                            // animation on its window. However when launching an activity
+                            // causes the orientation to change this is too late. In these cases
+                            // the default animation is used. This doesn't look good for
+                            // the camera (as it rotates the camera contents out of sync
+                            // with physical reality). So, we ask the WindowManager to
+                            // force the crossfade animation if an orientation change
+                            // happens to occur during the launch.
+                            options.setRotationAnimationHint(
+                                    WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS);
+                        }
+                        if (Settings.Panel.ACTION_VOLUME.equals(intent.getAction())) {
+                            // Settings Panel is implemented as activity(not a dialog), so
+                            // underlying app is paused and may enter picture-in-picture mode
+                            // as a result.
+                            // So we need to disable picture-in-picture mode here
+                            // if it is volume panel.
+                            options.setDisallowEnterPictureInPictureWhileLaunching(true);
+                        }
+
+                        try {
+                            result[0] = ActivityTaskManager.getService().startActivityAsUser(
+                                    null, mContext.getBasePackageName(),
+                                    mContext.getAttributionTag(),
+                                    intent,
+                                    intent.resolveTypeIfNeeded(mContext.getContentResolver()),
+                                    null, null, 0, Intent.FLAG_ACTIVITY_NEW_TASK, null,
+                                    options.toBundle(), userHandle.getIdentifier());
+                        } catch (RemoteException e) {
+                            Log.w(TAG, "Unable to start activity", e);
+                        }
+                        return result[0];
+                    });
+
+            if (callback != null) {
+                callback.onActivityStarted(result[0]);
+            }
+        };
+        Runnable cancelRunnable = () -> {
+            if (callback != null) {
+                callback.onActivityStarted(ActivityManager.START_CANCELED);
+            }
+        };
+        executeRunnableDismissingKeyguard(runnable, cancelRunnable, dismissShadeDirectly,
+                willLaunchResolverActivity, true /* deferred */, animate);
+    }
+
+    @Nullable
+    private ActivityLaunchAnimator.Controller wrapAnimationController(
+            ActivityLaunchAnimator.Controller animationController, boolean dismissShade) {
+        View rootView = animationController.getLaunchContainer().getRootView();
+
+        Optional<ActivityLaunchAnimator.Controller> controllerFromStatusBar =
+                mStatusBarWindowController.wrapAnimationControllerIfInStatusBar(
+                        rootView, animationController);
+        if (controllerFromStatusBar.isPresent()) {
+            return controllerFromStatusBar.get();
+        }
+
+        if (dismissShade) {
+            // If the view is not in the status bar, then we are animating a view in the shade.
+            // We have to make sure that we collapse it when the animation ends or is cancelled.
+            return new StatusBarLaunchAnimatorController(animationController, this,
+                    true /* isLaunchForActivity */);
+        }
+
+        return animationController;
+    }
+
+    @Override
+    public void readyForKeyguardDone() {
+        mStatusBarKeyguardViewManager.readyForKeyguardDone();
+    }
+
+    @Override
+    public void executeRunnableDismissingKeyguard(final Runnable runnable,
+            final Runnable cancelAction,
+            final boolean dismissShade,
+            final boolean afterKeyguardGone,
+            final boolean deferred) {
+        executeRunnableDismissingKeyguard(runnable, cancelAction, dismissShade, afterKeyguardGone,
+                deferred, false /* willAnimateOnKeyguard */);
+    }
+
+    @Override
+    public void executeRunnableDismissingKeyguard(final Runnable runnable,
+            final Runnable cancelAction,
+            final boolean dismissShade,
+            final boolean afterKeyguardGone,
+            final boolean deferred,
+            final boolean willAnimateOnKeyguard) {
+        OnDismissAction onDismissAction = new OnDismissAction() {
+            @Override
+            public boolean onDismiss() {
+                if (runnable != null) {
+                    if (mStatusBarKeyguardViewManager.isShowing()
+                            && mStatusBarKeyguardViewManager.isOccluded()) {
+                        mStatusBarKeyguardViewManager.addAfterKeyguardGoneRunnable(runnable);
+                    } else {
+                        mMainExecutor.execute(runnable);
+                    }
+                }
+                if (dismissShade) {
+                    if (mExpandedVisible && !mBouncerShowing) {
+                        mShadeController.animateCollapsePanels(
+                                CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
+                                true /* force */, true /* delayed*/);
+                    } else {
+
+                        // Do it after DismissAction has been processed to conserve the needed
+                        // ordering.
+                        mMainExecutor.execute(mShadeController::runPostCollapseRunnables);
+                    }
+                } else if (CentralSurfacesImpl.this.isInLaunchTransition()
+                        && mNotificationPanelViewController.isLaunchTransitionFinished()) {
+
+                    // We are not dismissing the shade, but the launch transition is already
+                    // finished,
+                    // so nobody will call readyForKeyguardDone anymore. Post it such that
+                    // keyguardDonePending gets called first.
+                    mMainExecutor.execute(mStatusBarKeyguardViewManager::readyForKeyguardDone);
+                }
+                return deferred;
+            }
+
+            @Override
+            public boolean willRunAnimationOnKeyguard() {
+                return willAnimateOnKeyguard;
+            }
+        };
+        dismissKeyguardThenExecute(onDismissAction, cancelAction, afterKeyguardGone);
+    }
+
+    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            Trace.beginSection("CentralSurfaces#onReceive");
+            if (DEBUG) Log.v(TAG, "onReceive: " + intent);
+            String action = intent.getAction();
+            String reason = intent.getStringExtra(SYSTEM_DIALOG_REASON_KEY);
+            if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
+                KeyboardShortcuts.dismiss();
+                mRemoteInputManager.closeRemoteInputs();
+                if (mLockscreenUserManager.isCurrentProfile(getSendingUserId())) {
+                    int flags = CommandQueue.FLAG_EXCLUDE_NONE;
+                    if (reason != null) {
+                        if (reason.equals(SYSTEM_DIALOG_REASON_RECENT_APPS)) {
+                            flags |= CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL;
+                        }
+                        // Do not collapse notifications when starting dreaming if the notifications
+                        // shade is used for the screen off animation. It might require expanded
+                        // state for the scrims to be visible
+                        if (reason.equals(SYSTEM_DIALOG_REASON_DREAM)
+                                && mScreenOffAnimationController.shouldExpandNotifications()) {
+                            flags |= CommandQueue.FLAG_EXCLUDE_NOTIFICATION_PANEL;
+                        }
+                    }
+                    mShadeController.animateCollapsePanels(flags);
+                }
+            } else if (Intent.ACTION_SCREEN_OFF.equals(action)) {
+                if (mNotificationShadeWindowController != null) {
+                    mNotificationShadeWindowController.setNotTouchable(false);
+                }
+                finishBarAnimations();
+                resetUserExpandedStates();
+            }
+            Trace.endSection();
+        }
+    };
+
+    private final BroadcastReceiver mDemoReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (DEBUG) Log.v(TAG, "onReceive: " + intent);
+            String action = intent.getAction();
+            if (ACTION_FAKE_ARTWORK.equals(action)) {
+                if (DEBUG_MEDIA_FAKE_ARTWORK) {
+                    mPresenter.updateMediaMetaData(true, true);
+                }
+            }
+        }
+    };
+
+    @Override
+    public void resetUserExpandedStates() {
+        mNotificationsController.resetUserExpandedStates();
+    }
+
+    private void executeWhenUnlocked(OnDismissAction action, boolean requiresShadeOpen,
+            boolean afterKeyguardGone) {
+        if (mStatusBarKeyguardViewManager.isShowing() && requiresShadeOpen) {
+            mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
+        }
+        dismissKeyguardThenExecute(action, null /* cancelAction */,
+                afterKeyguardGone /* afterKeyguardGone */);
+    }
+
+    protected void dismissKeyguardThenExecute(OnDismissAction action, boolean afterKeyguardGone) {
+        dismissKeyguardThenExecute(action, null /* cancelRunnable */, afterKeyguardGone);
+    }
+
+    @Override
+    public void dismissKeyguardThenExecute(OnDismissAction action, Runnable cancelAction,
+            boolean afterKeyguardGone) {
+        if (mWakefulnessLifecycle.getWakefulness() == WAKEFULNESS_ASLEEP
+                && mKeyguardStateController.canDismissLockScreen()
+                && !mStatusBarStateController.leaveOpenOnKeyguardHide()
+                && mDozeServiceHost.isPulsing()) {
+            // Reuse the biometric wake-and-unlock transition if we dismiss keyguard from a pulse.
+            // TODO: Factor this transition out of BiometricUnlockController.
+            mBiometricUnlockController.startWakeAndUnlock(
+                    BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING);
+        }
+        if (mStatusBarKeyguardViewManager.isShowing()) {
+            mStatusBarKeyguardViewManager.dismissWithAction(action, cancelAction,
+                    afterKeyguardGone);
+        } else {
+            action.onDismiss();
+        }
+    }
+    /**
+     * Notify the shade controller that the current user changed
+     *
+     * @param newUserId userId of the new user
+     */
+    @Override
+    public void setLockscreenUser(int newUserId) {
+        if (mLockscreenWallpaper != null) {
+            mLockscreenWallpaper.setCurrentUser(newUserId);
+        }
+        mScrimController.setCurrentUser(newUserId);
+        if (mWallpaperSupported) {
+            mWallpaperChangedReceiver.onReceive(mContext, null);
+        }
+    }
+
+    /**
+     * Reload some of our resources when the configuration changes.
+     *
+     * We don't reload everything when the configuration changes -- we probably
+     * should, but getting that smooth is tough.  Someday we'll fix that.  In the
+     * meantime, just update the things that we know change.
+     */
+    void updateResources() {
+        // Update the quick setting tiles
+        if (mQSPanelController != null) {
+            mQSPanelController.updateResources();
+        }
+
+        if (mStatusBarWindowController != null) {
+            mStatusBarWindowController.refreshStatusBarHeight();
+        }
+
+        if (mNotificationPanelViewController != null) {
+            mNotificationPanelViewController.updateResources();
+        }
+        if (mBrightnessMirrorController != null) {
+            mBrightnessMirrorController.updateResources();
+        }
+        if (mStatusBarKeyguardViewManager != null) {
+            mStatusBarKeyguardViewManager.updateResources();
+        }
+
+        mPowerButtonReveal = new PowerButtonReveal(mContext.getResources().getDimensionPixelSize(
+                com.android.systemui.R.dimen.physical_power_button_center_screen_location_y));
+    }
+
+    // Visibility reporting
+    protected void handleVisibleToUserChanged(boolean visibleToUser) {
+        if (visibleToUser) {
+            handleVisibleToUserChangedImpl(visibleToUser);
+            mNotificationLogger.startNotificationLogging();
+        } else {
+            mNotificationLogger.stopNotificationLogging();
+            handleVisibleToUserChangedImpl(visibleToUser);
+        }
+    }
+
+    // Visibility reporting
+    void handleVisibleToUserChangedImpl(boolean visibleToUser) {
+        if (visibleToUser) {
+            /* The LEDs are turned off when the notification panel is shown, even just a little bit.
+             * See also CentralSurfaces.setPanelExpanded for another place where we attempt to do
+             * this.
+             */
+            boolean pinnedHeadsUp = mHeadsUpManager.hasPinnedHeadsUp();
+            boolean clearNotificationEffects =
+                    !mPresenter.isPresenterFullyCollapsed() &&
+                            (mState == StatusBarState.SHADE
+                                    || mState == StatusBarState.SHADE_LOCKED);
+            int notificationLoad = mNotificationsController.getActiveNotificationsCount();
+            if (pinnedHeadsUp && mPresenter.isPresenterFullyCollapsed()) {
+                notificationLoad = 1;
+            }
+            final int finalNotificationLoad = notificationLoad;
+            mUiBgExecutor.execute(() -> {
+                try {
+                    mBarService.onPanelRevealed(clearNotificationEffects,
+                            finalNotificationLoad);
+                } catch (RemoteException ex) {
+                    // Won't fail unless the world has ended.
+                }
+            });
+        } else {
+            mUiBgExecutor.execute(() -> {
+                try {
+                    mBarService.onPanelHidden();
+                } catch (RemoteException ex) {
+                    // Won't fail unless the world has ended.
+                }
+            });
+        }
+
+    }
+
+    private void logStateToEventlog() {
+        boolean isShowing = mStatusBarKeyguardViewManager.isShowing();
+        boolean isOccluded = mStatusBarKeyguardViewManager.isOccluded();
+        boolean isBouncerShowing = mStatusBarKeyguardViewManager.isBouncerShowing();
+        boolean isSecure = mKeyguardStateController.isMethodSecure();
+        boolean unlocked = mKeyguardStateController.canDismissLockScreen();
+        int stateFingerprint = getLoggingFingerprint(mState,
+                isShowing,
+                isOccluded,
+                isBouncerShowing,
+                isSecure,
+                unlocked);
+        if (stateFingerprint != mLastLoggedStateFingerprint) {
+            if (mStatusBarStateLog == null) {
+                mStatusBarStateLog = new LogMaker(MetricsEvent.VIEW_UNKNOWN);
+            }
+            mMetricsLogger.write(mStatusBarStateLog
+                    .setCategory(isBouncerShowing ? MetricsEvent.BOUNCER : MetricsEvent.LOCKSCREEN)
+                    .setType(isShowing ? MetricsEvent.TYPE_OPEN : MetricsEvent.TYPE_CLOSE)
+                    .setSubtype(isSecure ? 1 : 0));
+            EventLogTags.writeSysuiStatusBarState(mState,
+                    isShowing ? 1 : 0,
+                    isOccluded ? 1 : 0,
+                    isBouncerShowing ? 1 : 0,
+                    isSecure ? 1 : 0,
+                    unlocked ? 1 : 0);
+            mLastLoggedStateFingerprint = stateFingerprint;
+
+            StringBuilder uiEventValueBuilder = new StringBuilder();
+            uiEventValueBuilder.append(isBouncerShowing ? "BOUNCER" : "LOCKSCREEN");
+            uiEventValueBuilder.append(isShowing ? "_OPEN" : "_CLOSE");
+            uiEventValueBuilder.append(isSecure ? "_SECURE" : "_INSECURE");
+            sUiEventLogger.log(StatusBarUiEvent.valueOf(uiEventValueBuilder.toString()));
+        }
+    }
+
+    /**
+     * Returns a fingerprint of fields logged to eventlog
+     */
+    private static int getLoggingFingerprint(int statusBarState, boolean keyguardShowing,
+            boolean keyguardOccluded, boolean bouncerShowing, boolean secure,
+            boolean currentlyInsecure) {
+        // Reserve 8 bits for statusBarState. We'll never go higher than
+        // that, right? Riiiight.
+        return (statusBarState & 0xFF)
+                | ((keyguardShowing   ? 1 : 0) <<  8)
+                | ((keyguardOccluded  ? 1 : 0) <<  9)
+                | ((bouncerShowing    ? 1 : 0) << 10)
+                | ((secure            ? 1 : 0) << 11)
+                | ((currentlyInsecure ? 1 : 0) << 12);
+    }
+
+    @Override
+    public void postQSRunnableDismissingKeyguard(final Runnable runnable) {
+        mMainExecutor.execute(() -> {
+            mStatusBarStateController.setLeaveOpenOnKeyguardHide(true);
+            executeRunnableDismissingKeyguard(
+                    () -> mMainExecutor.execute(runnable), null, false, false, false);
+        });
+    }
+
+    @Override
+    public void postStartActivityDismissingKeyguard(PendingIntent intent) {
+        postStartActivityDismissingKeyguard(intent, null /* animationController */);
+    }
+
+    @Override
+    public void postStartActivityDismissingKeyguard(final PendingIntent intent,
+            @Nullable ActivityLaunchAnimator.Controller animationController) {
+        mMainExecutor.execute(() -> startPendingIntentDismissingKeyguard(intent,
+                null /* intentSentUiThreadCallback */, animationController));
+    }
+
+    @Override
+    public void postStartActivityDismissingKeyguard(final Intent intent, int delay) {
+        postStartActivityDismissingKeyguard(intent, delay, null /* animationController */);
+    }
+
+    @Override
+    public void postStartActivityDismissingKeyguard(Intent intent, int delay,
+            @Nullable ActivityLaunchAnimator.Controller animationController) {
+        mMainExecutor.executeDelayed(
+                () ->
+                        startActivityDismissingKeyguard(intent, true /* onlyProvisioned */,
+                                true /* dismissShade */,
+                                false /* disallowEnterPictureInPictureWhileLaunching */,
+                                null /* callback */,
+                                0 /* flags */,
+                                animationController,
+                                getActivityUserHandle(intent)),
+                delay);
+    }
+
+    @Override
+    public void showKeyguard() {
+        mStatusBarStateController.setKeyguardRequested(true);
+        mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
+        updateIsKeyguard();
+        mAssistManagerLazy.get().onLockscreenShown();
+    }
+
+    @Override
+    public boolean hideKeyguard() {
+        mStatusBarStateController.setKeyguardRequested(false);
+        return updateIsKeyguard();
+    }
+
+    @Override
+    public boolean updateIsKeyguard() {
+        return updateIsKeyguard(false /* forceStateChange */);
+    }
+
+    @Override
+    public boolean updateIsKeyguard(boolean forceStateChange) {
+        boolean wakeAndUnlocking = mBiometricUnlockController.isWakeAndUnlock();
+
+        // For dozing, keyguard needs to be shown whenever the device is non-interactive. Otherwise
+        // there's no surface we can show to the user. Note that the device goes fully interactive
+        // late in the transition, so we also allow the device to start dozing once the screen has
+        // turned off fully.
+        boolean keyguardForDozing = mDozeServiceHost.getDozingRequested()
+                && (!mDeviceInteractive || (isGoingToSleep()
+                    && (isScreenFullyOff()
+                        || (mKeyguardStateController.isShowing() && !isOccluded()))));
+        boolean isWakingAndOccluded = isOccluded() && isWakingOrAwake();
+        boolean shouldBeKeyguard = (mStatusBarStateController.isKeyguardRequested()
+                || keyguardForDozing) && !wakeAndUnlocking && !isWakingAndOccluded;
+        if (keyguardForDozing) {
+            updatePanelExpansionForKeyguard();
+        }
+        if (shouldBeKeyguard) {
+            if (mScreenOffAnimationController.isKeyguardShowDelayed()
+                    || (isGoingToSleep()
+                    && mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_TURNING_OFF)) {
+                // Delay showing the keyguard until screen turned off.
+            } else {
+                showKeyguardImpl();
+            }
+        } else {
+            // During folding a foldable device this might be called as a result of
+            // 'onScreenTurnedOff' call for the inner display.
+            // In this case:
+            //  * When phone is locked on folding: it doesn't make sense to hide keyguard as it
+            //    will be immediately locked again
+            //  * When phone is unlocked: we still don't want to execute hiding of the keyguard
+            //    as the animation could prepare 'fake AOD' interface (without actually
+            //    transitioning to keyguard state) and this might reset the view states
+            if (!mScreenOffAnimationController.isKeyguardHideDelayed()) {
+                return hideKeyguardImpl(forceStateChange);
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public void showKeyguardImpl() {
+        Trace.beginSection("CentralSurfaces#showKeyguard");
+        // In case we're locking while a smartspace transition is in progress, reset it.
+        mKeyguardUnlockAnimationController.resetSmartspaceTransition();
+        if (mKeyguardStateController.isLaunchTransitionFadingAway()) {
+            mNotificationPanelViewController.cancelAnimation();
+            onLaunchTransitionFadingEnded();
+        }
+        mMessageRouter.cancelMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
+        if (!mLockscreenShadeTransitionController.isWakingToShadeLocked()) {
+            mStatusBarStateController.setState(StatusBarState.KEYGUARD);
+        }
+        updatePanelExpansionForKeyguard();
+        Trace.endSection();
+    }
+
+    private void updatePanelExpansionForKeyguard() {
+        if (mState == StatusBarState.KEYGUARD && mBiometricUnlockController.getMode()
+                != BiometricUnlockController.MODE_WAKE_AND_UNLOCK && !mBouncerShowing) {
+            mShadeController.instantExpandNotificationsPanel();
+        }
+    }
+
+    private void onLaunchTransitionFadingEnded() {
+        mNotificationPanelViewController.resetAlpha();
+        mNotificationPanelViewController.onAffordanceLaunchEnded();
+        releaseGestureWakeLock();
+        runLaunchTransitionEndRunnable();
+        mKeyguardStateController.setLaunchTransitionFadingAway(false);
+        mPresenter.updateMediaMetaData(true /* metaDataChanged */, true);
+    }
+
+    @Override
+    public boolean isInLaunchTransition() {
+        return mNotificationPanelViewController.isLaunchTransitionRunning()
+                || mNotificationPanelViewController.isLaunchTransitionFinished();
+    }
+
+    /**
+     * Fades the content of the keyguard away after the launch transition is done.
+     *
+     * @param beforeFading the runnable to be run when the circle is fully expanded and the fading
+     *                     starts
+     * @param endRunnable the runnable to be run when the transition is done. Will not run
+     *                    if the transition is cancelled, instead cancelRunnable will run
+     * @param cancelRunnable the runnable to be run if the transition is cancelled
+     */
+    @Override
+    public void fadeKeyguardAfterLaunchTransition(final Runnable beforeFading,
+            Runnable endRunnable, Runnable cancelRunnable) {
+        mMessageRouter.cancelMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
+        mLaunchTransitionEndRunnable = endRunnable;
+        mLaunchTransitionCancelRunnable = cancelRunnable;
+        Runnable hideRunnable = () -> {
+            mKeyguardStateController.setLaunchTransitionFadingAway(true);
+            if (beforeFading != null) {
+                beforeFading.run();
+            }
+            updateScrimController();
+            mPresenter.updateMediaMetaData(false, true);
+            mNotificationPanelViewController.resetAlpha();
+            mNotificationPanelViewController.fadeOut(
+                    FADE_KEYGUARD_START_DELAY, FADE_KEYGUARD_DURATION,
+                    this::onLaunchTransitionFadingEnded);
+            mCommandQueue.appTransitionStarting(mDisplayId, SystemClock.uptimeMillis(),
+                    LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true);
+        };
+        if (mNotificationPanelViewController.isLaunchTransitionRunning()) {
+            mNotificationPanelViewController.setLaunchTransitionEndRunnable(hideRunnable);
+        } else {
+            hideRunnable.run();
+        }
+    }
+
+    private void cancelAfterLaunchTransitionRunnables() {
+        if (mLaunchTransitionCancelRunnable != null) {
+            mLaunchTransitionCancelRunnable.run();
+        }
+        mLaunchTransitionEndRunnable = null;
+        mLaunchTransitionCancelRunnable = null;
+        mNotificationPanelViewController.setLaunchTransitionEndRunnable(null);
+    }
+
+    /**
+     * Fades the content of the Keyguard while we are dozing and makes it invisible when finished
+     * fading.
+     */
+    @Override
+    public void fadeKeyguardWhilePulsing() {
+        mNotificationPanelViewController.fadeOut(0, FADE_KEYGUARD_DURATION_PULSING,
+                ()-> {
+                hideKeyguard();
+                mStatusBarKeyguardViewManager.onKeyguardFadedAway();
+            }).start();
+    }
+
+    /**
+     * Plays the animation when an activity that was occluding Keyguard goes away.
+     */
+    @Override
+    public void animateKeyguardUnoccluding() {
+        mNotificationPanelViewController.setExpandedFraction(0f);
+        mCommandQueueCallbacks.animateExpandNotificationsPanel();
+        mScrimController.setUnocclusionAnimationRunning(true);
+    }
+
+    /**
+     * Starts the timeout when we try to start the affordances on Keyguard. We usually rely that
+     * Keyguard goes away via fadeKeyguardAfterLaunchTransition, however, that might not happen
+     * because the launched app crashed or something else went wrong.
+     */
+    @Override
+    public void startLaunchTransitionTimeout() {
+        mMessageRouter.sendMessageDelayed(
+                MSG_LAUNCH_TRANSITION_TIMEOUT, LAUNCH_TRANSITION_TIMEOUT_MS);
+    }
+
+    private void onLaunchTransitionTimeout() {
+        Log.w(TAG, "Launch transition: Timeout!");
+        mNotificationPanelViewController.onAffordanceLaunchEnded();
+        releaseGestureWakeLock();
+        mNotificationPanelViewController.resetViews(false /* animate */);
+    }
+
+    private void runLaunchTransitionEndRunnable() {
+        mLaunchTransitionCancelRunnable = null;
+        if (mLaunchTransitionEndRunnable != null) {
+            Runnable r = mLaunchTransitionEndRunnable;
+
+            // mLaunchTransitionEndRunnable might call showKeyguard, which would execute it again,
+            // which would lead to infinite recursion. Protect against it.
+            mLaunchTransitionEndRunnable = null;
+            r.run();
+        }
+    }
+
+    /**
+     * @return true if we would like to stay in the shade, false if it should go away entirely
+     */
+    @Override
+    public boolean hideKeyguardImpl(boolean forceStateChange) {
+        Trace.beginSection("CentralSurfaces#hideKeyguard");
+        boolean staying = mStatusBarStateController.leaveOpenOnKeyguardHide();
+        int previousState = mStatusBarStateController.getState();
+        if (!(mStatusBarStateController.setState(StatusBarState.SHADE, forceStateChange))) {
+            //TODO: StatusBarStateController should probably know about hiding the keyguard and
+            // notify listeners.
+
+            // If the state didn't change, we may still need to update public mode
+            mLockscreenUserManager.updatePublicMode();
+        }
+        if (mStatusBarStateController.leaveOpenOnKeyguardHide()) {
+            if (!mStatusBarStateController.isKeyguardRequested()) {
+                mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
+            }
+            long delay = mKeyguardStateController.calculateGoingToFullShadeDelay();
+            mLockscreenShadeTransitionController.onHideKeyguard(delay, previousState);
+
+            // Disable layout transitions in navbar for this transition because the load is just
+            // too heavy for the CPU and GPU on any device.
+            mNavigationBarController.disableAnimationsDuringHide(mDisplayId, delay);
+        } else if (!mNotificationPanelViewController.isCollapsing()) {
+            instantCollapseNotificationPanel();
+        }
+
+        // Keyguard state has changed, but QS is not listening anymore. Make sure to update the tile
+        // visibilities so next time we open the panel we know the correct height already.
+        if (mQSPanelController != null) {
+            mQSPanelController.refreshAllTiles();
+        }
+        mMessageRouter.cancelMessages(MSG_LAUNCH_TRANSITION_TIMEOUT);
+        releaseGestureWakeLock();
+        mNotificationPanelViewController.onAffordanceLaunchEnded();
+        mNotificationPanelViewController.resetAlpha();
+        mNotificationPanelViewController.resetTranslation();
+        mNotificationPanelViewController.resetViewGroupFade();
+        updateDozingState();
+        updateScrimController();
+        Trace.endSection();
+        return staying;
+    }
+
+    private void releaseGestureWakeLock() {
+        if (mGestureWakeLock.isHeld()) {
+            mGestureWakeLock.release();
+        }
+    }
+
+    /**
+     * Notifies the status bar that Keyguard is going away very soon.
+     */
+    @Override
+    public void keyguardGoingAway() {
+        // Treat Keyguard exit animation as an app transition to achieve nice transition for status
+        // bar.
+        mKeyguardStateController.notifyKeyguardGoingAway(true);
+        mCommandQueue.appTransitionPending(mDisplayId, true /* forced */);
+        updateScrimController();
+    }
+
+    /**
+     * Notifies the status bar the Keyguard is fading away with the specified timings.
+     *  @param startTime the start time of the animations in uptime millis
+     * @param delay the precalculated animation delay in milliseconds
+     * @param fadeoutDuration the duration of the exit animation, in milliseconds
+     * @param isBypassFading is this a fading away animation while bypassing
+     */
+    @Override
+    public void setKeyguardFadingAway(long startTime, long delay, long fadeoutDuration,
+            boolean isBypassFading) {
+        mCommandQueue.appTransitionStarting(mDisplayId, startTime + fadeoutDuration
+                        - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION,
+                LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true);
+        mCommandQueue.recomputeDisableFlags(mDisplayId, fadeoutDuration > 0 /* animate */);
+        mCommandQueue.appTransitionStarting(mDisplayId,
+                    startTime - LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION,
+                    LightBarTransitionsController.DEFAULT_TINT_ANIMATION_DURATION, true);
+        mKeyguardStateController.notifyKeyguardFadingAway(delay, fadeoutDuration, isBypassFading);
+    }
+
+    /**
+     * Notifies that the Keyguard fading away animation is done.
+     */
+    @Override
+    public void finishKeyguardFadingAway() {
+        mKeyguardStateController.notifyKeyguardDoneFading();
+        mScrimController.setExpansionAffectsAlpha(true);
+
+        // If the device was re-locked while unlocking, we might have a pending lock that was
+        // delayed because the keyguard was in the middle of going away.
+        mKeyguardViewMediator.maybeHandlePendingLock();
+    }
+
+    /**
+     * Switches theme from light to dark and vice-versa.
+     */
+    protected void updateTheme() {
+        // Set additional scrim only if the lock and system wallpaper are different to prevent
+        // applying the dimming effect twice.
+        mUiBgExecutor.execute(() -> {
+            float dimAmount = 0f;
+            if (mWallpaperManager.lockScreenWallpaperExists()) {
+                dimAmount = mWallpaperManager.getWallpaperDimAmount();
+            }
+            final float scrimDimAmount = dimAmount;
+            mMainExecutor.execute(() -> {
+                mScrimController.setAdditionalScrimBehindAlphaKeyguard(scrimDimAmount);
+                mScrimController.applyCompositeAlphaOnScrimBehindKeyguard();
+            });
+        });
+
+        // Lock wallpaper defines the color of the majority of the views, hence we'll use it
+        // to set our default theme.
+        final boolean lockDarkText = mColorExtractor.getNeutralColors().supportsDarkText();
+        final int themeResId = lockDarkText ? R.style.Theme_SystemUI_LightWallpaper
+                : R.style.Theme_SystemUI;
+        if (mContext.getThemeResId() != themeResId) {
+            mContext.setTheme(themeResId);
+            mConfigurationController.notifyThemeChanged();
+        }
+    }
+
+    private void updateDozingState() {
+        Trace.traceCounter(Trace.TRACE_TAG_APP, "dozing", mDozing ? 1 : 0);
+        Trace.beginSection("CentralSurfaces#updateDozingState");
+
+        boolean visibleNotOccluded = mStatusBarKeyguardViewManager.isShowing()
+                && !mStatusBarKeyguardViewManager.isOccluded();
+        // If we're dozing and we'll be animating the screen off, the keyguard isn't currently
+        // visible but will be shortly for the animation, so we should proceed as if it's visible.
+        boolean visibleNotOccludedOrWillBe =
+                visibleNotOccluded || (mDozing && mDozeParameters.shouldDelayKeyguardShow());
+
+        boolean wakeAndUnlock = mBiometricUnlockController.getMode()
+                == BiometricUnlockController.MODE_WAKE_AND_UNLOCK;
+        boolean animate = (!mDozing && mDozeServiceHost.shouldAnimateWakeup() && !wakeAndUnlock)
+                || (mDozing && mDozeParameters.shouldControlScreenOff()
+                && visibleNotOccludedOrWillBe);
+
+        mNotificationPanelViewController.setDozing(mDozing, animate, mWakeUpTouchLocation);
+        updateQsExpansionEnabled();
+        Trace.endSection();
+    }
+
+    @Override
+    public void userActivity() {
+        if (mState == StatusBarState.KEYGUARD) {
+            mKeyguardViewMediatorCallback.userActivity();
+        }
+    }
+
+    @Override
+    public boolean interceptMediaKey(KeyEvent event) {
+        return mState == StatusBarState.KEYGUARD
+                && mStatusBarKeyguardViewManager.interceptMediaKey(event);
+    }
+
+    /**
+     * While IME is active and a BACK event is detected, check with
+     * {@link StatusBarKeyguardViewManager#dispatchBackKeyEventPreIme()} to see if the event
+     * should be handled before routing to IME, in order to prevent the user having to hit back
+     * twice to exit bouncer.
+     */
+    @Override
+    public boolean dispatchKeyEventPreIme(KeyEvent event) {
+        switch (event.getKeyCode()) {
+            case KeyEvent.KEYCODE_BACK:
+                if (mState == StatusBarState.KEYGUARD
+                        && mStatusBarKeyguardViewManager.dispatchBackKeyEventPreIme()) {
+                    return onBackPressed();
+                }
+        }
+        return false;
+    }
+
+    protected boolean shouldUnlockOnMenuPressed() {
+        return mDeviceInteractive && mState != StatusBarState.SHADE
+            && mStatusBarKeyguardViewManager.shouldDismissOnMenuPressed();
+    }
+
+    @Override
+    public boolean onMenuPressed() {
+        if (shouldUnlockOnMenuPressed()) {
+            mShadeController.animateCollapsePanels(
+                    CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL /* flags */, true /* force */);
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void endAffordanceLaunch() {
+        releaseGestureWakeLock();
+        mNotificationPanelViewController.onAffordanceLaunchEnded();
+    }
+
+    @Override
+    public boolean onBackPressed() {
+        final boolean isScrimmedBouncer =
+                mScrimController.getState() == ScrimState.BOUNCER_SCRIMMED;
+        final boolean isBouncerOverDream = isBouncerShowingOverDream();
+
+        if (mStatusBarKeyguardViewManager.onBackPressed(
+                isScrimmedBouncer || isBouncerOverDream /* hideImmediately */)) {
+            if (isScrimmedBouncer || isBouncerOverDream) {
+                mStatusBarStateController.setLeaveOpenOnKeyguardHide(false);
+            } else {
+                mNotificationPanelViewController.expandWithoutQs();
+            }
+            return true;
+        }
+        if (mNotificationPanelViewController.isQsCustomizing()) {
+            mNotificationPanelViewController.closeQsCustomizer();
+            return true;
+        }
+        if (mNotificationPanelViewController.isQsExpanded()) {
+            if (mNotificationPanelViewController.isQsDetailShowing()) {
+                mNotificationPanelViewController.closeQsDetail();
+            } else {
+                mNotificationPanelViewController.animateCloseQs(false /* animateAway */);
+            }
+            return true;
+        }
+        if (mNotificationPanelViewController.closeUserSwitcherIfOpen()) {
+            return true;
+        }
+        if (mState != StatusBarState.KEYGUARD && mState != StatusBarState.SHADE_LOCKED
+                && !isBouncerOverDream) {
+            if (mNotificationPanelViewController.canPanelBeCollapsed()) {
+                mShadeController.animateCollapsePanels();
+            }
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean onSpacePressed() {
+        if (mDeviceInteractive && mState != StatusBarState.SHADE) {
+            mShadeController.animateCollapsePanels(
+                    CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL /* flags */, true /* force */);
+            return true;
+        }
+        return false;
+    }
+
+    private void showBouncerOrLockScreenIfKeyguard() {
+        // If the keyguard is animating away, we aren't really the keyguard anymore and should not
+        // show the bouncer/lockscreen.
+        if (!mKeyguardViewMediator.isHiding()
+                && !mKeyguardUnlockAnimationController.isPlayingCannedUnlockAnimation()) {
+            if (mState == StatusBarState.SHADE_LOCKED
+                    && mKeyguardUpdateMonitor.isUdfpsEnrolled()) {
+                // shade is showing while locked on the keyguard, so go back to showing the
+                // lock screen where users can use the UDFPS affordance to enter the device
+                mStatusBarKeyguardViewManager.reset(true);
+            } else if ((mState == StatusBarState.KEYGUARD
+                    && !mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing())
+                    || mState == StatusBarState.SHADE_LOCKED) {
+                mStatusBarKeyguardViewManager.showGenericBouncer(true /* scrimmed */);
+            }
+        }
+    }
+
+    /**
+     * Show the bouncer if we're currently on the keyguard or shade locked and aren't hiding.
+     * @param performAction the action to perform when the bouncer is dismissed.
+     * @param cancelAction the action to perform when unlock is aborted.
+     */
+    @Override
+    public void showBouncerWithDimissAndCancelIfKeyguard(OnDismissAction performAction,
+            Runnable cancelAction) {
+        if ((mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED)
+                && !mKeyguardViewMediator.isHiding()) {
+            mStatusBarKeyguardViewManager.dismissWithAction(performAction, cancelAction,
+                    false /* afterKeyguardGone */);
+        } else if (cancelAction != null) {
+            cancelAction.run();
+        }
+    }
+
+    @Override
+    public void instantCollapseNotificationPanel() {
+        mNotificationPanelViewController.instantCollapse();
+        mShadeController.runPostCollapseRunnables();
+    }
+
+    /**
+     * Collapse the panel directly if we are on the main thread, post the collapsing on the main
+     * thread if we are not.
+     */
+    @Override
+    public void collapsePanelOnMainThread() {
+        if (Looper.getMainLooper().isCurrentThread()) {
+            mShadeController.collapsePanel();
+        } else {
+            mContext.getMainExecutor().execute(mShadeController::collapsePanel);
+        }
+    }
+
+    /** Collapse the panel. The collapsing will be animated for the given {@code duration}. */
+    @Override
+    public void collapsePanelWithDuration(int duration) {
+        mNotificationPanelViewController.collapseWithDuration(duration);
+    }
+
+    /**
+     * Updates the light reveal effect to reflect the reason we're waking or sleeping (for example,
+     * from the power button).
+     * @param wakingUp Whether we're updating because we're waking up (true) or going to sleep
+     *                 (false).
+     */
+    private void updateRevealEffect(boolean wakingUp) {
+        if (mLightRevealScrim == null) {
+            return;
+        }
+
+        final boolean wakingUpFromPowerButton = wakingUp
+                && !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)
+                && mWakefulnessLifecycle.getLastWakeReason()
+                == PowerManager.WAKE_REASON_POWER_BUTTON;
+        final boolean sleepingFromPowerButton = !wakingUp
+                && mWakefulnessLifecycle.getLastSleepReason()
+                == PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON;
+
+        if (wakingUpFromPowerButton || sleepingFromPowerButton) {
+            mLightRevealScrim.setRevealEffect(mPowerButtonReveal);
+            mLightRevealScrim.setRevealAmount(1f - mStatusBarStateController.getDozeAmount());
+        } else if (!wakingUp || !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)) {
+            // If we're going to sleep, but it's not from the power button, use the default reveal.
+            // If we're waking up, only use the default reveal if the biometric controller didn't
+            // already set it to the circular reveal because we're waking up from a fingerprint/face
+            // auth.
+            mLightRevealScrim.setRevealEffect(LiftReveal.INSTANCE);
+            mLightRevealScrim.setRevealAmount(1f - mStatusBarStateController.getDozeAmount());
+        }
+    }
+
+    @Override
+    public LightRevealScrim getLightRevealScrim() {
+        return mLightRevealScrim;
+    }
+
+    @Override
+    public void onTrackingStarted() {
+        mShadeController.runPostCollapseRunnables();
+    }
+
+    @Override
+    public void onClosingFinished() {
+        mShadeController.runPostCollapseRunnables();
+        if (!mPresenter.isPresenterFullyCollapsed()) {
+            // if we set it not to be focusable when collapsing, we have to undo it when we aborted
+            // the closing
+            mNotificationShadeWindowController.setNotificationShadeFocusable(true);
+        }
+    }
+
+    @Override
+    public void onUnlockHintStarted() {
+        mFalsingCollector.onUnlockHintStarted();
+        mKeyguardIndicationController.showActionToUnlock();
+    }
+
+    @Override
+    public void onHintFinished() {
+        // Delay the reset a bit so the user can read the text.
+        mKeyguardIndicationController.hideTransientIndicationDelayed(HINT_RESET_DELAY_MS);
+    }
+
+    @Override
+    public void onCameraHintStarted() {
+        mFalsingCollector.onCameraHintStarted();
+        mKeyguardIndicationController.showTransientIndication(R.string.camera_hint);
+    }
+
+    @Override
+    public void onVoiceAssistHintStarted() {
+        mFalsingCollector.onLeftAffordanceHintStarted();
+        mKeyguardIndicationController.showTransientIndication(R.string.voice_hint);
+    }
+
+    @Override
+    public void onPhoneHintStarted() {
+        mFalsingCollector.onLeftAffordanceHintStarted();
+        mKeyguardIndicationController.showTransientIndication(R.string.phone_hint);
+    }
+
+    @Override
+    public void onTrackingStopped(boolean expand) {
+        if (mState == StatusBarState.KEYGUARD || mState == StatusBarState.SHADE_LOCKED) {
+            if (!expand && !mKeyguardStateController.canDismissLockScreen()) {
+                mStatusBarKeyguardViewManager.showBouncer(false /* scrimmed */);
+            }
+        }
+    }
+
+    // TODO: Figure out way to remove these.
+    @Override
+    public NavigationBarView getNavigationBarView() {
+        return mNavigationBarController.getNavigationBarView(mDisplayId);
+    }
+
+    @Override
+    public boolean isOverviewEnabled() {
+        return mNavigationBarController.isOverviewEnabled(mDisplayId);
+    }
+
+    @Override
+    public void showPinningEnterExitToast(boolean entering) {
+        mNavigationBarController.showPinningEnterExitToast(mDisplayId, entering);
+    }
+
+    @Override
+    public void showPinningEscapeToast() {
+        mNavigationBarController.showPinningEscapeToast(mDisplayId);
+    }
+
+    /**
+     * TODO: Remove this method. Views should not be passed forward. Will cause theme issues.
+     * @return bottom area view
+     */
+    @Override
+    public KeyguardBottomAreaView getKeyguardBottomAreaView() {
+        return mNotificationPanelViewController.getKeyguardBottomAreaView();
+    }
+
+    /**
+     * Propagation of the bouncer state, indicating that it's fully visible.
+     */
+    @Override
+    public void setBouncerShowing(boolean bouncerShowing) {
+        mBouncerShowing = bouncerShowing;
+        mKeyguardBypassController.setBouncerShowing(bouncerShowing);
+        mPulseExpansionHandler.setBouncerShowing(bouncerShowing);
+        setBouncerShowingForStatusBarComponents(bouncerShowing);
+        mStatusBarHideIconsForBouncerManager.setBouncerShowingAndTriggerUpdate(bouncerShowing);
+        mCommandQueue.recomputeDisableFlags(mDisplayId, true /* animate */);
+        updateScrimController();
+        if (!mBouncerShowing) {
+            updatePanelExpansionForKeyguard();
+        }
+    }
+
+    /**
+     * Sets whether the bouncer over dream is showing. Note that the bouncer over dream is handled
+     * independently of the rest of the notification panel. As a result, setting this state via
+     * {@link #setBouncerShowing(boolean)} leads to unintended side effects from states modified
+     * behind the dream.
+     */
+    @Override
+    public void setBouncerShowingOverDream(boolean bouncerShowingOverDream) {
+        mBouncerShowingOverDream = bouncerShowingOverDream;
+    }
+  
+    /**
+     * Propagate the bouncer state to status bar components.
+     *
+     * Separate from {@link #setBouncerShowing} because we sometimes re-create the status bar and
+     * should update only the status bar components.
+     */
+    private void setBouncerShowingForStatusBarComponents(boolean bouncerShowing) {
+        int importance = bouncerShowing
+                ? IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
+                : IMPORTANT_FOR_ACCESSIBILITY_AUTO;
+        if (mPhoneStatusBarViewController != null) {
+            mPhoneStatusBarViewController.setImportantForAccessibility(importance);
+        }
+        mNotificationPanelViewController.setImportantForAccessibility(importance);
+        mNotificationPanelViewController.setBouncerShowing(bouncerShowing);
+    }
+
+    /**
+     * Collapses the notification shade if it is tracking or expanded.
+     */
+    @Override
+    public void collapseShade() {
+        if (mNotificationPanelViewController.isTracking()) {
+            mNotificationShadeWindowViewController.cancelCurrentTouch();
+        }
+        if (mPanelExpanded && mState == StatusBarState.SHADE) {
+            mShadeController.animateCollapsePanels();
+        }
+    }
+
+    @VisibleForTesting
+    final WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() {
+        @Override
+        public void onFinishedGoingToSleep() {
+            mNotificationPanelViewController.onAffordanceLaunchEnded();
+            releaseGestureWakeLock();
+            mLaunchCameraWhenFinishedWaking = false;
+            mDeviceInteractive = false;
+            mWakeUpComingFromTouch = false;
+            mWakeUpTouchLocation = null;
+            updateVisibleToUser();
+
+            updateNotificationPanelTouchState();
+            mNotificationShadeWindowViewController.cancelCurrentTouch();
+            if (mLaunchCameraOnFinishedGoingToSleep) {
+                mLaunchCameraOnFinishedGoingToSleep = false;
+
+                // This gets executed before we will show Keyguard, so post it in order that the state
+                // is correct.
+                mMainExecutor.execute(() -> mCommandQueueCallbacks.onCameraLaunchGestureDetected(
+                        mLastCameraLaunchSource));
+            }
+
+            if (mLaunchEmergencyActionOnFinishedGoingToSleep) {
+                mLaunchEmergencyActionOnFinishedGoingToSleep = false;
+
+                // This gets executed before we will show Keyguard, so post it in order that the
+                // state is correct.
+                mMainExecutor.execute(
+                        () -> mCommandQueueCallbacks.onEmergencyActionLaunchGestureDetected());
+            }
+            updateIsKeyguard();
+        }
+
+        @Override
+        public void onStartedGoingToSleep() {
+            String tag = "CentralSurfaces#onStartedGoingToSleep";
+            DejankUtils.startDetectingBlockingIpcs(tag);
+
+            //  cancel stale runnables that could put the device in the wrong state
+            cancelAfterLaunchTransitionRunnables();
+
+            updateRevealEffect(false /* wakingUp */);
+            updateNotificationPanelTouchState();
+            maybeEscalateHeadsUp();
+            dismissVolumeDialog();
+            mWakeUpCoordinator.setFullyAwake(false);
+            mKeyguardBypassController.onStartedGoingToSleep();
+
+            // The unlocked screen off and fold to aod animations might use our LightRevealScrim -
+            // we need to be expanded for it to be visible.
+            if (mDozeParameters.shouldShowLightRevealScrim()) {
+                makeExpandedVisible(true);
+            }
+
+            DejankUtils.stopDetectingBlockingIpcs(tag);
+        }
+
+        @Override
+        public void onStartedWakingUp() {
+            String tag = "CentralSurfaces#onStartedWakingUp";
+            DejankUtils.startDetectingBlockingIpcs(tag);
+            mNotificationShadeWindowController.batchApplyWindowLayoutParams(()-> {
+                mDeviceInteractive = true;
+                mWakeUpCoordinator.setWakingUp(true);
+                if (!mKeyguardBypassController.getBypassEnabled()) {
+                    mHeadsUpManager.releaseAllImmediately();
+                }
+                updateVisibleToUser();
+                updateIsKeyguard();
+                mDozeServiceHost.stopDozing();
+                // This is intentionally below the stopDozing call above, since it avoids that we're
+                // unnecessarily animating the wakeUp transition. Animations should only be enabled
+                // once we fully woke up.
+                updateRevealEffect(true /* wakingUp */);
+                updateNotificationPanelTouchState();
+
+                // If we are waking up during the screen off animation, we should undo making the
+                // expanded visible (we did that so the LightRevealScrim would be visible).
+                if (mScreenOffAnimationController.shouldHideLightRevealScrimOnWakeUp()) {
+                    makeExpandedInvisible();
+                }
+
+            });
+            DejankUtils.stopDetectingBlockingIpcs(tag);
+        }
+
+        @Override
+        public void onFinishedWakingUp() {
+            mWakeUpCoordinator.setFullyAwake(true);
+            mWakeUpCoordinator.setWakingUp(false);
+            if (mLaunchCameraWhenFinishedWaking) {
+                mNotificationPanelViewController.launchCamera(
+                        false /* animate */, mLastCameraLaunchSource);
+                mLaunchCameraWhenFinishedWaking = false;
+            }
+            if (mLaunchEmergencyActionWhenFinishedWaking) {
+                mLaunchEmergencyActionWhenFinishedWaking = false;
+                Intent emergencyIntent = getEmergencyActionIntent();
+                if (emergencyIntent != null) {
+                    mContext.startActivityAsUser(emergencyIntent,
+                            getActivityUserHandle(emergencyIntent));
+                }
+            }
+            updateScrimController();
+        }
+    };
+
+    /**
+     * We need to disable touch events because these might
+     * collapse the panel after we expanded it, and thus we would end up with a blank
+     * Keyguard.
+     */
+    @Override
+    public void updateNotificationPanelTouchState() {
+        boolean goingToSleepWithoutAnimation = isGoingToSleep()
+                && !mDozeParameters.shouldControlScreenOff();
+        boolean disabled = (!mDeviceInteractive && !mDozeServiceHost.isPulsing())
+                || goingToSleepWithoutAnimation;
+        mNotificationPanelViewController.setTouchAndAnimationDisabled(disabled);
+        mNotificationIconAreaController.setAnimationsEnabled(!disabled);
+    }
+
+    final ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() {
+        @Override
+        public void onScreenTurningOn(Runnable onDrawn) {
+            mFalsingCollector.onScreenTurningOn();
+            mNotificationPanelViewController.onScreenTurningOn();
+        }
+
+        @Override
+        public void onScreenTurnedOn() {
+            mScrimController.onScreenTurnedOn();
+        }
+
+        @Override
+        public void onScreenTurnedOff() {
+            Trace.beginSection("CentralSurfaces#onScreenTurnedOff");
+            mFalsingCollector.onScreenOff();
+            mScrimController.onScreenTurnedOff();
+            if (mCloseQsBeforeScreenOff) {
+                mNotificationPanelViewController.closeQs();
+                mCloseQsBeforeScreenOff = false;
+            }
+            updateIsKeyguard();
+            Trace.endSection();
+        }
+    };
+
+    @Override
+    public int getWakefulnessState() {
+        return mWakefulnessLifecycle.getWakefulness();
+    }
+
+    /**
+     * @return true if the screen is currently fully off, i.e. has finished turning off and has
+     * since not started turning on.
+     */
+    @Override
+    public boolean isScreenFullyOff() {
+        return mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_OFF;
+    }
+
+    @Override
+    public void showScreenPinningRequest(int taskId, boolean allowCancel) {
+        mScreenPinningRequest.showPrompt(taskId, allowCancel);
+    }
+
+    @Nullable
+    @Override
+    public Intent getEmergencyActionIntent() {
+        Intent emergencyIntent = new Intent(EmergencyGesture.ACTION_LAUNCH_EMERGENCY);
+        PackageManager pm = mContext.getPackageManager();
+        List<ResolveInfo> emergencyActivities = pm.queryIntentActivities(emergencyIntent,
+                PackageManager.MATCH_SYSTEM_ONLY);
+        ResolveInfo resolveInfo = getTopEmergencySosInfo(emergencyActivities);
+        if (resolveInfo == null) {
+            Log.wtf(TAG, "Couldn't find an app to process the emergency intent.");
+            return null;
+        }
+        emergencyIntent.setComponent(new ComponentName(resolveInfo.activityInfo.packageName,
+                resolveInfo.activityInfo.name));
+        emergencyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        return emergencyIntent;
+    }
+
+    /**
+     * Select and return the "best" ResolveInfo for Emergency SOS Activity.
+     */
+    private @Nullable ResolveInfo getTopEmergencySosInfo(List<ResolveInfo> emergencyActivities) {
+        // No matched activity.
+        if (emergencyActivities == null || emergencyActivities.isEmpty()) {
+            return null;
+        }
+
+        // Of multiple matched Activities, give preference to the pre-set package name.
+        String preferredAppPackageName =
+                mContext.getString(R.string.config_preferredEmergencySosPackage);
+
+        // If there is no preferred app, then return first match.
+        if (TextUtils.isEmpty(preferredAppPackageName)) {
+            return emergencyActivities.get(0);
+        }
+
+        for (ResolveInfo emergencyInfo: emergencyActivities) {
+            // If activity is from the preferred app, use it.
+            if (TextUtils.equals(emergencyInfo.activityInfo.packageName, preferredAppPackageName)) {
+                return emergencyInfo;
+            }
+        }
+        // No matching activity: return first match
+        return emergencyActivities.get(0);
+    }
+
+    @Override
+    public boolean isCameraAllowedByAdmin() {
+        if (mDevicePolicyManager.getCameraDisabled(null,
+                mLockscreenUserManager.getCurrentUserId())) {
+            return false;
+        } else if (mStatusBarKeyguardViewManager == null
+                || (isKeyguardShowing() && isKeyguardSecure())) {
+            // Check if the admin has disabled the camera specifically for the keyguard
+            return (mDevicePolicyManager.getKeyguardDisabledFeatures(null,
+                    mLockscreenUserManager.getCurrentUserId())
+                    & DevicePolicyManager.KEYGUARD_DISABLE_SECURE_CAMERA) == 0;
+        }
+        return true;
+    }
+
+    @Override
+    public boolean isGoingToSleep() {
+        return mWakefulnessLifecycle.getWakefulness()
+                == WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP;
+    }
+
+    boolean isWakingOrAwake() {
+        return mWakefulnessLifecycle.getWakefulness() == WakefulnessLifecycle.WAKEFULNESS_WAKING
+                || mWakefulnessLifecycle.getWakefulness() == WakefulnessLifecycle.WAKEFULNESS_AWAKE;
+    }
+
+    @Override
+    public void notifyBiometricAuthModeChanged() {
+        mDozeServiceHost.updateDozing();
+        updateScrimController();
+    }
+
+    /**
+     * Set the amount of progress we are currently in if we're transitioning to the full shade.
+     * 0.0f means we're not transitioning yet, while 1 means we're all the way in the full
+     * shade.
+     */
+    @Override
+    public void setTransitionToFullShadeProgress(float transitionToFullShadeProgress) {
+        mTransitionToFullShadeProgress = transitionToFullShadeProgress;
+    }
+
+    /**
+     * Sets the amount of progress to the bouncer being fully hidden/visible. 1 means the bouncer
+     * is fully hidden, while 0 means the bouncer is visible.
+     */
+    @Override
+    public void setBouncerHiddenFraction(float expansion) {
+        mScrimController.setBouncerHiddenFraction(expansion);
+    }
+
+    @Override
+    @VisibleForTesting
+    public void updateScrimController() {
+        Trace.beginSection("CentralSurfaces#updateScrimController");
+
+        boolean unlocking = mKeyguardStateController.isShowing() && (
+                mBiometricUnlockController.isWakeAndUnlock()
+                        || mKeyguardStateController.isKeyguardFadingAway()
+                        || mKeyguardStateController.isKeyguardGoingAway()
+                        || mKeyguardViewMediator.requestedShowSurfaceBehindKeyguard()
+                        || mKeyguardViewMediator.isAnimatingBetweenKeyguardAndSurfaceBehind());
+
+        mScrimController.setExpansionAffectsAlpha(!unlocking);
+
+        boolean launchingAffordanceWithPreview =
+                mNotificationPanelViewController.isLaunchingAffordanceWithPreview();
+        mScrimController.setLaunchingAffordanceWithPreview(launchingAffordanceWithPreview);
+
+        if (mStatusBarKeyguardViewManager.isShowingAlternateAuth()) {
+            if (mState == StatusBarState.SHADE || mState == StatusBarState.SHADE_LOCKED
+                    || mTransitionToFullShadeProgress > 0f) {
+                mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED_SHADE);
+            } else {
+                mScrimController.transitionTo(ScrimState.AUTH_SCRIMMED);
+            }
+        } else if (mBouncerShowing && !unlocking) {
+            // Bouncer needs the front scrim when it's on top of an activity,
+            // tapping on a notification, editing QS or being dismissed by
+            // FLAG_DISMISS_KEYGUARD_ACTIVITY.
+            ScrimState state = mStatusBarKeyguardViewManager.bouncerNeedsScrimming()
+                    ? ScrimState.BOUNCER_SCRIMMED : ScrimState.BOUNCER;
+            mScrimController.transitionTo(state);
+        } else if (launchingAffordanceWithPreview) {
+            // We want to avoid animating when launching with a preview.
+            mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
+        } else if (mBrightnessMirrorVisible) {
+            mScrimController.transitionTo(ScrimState.BRIGHTNESS_MIRROR);
+        } else if (mState == StatusBarState.SHADE_LOCKED) {
+            mScrimController.transitionTo(ScrimState.SHADE_LOCKED);
+        } else if (mDozeServiceHost.isPulsing()) {
+            mScrimController.transitionTo(ScrimState.PULSING,
+                    mDozeScrimController.getScrimCallback());
+        } else if (mDozeServiceHost.hasPendingScreenOffCallback()) {
+            mScrimController.transitionTo(ScrimState.OFF, new ScrimController.Callback() {
+                @Override
+                public void onFinished() {
+                    mDozeServiceHost.executePendingScreenOffCallback();
+                }
+            });
+        } else if (mDozing && !unlocking) {
+            mScrimController.transitionTo(ScrimState.AOD);
+        } else if (mKeyguardStateController.isShowing() && !isOccluded() && !unlocking) {
+            mScrimController.transitionTo(ScrimState.KEYGUARD);
+        } else if (mKeyguardStateController.isShowing() && mKeyguardUpdateMonitor.isDreaming()) {
+            mScrimController.transitionTo(ScrimState.DREAMING);
+        } else {
+            mScrimController.transitionTo(ScrimState.UNLOCKED, mUnlockScrimCallback);
+        }
+        updateLightRevealScrimVisibility();
+
+        Trace.endSection();
+    }
+
+    @Override
+    public boolean isKeyguardShowing() {
+        if (mStatusBarKeyguardViewManager == null) {
+            Slog.i(TAG, "isKeyguardShowing() called before startKeyguard(), returning true");
+            return true;
+        }
+        return mStatusBarKeyguardViewManager.isShowing();
+    }
+
+    @Override
+    public boolean shouldIgnoreTouch() {
+        return (mStatusBarStateController.isDozing()
+                && mDozeServiceHost.getIgnoreTouchWhilePulsing())
+                || mScreenOffAnimationController.shouldIgnoreKeyguardTouches();
+    }
+
+    // Begin Extra BaseStatusBar methods.
+
+    protected final CommandQueue mCommandQueue;
+    protected IStatusBarService mBarService;
+
+    // all notifications
+    protected NotificationStackScrollLayout mStackScroller;
+
+    // handling reordering
+    private final VisualStabilityManager mVisualStabilityManager;
+
+    protected AccessibilityManager mAccessibilityManager;
+
+    protected boolean mDeviceInteractive;
+
+    protected boolean mVisible;
+
+    // mScreenOnFromKeyguard && mVisible.
+    private boolean mVisibleToUser;
+
+    protected DevicePolicyManager mDevicePolicyManager;
+    private final PowerManager mPowerManager;
+    protected StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+
+    protected KeyguardManager mKeyguardManager;
+    private final DeviceProvisionedController mDeviceProvisionedController;
+
+    private final NavigationBarController mNavigationBarController;
+    private final AccessibilityFloatingMenuController mAccessibilityFloatingMenuController;
+
+    // UI-specific methods
+
+    protected WindowManager mWindowManager;
+    protected IWindowManager mWindowManagerService;
+    private IDreamManager mDreamManager;
+
+    protected Display mDisplay;
+    private int mDisplayId;
+
+    protected NotificationShelfController mNotificationShelfController;
+
+    private final Lazy<AssistManager> mAssistManagerLazy;
+
+    @Override
+    public boolean isDeviceInteractive() {
+        return mDeviceInteractive;
+    }
+
+    private final BroadcastReceiver mBannerActionBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+            if (BANNER_ACTION_CANCEL.equals(action) || BANNER_ACTION_SETUP.equals(action)) {
+                NotificationManager noMan = (NotificationManager)
+                        mContext.getSystemService(Context.NOTIFICATION_SERVICE);
+                noMan.cancel(com.android.internal.messages.nano.SystemMessageProto.SystemMessage.
+                        NOTE_HIDDEN_NOTIFICATIONS);
+
+                Settings.Secure.putInt(mContext.getContentResolver(),
+                        Settings.Secure.SHOW_NOTE_ABOUT_NOTIFICATION_HIDING, 0);
+                if (BANNER_ACTION_SETUP.equals(action)) {
+                    mShadeController.animateCollapsePanels(CommandQueue.FLAG_EXCLUDE_RECENTS_PANEL,
+                            true /* force */);
+                    mContext.startActivity(new Intent(Settings.ACTION_APP_NOTIFICATION_REDACTION)
+                            .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+
+                    );
+                }
+            }
+        }
+    };
+
+    @Override
+    public void setNotificationSnoozed(StatusBarNotification sbn, SnoozeOption snoozeOption) {
+        mNotificationsController.setNotificationSnoozed(sbn, snoozeOption);
+    }
+
+
+    @Override
+    public void awakenDreams() {
+        mUiBgExecutor.execute(() -> {
+            try {
+                mDreamManager.awaken();
+            } catch (RemoteException e) {
+                e.printStackTrace();
+            }
+        });
+    }
+
+    protected void toggleKeyboardShortcuts(int deviceId) {
+        KeyboardShortcuts.toggle(mContext, deviceId);
+    }
+
+    protected void dismissKeyboardShortcuts() {
+        KeyboardShortcuts.dismiss();
+    }
+
+    /**
+     * Dismiss the keyguard then execute an action.
+     *
+     * @param action The action to execute after dismissing the keyguard.
+     * @param collapsePanel Whether we should collapse the panel after dismissing the keyguard.
+     * @param willAnimateOnKeyguard Whether {@param action} will run an animation on the keyguard if
+     *                              we are locked.
+     */
+    private void executeActionDismissingKeyguard(Runnable action, boolean afterKeyguardGone,
+            boolean collapsePanel, boolean willAnimateOnKeyguard) {
+        if (!mDeviceProvisionedController.isDeviceProvisioned()) return;
+
+        OnDismissAction onDismissAction = new OnDismissAction() {
+            @Override
+            public boolean onDismiss() {
+                new Thread(() -> {
+                    try {
+                        // The intent we are sending is for the application, which
+                        // won't have permission to immediately start an activity after
+                        // the user switches to home.  We know it is safe to do at this
+                        // point, so make sure new activity switches are now allowed.
+                        ActivityManager.getService().resumeAppSwitches();
+                    } catch (RemoteException e) {
+                    }
+                    action.run();
+                }).start();
+
+                return collapsePanel ? mShadeController.collapsePanel() : willAnimateOnKeyguard;
+            }
+
+            @Override
+            public boolean willRunAnimationOnKeyguard() {
+                return willAnimateOnKeyguard;
+            }
+        };
+        dismissKeyguardThenExecute(onDismissAction, afterKeyguardGone);
+    }
+
+    @Override
+    public void startPendingIntentDismissingKeyguard(final PendingIntent intent) {
+        startPendingIntentDismissingKeyguard(intent, null);
+    }
+
+    @Override
+    public void startPendingIntentDismissingKeyguard(
+            final PendingIntent intent, @Nullable final Runnable intentSentUiThreadCallback) {
+        startPendingIntentDismissingKeyguard(intent, intentSentUiThreadCallback,
+                (ActivityLaunchAnimator.Controller) null);
+    }
+
+    @Override
+    public void startPendingIntentDismissingKeyguard(PendingIntent intent,
+            Runnable intentSentUiThreadCallback, View associatedView) {
+        ActivityLaunchAnimator.Controller animationController = null;
+        if (associatedView instanceof ExpandableNotificationRow) {
+            animationController = mNotificationAnimationProvider.getAnimatorController(
+                    ((ExpandableNotificationRow) associatedView));
+        }
+
+        startPendingIntentDismissingKeyguard(intent, intentSentUiThreadCallback,
+                animationController);
+    }
+
+    @Override
+    public void startPendingIntentDismissingKeyguard(
+            final PendingIntent intent, @Nullable final Runnable intentSentUiThreadCallback,
+            @Nullable ActivityLaunchAnimator.Controller animationController) {
+        final boolean willLaunchResolverActivity = intent.isActivity()
+                && mActivityIntentHelper.wouldLaunchResolverActivity(intent.getIntent(),
+                mLockscreenUserManager.getCurrentUserId());
+
+        boolean animate = !willLaunchResolverActivity
+                && animationController != null
+                && shouldAnimateLaunch(intent.isActivity());
+
+        // If we animate, don't collapse the shade and defer the keyguard dismiss (in case we run
+        // the animation on the keyguard). The animation will take care of (instantly) collapsing
+        // the shade and hiding the keyguard once it is done.
+        boolean collapse = !animate;
+        executeActionDismissingKeyguard(() -> {
+            try {
+                // We wrap animationCallback with a StatusBarLaunchAnimatorController so that the
+                // shade is collapsed after the animation (or when it is cancelled, aborted, etc).
+                ActivityLaunchAnimator.Controller controller =
+                        animationController != null ? new StatusBarLaunchAnimatorController(
+                                animationController, this, intent.isActivity()) : null;
+
+                mActivityLaunchAnimator.startPendingIntentWithAnimation(
+                        controller, animate, intent.getCreatorPackage(),
+                        (animationAdapter) -> {
+                            ActivityOptions options = new ActivityOptions(
+                                    CentralSurfaces.getActivityOptions(
+                                            mDisplayId, animationAdapter));
+                            // TODO b/221255671: restrict this to only be set for notifications
+                            options.setEligibleForLegacyPermissionPrompt(true);
+                            return intent.sendAndReturnResult(null, 0, null, null, null,
+                                    null, options.toBundle());
+                        });
+            } catch (PendingIntent.CanceledException e) {
+                // the stack trace isn't very helpful here.
+                // Just log the exception message.
+                Log.w(TAG, "Sending intent failed: " + e);
+                if (!collapse) {
+                    // executeActionDismissingKeyguard did not collapse for us already.
+                    collapsePanelOnMainThread();
+                }
+                // TODO: Dismiss Keyguard.
+            }
+            if (intent.isActivity()) {
+                mAssistManagerLazy.get().hideAssist();
+            }
+            if (intentSentUiThreadCallback != null) {
+                postOnUiThread(intentSentUiThreadCallback);
+            }
+        }, willLaunchResolverActivity, collapse, animate);
+    }
+
+    private void postOnUiThread(Runnable runnable) {
+        mMainExecutor.execute(runnable);
+    }
+
+    @Override
+    public void visibilityChanged(boolean visible) {
+        if (mVisible != visible) {
+            mVisible = visible;
+            if (!visible) {
+                mGutsManager.closeAndSaveGuts(true /* removeLeavebehind */, true /* force */,
+                        true /* removeControls */, -1 /* x */, -1 /* y */, true /* resetMenu */);
+            }
+        }
+        updateVisibleToUser();
+    }
+
+    protected void updateVisibleToUser() {
+        boolean oldVisibleToUser = mVisibleToUser;
+        mVisibleToUser = mVisible && mDeviceInteractive;
+
+        if (oldVisibleToUser != mVisibleToUser) {
+            handleVisibleToUserChanged(mVisibleToUser);
+        }
+    }
+
+    /**
+     * Clear Buzz/Beep/Blink.
+     */
+    @Override
+    public void clearNotificationEffects() {
+        try {
+            mBarService.clearNotificationEffects();
+        } catch (RemoteException e) {
+            // Won't fail unless the world has ended.
+        }
+    }
+
+    /**
+     * @return Whether the security bouncer from Keyguard is showing.
+     */
+    @Override
+    public boolean isBouncerShowing() {
+        return mBouncerShowing;
+    }
+
+    /**
+     * @return Whether the security bouncer from Keyguard is showing.
+     */
+    @Override
+    public boolean isBouncerShowingScrimmed() {
+        return isBouncerShowing() && mStatusBarKeyguardViewManager.bouncerNeedsScrimming();
+    }
+
+    @Override
+    public boolean isBouncerShowingOverDream() {
+        return mBouncerShowingOverDream;
+    }
+
+    /**
+     * When {@link KeyguardBouncer} starts to be dismissed, playing its animation.
+     */
+    @Override
+    public void onBouncerPreHideAnimation() {
+        mNotificationPanelViewController.onBouncerPreHideAnimation();
+
+    }
+
+    @Override
+    public boolean isKeyguardSecure() {
+        if (mStatusBarKeyguardViewManager == null) {
+            // startKeyguard() hasn't been called yet, so we don't know.
+            // Make sure anything that needs to know isKeyguardSecure() checks and re-checks this
+            // value onVisibilityChanged().
+            Slog.w(TAG, "isKeyguardSecure() called before startKeyguard(), returning false",
+                    new Throwable());
+            return false;
+        }
+        return mStatusBarKeyguardViewManager.isSecure();
+    }
+    @Override
+    public NotificationPanelViewController getPanelController() {
+        return mNotificationPanelViewController;
+    }
+    // End Extra BaseStatusBarMethods.
+
+    @Override
+    public NotificationGutsManager getGutsManager() {
+        return mGutsManager;
+    }
+
+    boolean isTransientShown() {
+        return mTransientShown;
+    }
+
+    private void updateLightRevealScrimVisibility() {
+        if (mLightRevealScrim == null) {
+            // status bar may not be inflated yet
+            return;
+        }
+
+        mLightRevealScrim.setAlpha(mScrimController.getState().getMaxLightRevealScrimAlpha());
+    }
+
+    @Override
+    public void extendDozePulse(){
+        mDozeScrimController.extendPulse();
+    }
+
+    private final KeyguardUpdateMonitorCallback mUpdateCallback =
+            new KeyguardUpdateMonitorCallback() {
+                @Override
+                public void onDreamingStateChanged(boolean dreaming) {
+                    updateScrimController();
+                    if (dreaming) {
+                        maybeEscalateHeadsUp();
+                    }
+                }
+
+                // TODO: (b/145659174) remove when moving to NewNotifPipeline. Replaced by
+                //  KeyguardCoordinator
+                @Override
+                public void onStrongAuthStateChanged(int userId) {
+                    super.onStrongAuthStateChanged(userId);
+                    mNotificationsController.requestNotificationUpdate("onStrongAuthStateChanged");
+                }
+            };
+
+
+    private final FalsingManager.FalsingBeliefListener mFalsingBeliefListener =
+            new FalsingManager.FalsingBeliefListener() {
+                @Override
+                public void onFalse() {
+                    // Hides quick settings, bouncer, and quick-quick settings.
+                    mStatusBarKeyguardViewManager.reset(true);
+                }
+            };
+
+    // Notifies StatusBarKeyguardViewManager every time the keyguard transition is over,
+    // this animation is tied to the scrim for historic reasons.
+    // TODO: notify when keyguard has faded away instead of the scrim.
+    private final ScrimController.Callback mUnlockScrimCallback = new ScrimController
+            .Callback() {
+        @Override
+        public void onFinished() {
+            if (mStatusBarKeyguardViewManager == null) {
+                Log.w(TAG, "Tried to notify keyguard visibility when "
+                        + "mStatusBarKeyguardViewManager was null");
+                return;
+            }
+            if (mKeyguardStateController.isKeyguardFadingAway()) {
+                mStatusBarKeyguardViewManager.onKeyguardFadedAway();
+            }
+        }
+
+        @Override
+        public void onCancelled() {
+            onFinished();
+        }
+    };
+
+    private final DeviceProvisionedListener mUserSetupObserver = new DeviceProvisionedListener() {
+        @Override
+        public void onUserSetupChanged() {
+            final boolean userSetup = mDeviceProvisionedController.isCurrentUserSetup();
+            Log.d(TAG, "mUserSetupObserver - DeviceProvisionedListener called for "
+                    + "current user");
+            if (MULTIUSER_DEBUG) {
+                Log.d(TAG, String.format("User setup changed: userSetup=%s mUserSetup=%s",
+                        userSetup, mUserSetup));
+            }
+
+            if (userSetup != mUserSetup) {
+                mUserSetup = userSetup;
+                if (!mUserSetup) {
+                    animateCollapseQuickSettings();
+                }
+                if (mNotificationPanelViewController != null) {
+                    mNotificationPanelViewController.setUserSetupComplete(mUserSetup);
+                }
+                updateQsExpansionEnabled();
+            }
+        }
+    };
+
+    private final BroadcastReceiver mWallpaperChangedReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (!mWallpaperSupported) {
+                // Receiver should not have been registered at all...
+                Log.wtf(TAG, "WallpaperManager not supported");
+                return;
+            }
+            WallpaperInfo info = mWallpaperManager.getWallpaperInfo(UserHandle.USER_CURRENT);
+            mWallpaperController.onWallpaperInfoUpdated(info);
+
+            final boolean deviceSupportsAodWallpaper = mContext.getResources().getBoolean(
+                    com.android.internal.R.bool.config_dozeSupportsAodWallpaper);
+            // If WallpaperInfo is null, it must be ImageWallpaper.
+            final boolean supportsAmbientMode = deviceSupportsAodWallpaper
+                    && (info != null && info.supportsAmbientMode());
+
+            mNotificationShadeWindowController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
+            mScrimController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
+            mKeyguardViewMediator.setWallpaperSupportsAmbientMode(supportsAmbientMode);
+        }
+    };
+
+    private final ConfigurationListener mConfigurationListener = new ConfigurationListener() {
+        @Override
+        public void onConfigChanged(Configuration newConfig) {
+            updateResources();
+            updateDisplaySize(); // populates mDisplayMetrics
+
+            if (DEBUG) {
+                Log.v(TAG, "configuration changed: " + mContext.getResources().getConfiguration());
+            }
+
+            if (!mNotifPipelineFlags.isNewPipelineEnabled()) {
+                mViewHierarchyManager.updateRowStates();
+            }
+            mScreenPinningRequest.onConfigurationChanged();
+        }
+
+        @Override
+        public void onDensityOrFontScaleChanged() {
+            // TODO: Remove this.
+            if (mBrightnessMirrorController != null) {
+                mBrightnessMirrorController.onDensityOrFontScaleChanged();
+            }
+            // TODO: Bring these out of CentralSurfaces.
+            mUserInfoControllerImpl.onDensityOrFontScaleChanged();
+            mUserSwitcherController.onDensityOrFontScaleChanged();
+            mNotificationIconAreaController.onDensityOrFontScaleChanged(mContext);
+            mHeadsUpManager.onDensityOrFontScaleChanged();
+        }
+
+        @Override
+        public void onThemeChanged() {
+            if (mBrightnessMirrorController != null) {
+                mBrightnessMirrorController.onOverlayChanged();
+            }
+            // We need the new R.id.keyguard_indication_area before recreating
+            // mKeyguardIndicationController
+            mNotificationPanelViewController.onThemeChanged();
+
+            if (mStatusBarKeyguardViewManager != null) {
+                mStatusBarKeyguardViewManager.onThemeChanged();
+            }
+            if (mAmbientIndicationContainer instanceof AutoReinflateContainer) {
+                ((AutoReinflateContainer) mAmbientIndicationContainer).inflateLayout();
+            }
+            mNotificationIconAreaController.onThemeChanged();
+        }
+
+        @Override
+        public void onUiModeChanged() {
+            if (mBrightnessMirrorController != null) {
+                mBrightnessMirrorController.onUiModeChanged();
+            }
+        }
+    };
+
+    private StatusBarStateController.StateListener mStateListener =
+            new StatusBarStateController.StateListener() {
+                @Override
+                public void onStatePreChange(int oldState, int newState) {
+                    // If we're visible and switched to SHADE_LOCKED (the user dragged
+                    // down on the lockscreen), clear notification LED, vibration,
+                    // ringing.
+                    // Other transitions are covered in handleVisibleToUserChanged().
+                    if (mVisible && (newState == StatusBarState.SHADE_LOCKED
+                            || mStatusBarStateController.goingToFullShade())) {
+                        clearNotificationEffects();
+                    }
+                    if (newState == StatusBarState.KEYGUARD) {
+                        mRemoteInputManager.onPanelCollapsed();
+                        maybeEscalateHeadsUp();
+                    }
+                }
+
+                @Override
+                public void onStateChanged(int newState) {
+                    mState = newState;
+                    updateReportRejectedTouchVisibility();
+                    mDozeServiceHost.updateDozing();
+                    updateTheme();
+                    mNavigationBarController.touchAutoDim(mDisplayId);
+                    Trace.beginSection("CentralSurfaces#updateKeyguardState");
+                    if (mState == StatusBarState.KEYGUARD) {
+                        mNotificationPanelViewController.cancelPendingPanelCollapse();
+                    }
+                    updateDozingState();
+                    checkBarModes();
+                    updateScrimController();
+                    mPresenter.updateMediaMetaData(false, mState != StatusBarState.KEYGUARD);
+                    Trace.endSection();
+                }
+
+                @Override
+                public void onDozeAmountChanged(float linear, float eased) {
+                    if (mFeatureFlags.isEnabled(Flags.LOCKSCREEN_ANIMATIONS)
+                            && !(mLightRevealScrim.getRevealEffect() instanceof CircleReveal)) {
+                        mLightRevealScrim.setRevealAmount(1f - linear);
+                    }
+                }
+
+                @Override
+                public void onDozingChanged(boolean isDozing) {
+                    Trace.beginSection("CentralSurfaces#updateDozing");
+                    mDozing = isDozing;
+
+                    // Collapse the notification panel if open
+                    boolean dozingAnimated = mDozeServiceHost.getDozingRequested()
+                            && mDozeParameters.shouldControlScreenOff();
+                    mNotificationPanelViewController.resetViews(dozingAnimated);
+
+                    updateQsExpansionEnabled();
+                    mKeyguardViewMediator.setDozing(mDozing);
+
+                    mNotificationsController.requestNotificationUpdate("onDozingChanged");
+                    updateDozingState();
+                    mDozeServiceHost.updateDozing();
+                    updateScrimController();
+                    updateReportRejectedTouchVisibility();
+                    Trace.endSection();
+                }
+
+                @Override
+                public void onFullscreenStateChanged(boolean isFullscreen) {
+                    mIsFullscreen = isFullscreen;
+                    maybeUpdateBarMode();
+                }
+            };
+
+    private final BatteryController.BatteryStateChangeCallback mBatteryStateChangeCallback =
+            new BatteryController.BatteryStateChangeCallback() {
+                @Override
+                public void onPowerSaveChanged(boolean isPowerSave) {
+                    mMainExecutor.execute(mCheckBarModes);
+                    if (mDozeServiceHost != null) {
+                        mDozeServiceHost.firePowerSaveChanged(isPowerSave);
+                    }
+                }
+            };
+
+    private final ActivityLaunchAnimator.Callback mActivityLaunchAnimatorCallback =
+            new ActivityLaunchAnimator.Callback() {
+                @Override
+                public boolean isOnKeyguard() {
+                    return mKeyguardStateController.isShowing();
+                }
+
+                @Override
+                public void hideKeyguardWithAnimation(IRemoteAnimationRunner runner) {
+                    // We post to the main thread for 2 reasons:
+                    //   1. KeyguardViewMediator is not thread-safe.
+                    //   2. To ensure that ViewMediatorCallback#keyguardDonePending is called before
+                    //      ViewMediatorCallback#readyForKeyguardDone. The wrong order could occur
+                    //      when doing
+                    //      dismissKeyguardThenExecute { hideKeyguardWithAnimation(runner) }.
+                    mMainExecutor.execute(() -> mKeyguardViewMediator.hideWithAnimation(runner));
+                }
+
+                @Override
+                public int getBackgroundColor(TaskInfo task) {
+                    if (!mStartingSurfaceOptional.isPresent()) {
+                        Log.w(TAG, "No starting surface, defaulting to SystemBGColor");
+                        return SplashscreenContentDrawer.getSystemBGColor();
+                    }
+
+                    return mStartingSurfaceOptional.get().getBackgroundColor(task);
+                }
+            };
+
+    private final ActivityLaunchAnimator.Listener mActivityLaunchAnimatorListener =
+            new ActivityLaunchAnimator.Listener() {
+                @Override
+                public void onLaunchAnimationStart() {
+                    mKeyguardViewMediator.setBlursDisabledForAppLaunch(true);
+                }
+
+                @Override
+                public void onLaunchAnimationEnd() {
+                    mKeyguardViewMediator.setBlursDisabledForAppLaunch(false);
+                }
+            };
+
+    private final DemoMode mDemoModeCallback = new DemoMode() {
+        @Override
+        public void onDemoModeFinished() {
+            checkBarModes();
+        }
+
+        @Override
+        public void dispatchDemoCommand(String command, Bundle args) { }
+    };
+
+    /**
+     *  Determines what UserHandle to use when launching an activity.
+     *
+     *  We want to ensure that activities that are launched within the systemui process should be
+     *  launched as user of the current process.
+     * @param intent
+     * @return UserHandle
+     */
+    private UserHandle getActivityUserHandle(Intent intent) {
+        String[] packages = mContext.getResources().getStringArray(R.array.system_ui_packages);
+        for (String pkg : packages) {
+            if (intent.getComponent() == null) break;
+            if (pkg.equals(intent.getComponent().getPackageName())) {
+                return new UserHandle(UserHandle.myUserId());
+            }
+        }
+        return UserHandle.CURRENT;
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LargeScreenShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LargeScreenShadeHeaderController.kt
index 289dfc8..178c17d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LargeScreenShadeHeaderController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LargeScreenShadeHeaderController.kt
@@ -18,9 +18,11 @@
 
 import android.app.StatusBarManager
 import android.view.View
+import android.widget.TextView
 import androidx.constraintlayout.motion.widget.MotionLayout
 import com.android.settingslib.Utils
 import com.android.systemui.Dumpable
+import com.android.systemui.FontSizeUtils
 import com.android.systemui.R
 import com.android.systemui.animation.ShadeInterpolation
 import com.android.systemui.battery.BatteryMeterView
@@ -30,10 +32,12 @@
 import com.android.systemui.flags.Flags
 import com.android.systemui.qs.ChipVisibilityListener
 import com.android.systemui.qs.HeaderPrivacyIconsController
+import com.android.systemui.qs.carrier.QSCarrierGroup
 import com.android.systemui.qs.carrier.QSCarrierGroupController
 import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent.CentralSurfacesScope
 import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.LARGE_SCREEN_BATTERY_CONTROLLER
 import com.android.systemui.statusbar.phone.dagger.StatusBarViewModule.LARGE_SCREEN_SHADE_HEADER
+import com.android.systemui.statusbar.policy.ConfigurationController
 import java.io.PrintWriter
 import javax.inject.Inject
 import javax.inject.Named
@@ -43,6 +47,7 @@
     @Named(LARGE_SCREEN_SHADE_HEADER) private val header: View,
     private val statusBarIconController: StatusBarIconController,
     private val privacyIconsController: HeaderPrivacyIconsController,
+    private val configurationController: ConfigurationController,
     qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder,
     featureFlags: FeatureFlags,
     @Named(LARGE_SCREEN_BATTERY_CONTROLLER) batteryMeterViewController: BatteryMeterViewController,
@@ -69,6 +74,9 @@
     private val iconContainer: StatusIconContainer
     private val carrierIconSlots: List<String>
     private val qsCarrierGroupController: QSCarrierGroupController
+    private val clock: TextView = header.findViewById(R.id.clock)
+    private val date: TextView = header.findViewById(R.id.date)
+    private val qsCarrierGroup: QSCarrierGroup = header.findViewById(R.id.carrier_group)
 
     private var qsDisabled = false
 
@@ -148,9 +156,9 @@
                     .load(context, resources.getXml(R.xml.large_screen_shade_header))
             privacyIconsController.chipVisibilityListener = chipVisibilityListener
         }
-    }
 
-    init {
+        bindConfigurationListener()
+
         batteryMeterViewController.init()
         val batteryIcon: BatteryMeterView = header.findViewById(R.id.batteryRemainingIcon)
 
@@ -194,6 +202,18 @@
         }
     }
 
+    private fun bindConfigurationListener() {
+        val listener = object : ConfigurationController.ConfigurationListener {
+            override fun onDensityOrFontScaleChanged() {
+                val qsStatusStyle = R.style.TextAppearance_QS_Status
+                FontSizeUtils.updateFontSizeFromStyle(clock, qsStatusStyle)
+                FontSizeUtils.updateFontSizeFromStyle(date, qsStatusStyle)
+                qsCarrierGroup.updateTextAppearance(qsStatusStyle)
+            }
+        }
+        configurationController.addCallback(listener)
+    }
+
     private fun onShadeExpandedChanged() {
         if (shadeExpanded) {
             privacyIconsController.startListening()
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 adf70a2..e4f42b1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -1233,6 +1233,11 @@
         mKeyguardBottomArea.initQRCodeScanner(mQRCodeScannerController);
     }
 
+    @VisibleForTesting
+    void setMaxDisplayedNotifications(int maxAllowed) {
+        mMaxAllowedKeyguardNotifications = maxAllowed;
+    }
+
     private void updateMaxDisplayedNotifications(boolean recompute) {
         if (recompute) {
             mMaxAllowedKeyguardNotifications = Math.max(computeMaxKeyguardNotifications(), 1);
@@ -1463,7 +1468,11 @@
     /**
      * @return the maximum keyguard notifications that can fit on the screen
      */
-    private int computeMaxKeyguardNotifications() {
+    @VisibleForTesting
+    int computeMaxKeyguardNotifications() {
+        if (mAmbientState.getFractionToShade() > 0 || mAmbientState.getDozeAmount() > 0) {
+            return mMaxAllowedKeyguardNotifications;
+        }
         float topPadding = mNotificationStackScrollLayoutController.getTopPadding();
         float shelfIntrinsicHeight =
                 mNotificationShelfController.getVisibility() == View.GONE
@@ -3169,12 +3178,6 @@
         mFalsingCollector.onTrackingStarted(!mKeyguardStateController.canDismissLockScreen());
         super.onTrackingStarted();
         mScrimController.onTrackingStarted();
-        // normally we want to set mQsExpandImmediate for every split shade case (at least when
-        // expanding), but keyguard tracking logic is different - this callback is called when
-        // unlocking with swipe up but not when swiping down to reveal shade
-        if (mShouldUseSplitNotificationShade && !mKeyguardShowing) {
-            mQsExpandImmediate = true;
-        }
         if (mQsFullyExpanded) {
             mQsExpandImmediate = true;
             setShowShelfOnly(true);
@@ -4921,6 +4924,12 @@
             mView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
         }
         if (state == STATE_OPENING) {
+            // we need to ignore it on keyguard as this is a false alarm - transition from unlocked
+            // to locked will trigger this event and we're not actually in the process of opening
+            // the shade, lockscreen is just always expanded
+            if (mShouldUseSplitNotificationShade && !isOnKeyguard()) {
+                mQsExpandImmediate = true;
+            }
             mCentralSurfaces.makeExpandedVisible(false);
         }
         if (state == STATE_CLOSED) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java
index 2f11b16..be5b33e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java
@@ -252,7 +252,7 @@
                 }
 
                 if (mStatusBarStateController.isDozing()) {
-                    mService.mDozeScrimController.extendPulse();
+                    mService.extendDozePulse();
                 }
                 mLockIconViewController.onTouchEvent(
                         ev,
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 052a4f7..7f5cef0 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -164,6 +164,10 @@
 
         @Override
         public void onVisibilityChanged(boolean isVisible) {
+            mCentralSurfaces
+                    .setBouncerShowingOverDream(
+                            isVisible && mDreamOverlayStateController.isOverlayActive());
+
             if (!isVisible) {
                 mCentralSurfaces.setBouncerHiddenFraction(KeyguardBouncer.EXPANSION_HIDDEN);
             }
@@ -390,6 +394,11 @@
                     && !mBouncer.isShowing() && !mBouncer.isAnimatingAway()) {
                 mBouncer.show(false /* resetSecuritySelection */, false /* scrimmed */);
             }
+        } else if (!mShowing && mBouncer.inTransit()) {
+            // Keyguard is not visible anymore, but expansion animation was still running.
+            // We need to keep propagating the expansion state to the bouncer, otherwise it will be
+            // stuck in transit.
+            mBouncer.setExpansion(fraction);
         } else if (mPulsing && fraction == KeyguardBouncer.EXPANSION_VISIBLE) {
             // Panel expanded while pulsing but didn't translate the bouncer (because we are
             // unlocked.) Let's simply wake-up to dismiss the lock screen.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java
index 5d38eea..c5e5297 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/CentralSurfacesComponent.java
@@ -31,6 +31,7 @@
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutListContainerModule;
 import com.android.systemui.statusbar.phone.CentralSurfacesCommandQueueCallbacks;
+import com.android.systemui.statusbar.phone.CentralSurfacesImpl;
 import com.android.systemui.statusbar.phone.LargeScreenShadeHeaderController;
 import com.android.systemui.statusbar.phone.NotificationPanelViewController;
 import com.android.systemui.statusbar.phone.NotificationShadeWindowView;
@@ -51,7 +52,7 @@
 
 /**
  * Dagger subcomponent for classes (semi-)related to the status bar. The component is created once
- * inside {@link com.android.systemui.statusbar.phone.CentralSurfaces} and never re-created.
+ * inside {@link CentralSurfacesImpl} 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
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 c024c72..942d186 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
@@ -16,317 +16,22 @@
 
 package com.android.systemui.statusbar.phone.dagger;
 
-import static com.android.systemui.Dependency.TIME_TICK_HANDLER_NAME;
-
-import android.app.WallpaperManager;
-import android.content.Context;
-import android.hardware.devicestate.DeviceStateManager;
-import android.os.Handler;
-import android.os.PowerManager;
-import android.util.DisplayMetrics;
-
-import com.android.internal.jank.InteractionJankMonitor;
-import com.android.internal.logging.MetricsLogger;
-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;
-import com.android.systemui.classifier.FalsingCollector;
-import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.dagger.qualifiers.UiBackground;
-import com.android.systemui.demomode.DemoModeController;
-import com.android.systemui.dreams.DreamOverlayStateController;
-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;
-import com.android.systemui.keyguard.WakefulnessLifecycle;
-import com.android.systemui.navigationbar.NavigationBarController;
-import com.android.systemui.plugins.FalsingManager;
-import com.android.systemui.plugins.PluginDependencyProvider;
-import com.android.systemui.recents.ScreenPinningRequest;
-import com.android.systemui.settings.brightness.BrightnessSliderController;
-import com.android.systemui.shared.plugins.PluginManager;
-import com.android.systemui.statusbar.CommandQueue;
-import com.android.systemui.statusbar.KeyguardIndicationController;
-import com.android.systemui.statusbar.LockscreenShadeTransitionController;
-import com.android.systemui.statusbar.NotificationLockscreenUserManager;
-import com.android.systemui.statusbar.NotificationMediaManager;
-import com.android.systemui.statusbar.NotificationRemoteInputManager;
-import com.android.systemui.statusbar.NotificationShadeDepthController;
-import com.android.systemui.statusbar.NotificationShadeWindowController;
-import com.android.systemui.statusbar.NotificationViewHierarchyManager;
-import com.android.systemui.statusbar.PulseExpansionHandler;
-import com.android.systemui.statusbar.SysuiStatusBarStateController;
-import com.android.systemui.statusbar.charging.WiredChargingRippleController;
-import com.android.systemui.statusbar.connectivity.NetworkController;
-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;
-import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
-import com.android.systemui.statusbar.notification.init.NotificationsController;
-import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
-import com.android.systemui.statusbar.notification.logging.NotificationLogger;
-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.DozeParameters;
-import com.android.systemui.statusbar.phone.DozeScrimController;
-import com.android.systemui.statusbar.phone.DozeServiceHost;
-import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
-import com.android.systemui.statusbar.phone.KeyguardBypassController;
-import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
-import com.android.systemui.statusbar.phone.LightBarController;
-import com.android.systemui.statusbar.phone.LockscreenGestureLogger;
-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.ScreenOffAnimationController;
-import com.android.systemui.statusbar.phone.ScrimController;
-import com.android.systemui.statusbar.phone.ShadeController;
 import com.android.systemui.statusbar.phone.CentralSurfaces;
-import com.android.systemui.statusbar.phone.StatusBarHideIconsForBouncerManager;
-import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
-import com.android.systemui.statusbar.phone.StatusBarSignalPolicy;
-import com.android.systemui.statusbar.phone.StatusBarTouchableRegionManager;
-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.DeviceProvisionedController;
-import com.android.systemui.statusbar.policy.ExtensionController;
-import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.statusbar.policy.UserInfoControllerImpl;
-import com.android.systemui.statusbar.policy.UserSwitcherController;
-import com.android.systemui.statusbar.window.StatusBarWindowController;
-import com.android.systemui.statusbar.window.StatusBarWindowStateController;
-import com.android.systemui.util.WallpaperController;
-import com.android.systemui.util.concurrency.DelayableExecutor;
-import com.android.systemui.util.concurrency.MessageRouter;
-import com.android.systemui.volume.VolumeComponent;
-import com.android.systemui.wmshell.BubblesManager;
-import com.android.wm.shell.bubbles.Bubbles;
-import com.android.wm.shell.startingsurface.StartingSurface;
+import com.android.systemui.statusbar.phone.CentralSurfacesImpl;
 
-import java.util.Optional;
-import java.util.concurrent.Executor;
-
-import javax.inject.Named;
-
-import dagger.Lazy;
+import dagger.Binds;
 import dagger.Module;
-import dagger.Provides;
 
 /**
- * Dagger Module providing {@link CentralSurfaces}.
+ * Dagger Module providing {@link CentralSurfacesImpl}.
  */
 @Module
 public interface StatusBarPhoneModule {
     /**
      * Provides our instance of CentralSurfaces which is considered optional.
      */
-    @Provides
+    @Binds
     @SysUISingleton
-    static CentralSurfaces provideCentralSurfaces(
-            Context context,
-            NotificationsController notificationsController,
-            FragmentService fragmentService,
-            LightBarController lightBarController,
-            AutoHideController autoHideController,
-            StatusBarWindowController statusBarWindowController,
-            StatusBarWindowStateController statusBarWindowStateController,
-            KeyguardUpdateMonitor keyguardUpdateMonitor,
-            StatusBarSignalPolicy statusBarSignalPolicy,
-            PulseExpansionHandler pulseExpansionHandler,
-            NotificationWakeUpCoordinator notificationWakeUpCoordinator,
-            KeyguardBypassController keyguardBypassController,
-            KeyguardStateController keyguardStateController,
-            HeadsUpManagerPhone headsUpManagerPhone,
-            DynamicPrivacyController dynamicPrivacyController,
-            FalsingManager falsingManager,
-            FalsingCollector falsingCollector,
-            BroadcastDispatcher broadcastDispatcher,
-            NotifShadeEventSource notifShadeEventSource,
-            NotificationEntryManager notificationEntryManager,
-            NotificationGutsManager notificationGutsManager,
-            NotificationLogger notificationLogger,
-            NotificationInterruptStateProvider notificationInterruptStateProvider,
-            NotificationViewHierarchyManager notificationViewHierarchyManager,
-            PanelExpansionStateManager panelExpansionStateManager,
-            KeyguardViewMediator keyguardViewMediator,
-            DisplayMetrics displayMetrics,
-            MetricsLogger metricsLogger,
-            @UiBackground Executor uiBgExecutor,
-            NotificationMediaManager notificationMediaManager,
-            NotificationLockscreenUserManager lockScreenUserManager,
-            NotificationRemoteInputManager remoteInputManager,
-            UserSwitcherController userSwitcherController,
-            NetworkController networkController,
-            BatteryController batteryController,
-            SysuiColorExtractor colorExtractor,
-            ScreenLifecycle screenLifecycle,
-            WakefulnessLifecycle wakefulnessLifecycle,
-            SysuiStatusBarStateController statusBarStateController,
-            Optional<BubblesManager> bubblesManagerOptional,
-            Optional<Bubbles> bubblesOptional,
-            VisualStabilityManager visualStabilityManager,
-            DeviceProvisionedController deviceProvisionedController,
-            NavigationBarController navigationBarController,
-            AccessibilityFloatingMenuController accessibilityFloatingMenuController,
-            Lazy<AssistManager> assistManagerLazy,
-            ConfigurationController configurationController,
-            NotificationShadeWindowController notificationShadeWindowController,
-            DozeParameters dozeParameters,
-            ScrimController scrimController,
-            Lazy<LockscreenWallpaper> lockscreenWallpaperLazy,
-            LockscreenGestureLogger lockscreenGestureLogger,
-            Lazy<BiometricUnlockController> biometricUnlockControllerLazy,
-            DozeServiceHost dozeServiceHost,
-            PowerManager powerManager,
-            ScreenPinningRequest screenPinningRequest,
-            DozeScrimController dozeScrimController,
-            VolumeComponent volumeComponent,
-            CommandQueue commandQueue,
-            CentralSurfacesComponent.Factory statusBarComponentFactory,
-            PluginManager pluginManager,
-            ShadeController shadeController,
-            StatusBarKeyguardViewManager statusBarKeyguardViewManager,
-            ViewMediatorCallback viewMediatorCallback,
-            InitController initController,
-            @Named(TIME_TICK_HANDLER_NAME) Handler timeTickHandler,
-            PluginDependencyProvider pluginDependencyProvider,
-            KeyguardDismissUtil keyguardDismissUtil,
-            ExtensionController extensionController,
-            UserInfoControllerImpl userInfoControllerImpl,
-            PhoneStatusBarPolicy phoneStatusBarPolicy,
-            KeyguardIndicationController keyguardIndicationController,
-            DemoModeController demoModeController,
-            Lazy<NotificationShadeDepthController> notificationShadeDepthController,
-            StatusBarTouchableRegionManager statusBarTouchableRegionManager,
-            NotificationIconAreaController notificationIconAreaController,
-            BrightnessSliderController.Factory brightnessSliderFactory,
-            ScreenOffAnimationController screenOffAnimationController,
-            WallpaperController wallpaperController,
-            OngoingCallController ongoingCallController,
-            StatusBarHideIconsForBouncerManager statusBarHideIconsForBouncerManager,
-            LockscreenShadeTransitionController transitionController,
-            FeatureFlags featureFlags,
-            KeyguardUnlockAnimationController keyguardUnlockAnimationController,
-            @Main Handler mainHandler,
-            @Main DelayableExecutor delayableExecutor,
-            @Main MessageRouter messageRouter,
-            WallpaperManager wallpaperManager,
-            Optional<StartingSurface> startingSurfaceOptional,
-            ActivityLaunchAnimator activityLaunchAnimator,
-            NotifPipelineFlags notifPipelineFlags,
-            InteractionJankMonitor jankMonitor,
-            DeviceStateManager deviceStateManager,
-            DreamOverlayStateController dreamOverlayStateController,
-            WiredChargingRippleController wiredChargingRippleController) {
-        return new CentralSurfaces(
-                context,
-                notificationsController,
-                fragmentService,
-                lightBarController,
-                autoHideController,
-                statusBarWindowController,
-                statusBarWindowStateController,
-                keyguardUpdateMonitor,
-                statusBarSignalPolicy,
-                pulseExpansionHandler,
-                notificationWakeUpCoordinator,
-                keyguardBypassController,
-                keyguardStateController,
-                headsUpManagerPhone,
-                dynamicPrivacyController,
-                falsingManager,
-                falsingCollector,
-                broadcastDispatcher,
-                notifShadeEventSource,
-                notificationEntryManager,
-                notificationGutsManager,
-                notificationLogger,
-                notificationInterruptStateProvider,
-                notificationViewHierarchyManager,
-                panelExpansionStateManager,
-                keyguardViewMediator,
-                displayMetrics,
-                metricsLogger,
-                uiBgExecutor,
-                notificationMediaManager,
-                lockScreenUserManager,
-                remoteInputManager,
-                userSwitcherController,
-                networkController,
-                batteryController,
-                colorExtractor,
-                screenLifecycle,
-                wakefulnessLifecycle,
-                statusBarStateController,
-                bubblesManagerOptional,
-                bubblesOptional,
-                visualStabilityManager,
-                deviceProvisionedController,
-                navigationBarController,
-                accessibilityFloatingMenuController,
-                assistManagerLazy,
-                configurationController,
-                notificationShadeWindowController,
-                dozeParameters,
-                scrimController,
-                lockscreenWallpaperLazy,
-                lockscreenGestureLogger,
-                biometricUnlockControllerLazy,
-                dozeServiceHost,
-                powerManager,
-                screenPinningRequest,
-                dozeScrimController,
-                volumeComponent,
-                commandQueue,
-                statusBarComponentFactory,
-                pluginManager,
-                shadeController,
-                statusBarKeyguardViewManager,
-                viewMediatorCallback,
-                initController,
-                timeTickHandler,
-                pluginDependencyProvider,
-                keyguardDismissUtil,
-                extensionController,
-                userInfoControllerImpl,
-                phoneStatusBarPolicy,
-                keyguardIndicationController,
-                demoModeController,
-                notificationShadeDepthController,
-                statusBarTouchableRegionManager,
-                notificationIconAreaController,
-                brightnessSliderFactory,
-                screenOffAnimationController,
-                wallpaperController,
-                ongoingCallController,
-                statusBarHideIconsForBouncerManager,
-                transitionController,
-                featureFlags,
-                keyguardUnlockAnimationController,
-                mainHandler,
-                delayableExecutor,
-                messageRouter,
-                wallpaperManager,
-                startingSurfaceOptional,
-                activityLaunchAnimator,
-                notifPipelineFlags,
-                jankMonitor,
-                deviceStateManager,
-                dreamOverlayStateController,
-                wiredChargingRippleController
-        );
-    }
+    CentralSurfaces bindsCentralSurfaces(CentralSurfacesImpl impl);
 }
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
index 2eba325..6717bc7 100644
--- 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
@@ -18,14 +18,12 @@
 
 import com.android.systemui.battery.BatteryMeterViewController;
 import com.android.systemui.dagger.qualifiers.RootView;
-import com.android.systemui.statusbar.phone.CentralSurfaces;
 import com.android.systemui.statusbar.phone.HeadsUpAppearanceController;
 import com.android.systemui.statusbar.phone.LightsOutNotifController;
 import com.android.systemui.statusbar.phone.PhoneStatusBarTransitions;
 import com.android.systemui.statusbar.phone.PhoneStatusBarView;
 import com.android.systemui.statusbar.phone.PhoneStatusBarViewController;
 import com.android.systemui.statusbar.phone.StatusBarDemoMode;
-import com.android.systemui.statusbar.phone.dagger.CentralSurfacesComponent;
 import com.android.systemui.statusbar.phone.fragment.CollapsedStatusBarFragment;
 
 import dagger.BindsInstance;
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 2a9048a..169347a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardQsUserSwitchController.java
@@ -78,6 +78,7 @@
     private final UiEventLogger mUiEventLogger;
     @VisibleForTesting
     UserAvatarView mUserAvatarView;
+    private View mUserAvatarViewWithBackground;
     UserSwitcherController.UserRecord mCurrentUser;
     private boolean mIsKeyguardShowing;
 
@@ -167,6 +168,8 @@
         super.onInit();
         if (DEBUG) Log.d(TAG, "onInit");
         mUserAvatarView = mView.findViewById(R.id.kg_multi_user_avatar);
+        mUserAvatarViewWithBackground = mView.findViewById(
+                R.id.kg_multi_user_avatar_with_background);
         mAdapter = new UserSwitcherController.BaseUserAdapter(mUserSwitcherController) {
             @Override
             public View getView(int position, View convertView, ViewGroup parent) {
@@ -186,7 +189,7 @@
             mUiEventLogger.log(
                     LockscreenGestureLogger.LockscreenUiEvent.LOCKSCREEN_SWITCH_USER_TAP);
 
-            mUserSwitchDialogController.showDialog(mView);
+            mUserSwitchDialogController.showDialog(mUserAvatarViewWithBackground);
         });
 
         mUserAvatarView.setAccessibilityDelegate(new View.AccessibilityDelegate() {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt
index 23129d2..6a9bb3e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/animation/ViewHierarchyAnimatorTest.kt
@@ -6,8 +6,10 @@
 import android.view.View
 import android.view.ViewGroup
 import android.widget.LinearLayout
+import android.widget.RelativeLayout
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.util.children
 import junit.framework.Assert.assertEquals
 import junit.framework.Assert.assertFalse
 import junit.framework.Assert.assertNotNull
@@ -28,18 +30,11 @@
         private val TEST_INTERPOLATOR = Interpolators.LINEAR
     }
 
-    private val childParams = LinearLayout.LayoutParams(
-        0 /* width */,
-        LinearLayout.LayoutParams.MATCH_PARENT
-    )
-    private lateinit var rootView: LinearLayout
+    private lateinit var rootView: ViewGroup
 
     @Before
     fun setUp() {
         rootView = LinearLayout(mContext)
-        rootView.orientation = LinearLayout.HORIZONTAL
-        rootView.weightSum = 1f
-        childParams.weight = 0.5f
     }
 
     @After
@@ -93,6 +88,19 @@
         animator = rootView.getTag(R.id.tag_animator) as ObjectAnimator
         assertEquals(animator.interpolator, TEST_INTERPOLATOR)
         assertEquals(animator.duration, TEST_DURATION)
+
+        // animateRemoval()
+        setUpRootWithChildren()
+        val child = rootView.getChildAt(0)
+        success = ViewHierarchyAnimator.animateRemoval(
+            child, interpolator = TEST_INTERPOLATOR, duration = TEST_DURATION
+        )
+
+        assertTrue(success)
+        assertNotNull(child.getTag(R.id.tag_animator))
+        animator = child.getTag(R.id.tag_animator) as ObjectAnimator
+        assertEquals(animator.interpolator, TEST_INTERPOLATOR)
+        assertEquals(animator.duration, TEST_DURATION)
     }
 
     @Test
@@ -170,17 +178,7 @@
 
     @Test
     fun animatesRootAndChildren() {
-        val firstChild = View(mContext)
-        firstChild.layoutParams = childParams
-        rootView.addView(firstChild)
-        val secondChild = View(mContext)
-        secondChild.layoutParams = childParams
-        rootView.addView(secondChild)
-        rootView.measure(
-            View.MeasureSpec.makeMeasureSpec(150, View.MeasureSpec.EXACTLY),
-            View.MeasureSpec.makeMeasureSpec(100, View.MeasureSpec.EXACTLY)
-        )
-        rootView.layout(0 /* l */, 0 /* t */, 150 /* r */, 100 /* b */)
+        setUpRootWithChildren()
 
         val success = ViewHierarchyAnimator.animate(rootView)
         // Change all bounds.
@@ -192,20 +190,20 @@
 
         assertTrue(success)
         assertNotNull(rootView.getTag(R.id.tag_animator))
-        assertNotNull(firstChild.getTag(R.id.tag_animator))
-        assertNotNull(secondChild.getTag(R.id.tag_animator))
+        assertNotNull(rootView.getChildAt(0).getTag(R.id.tag_animator))
+        assertNotNull(rootView.getChildAt(1).getTag(R.id.tag_animator))
         // The initial values should be those of the previous layout.
-        checkBounds(rootView, l = 0, t = 0, r = 150, b = 100)
-        checkBounds(firstChild, l = 0, t = 0, r = 75, b = 100)
-        checkBounds(secondChild, l = 75, t = 0, r = 150, b = 100)
+        checkBounds(rootView, l = 0, t = 0, r = 200, b = 100)
+        checkBounds(rootView.getChildAt(0), l = 0, t = 0, r = 100, b = 100)
+        checkBounds(rootView.getChildAt(1), l = 100, t = 0, r = 200, b = 100)
         endAnimation(rootView)
         assertNull(rootView.getTag(R.id.tag_animator))
-        assertNull(firstChild.getTag(R.id.tag_animator))
-        assertNull(secondChild.getTag(R.id.tag_animator))
+        assertNull(rootView.getChildAt(0).getTag(R.id.tag_animator))
+        assertNull(rootView.getChildAt(1).getTag(R.id.tag_animator))
         // The end values should be those of the latest layout.
         checkBounds(rootView, l = 10, t = 20, r = 200, b = 120)
-        checkBounds(firstChild, l = 0, t = 0, r = 95, b = 100)
-        checkBounds(secondChild, l = 95, t = 0, r = 190, b = 100)
+        checkBounds(rootView.getChildAt(0), l = 0, t = 0, r = 95, b = 100)
+        checkBounds(rootView.getChildAt(1), l = 95, t = 0, r = 190, b = 100)
     }
 
     @Test
@@ -522,6 +520,251 @@
         endAnimation(rootView)
     }
 
+    fun animatesViewRemovalFromStartToEnd() {
+        setUpRootWithChildren()
+
+        val child = rootView.getChildAt(0)
+        val success = ViewHierarchyAnimator.animateRemoval(
+            child,
+            destination = ViewHierarchyAnimator.Hotspot.LEFT,
+            interpolator = Interpolators.LINEAR
+        )
+
+        assertTrue(success)
+        assertNotNull(child.getTag(R.id.tag_animator))
+        checkBounds(child, l = 0, t = 0, r = 100, b = 100)
+        advanceAnimation(child, 0.5f)
+        checkBounds(child, l = 0, t = 0, r = 50, b = 100)
+        advanceAnimation(child, 1.0f)
+        checkBounds(child, l = 0, t = 0, r = 0, b = 100)
+        endAnimation(rootView)
+        endAnimation(child)
+        assertEquals(1, rootView.childCount)
+        assertFalse(child in rootView.children)
+    }
+
+    @Test
+    fun animatesViewRemovalRespectingDestination() {
+        // CENTER
+        setUpRootWithChildren()
+        var removedChild = rootView.getChildAt(0)
+        var remainingChild = rootView.getChildAt(1)
+        var success = ViewHierarchyAnimator.animateRemoval(
+            removedChild, destination = ViewHierarchyAnimator.Hotspot.CENTER
+        )
+        // Ensure that the layout happens before the checks.
+        forceLayout()
+
+        assertTrue(success)
+        assertNotNull(removedChild.getTag(R.id.tag_animator))
+        advanceAnimation(removedChild, 1.0f)
+        checkBounds(removedChild, l = 50, t = 50, r = 50, b = 50)
+        endAnimation(rootView)
+        endAnimation(removedChild)
+        checkBounds(remainingChild, l = 0, t = 0, r = 100, b = 100)
+
+        // LEFT
+        setUpRootWithChildren()
+        removedChild = rootView.getChildAt(0)
+        remainingChild = rootView.getChildAt(1)
+        success = ViewHierarchyAnimator.animateRemoval(
+            removedChild, destination = ViewHierarchyAnimator.Hotspot.LEFT
+        )
+        // Ensure that the layout happens before the checks.
+        forceLayout()
+
+        assertTrue(success)
+        assertNotNull(removedChild.getTag(R.id.tag_animator))
+        advanceAnimation(removedChild, 1.0f)
+        checkBounds(removedChild, l = 0, t = 0, r = 0, b = 100)
+        endAnimation(rootView)
+        endAnimation(removedChild)
+        checkBounds(remainingChild, l = 0, t = 0, r = 100, b = 100)
+
+        // TOP_LEFT
+        setUpRootWithChildren()
+        removedChild = rootView.getChildAt(0)
+        remainingChild = rootView.getChildAt(1)
+        success = ViewHierarchyAnimator.animateRemoval(
+            removedChild, destination = ViewHierarchyAnimator.Hotspot.TOP_LEFT
+        )
+        // Ensure that the layout happens before the checks.
+        forceLayout()
+
+        assertTrue(success)
+        assertNotNull(removedChild.getTag(R.id.tag_animator))
+        advanceAnimation(removedChild, 1.0f)
+        checkBounds(removedChild, l = 0, t = 0, r = 0, b = 0)
+        endAnimation(rootView)
+        endAnimation(removedChild)
+        checkBounds(remainingChild, l = 0, t = 0, r = 100, b = 100)
+
+        // TOP
+        setUpRootWithChildren()
+        removedChild = rootView.getChildAt(0)
+        remainingChild = rootView.getChildAt(1)
+        success = ViewHierarchyAnimator.animateRemoval(
+            removedChild, destination = ViewHierarchyAnimator.Hotspot.TOP
+        )
+        // Ensure that the layout happens before the checks.
+        forceLayout()
+
+        assertTrue(success)
+        assertNotNull(removedChild.getTag(R.id.tag_animator))
+        advanceAnimation(removedChild, 1.0f)
+        checkBounds(removedChild, l = 0, t = 0, r = 100, b = 0)
+        endAnimation(rootView)
+        endAnimation(removedChild)
+        checkBounds(remainingChild, l = 0, t = 0, r = 100, b = 100)
+
+        // TOP_RIGHT
+        setUpRootWithChildren()
+        removedChild = rootView.getChildAt(0)
+        remainingChild = rootView.getChildAt(1)
+        success = ViewHierarchyAnimator.animateRemoval(
+            removedChild, destination = ViewHierarchyAnimator.Hotspot.TOP_RIGHT
+        )
+        // Ensure that the layout happens before the checks.
+        forceLayout()
+
+        assertTrue(success)
+        assertNotNull(removedChild.getTag(R.id.tag_animator))
+        advanceAnimation(removedChild, 1.0f)
+        checkBounds(removedChild, l = 100, t = 0, r = 100, b = 0)
+        endAnimation(rootView)
+        endAnimation(removedChild)
+        checkBounds(remainingChild, l = 0, t = 0, r = 100, b = 100)
+
+        // RIGHT
+        setUpRootWithChildren()
+        removedChild = rootView.getChildAt(0)
+        remainingChild = rootView.getChildAt(1)
+        success = ViewHierarchyAnimator.animateRemoval(
+            removedChild, destination = ViewHierarchyAnimator.Hotspot.RIGHT
+        )
+        // Ensure that the layout happens before the checks.
+        forceLayout()
+
+        assertTrue(success)
+        assertNotNull(removedChild.getTag(R.id.tag_animator))
+        advanceAnimation(removedChild, 1.0f)
+        checkBounds(removedChild, l = 100, t = 0, r = 100, b = 100)
+        endAnimation(rootView)
+        endAnimation(removedChild)
+        checkBounds(remainingChild, l = 0, t = 0, r = 100, b = 100)
+
+        // BOTTOM_RIGHT
+        setUpRootWithChildren()
+        removedChild = rootView.getChildAt(0)
+        remainingChild = rootView.getChildAt(1)
+        success = ViewHierarchyAnimator.animateRemoval(
+            removedChild, destination = ViewHierarchyAnimator.Hotspot.BOTTOM_RIGHT
+        )
+        // Ensure that the layout happens before the checks.
+        forceLayout()
+
+        assertTrue(success)
+        assertNotNull(removedChild.getTag(R.id.tag_animator))
+        advanceAnimation(removedChild, 1.0f)
+        checkBounds(removedChild, l = 100, t = 100, r = 100, b = 100)
+        endAnimation(rootView)
+        endAnimation(removedChild)
+        checkBounds(remainingChild, l = 0, t = 0, r = 100, b = 100)
+
+        // BOTTOM
+        setUpRootWithChildren()
+        removedChild = rootView.getChildAt(0)
+        remainingChild = rootView.getChildAt(1)
+        success = ViewHierarchyAnimator.animateRemoval(
+            removedChild, destination = ViewHierarchyAnimator.Hotspot.BOTTOM
+        )
+        // Ensure that the layout happens before the checks.
+        forceLayout()
+
+        assertTrue(success)
+        assertNotNull(removedChild.getTag(R.id.tag_animator))
+        advanceAnimation(removedChild, 1.0f)
+        checkBounds(removedChild, l = 0, t = 100, r = 100, b = 100)
+        endAnimation(rootView)
+        endAnimation(removedChild)
+        checkBounds(remainingChild, l = 0, t = 0, r = 100, b = 100)
+
+        // BOTTOM_LEFT
+        setUpRootWithChildren()
+        removedChild = rootView.getChildAt(0)
+        remainingChild = rootView.getChildAt(1)
+        success = ViewHierarchyAnimator.animateRemoval(
+            removedChild, destination = ViewHierarchyAnimator.Hotspot.BOTTOM_LEFT
+        )
+        // Ensure that the layout happens before the checks.
+        forceLayout()
+
+        assertTrue(success)
+        assertNotNull(removedChild.getTag(R.id.tag_animator))
+        advanceAnimation(removedChild, 1.0f)
+        checkBounds(removedChild, l = 0, t = 100, r = 0, b = 100)
+        endAnimation(rootView)
+        endAnimation(removedChild)
+        checkBounds(remainingChild, l = 0, t = 0, r = 100, b = 100)
+    }
+
+    @Test
+    fun animatesChildrenDuringViewRemoval() {
+        setUpRootWithChildren()
+
+        val child = rootView.getChildAt(0) as ViewGroup
+        val firstGrandChild = child.getChildAt(0)
+        val secondGrandChild = child.getChildAt(1)
+        val success = ViewHierarchyAnimator.animateRemoval(
+            child, interpolator = Interpolators.LINEAR
+        )
+
+        assertTrue(success)
+        assertNotNull(child.getTag(R.id.tag_animator))
+        assertNotNull(firstGrandChild.getTag(R.id.tag_animator))
+        assertNotNull(secondGrandChild.getTag(R.id.tag_animator))
+        checkBounds(child, l = 0, t = 0, r = 100, b = 100)
+        checkBounds(firstGrandChild, l = 0, t = 0, r = 40, b = 40)
+        checkBounds(secondGrandChild, l = 60, t = 60, r = 100, b = 100)
+
+        advanceAnimation(child, 0.5f)
+        checkBounds(child, l = 25, t = 25, r = 75, b = 75)
+        checkBounds(firstGrandChild, l = -10, t = -10, r = 30, b = 30)
+        checkBounds(secondGrandChild, l = 20, t = 20, r = 60, b = 60)
+
+        advanceAnimation(child, 1.0f)
+        checkBounds(child, l = 50, t = 50, r = 50, b = 50)
+        checkBounds(firstGrandChild, l = -20, t = -20, r = 20, b = 20)
+        checkBounds(secondGrandChild, l = -20, t = -20, r = 20, b = 20)
+
+        endAnimation(rootView)
+        endAnimation(child)
+    }
+
+    @Test
+    fun animatesSiblingsDuringViewRemoval() {
+        setUpRootWithChildren()
+
+        val removedChild = rootView.getChildAt(0)
+        val remainingChild = rootView.getChildAt(1)
+        val success = ViewHierarchyAnimator.animateRemoval(
+            removedChild, interpolator = Interpolators.LINEAR
+        )
+        // Ensure that the layout happens before the checks.
+        forceLayout()
+
+        assertTrue(success)
+        assertNotNull(remainingChild.getTag(R.id.tag_animator))
+        checkBounds(remainingChild, l = 100, t = 0, r = 200, b = 100)
+        advanceAnimation(rootView, 0.5f)
+        checkBounds(remainingChild, l = 50, t = 0, r = 150, b = 100)
+        advanceAnimation(rootView, 1.0f)
+        checkBounds(remainingChild, l = 0, t = 0, r = 100, b = 100)
+        endAnimation(rootView)
+        endAnimation(removedChild)
+        assertNull(remainingChild.getTag(R.id.tag_animator))
+    }
+
     @Test
     fun cleansUpListenersCorrectly() {
         val firstChild = View(mContext)
@@ -700,6 +943,49 @@
         checkBounds(rootView, l = 10, t = 10, r = 50, b = 50)
     }
 
+    private fun setUpRootWithChildren() {
+        rootView = LinearLayout(mContext)
+        (rootView as LinearLayout).orientation = LinearLayout.HORIZONTAL
+        (rootView as LinearLayout).weightSum = 1f
+
+        val firstChild = RelativeLayout(mContext)
+        rootView.addView(firstChild)
+        val firstGrandChild = View(mContext)
+        firstChild.addView(firstGrandChild)
+        val secondGrandChild = View(mContext)
+        firstChild.addView(secondGrandChild)
+        val secondChild = View(mContext)
+        rootView.addView(secondChild)
+
+        val childParams = LinearLayout.LayoutParams(
+            0 /* width */,
+            LinearLayout.LayoutParams.MATCH_PARENT
+        )
+        childParams.weight = 0.5f
+        firstChild.layoutParams = childParams
+        secondChild.layoutParams = childParams
+        firstGrandChild.layoutParams = RelativeLayout.LayoutParams(40 /* width */, 40 /* height */)
+        (firstGrandChild.layoutParams as RelativeLayout.LayoutParams)
+            .addRule(RelativeLayout.ALIGN_PARENT_START)
+        (firstGrandChild.layoutParams as RelativeLayout.LayoutParams)
+            .addRule(RelativeLayout.ALIGN_PARENT_TOP)
+        secondGrandChild.layoutParams = RelativeLayout.LayoutParams(40 /* width */, 40 /* height */)
+        (secondGrandChild.layoutParams as RelativeLayout.LayoutParams)
+            .addRule(RelativeLayout.ALIGN_PARENT_END)
+        (secondGrandChild.layoutParams as RelativeLayout.LayoutParams)
+            .addRule(RelativeLayout.ALIGN_PARENT_BOTTOM)
+
+        forceLayout()
+    }
+
+    private fun forceLayout() {
+        rootView.measure(
+            View.MeasureSpec.makeMeasureSpec(200 /* width */, View.MeasureSpec.AT_MOST),
+            View.MeasureSpec.makeMeasureSpec(100 /* height */, View.MeasureSpec.AT_MOST)
+        )
+        rootView.layout(0 /* l */, 0 /* t */, 200 /* r */, 100 /* b */)
+    }
+
     private fun checkBounds(v: View, l: Int, t: Int, r: Int, b: Int) {
         assertEquals(l, v.left)
         assertEquals(t, v.top)
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 80df1e3..b733c5e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -564,6 +564,7 @@
         // Configure UdfpsView to accept the ACTION_DOWN event
         when(mUdfpsView.isIlluminationRequested()).thenReturn(false);
         when(mUdfpsView.isWithinSensorArea(anyFloat(), anyFloat())).thenReturn(true);
+        when(mKeyguardUpdateMonitor.isFingerprintDetectionRunning()).thenReturn(true);
 
         // GIVEN that the overlay is showing
         mOverlayController.showUdfpsOverlay(TEST_REQUEST_ID, TEST_UDFPS_SENSOR_ID,
@@ -579,6 +580,7 @@
         // FIX THIS TEST
         mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent);
         moveEvent.recycle();
+        mFgExecutor.runAllReady();
         // THEN FingerprintManager is notified about onPointerDown
         verify(mAlternateTouchProvider).onPointerDown(eq(TEST_REQUEST_ID), eq(0), eq(0), eq(0f),
                 eq(0f));
@@ -588,6 +590,7 @@
         // AND illumination begins
         verify(mUdfpsView).startIllumination(mOnIlluminatedRunnableCaptor.capture());
         verify(mLatencyTracker, never()).onActionEnd(eq(LatencyTracker.ACTION_UDFPS_ILLUMINATE));
+        verify(mKeyguardUpdateMonitor).onUdfpsPointerDown(eq((int) TEST_REQUEST_ID));
         // AND onIlluminatedRunnable notifies FingerprintManager about onUiReady
         mOnIlluminatedRunnableCaptor.getValue().run();
         InOrder inOrder = inOrder(mFingerprintManager, mLatencyTracker);
@@ -606,6 +609,7 @@
         when(mKeyguardUpdateMonitor.isFingerprintDetectionRunning()).thenReturn(true);
         // WHEN fingerprint is requested because of AOD interrupt
         mUdfpsController.onAodInterrupt(0, 0, 2f, 3f);
+        mFgExecutor.runAllReady();
         // THEN illumination begins
         // AND onIlluminatedRunnable that notifies FingerprintManager is set
         verify(mUdfpsView).startIllumination(mOnIlluminatedRunnableCaptor.capture());
@@ -614,6 +618,7 @@
                 eq(0), eq(0), eq(3f) /* minor */, eq(2f) /* major */);
         verify(mFingerprintManager, never()).onPointerDown(anyLong(), anyInt(), anyInt(), anyInt(),
                 anyFloat(), anyFloat());
+        verify(mKeyguardUpdateMonitor).onUdfpsPointerDown(eq((int) TEST_REQUEST_ID));
     }
 
     @Test
@@ -641,6 +646,7 @@
         mFgExecutor.runAllReady();
         when(mKeyguardUpdateMonitor.isFingerprintDetectionRunning()).thenReturn(true);
         mUdfpsController.onAodInterrupt(0, 0, 0f, 0f);
+        mFgExecutor.runAllReady();
         when(mUdfpsView.isIlluminationRequested()).thenReturn(true);
         // WHEN it times out
         mFgExecutor.advanceClockToNext();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/SmartSpaceComplicationTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/SmartSpaceComplicationTest.java
index ed1cf69..cefdf28 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/SmartSpaceComplicationTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/SmartSpaceComplicationTest.java
@@ -27,7 +27,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
-import com.android.systemui.dreams.smartspace.DreamsSmartspaceController;
+import com.android.systemui.dreams.smartspace.DreamSmartspaceController;
 import com.android.systemui.plugins.BcSmartspaceDataPlugin;
 
 import org.junit.Before;
@@ -47,7 +47,7 @@
     private Context mContext;
 
     @Mock
-    private DreamsSmartspaceController mSmartspaceController;
+    private DreamSmartspaceController mSmartspaceController;
 
     @Mock
     private DreamOverlayStateController mDreamOverlayStateController;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
index 442e41c..c3fca29 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/dreams/touch/BouncerSwipeTouchHandlerTest.java
@@ -428,7 +428,6 @@
     @Test
     public void testInformBouncerShowingOnExpand() {
         swipeToPosition(1f, Direction.UP, 0);
-        verify(mCentralSurfaces).setBouncerShowingOverDream(true);
     }
 
     /**
@@ -441,7 +440,6 @@
         Mockito.clearInvocations(mCentralSurfaces);
 
         swipeToPosition(0f, Direction.DOWN, 0);
-        verify(mCentralSurfaces).setBouncerShowingOverDream(false);
     }
 
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
index 6a9c3e3..b8c85bb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/MediaControlPanelTest.kt
@@ -25,8 +25,12 @@
 import android.content.Intent
 import android.content.pm.ApplicationInfo
 import android.content.pm.PackageManager
+import android.graphics.Bitmap
+import android.graphics.Canvas
+import android.graphics.Color
 import android.graphics.drawable.Animatable2
 import android.graphics.drawable.AnimatedVectorDrawable
+import android.graphics.drawable.Drawable
 import android.graphics.drawable.GradientDrawable
 import android.graphics.drawable.Icon
 import android.graphics.drawable.RippleDrawable
@@ -124,7 +128,7 @@
     @Mock private lateinit var falsingManager: FalsingManager
     @Mock private lateinit var transitionParent: ViewGroup
     private lateinit var appIcon: ImageView
-    private lateinit var albumView: ImageView
+    @Mock private lateinit var albumView: ImageView
     private lateinit var titleText: TextView
     private lateinit var artistText: TextView
     private lateinit var seamless: ViewGroup
@@ -296,7 +300,6 @@
 
         // Set up mock views for the players
         appIcon = ImageView(context)
-        albumView = ImageView(context)
         titleText = TextView(context)
         artistText = TextView(context)
         seamless = FrameLayout(context)
@@ -416,7 +419,6 @@
         whenever(coverContainer1.context).thenReturn(mockContext)
         whenever(coverContainer2.context).thenReturn(mockContext)
         whenever(coverContainer3.context).thenReturn(mockContext)
-
     }
 
     @After
@@ -537,6 +539,60 @@
     }
 
     @Test
+    fun bindAlbumView_setAfterExecutors() {
+        val bmp = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888)
+        val canvas = Canvas(bmp)
+        canvas.drawColor(Color.RED)
+        val albumArt = Icon.createWithBitmap(bmp)
+        val state = mediaData.copy(artwork = albumArt)
+
+        player.attachPlayer(viewHolder)
+        player.bindPlayer(state, PACKAGE)
+        bgExecutor.runAllReady()
+        mainExecutor.runAllReady()
+
+        verify(albumView).setImageDrawable(any(Drawable::class.java))
+    }
+
+    @Test
+    fun bindAlbumView_bitmapInLaterStates_setAfterExecutors() {
+        val bmp = Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888)
+        val canvas = Canvas(bmp)
+        canvas.drawColor(Color.RED)
+        val albumArt = Icon.createWithBitmap(bmp)
+
+        val state0 = mediaData.copy(artwork = null)
+        val state1 = mediaData.copy(artwork = albumArt)
+        val state2 = mediaData.copy(artwork = albumArt)
+        player.attachPlayer(viewHolder)
+
+        // First binding sets (empty) drawable
+        player.bindPlayer(state0, PACKAGE)
+        bgExecutor.runAllReady()
+        mainExecutor.runAllReady()
+        verify(albumView).setImageDrawable(any(Drawable::class.java))
+
+        // Run Metadata update so that later states don't update
+        val captor = argumentCaptor<Animator.AnimatorListener>()
+        verify(mockAnimator, times(2)).addListener(captor.capture())
+        captor.value.onAnimationEnd(mockAnimator)
+        assertThat(titleText.getText()).isEqualTo(TITLE)
+        assertThat(artistText.getText()).isEqualTo(ARTIST)
+
+        // Second binding sets transition drawable
+        player.bindPlayer(state1, PACKAGE)
+        bgExecutor.runAllReady()
+        mainExecutor.runAllReady()
+        verify(albumView, times(2)).setImageDrawable(any(Drawable::class.java))
+
+        // Third binding does run transition or update background
+        player.bindPlayer(state2, PACKAGE)
+        bgExecutor.runAllReady()
+        mainExecutor.runAllReady()
+        verify(albumView, times(2)).setImageDrawable(any(Drawable::class.java))
+    }
+
+    @Test
     fun bind_seekBarDisabled_hasActions_seekBarVisibilityIsSetToInvisible() {
         useRealConstraintSets()
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogTest.kt
index c714fa0..1d687b1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/privacy/PrivacyDialogTest.kt
@@ -35,6 +35,7 @@
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
 import android.content.Intent
+import android.text.TextUtils
 
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
@@ -373,4 +374,31 @@
                 )
         )
     }
+
+    @Test
+    fun testDialogHasTitle() {
+        // Dialog must have a non-empty title for a11y purposes.
+
+        val list = listOf(
+            PrivacyDialog.PrivacyElement(
+                PrivacyType.TYPE_MICROPHONE,
+                TEST_PACKAGE_NAME,
+                TEST_USER_ID,
+                "App",
+                null,
+                null,
+                null,
+                0L,
+                false,
+                false,
+                false,
+                TEST_PERM_GROUP,
+                null
+            )
+        )
+        dialog = PrivacyDialog(context, list, starter)
+        dialog.show()
+
+        assertThat(TextUtils.isEmpty(dialog.window?.attributes?.title)).isFalse()
+    }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
index 633a9c3..4a8cb0b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
@@ -138,6 +138,8 @@
     private DialogLaunchAnimator mDialogLaunchAnimator;
     @Mock
     private View mDialogLaunchView;
+    @Mock
+    private WifiStateWorker mWifiStateWorker;
 
     private TestableResources mTestableResources;
     private InternetDialogController mInternetDialogController;
@@ -166,6 +168,7 @@
         when(mSystemUIToast.getView()).thenReturn(mToastView);
         when(mSystemUIToast.getGravity()).thenReturn(GRAVITY_FLAGS);
         when(mSystemUIToast.getInAnimation()).thenReturn(mAnimator);
+        when(mWifiStateWorker.isWifiEnabled()).thenReturn(true);
 
         mInternetDialogController = new InternetDialogController(mContext,
                 mock(UiEventLogger.class), mock(ActivityStarter.class), mAccessPointController,
@@ -173,7 +176,7 @@
                 mock(ConnectivityManager.class), mHandler, mExecutor, mBroadcastDispatcher,
                 mock(KeyguardUpdateMonitor.class), mGlobalSettings, mKeyguardStateController,
                 mWindowManager, mToastFactory, mWorkerHandler, mCarrierConfigTracker,
-                mLocationController, mDialogLaunchAnimator);
+                mLocationController, mDialogLaunchAnimator, mWifiStateWorker);
         mSubscriptionManager.addOnSubscriptionsChangedListener(mExecutor,
                 mInternetDialogController.mOnSubscriptionsChangedListener);
         mInternetDialogController.onStart(mInternetDialogCallback, true);
@@ -239,7 +242,7 @@
     @Test
     public void getSubtitleText_withApmOnAndWifiOff_returnWifiIsOff() {
         fakeAirplaneModeEnabled(true);
-        when(mWifiManager.isWifiEnabled()).thenReturn(false);
+        when(mWifiStateWorker.isWifiEnabled()).thenReturn(false);
 
         assertThat(mInternetDialogController.getSubtitleText(false))
                 .isEqualTo(getResourcesString("wifi_is_off"));
@@ -254,7 +257,7 @@
     @Test
     public void getSubtitleText_withWifiOff_returnWifiIsOff() {
         fakeAirplaneModeEnabled(false);
-        when(mWifiManager.isWifiEnabled()).thenReturn(false);
+        when(mWifiStateWorker.isWifiEnabled()).thenReturn(false);
 
         assertThat(mInternetDialogController.getSubtitleText(false))
                 .isEqualTo(getResourcesString("wifi_is_off"));
@@ -269,7 +272,7 @@
     @Test
     public void getSubtitleText_withNoWifiEntry_returnSearchWifi() {
         fakeAirplaneModeEnabled(false);
-        when(mWifiManager.isWifiEnabled()).thenReturn(true);
+        when(mWifiStateWorker.isWifiEnabled()).thenReturn(true);
         mInternetDialogController.onAccessPointsChanged(null /* accessPoints */);
 
         assertThat(mInternetDialogController.getSubtitleText(true))
@@ -286,7 +289,7 @@
     public void getSubtitleText_withWifiEntry_returnTapToConnect() {
         // The preconditions WiFi Entries is already in setUp()
         fakeAirplaneModeEnabled(false);
-        when(mWifiManager.isWifiEnabled()).thenReturn(true);
+        when(mWifiStateWorker.isWifiEnabled()).thenReturn(true);
 
         assertThat(mInternetDialogController.getSubtitleText(false))
                 .isEqualTo(getResourcesString("tap_a_network_to_connect"));
@@ -301,7 +304,7 @@
     @Test
     public void getSubtitleText_deviceLockedWithWifiOn_returnUnlockToViewNetworks() {
         fakeAirplaneModeEnabled(false);
-        when(mWifiManager.isWifiEnabled()).thenReturn(true);
+        when(mWifiStateWorker.isWifiEnabled()).thenReturn(true);
         when(mKeyguardStateController.isUnlocked()).thenReturn(false);
 
         assertTrue(TextUtils.equals(mInternetDialogController.getSubtitleText(false),
@@ -311,7 +314,7 @@
     @Test
     public void getSubtitleText_withNoService_returnNoNetworksAvailable() {
         fakeAirplaneModeEnabled(false);
-        when(mWifiManager.isWifiEnabled()).thenReturn(true);
+        when(mWifiStateWorker.isWifiEnabled()).thenReturn(true);
         mInternetDialogController.onAccessPointsChanged(null /* accessPoints */);
 
         doReturn(ServiceState.STATE_OUT_OF_SERVICE).when(mServiceState).getState();
@@ -325,7 +328,7 @@
     @Test
     public void getSubtitleText_withMobileDataDisabled_returnNoOtherAvailable() {
         fakeAirplaneModeEnabled(false);
-        when(mWifiManager.isWifiEnabled()).thenReturn(true);
+        when(mWifiStateWorker.isWifiEnabled()).thenReturn(true);
         mInternetDialogController.onAccessPointsChanged(null /* accessPoints */);
 
         doReturn(ServiceState.STATE_IN_SERVICE).when(mServiceState).getState();
@@ -346,7 +349,7 @@
     @Test
     public void getSubtitleText_withCarrierNetworkActiveOnly_returnNoOtherAvailable() {
         fakeAirplaneModeEnabled(false);
-        when(mWifiManager.isWifiEnabled()).thenReturn(true);
+        when(mWifiStateWorker.isWifiEnabled()).thenReturn(true);
         mInternetDialogController.onAccessPointsChanged(null /* accessPoints */);
         when(mMergedCarrierEntry.isDefaultNetwork()).thenReturn(true);
 
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 616f894..d09a5a1 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
@@ -14,7 +14,6 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
-import android.net.wifi.WifiManager;
 import android.os.Handler;
 import android.telephony.TelephonyManager;
 import android.testing.AndroidTestingRunner;
@@ -64,8 +63,6 @@
     @Mock
     private TelephonyManager mTelephonyManager;
     @Mock
-    private WifiManager mWifiManager;
-    @Mock
     private WifiEntry mInternetWifiEntry;
     @Mock
     private List<WifiEntry> mWifiEntries;
@@ -97,7 +94,6 @@
     public void setUp() {
         MockitoAnnotations.initMocks(this);
         doReturn(mTelephonyManager).when(mTelephonyManager).createForSubscriptionId(anyInt());
-        when(mWifiManager.isWifiEnabled()).thenReturn(true);
         when(mInternetWifiEntry.getTitle()).thenReturn(WIFI_TITLE);
         when(mInternetWifiEntry.getSummary(false)).thenReturn(WIFI_SUMMARY);
         when(mInternetWifiEntry.isDefaultNetwork()).thenReturn(true);
@@ -107,7 +103,7 @@
         when(mInternetDialogController.getMobileNetworkTitle()).thenReturn(MOBILE_NETWORK_TITLE);
         when(mInternetDialogController.getMobileNetworkSummary())
                 .thenReturn(MOBILE_NETWORK_SUMMARY);
-        when(mInternetDialogController.getWifiManager()).thenReturn(mWifiManager);
+        when(mInternetDialogController.isWifiEnabled()).thenReturn(true);
 
         mMockitoSession = ExtendedMockito.mockitoSession()
                 .spyStatic(WifiEnterpriseRestrictionUtils.class)
@@ -232,7 +228,7 @@
         // Carrier network should be gone if airplane mode ON and Wi-Fi is off.
         when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(true);
         when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true);
-        when(mWifiManager.isWifiEnabled()).thenReturn(false);
+        when(mInternetDialogController.isWifiEnabled()).thenReturn(false);
 
         mInternetDialog.updateDialog(true);
 
@@ -241,7 +237,7 @@
         // Carrier network should be visible if airplane mode ON and Wi-Fi is ON.
         when(mInternetDialogController.isCarrierNetworkActive()).thenReturn(true);
         when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true);
-        when(mWifiManager.isWifiEnabled()).thenReturn(true);
+        when(mInternetDialogController.isWifiEnabled()).thenReturn(true);
 
         mInternetDialog.updateDialog(true);
 
@@ -468,7 +464,7 @@
 
     @Test
     public void updateDialog_wifiOffAndWifiScanOff_hideWifiScanNotify() {
-        when(mWifiManager.isWifiEnabled()).thenReturn(false);
+        when(mInternetDialogController.isWifiEnabled()).thenReturn(false);
         when(mInternetDialogController.isWifiScanEnabled()).thenReturn(false);
 
         mInternetDialog.updateDialog(false);
@@ -478,7 +474,7 @@
 
     @Test
     public void updateDialog_wifiOffAndWifiScanOnAndDeviceLocked_hideWifiScanNotify() {
-        when(mWifiManager.isWifiEnabled()).thenReturn(false);
+        when(mInternetDialogController.isWifiEnabled()).thenReturn(false);
         when(mInternetDialogController.isWifiScanEnabled()).thenReturn(true);
         when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
 
@@ -489,7 +485,7 @@
 
     @Test
     public void updateDialog_wifiOffAndWifiScanOnAndDeviceUnlocked_showWifiScanNotify() {
-        when(mWifiManager.isWifiEnabled()).thenReturn(false);
+        when(mInternetDialogController.isWifiEnabled()).thenReturn(false);
         when(mInternetDialogController.isWifiScanEnabled()).thenReturn(true);
         when(mInternetDialogController.isDeviceLocked()).thenReturn(false);
 
@@ -502,6 +498,26 @@
     }
 
     @Test
+    public void updateDialog_wifiIsDisabled_uncheckWifiSwitch() {
+        when(mInternetDialogController.isWifiEnabled()).thenReturn(false);
+        mWifiToggleSwitch.setChecked(true);
+
+        mInternetDialog.updateDialog(false);
+
+        assertThat(mWifiToggleSwitch.isChecked()).isFalse();
+    }
+
+    @Test
+    public void updateDialog_wifiIsEnabled_checkWifiSwitch() {
+        when(mInternetDialogController.isWifiEnabled()).thenReturn(true);
+        mWifiToggleSwitch.setChecked(false);
+
+        mInternetDialog.updateDialog(false);
+
+        assertThat(mWifiToggleSwitch.isChecked()).isTrue();
+    }
+
+    @Test
     public void onClickSeeMoreButton_clickSeeAll_verifyLaunchNetworkSetting() {
         mSeeAll.performClick();
 
@@ -512,7 +528,7 @@
     @Test
     public void showProgressBar_wifiDisabled_hideProgressBar() {
         Mockito.reset(mHandler);
-        when(mWifiManager.isWifiEnabled()).thenReturn(false);
+        when(mInternetDialogController.isWifiEnabled()).thenReturn(false);
 
         mInternetDialog.showProgressBar();
 
@@ -534,7 +550,7 @@
     @Test
     public void showProgressBar_wifiEnabledWithWifiEntry_showProgressBarThenHide() {
         Mockito.reset(mHandler);
-        when(mWifiManager.isWifiEnabled()).thenReturn(true);
+        when(mInternetDialogController.isWifiEnabled()).thenReturn(true);
 
         mInternetDialog.showProgressBar();
 
@@ -553,7 +569,7 @@
     @Test
     public void showProgressBar_wifiEnabledWithoutWifiEntries_showProgressBarThenHideSearch() {
         Mockito.reset(mHandler);
-        when(mWifiManager.isWifiEnabled()).thenReturn(true);
+        when(mInternetDialogController.isWifiEnabled()).thenReturn(true);
         mInternetDialog.mConnectedWifiEntry = null;
         mInternetDialog.mWifiEntriesCount = 0;
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/WifiStateWorkerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/WifiStateWorkerTest.java
new file mode 100644
index 0000000..5d7ba7b
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/WifiStateWorkerTest.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2022 The Android Open 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.dialog;
+
+import static android.net.wifi.WifiManager.EXTRA_WIFI_STATE;
+import static android.net.wifi.WifiManager.WIFI_STATE_CHANGED_ACTION;
+import static android.net.wifi.WifiManager.WIFI_STATE_DISABLED;
+import static android.net.wifi.WifiManager.WIFI_STATE_DISABLING;
+import static android.net.wifi.WifiManager.WIFI_STATE_ENABLED;
+import static android.net.wifi.WifiManager.WIFI_STATE_ENABLING;
+import static android.net.wifi.WifiManager.WIFI_STATE_UNKNOWN;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Intent;
+import android.net.wifi.WifiManager;
+import android.testing.AndroidTestingRunner;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.broadcast.BroadcastDispatcher;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+
+@RunWith(AndroidTestingRunner.class)
+@SmallTest
+public class WifiStateWorkerTest extends SysuiTestCase {
+
+    @Rule
+    public MockitoRule mRule = MockitoJUnit.rule();
+    @Mock
+    private BroadcastDispatcher mBroadcastDispatcher;
+    @Mock
+    private WifiManager mWifiManager;
+    @Mock
+    private Intent mIntent;
+
+    private WifiStateWorker mWifiStateWorker;
+    private FakeExecutor mBackgroundExecutor = new FakeExecutor(new FakeSystemClock());
+
+    @Before
+    public void setup() {
+        when(mWifiManager.setWifiEnabled(anyBoolean())).thenReturn(true);
+        when(mWifiManager.getWifiState()).thenReturn(WIFI_STATE_ENABLED);
+        when(mIntent.getAction()).thenReturn(WIFI_STATE_CHANGED_ACTION);
+        when(mIntent.getIntExtra(eq(EXTRA_WIFI_STATE), anyInt())).thenReturn(WIFI_STATE_ENABLED);
+
+        mWifiStateWorker = new WifiStateWorker(mBroadcastDispatcher, mBackgroundExecutor,
+                mWifiManager);
+        mBackgroundExecutor.runAllReady();
+    }
+
+    @Test
+    public void constructor_shouldGetWifiState() {
+        verify(mWifiManager).getWifiState();
+    }
+
+    @Test
+    public void setWifiEnabled_wifiManagerIsNull_shouldNotSetWifiEnabled() {
+        mWifiStateWorker = new WifiStateWorker(mBroadcastDispatcher, mBackgroundExecutor,
+                null /* wifiManager */);
+
+        mWifiStateWorker.setWifiEnabled(true);
+        mBackgroundExecutor.runAllReady();
+
+        verify(mWifiManager, never()).setWifiEnabled(anyBoolean());
+    }
+
+    @Test
+    public void setWifiEnabled_enabledIsTrue_shouldSetWifiEnabled() {
+        mWifiStateWorker.setWifiEnabled(true);
+        mBackgroundExecutor.runAllReady();
+
+        verify(mWifiManager).setWifiEnabled(true);
+    }
+
+    @Test
+    public void setWifiEnabled_enabledIsFalse_shouldSetWifiDisabled() {
+        mWifiStateWorker.setWifiEnabled(false);
+        mBackgroundExecutor.runAllReady();
+
+        verify(mWifiManager).setWifiEnabled(false);
+    }
+
+    @Test
+    public void getWifiState_receiveWifiStateDisabling_getWifiStateDisabling() {
+        when(mIntent.getIntExtra(eq(EXTRA_WIFI_STATE), anyInt())).thenReturn(WIFI_STATE_DISABLING);
+        mWifiStateWorker.onReceive(mContext, mIntent);
+
+        assertThat(mWifiStateWorker.getWifiState()).isEqualTo(WIFI_STATE_DISABLING);
+    }
+
+    @Test
+    public void getWifiState_receiveWifiStateDisabled_getWifiStateDisabled() {
+        when(mIntent.getIntExtra(eq(EXTRA_WIFI_STATE), anyInt())).thenReturn(WIFI_STATE_DISABLED);
+        mWifiStateWorker.onReceive(mContext, mIntent);
+
+        assertThat(mWifiStateWorker.getWifiState()).isEqualTo(WIFI_STATE_DISABLED);
+    }
+
+    @Test
+    public void getWifiState_receiveWifiStateEnabling_getWifiStateEnabling() {
+        when(mIntent.getIntExtra(eq(EXTRA_WIFI_STATE), anyInt())).thenReturn(WIFI_STATE_ENABLING);
+        mWifiStateWorker.onReceive(mContext, mIntent);
+
+        assertThat(mWifiStateWorker.getWifiState()).isEqualTo(WIFI_STATE_ENABLING);
+    }
+
+    @Test
+    public void getWifiState_receiveWifiStateEnabled_getWifiStateEnabled() {
+        when(mIntent.getIntExtra(eq(EXTRA_WIFI_STATE), anyInt())).thenReturn(WIFI_STATE_ENABLED);
+        mWifiStateWorker.onReceive(mContext, mIntent);
+
+        assertThat(mWifiStateWorker.getWifiState()).isEqualTo(WIFI_STATE_ENABLED);
+    }
+
+    @Test
+    public void getWifiState_receiveWifiStateUnknown_ignoreTheIntent() {
+        // Update the Wi-Fi state to WIFI_STATE_DISABLED
+        when(mIntent.getIntExtra(eq(EXTRA_WIFI_STATE), anyInt())).thenReturn(WIFI_STATE_DISABLED);
+        mWifiStateWorker.onReceive(mContext, mIntent);
+        assertThat(mWifiStateWorker.getWifiState()).isEqualTo(WIFI_STATE_DISABLED);
+
+        // Receiver WIFI_STATE_UNKNOWN
+        when(mIntent.getIntExtra(eq(EXTRA_WIFI_STATE), anyInt())).thenReturn(WIFI_STATE_UNKNOWN);
+        mWifiStateWorker.onReceive(mContext, mIntent);
+
+        // Ignore the intent and keep the Wi-Fi state to WIFI_STATE_DISABLED
+        assertThat(mWifiStateWorker.getWifiState()).isEqualTo(WIFI_STATE_DISABLED);
+
+        // Update the Wi-Fi state to WIFI_STATE_ENABLED
+        when(mIntent.getIntExtra(eq(EXTRA_WIFI_STATE), anyInt())).thenReturn(WIFI_STATE_ENABLED);
+        mWifiStateWorker.onReceive(mContext, mIntent);
+        assertThat(mWifiStateWorker.getWifiState()).isEqualTo(WIFI_STATE_ENABLED);
+
+        // Receiver WIFI_STATE_UNKNOWN change
+        when(mIntent.getIntExtra(eq(EXTRA_WIFI_STATE), anyInt())).thenReturn(WIFI_STATE_UNKNOWN);
+        mWifiStateWorker.onReceive(mContext, mIntent);
+
+        // Ignore the intent and keep the Wi-Fi state to WIFI_STATE_ENABLED
+        assertThat(mWifiStateWorker.getWifiState()).isEqualTo(WIFI_STATE_ENABLED);
+    }
+
+    @Test
+    public void isWifiEnabled_receiveWifiStateDisabling_returnFalse() {
+        when(mIntent.getIntExtra(eq(EXTRA_WIFI_STATE), anyInt())).thenReturn(WIFI_STATE_DISABLING);
+        mWifiStateWorker.onReceive(mContext, mIntent);
+
+        assertThat(mWifiStateWorker.isWifiEnabled()).isFalse();
+    }
+
+    @Test
+    public void isWifiEnabled_receiveWifiStateDisabled_returnFalse() {
+        when(mIntent.getIntExtra(eq(EXTRA_WIFI_STATE), anyInt())).thenReturn(WIFI_STATE_DISABLED);
+        mWifiStateWorker.onReceive(mContext, mIntent);
+
+        assertThat(mWifiStateWorker.isWifiEnabled()).isFalse();
+    }
+
+    @Test
+    public void isWifiEnabled_receiveWifiStateEnabling_returnTrue() {
+        when(mIntent.getIntExtra(eq(EXTRA_WIFI_STATE), anyInt())).thenReturn(WIFI_STATE_ENABLING);
+        mWifiStateWorker.onReceive(mContext, mIntent);
+
+        assertThat(mWifiStateWorker.isWifiEnabled()).isTrue();
+    }
+
+    @Test
+    public void isWifiEnabled_receiveWifiStateEnabled_returnTrue() {
+        when(mIntent.getIntExtra(eq(EXTRA_WIFI_STATE), anyInt())).thenReturn(WIFI_STATE_ENABLED);
+        mWifiStateWorker.onReceive(mContext, mIntent);
+
+        assertThat(mWifiStateWorker.isWifiEnabled()).isTrue();
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt
index 8340900..446b51d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/smartspace/DreamSmartspaceControllerTest.kt
@@ -26,7 +26,7 @@
 import android.view.ViewGroup
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.dreams.smartspace.DreamsSmartspaceController
+import com.android.systemui.dreams.smartspace.DreamSmartspaceController
 import com.android.systemui.plugins.BcSmartspaceDataPlugin
 import com.android.systemui.plugins.FalsingManager
 import com.android.systemui.smartspace.dagger.SmartspaceViewComponent
@@ -97,7 +97,7 @@
      */
     @Test
     fun testConnectOnListen() {
-        val controller = DreamsSmartspaceController(context,
+        val controller = DreamSmartspaceController(context,
         smartspaceManager, execution, uiExecutor, viewComponentFactory, precondition,
                 Optional.of(targetFilter), Optional.of(plugin))
 
@@ -158,7 +158,7 @@
      */
     @Test
     fun testConnectOnViewCreate() {
-        val controller = DreamsSmartspaceController(context,
+        val controller = DreamSmartspaceController(context,
                 smartspaceManager, execution, uiExecutor, viewComponentFactory, precondition,
                 Optional.of(targetFilter),
                 Optional.of(plugin))
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 c9de608..6409967 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
@@ -228,19 +228,15 @@
     public void testUpdateEmptyShadeView_notificationsVisible_zenHiding() {
         when(mZenModeController.areNotificationsHiddenInShade()).thenReturn(true);
         mController.attach(mNotificationStackScrollLayout);
-        verify(mSysuiStatusBarStateController).addCallback(
-                mStateListenerArgumentCaptor.capture(), anyInt());
-        StatusBarStateController.StateListener stateListener =
-                mStateListenerArgumentCaptor.getValue();
 
-        setupShowEmptyShadeViewState(stateListener, true);
+        setupShowEmptyShadeViewState(true);
         reset(mNotificationStackScrollLayout);
         mController.updateShowEmptyShadeView();
         verify(mNotificationStackScrollLayout).updateEmptyShadeView(
                 /* visible= */ true,
                 /* notifVisibleInShade= */ true);
 
-        setupShowEmptyShadeViewState(stateListener, false);
+        setupShowEmptyShadeViewState(false);
         reset(mNotificationStackScrollLayout);
         mController.updateShowEmptyShadeView();
         verify(mNotificationStackScrollLayout).updateEmptyShadeView(
@@ -252,19 +248,15 @@
     public void testUpdateEmptyShadeView_notificationsHidden_zenNotHiding() {
         when(mZenModeController.areNotificationsHiddenInShade()).thenReturn(false);
         mController.attach(mNotificationStackScrollLayout);
-        verify(mSysuiStatusBarStateController).addCallback(
-                mStateListenerArgumentCaptor.capture(), anyInt());
-        StatusBarStateController.StateListener stateListener =
-                mStateListenerArgumentCaptor.getValue();
 
-        setupShowEmptyShadeViewState(stateListener, true);
+        setupShowEmptyShadeViewState(true);
         reset(mNotificationStackScrollLayout);
         mController.updateShowEmptyShadeView();
         verify(mNotificationStackScrollLayout).updateEmptyShadeView(
                 /* visible= */ true,
                 /* notifVisibleInShade= */ false);
 
-        setupShowEmptyShadeViewState(stateListener, false);
+        setupShowEmptyShadeViewState(false);
         reset(mNotificationStackScrollLayout);
         mController.updateShowEmptyShadeView();
         verify(mNotificationStackScrollLayout).updateEmptyShadeView(
@@ -407,15 +399,13 @@
         return argThat(new LogMatcher(category, type));
     }
 
-    private void setupShowEmptyShadeViewState(
-            StatusBarStateController.StateListener statusBarStateListener,
-            boolean toShow) {
+    private void setupShowEmptyShadeViewState(boolean toShow) {
         if (toShow) {
-            statusBarStateListener.onStateChanged(SHADE);
+            when(mSysuiStatusBarStateController.getCurrentOrUpcomingState()).thenReturn(SHADE);
             mController.setQsFullScreen(false);
             mController.getView().removeAllViews();
         } else {
-            statusBarStateListener.onStateChanged(KEYGUARD);
+            when(mSysuiStatusBarStateController.getCurrentOrUpcomingState()).thenReturn(KEYGUARD);
             mController.setQsFullScreen(true);
             mController.getView().addContainerView(mock(ExpandableNotificationRow.class));
         }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
similarity index 99%
rename from packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesTest.java
rename to packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
index 84edabd..d364505 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/CentralSurfacesImplTest.java
@@ -178,12 +178,12 @@
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @RunWithLooper(setAsMainLooper = true)
-public class CentralSurfacesTest extends SysuiTestCase {
+public class CentralSurfacesImplTest extends SysuiTestCase {
 
     private static final int FOLD_STATE_FOLDED = 0;
     private static final int FOLD_STATE_UNFOLDED = 1;
 
-    private CentralSurfaces mCentralSurfaces;
+    private CentralSurfacesImpl mCentralSurfaces;
     private FakeMetricsLogger mMetricsLogger;
     private PowerManager mPowerManager;
     private TestableNotificationInterruptStateProviderImpl mNotificationInterruptStateProvider;
@@ -383,7 +383,7 @@
         when(mOperatorNameViewControllerFactory.create(any()))
                 .thenReturn(mOperatorNameViewController);
 
-        mCentralSurfaces = new CentralSurfaces(
+        mCentralSurfaces = new CentralSurfacesImpl(
                 mContext,
                 mNotificationsController,
                 mock(FragmentService.class),
@@ -479,7 +479,7 @@
                 mDreamOverlayStateController,
                 mWiredChargingRippleController);
         when(mKeyguardViewMediator.registerCentralSurfaces(
-                any(CentralSurfaces.class),
+                any(CentralSurfacesImpl.class),
                 any(NotificationPanelViewController.class),
                 any(PanelExpansionStateManager.class),
                 any(BiometricUnlockController.class),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LargeScreenShadeHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LargeScreenShadeHeaderControllerTest.kt
index 01e9595..8066401 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LargeScreenShadeHeaderControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/LargeScreenShadeHeaderControllerTest.kt
@@ -1,8 +1,12 @@
 package com.android.systemui.statusbar.phone
 
 import android.app.StatusBarManager
+import android.content.Context
+import android.content.res.TypedArray
 import android.testing.AndroidTestingRunner
+import android.util.TypedValue.COMPLEX_UNIT_PX
 import android.view.View
+import android.widget.TextView
 import androidx.test.filters.SmallTest
 import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
@@ -13,7 +17,9 @@
 import com.android.systemui.flags.FeatureFlags
 import com.android.systemui.flags.Flags
 import com.android.systemui.qs.HeaderPrivacyIconsController
+import com.android.systemui.qs.carrier.QSCarrierGroup
 import com.android.systemui.qs.carrier.QSCarrierGroupController
+import com.android.systemui.statusbar.policy.FakeConfigurationController
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
 import org.junit.Rule
@@ -22,6 +28,7 @@
 import org.mockito.ArgumentMatchers.any
 import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.Mock
+import org.mockito.Mockito.clearInvocations
 import org.mockito.Mockito.verify
 import org.mockito.junit.MockitoJUnit
 import org.mockito.Mockito.`when` as whenever
@@ -36,19 +43,32 @@
     @Mock private lateinit var qsCarrierGroupController: QSCarrierGroupController
     @Mock private lateinit var qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder
     @Mock private lateinit var featureFlags: FeatureFlags
+    @Mock private lateinit var clock: TextView
+    @Mock private lateinit var date: TextView
+    @Mock private lateinit var carrierGroup: QSCarrierGroup
     @Mock private lateinit var batteryMeterView: BatteryMeterView
     @Mock private lateinit var batteryMeterViewController: BatteryMeterViewController
     @Mock private lateinit var privacyIconsController: HeaderPrivacyIconsController
     @Mock private lateinit var dumpManager: DumpManager
 
+    @Mock private lateinit var mockedContext: Context
+    @Mock private lateinit var typedArray: TypedArray
+
     @JvmField @Rule val mockitoRule = MockitoJUnit.rule()
     var viewVisibility = View.GONE
 
     private lateinit var mLargeScreenShadeHeaderController: LargeScreenShadeHeaderController
     private lateinit var carrierIconSlots: List<String>
+    private val configurationController = FakeConfigurationController()
 
     @Before
     fun setup() {
+        whenever<TextView>(view.findViewById(R.id.clock)).thenReturn(clock)
+        whenever(clock.context).thenReturn(mockedContext)
+        whenever(mockedContext.obtainStyledAttributes(anyInt(), any())).thenReturn(typedArray)
+        whenever<TextView>(view.findViewById(R.id.date)).thenReturn(date)
+        whenever(date.context).thenReturn(mockedContext)
+        whenever<QSCarrierGroup>(view.findViewById(R.id.carrier_group)).thenReturn(carrierGroup)
         whenever<BatteryMeterView>(view.findViewById(R.id.batteryRemainingIcon))
                 .thenReturn(batteryMeterView)
         whenever<StatusIconContainer>(view.findViewById(R.id.statusIcons)).thenReturn(statusIcons)
@@ -67,6 +87,7 @@
                 view,
                 statusBarIconController,
                 privacyIconsController,
+                configurationController,
                 qsCarrierGroupControllerBuilder,
                 featureFlags,
                 batteryMeterViewController,
@@ -138,4 +159,38 @@
         mLargeScreenShadeHeaderController.active = true
         mLargeScreenShadeHeaderController.shadeExpanded = true
     }
+
+    @Test
+    fun updateConfig_changesFontSize() {
+        val updatedTextPixelSize = 32
+        setReturnTextSize(updatedTextPixelSize)
+
+        configurationController.notifyDensityOrFontScaleChanged()
+
+        verify(clock).setTextSize(COMPLEX_UNIT_PX, updatedTextPixelSize.toFloat())
+        verify(date).setTextSize(COMPLEX_UNIT_PX, updatedTextPixelSize.toFloat())
+        verify(carrierGroup).updateTextAppearance(R.style.TextAppearance_QS_Status)
+    }
+
+    @Test
+    fun updateConfig_changesFontSizeMultipleTimes() {
+        val updatedTextPixelSize1 = 32
+        setReturnTextSize(updatedTextPixelSize1)
+        configurationController.notifyDensityOrFontScaleChanged()
+        verify(clock).setTextSize(COMPLEX_UNIT_PX, updatedTextPixelSize1.toFloat())
+        verify(date).setTextSize(COMPLEX_UNIT_PX, updatedTextPixelSize1.toFloat())
+        verify(carrierGroup).updateTextAppearance(R.style.TextAppearance_QS_Status)
+        clearInvocations(carrierGroup)
+
+        val updatedTextPixelSize2 = 42
+        setReturnTextSize(updatedTextPixelSize2)
+        configurationController.notifyDensityOrFontScaleChanged()
+        verify(clock).setTextSize(COMPLEX_UNIT_PX, updatedTextPixelSize2.toFloat())
+        verify(date).setTextSize(COMPLEX_UNIT_PX, updatedTextPixelSize2.toFloat())
+        verify(carrierGroup).updateTextAppearance(R.style.TextAppearance_QS_Status)
+    }
+
+    private fun setReturnTextSize(resultTextSize: Int) {
+        whenever(typedArray.getDimensionPixelSize(anyInt(), anyInt())).thenReturn(resultTextSize)
+    }
 }
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 71f1f0b..f51c428 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
@@ -352,6 +352,8 @@
     private FalsingManagerFake mFalsingManager = new FalsingManagerFake();
     private FakeExecutor mExecutor = new FakeExecutor(new FakeSystemClock());
     private Handler mMainHandler;
+    private final PanelExpansionStateManager mPanelExpansionStateManager =
+            new PanelExpansionStateManager();
 
     @Before
     public void setup() {
@@ -516,7 +518,7 @@
                 mLargeScreenShadeHeaderController,
                 mScreenOffAnimationController,
                 mLockscreenGestureLogger,
-                new PanelExpansionStateManager(),
+                mPanelExpansionStateManager,
                 mNotificationRemoteInputManager,
                 mSysUIUnfoldComponent,
                 mControlsComponent,
@@ -558,6 +560,37 @@
     }
 
     @Test
+    public void computeMaxKeyguardNotifications_lockscreenToShade_returnsExistingMax() {
+        when(mAmbientState.getFractionToShade()).thenReturn(0.5f);
+        mNotificationPanelViewController.setMaxDisplayedNotifications(-1);
+
+        // computeMaxKeyguardNotifications sets maxAllowed to 0 at minimum if it updates the value
+        assertThat(mNotificationPanelViewController.computeMaxKeyguardNotifications())
+                .isEqualTo(-1);
+    }
+
+    @Test
+    public void computeMaxKeyguardNotifications_dozeAmountNotZero_returnsExistingMax() {
+        when(mAmbientState.getDozeAmount()).thenReturn(0.5f);
+        mNotificationPanelViewController.setMaxDisplayedNotifications(-1);
+
+        // computeMaxKeyguardNotifications sets maxAllowed to 0 at minimum if it updates the value
+        assertThat(mNotificationPanelViewController.computeMaxKeyguardNotifications())
+                .isEqualTo(-1);
+    }
+
+    @Test
+    public void computeMaxKeyguardNotifications_noTransition_updatesMax() {
+        when(mAmbientState.getFractionToShade()).thenReturn(0f);
+        when(mAmbientState.getDozeAmount()).thenReturn(0f);
+        mNotificationPanelViewController.setMaxDisplayedNotifications(-1);
+
+        // computeMaxKeyguardNotifications sets maxAllowed to 0 at minimum if it updates the value
+        assertThat(mNotificationPanelViewController.computeMaxKeyguardNotifications())
+                .isNotEqualTo(-1);
+    }
+
+    @Test
     public void testSetPanelScrimMinFraction() {
         mNotificationPanelViewController.setPanelScrimMinFraction(0.5f);
         verify(mNotificationShadeDepthController).setPanelPullDownMinFraction(eq(0.5f));
@@ -987,15 +1020,36 @@
     }
 
     @Test
-    public void testQsToBeImmediatelyExpandedInSplitShade() {
+    public void testQsToBeImmediatelyExpandedWhenOpeningPanelInSplitShade() {
         enableSplitShade(/* enabled= */ true);
+        // set panel state to CLOSED
+        mPanelExpansionStateManager.onPanelExpansionChanged(/* fraction= */ 0,
+                /* expanded= */ false, /* tracking= */ false, /* dragDownPxAmount= */ 0);
+        assertThat(mNotificationPanelViewController.mQsExpandImmediate).isFalse();
 
-        mNotificationPanelViewController.onTrackingStarted();
+        // change panel state to OPENING
+        mPanelExpansionStateManager.onPanelExpansionChanged(/* fraction= */ 0.5f,
+                /* expanded= */ true, /* tracking= */ true, /* dragDownPxAmount= */ 100);
 
         assertThat(mNotificationPanelViewController.mQsExpandImmediate).isTrue();
     }
 
     @Test
+    public void testQsNotToBeImmediatelyExpandedWhenGoingFromUnlockedToLocked() {
+        enableSplitShade(/* enabled= */ true);
+        // set panel state to CLOSED
+        mPanelExpansionStateManager.onPanelExpansionChanged(/* fraction= */ 0,
+                /* expanded= */ false, /* tracking= */ false, /* dragDownPxAmount= */ 0);
+
+        // go to lockscreen, which also sets fraction to 1.0f and makes shade "expanded"
+        mStatusBarStateController.setState(KEYGUARD);
+        mPanelExpansionStateManager.onPanelExpansionChanged(/* fraction= */ 1,
+                /* expanded= */ true, /* tracking= */ true, /* dragDownPxAmount= */ 0);
+
+        assertThat(mNotificationPanelViewController.mQsExpandImmediate).isFalse();
+    }
+
+    @Test
     public void interceptTouchEvent_withinQs_shadeExpanded_startsQsTracking() {
         mNotificationPanelViewController.mQs = mQs;
         when(mQsFrame.getX()).thenReturn(0f);
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 a94ad0b..aaa5a6b 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
@@ -61,7 +61,9 @@
 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;
@@ -97,6 +99,7 @@
     @Mock private LatencyTracker mLatencyTracker;
 
     private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
+    private KeyguardBouncer.BouncerExpansionCallback mBouncerExpansionCallback;
 
     @Before
     public void setUp() {
@@ -136,6 +139,11 @@
                 mBypassController);
         when(mKeyguardStateController.isOccluded()).thenReturn(false);
         mStatusBarKeyguardViewManager.show(null);
+        ArgumentCaptor<KeyguardBouncer.BouncerExpansionCallback> callbackArgumentCaptor =
+                ArgumentCaptor.forClass(KeyguardBouncer.BouncerExpansionCallback.class);
+        verify(mKeyguardBouncerFactory).create(any(ViewGroup.class),
+                callbackArgumentCaptor.capture());
+        mBouncerExpansionCallback = callbackArgumentCaptor.getValue();
     }
 
     @Test
@@ -192,6 +200,15 @@
     }
 
     @Test
+    public void onPanelExpansionChanged_propagatesToBouncer_evenAfterHidden() {
+        mStatusBarKeyguardViewManager.hide(0, 0);
+        when(mBouncer.inTransit()).thenReturn(true);
+
+        mStatusBarKeyguardViewManager.onPanelExpansionChanged(EXPANSION_EVENT);
+        verify(mBouncer).setExpansion(eq(EXPANSION_EVENT.getFraction()));
+    }
+
+    @Test
     public void onPanelExpansionChanged_showsBouncerWhenSwiping() {
         when(mKeyguardStateController.canDismissLockScreen()).thenReturn(false);
         mStatusBarKeyguardViewManager.onPanelExpansionChanged(EXPANSION_EVENT);
@@ -417,4 +434,24 @@
         return new PanelExpansionChangeEvent(
                 fraction, expanded, tracking, /* dragDownPxAmount= */ 0f);
     }
+
+    @Test
+    public void testReportBouncerOnDreamWhenVisible() {
+        mBouncerExpansionCallback.onVisibilityChanged(true);
+        verify(mCentralSurfaces).setBouncerShowingOverDream(false);
+        Mockito.clearInvocations(mCentralSurfaces);
+        when(mDreamOverlayStateController.isOverlayActive()).thenReturn(true);
+        mBouncerExpansionCallback.onVisibilityChanged(true);
+        verify(mCentralSurfaces).setBouncerShowingOverDream(true);
+    }
+
+    @Test
+    public void testReportBouncerOnDreamWhenNotVisible() {
+        mBouncerExpansionCallback.onVisibilityChanged(false);
+        verify(mCentralSurfaces).setBouncerShowingOverDream(false);
+        Mockito.clearInvocations(mCentralSurfaces);
+        when(mDreamOverlayStateController.isOverlayActive()).thenReturn(true);
+        mBouncerExpansionCallback.onVisibilityChanged(false);
+        verify(mCentralSurfaces).setBouncerShowingOverDream(false);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/FakeConfigurationController.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/FakeConfigurationController.kt
index 146b56e..16a3268 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/FakeConfigurationController.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/FakeConfigurationController.kt
@@ -23,6 +23,10 @@
         listeners.forEach { it.onThemeChanged() }
     }
 
+    fun notifyDensityOrFontScaleChanged() {
+        listeners.forEach { it.onDensityOrFontScaleChanged() }
+    }
+
     fun notifyConfigurationChanged() {
         onConfigurationChanged(newConfiguration = null)
     }
diff --git a/services/core/java/com/android/server/am/AppBatteryTracker.java b/services/core/java/com/android/server/am/AppBatteryTracker.java
index 9894a52..6e28d8f 100644
--- a/services/core/java/com/android/server/am/AppBatteryTracker.java
+++ b/services/core/java/com/android/server/am/AppBatteryTracker.java
@@ -276,7 +276,9 @@
                         AppBackgroundRestrictionsInfo.REASON_UNKNOWN, // ExemptionReason
                         AppBackgroundRestrictionsInfo.UNKNOWN, // OptimizationLevel
                         AppBackgroundRestrictionsInfo.SDK_UNKNOWN, // TargetSdk
-                        isLowRamDeviceStatic());
+                        isLowRamDeviceStatic(),
+                        AppBackgroundRestrictionsInfo.LEVEL_UNKNOWN // previous RestrictionLevel
+                );
             }
         }
     }
@@ -304,11 +306,17 @@
                 bgUsage.mPercentage[BatteryUsage.BATTERY_USAGE_INDEX_BACKGROUND];
         final double usageFgs =
                 bgUsage.mPercentage[BatteryUsage.BATTERY_USAGE_INDEX_FOREGROUND_SERVICE];
+        final double usageForeground =
+                bgUsage.mPercentage[BatteryUsage.BATTERY_USAGE_INDEX_FOREGROUND];
+        final double usageCached =
+                bgUsage.mPercentage[BatteryUsage.BATTERY_USAGE_INDEX_CACHED];
         if (DEBUG_BACKGROUND_BATTERY_TRACKER_VERBOSE) {
             Slog.d(TAG, "getBatteryTrackerInfoProtoLocked uid:" + uid
                     + " allUsage:" + String.format("%4.2f%%", allUsage)
                     + " usageBackground:" + String.format("%4.2f%%", usageBackground)
-                    + " usageFgs:" + String.format("%4.2f%%", usageFgs));
+                    + " usageFgs:" + String.format("%4.2f%%", usageFgs)
+                    + " usageForeground:" + String.format("%4.2f%%", usageForeground)
+                    + " usageCached:" + String.format("%4.2f%%", usageCached));
         }
         final ProtoOutputStream proto = new ProtoOutputStream();
         proto.write(AppBackgroundRestrictionsInfo.BatteryTrackerInfo.BATTERY_24H,
@@ -317,6 +325,10 @@
                 usageBackground * 10000);
         proto.write(AppBackgroundRestrictionsInfo.BatteryTrackerInfo.BATTERY_USAGE_FGS,
                 usageFgs * 10000);
+        proto.write(AppBackgroundRestrictionsInfo.BatteryTrackerInfo.BATTERY_USAGE_FOREGROUND,
+                usageForeground * 10000);
+        proto.write(AppBackgroundRestrictionsInfo.BatteryTrackerInfo.BATTERY_USAGE_CACHED,
+                usageCached * 10000);
         proto.flush();
         return proto.getBytes();
     }
diff --git a/services/core/java/com/android/server/am/AppRestrictionController.java b/services/core/java/com/android/server/am/AppRestrictionController.java
index 0c1ab81..f7abb11 100644
--- a/services/core/java/com/android/server/am/AppRestrictionController.java
+++ b/services/core/java/com/android/server/am/AppRestrictionController.java
@@ -2086,6 +2086,9 @@
         int curLevel;
         int prevReason;
         final AppStandbyInternal appStandbyInternal = mInjector.getAppStandbyInternal();
+        if (trackerInfo == null) {
+            trackerInfo = mEmptyTrackerInfo;
+        }
         synchronized (mSettingsLock) {
             curLevel = getRestrictionLevel(uid, pkgName);
             if (curLevel == level) {
@@ -2138,14 +2141,21 @@
                         // It's currently active, enqueue it.
                         final int localReason = reason;
                         final int localSubReason = subReason;
-                        mActiveUids.add(uid, pkgName, () -> appStandbyInternal.restrictApp(
-                                pkgName, UserHandle.getUserId(uid), localReason, localSubReason));
+                        final TrackerInfo localTrackerInfo = trackerInfo;
+                        mActiveUids.add(uid, pkgName, () -> {
+                            appStandbyInternal.restrictApp(pkgName, UserHandle.getUserId(uid),
+                                    localReason, localSubReason);
+                            logAppBackgroundRestrictionInfo(pkgName, uid, curLevel, level,
+                                    localTrackerInfo, localReason);
+                        });
                         doIt = false;
                     }
                 }
                 if (doIt) {
                     appStandbyInternal.restrictApp(pkgName, UserHandle.getUserId(uid),
                             reason, subReason);
+                    logAppBackgroundRestrictionInfo(pkgName, uid, curLevel, level, trackerInfo,
+                            reason);
                 }
             }
         } else if (curLevel >= RESTRICTION_LEVEL_RESTRICTED_BUCKET
@@ -2160,11 +2170,14 @@
             appStandbyInternal.maybeUnrestrictApp(pkgName, UserHandle.getUserId(uid),
                     prevReason & REASON_MAIN_MASK, prevReason & REASON_SUB_MASK,
                     reason, subReason);
+            logAppBackgroundRestrictionInfo(pkgName, uid, curLevel, level, trackerInfo,
+                    reason);
         }
+    }
 
-        if (trackerInfo == null) {
-            trackerInfo = mEmptyTrackerInfo;
-        }
+    private void logAppBackgroundRestrictionInfo(String pkgName, int uid,
+            @RestrictionLevel int prevLevel, @RestrictionLevel int level,
+            @NonNull TrackerInfo trackerInfo, int reason) {
         FrameworkStatsLog.write(FrameworkStatsLog.APP_BACKGROUND_RESTRICTIONS_INFO, uid,
                 getRestrictionLevelStatsd(level),
                 getThresholdStatsd(reason),
@@ -2176,7 +2189,8 @@
                 getExemptionReasonStatsd(uid, level),
                 getOptimizationLevelStatsd(level),
                 getTargetSdkStatsd(pkgName),
-                ActivityManager.isLowRamDeviceStatic());
+                ActivityManager.isLowRamDeviceStatic(),
+                getRestrictionLevelStatsd(prevLevel));
     }
 
     private void handleBackgroundRestrictionChanged(int uid, String pkgName, boolean restricted) {
@@ -2449,7 +2463,8 @@
                             mBgController.getBackgroundRestrictionExemptionReason(uid)),
                     AppBackgroundRestrictionsInfo.UNKNOWN, // OptimizationLevel
                     AppBackgroundRestrictionsInfo.SDK_UNKNOWN, // TargetSdk
-                    ActivityManager.isLowRamDeviceStatic());
+                    ActivityManager.isLowRamDeviceStatic(),
+                    mBgController.getRestrictionLevel(uid));
             PendingIntent pendingIntent;
             if (!mBgController.mConstantsObserver.mBgPromptFgsWithNotiOnLongRunning
                     && mBgController.hasForegroundServiceNotifications(packageName, uid)) {
diff --git a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
index c48ff9f..2dadcec 100644
--- a/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
+++ b/services/core/java/com/android/server/am/SettingsToPropertiesMapper.java
@@ -97,6 +97,7 @@
         DeviceConfig.NAMESPACE_SURFACE_FLINGER_NATIVE_BOOT,
         DeviceConfig.NAMESPACE_SWCODEC_NATIVE,
         DeviceConfig.NAMESPACE_TETHERING,
+        DeviceConfig.NAMESPACE_VENDOR_SYSTEM_NATIVE,
         DeviceConfig.NAMESPACE_VIRTUALIZATION_FRAMEWORK_NATIVE,
         DeviceConfig.NAMESPACE_WINDOW_MANAGER_NATIVE_BOOT,
     };
diff --git a/services/core/java/com/android/server/app/GameServiceProviderInstanceFactoryImpl.java b/services/core/java/com/android/server/app/GameServiceProviderInstanceFactoryImpl.java
index a76eb8f..90b1b63 100644
--- a/services/core/java/com/android/server/app/GameServiceProviderInstanceFactoryImpl.java
+++ b/services/core/java/com/android/server/app/GameServiceProviderInstanceFactoryImpl.java
@@ -20,9 +20,11 @@
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
 import android.app.ActivityTaskManager;
+import android.app.IActivityTaskManager;
 import android.content.Context;
 import android.content.Intent;
 import android.os.ServiceManager;
+import android.os.UserHandle;
 import android.service.games.GameService;
 import android.service.games.GameSessionService;
 import android.service.games.IGameService;
@@ -47,14 +49,17 @@
     @Override
     public GameServiceProviderInstance create(
             @NonNull GameServiceComponentConfiguration configuration) {
+        final UserHandle userHandle = configuration.getUserHandle();
+        final IActivityTaskManager activityTaskManager = ActivityTaskManager.getService();
         return new GameServiceProviderInstanceImpl(
-                configuration.getUserHandle(),
+                userHandle,
                 BackgroundThread.getExecutor(),
                 mContext,
-                new GameClassifierImpl(mContext.getPackageManager()),
+                new GameTaskInfoProvider(userHandle, activityTaskManager,
+                        new GameClassifierImpl(mContext.getPackageManager())),
                 ActivityManager.getService(),
                 LocalServices.getService(ActivityManagerInternal.class),
-                ActivityTaskManager.getService(),
+                activityTaskManager,
                 (WindowManagerService) ServiceManager.getService(Context.WINDOW_SERVICE),
                 LocalServices.getService(WindowManagerInternal.class),
                 new GameServiceConnector(mContext, configuration),
diff --git a/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java b/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java
index b38195a..a200067 100644
--- a/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java
+++ b/services/core/java/com/android/server/app/GameServiceProviderInstanceImpl.java
@@ -64,7 +64,6 @@
 import com.android.server.wm.WindowManagerInternal.TaskSystemBarsListener;
 import com.android.server.wm.WindowManagerService;
 
-import java.util.List;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.Executor;
 import java.util.concurrent.TimeUnit;
@@ -218,7 +217,7 @@
     private final UserHandle mUserHandle;
     private final Executor mBackgroundExecutor;
     private final Context mContext;
-    private final GameClassifier mGameClassifier;
+    private final GameTaskInfoProvider mGameTaskInfoProvider;
     private final IActivityManager mActivityManager;
     private final ActivityManagerInternal mActivityManagerInternal;
     private final IActivityTaskManager mActivityTaskManager;
@@ -244,7 +243,7 @@
             @NonNull UserHandle userHandle,
             @NonNull Executor backgroundExecutor,
             @NonNull Context context,
-            @NonNull GameClassifier gameClassifier,
+            @NonNull GameTaskInfoProvider gameTaskInfoProvider,
             @NonNull IActivityManager activityManager,
             @NonNull ActivityManagerInternal activityManagerInternal,
             @NonNull IActivityTaskManager activityTaskManager,
@@ -256,7 +255,7 @@
         mUserHandle = userHandle;
         mBackgroundExecutor = backgroundExecutor;
         mContext = context;
-        mGameClassifier = gameClassifier;
+        mGameTaskInfoProvider = gameTaskInfoProvider;
         mActivityManager = activityManager;
         mActivityManagerInternal = activityManagerInternal;
         mActivityTaskManager = activityTaskManager;
@@ -344,13 +343,14 @@
     }
 
     private void onTaskCreated(int taskId, @NonNull ComponentName componentName) {
-        String packageName = componentName.getPackageName();
-        if (!mGameClassifier.isGame(packageName, mUserHandle)) {
+        final GameTaskInfo taskInfo = mGameTaskInfoProvider.get(taskId, componentName);
+
+        if (!taskInfo.mIsGameTask) {
             return;
         }
 
         synchronized (mLock) {
-            gameTaskStartedLocked(taskId, componentName);
+            gameTaskStartedLocked(taskInfo);
         }
     }
 
@@ -367,7 +367,17 @@
         }
 
         final GameSessionRecord gameSessionRecord = mGameSessions.get(taskId);
-        if (gameSessionRecord == null || gameSessionRecord.getGameSession() == null) {
+        if (gameSessionRecord == null) {
+            if (focused) {
+                // The game session for a game task may have been destroyed when the game task
+                // was put into the background by pressing the back button. If the task is restored
+                // via the Recents UI there will be no TaskStackListener#onCreated call for the
+                // restoration, so this focus event is the first opportunity to re-create the game
+                // session.
+                maybeCreateGameSessionForFocusedTaskLocked(taskId);
+            }
+            return;
+        } else if (gameSessionRecord.getGameSession() == null) {
             return;
         }
 
@@ -379,30 +389,50 @@
     }
 
     @GuardedBy("mLock")
-    private void gameTaskStartedLocked(int taskId, @NonNull ComponentName componentName) {
+    private void maybeCreateGameSessionForFocusedTaskLocked(int taskId) {
         if (DEBUG) {
-            Slog.i(TAG, "gameStartedLocked() id: " + taskId + " component: " + componentName);
+            Slog.d(TAG, "maybeRecreateGameSessionForFocusedTaskLocked() id: " + taskId);
+        }
+
+        final GameTaskInfo taskInfo = mGameTaskInfoProvider.get(taskId);
+        if (taskInfo == null) {
+            Slog.w(TAG, "No task info for focused task: " + taskId);
+            return;
+        }
+
+        if (!taskInfo.mIsGameTask) {
+            return;
+        }
+
+        gameTaskStartedLocked(taskInfo);
+    }
+
+    @GuardedBy("mLock")
+    private void gameTaskStartedLocked(@NonNull GameTaskInfo gameTaskInfo) {
+        if (DEBUG) {
+            Slog.i(TAG, "gameStartedLocked(): " + gameTaskInfo);
         }
 
         if (!mIsRunning) {
             return;
         }
 
-        GameSessionRecord existingGameSessionRecord = mGameSessions.get(taskId);
+        GameSessionRecord existingGameSessionRecord = mGameSessions.get(gameTaskInfo.mTaskId);
         if (existingGameSessionRecord != null) {
-            Slog.w(TAG, "Existing game session found for task (id: " + taskId
+            Slog.w(TAG, "Existing game session found for task (id: " + gameTaskInfo.mTaskId
                     + ") creation. Ignoring.");
             return;
         }
 
         GameSessionRecord gameSessionRecord = GameSessionRecord.awaitingGameSessionRequest(
-                taskId, componentName);
-        mGameSessions.put(taskId, gameSessionRecord);
+                gameTaskInfo.mTaskId, gameTaskInfo.mComponentName);
+        mGameSessions.put(gameTaskInfo.mTaskId, gameSessionRecord);
 
         AndroidFuture<Void> unusedPostGameStartedFuture = mGameServiceConnector.post(
                 gameService -> {
                     gameService.gameStarted(
-                            new GameStartedEvent(taskId, componentName.getPackageName()));
+                            new GameStartedEvent(gameTaskInfo.mTaskId,
+                                    gameTaskInfo.mComponentName.getPackageName()));
                 });
     }
 
@@ -769,7 +799,7 @@
 
     @Nullable
     private GameSessionViewHostConfiguration createViewHostConfigurationForTask(int taskId) {
-        RunningTaskInfo runningTaskInfo = getRunningTaskInfoForTask(taskId);
+        RunningTaskInfo runningTaskInfo = mGameTaskInfoProvider.getRunningTaskInfo(taskId);
         if (runningTaskInfo == null) {
             return null;
         }
@@ -781,28 +811,6 @@
                 bounds.height());
     }
 
-    @Nullable
-    private RunningTaskInfo getRunningTaskInfoForTask(int taskId) {
-        List<RunningTaskInfo> runningTaskInfos;
-        try {
-            runningTaskInfos = mActivityTaskManager.getTasks(
-                    /* maxNum= */ Integer.MAX_VALUE,
-                    /* filterOnlyVisibleRecents= */ true,
-                    /* keepIntentExtra= */ false);
-        } catch (RemoteException ex) {
-            Slog.w(TAG, "Failed to fetch running tasks");
-            return null;
-        }
-
-        for (RunningTaskInfo taskInfo : runningTaskInfos) {
-            if (taskInfo.taskId == taskId) {
-                return taskInfo;
-            }
-        }
-
-        return null;
-    }
-
     @VisibleForTesting
     void takeScreenshot(int taskId, @NonNull AndroidFuture callback) {
         GameSessionRecord gameSessionRecord;
@@ -834,7 +842,8 @@
             } else {
                 final Bundle bundle = ScreenshotHelper.HardwareBitmapBundler.hardwareBitmapToBundle(
                         bitmap);
-                final RunningTaskInfo runningTaskInfo = getRunningTaskInfoForTask(taskId);
+                final RunningTaskInfo runningTaskInfo =
+                        mGameTaskInfoProvider.getRunningTaskInfo(taskId);
                 if (runningTaskInfo == null) {
                     Slog.w(TAG, "Could not get running task info for id: " + taskId);
                     callback.complete(GameScreenshotResult.createInternalErrorResult());
diff --git a/services/core/java/com/android/server/app/GameTaskInfo.java b/services/core/java/com/android/server/app/GameTaskInfo.java
new file mode 100644
index 0000000..7548dbd
--- /dev/null
+++ b/services/core/java/com/android/server/app/GameTaskInfo.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2022 The Android Open 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.app;
+
+import android.content.ComponentName;
+
+import java.util.Objects;
+
+final class GameTaskInfo {
+    final int mTaskId;
+    final boolean mIsGameTask;
+    final ComponentName mComponentName;
+
+    GameTaskInfo(int taskId, boolean isGameTask, ComponentName componentName) {
+        mTaskId = taskId;
+        mIsGameTask = isGameTask;
+        mComponentName = componentName;
+    }
+
+    @Override
+    public String toString() {
+        return "GameTaskInfo{"
+                + "mTaskId="
+                + mTaskId
+                + ", mIsGameTask="
+                + mIsGameTask
+                + ", mComponentName="
+                + mComponentName
+                + '}';
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+
+        if (!(o instanceof GameTaskInfo)) {
+            return false;
+        }
+
+        GameTaskInfo that = (GameTaskInfo) o;
+        return mTaskId == that.mTaskId
+                && mIsGameTask == that.mIsGameTask
+                && mComponentName.equals(that.mComponentName);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(mTaskId, mIsGameTask, mComponentName);
+    }
+}
diff --git a/services/core/java/com/android/server/app/GameTaskInfoProvider.java b/services/core/java/com/android/server/app/GameTaskInfoProvider.java
new file mode 100644
index 0000000..f078d98
--- /dev/null
+++ b/services/core/java/com/android/server/app/GameTaskInfoProvider.java
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2022 The Android Open 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.app;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.ActivityManager.RunningTaskInfo;
+import android.app.IActivityTaskManager;
+import android.content.ComponentName;
+import android.os.RemoteException;
+import android.os.UserHandle;
+import android.util.LruCache;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+
+import java.util.List;
+
+final class GameTaskInfoProvider {
+    private static final String TAG = "GameTaskInfoProvider";
+    private static final int TASK_INFO_CACHE_MAX_SIZE = 50;
+
+    private final Object mLock = new Object();
+
+    @GuardedBy("mLock")
+    private final LruCache<Integer, GameTaskInfo> mGameTaskInfoCache = new LruCache<>(
+            TASK_INFO_CACHE_MAX_SIZE);
+
+    private final UserHandle mUserHandle;
+    private final IActivityTaskManager mActivityTaskManager;
+    private final GameClassifier mGameClassifier;
+
+    GameTaskInfoProvider(@NonNull UserHandle userHandle,
+            @NonNull IActivityTaskManager activityTaskManager,
+            @NonNull GameClassifier gameClassifier) {
+        mUserHandle = userHandle;
+        mActivityTaskManager = activityTaskManager;
+        mGameClassifier = gameClassifier;
+    }
+
+    @Nullable
+    GameTaskInfo get(int taskId) {
+        synchronized (mLock) {
+            final GameTaskInfo cachedTaskInfo = mGameTaskInfoCache.get(taskId);
+            if (cachedTaskInfo != null) {
+                return cachedTaskInfo;
+            }
+        }
+
+        final RunningTaskInfo runningTaskInfo = getRunningTaskInfo(taskId);
+        if (runningTaskInfo == null || runningTaskInfo.baseActivity == null) {
+            return null;
+        }
+
+        return generateGameInfo(taskId, runningTaskInfo.baseActivity);
+    }
+
+    GameTaskInfo get(int taskId, @NonNull ComponentName componentName) {
+        synchronized (mLock) {
+            final GameTaskInfo cachedTaskInfo = mGameTaskInfoCache.get(taskId);
+            if (cachedTaskInfo != null) {
+                if (cachedTaskInfo.mComponentName.equals(componentName)) {
+                    Slog.w(TAG, "Found cached task info for taskId " + taskId
+                            + " but cached component name " + cachedTaskInfo.mComponentName
+                            + " does not match " + componentName);
+                } else {
+                    return cachedTaskInfo;
+                }
+            }
+        }
+
+        return generateGameInfo(taskId, componentName);
+    }
+
+    @Nullable
+    RunningTaskInfo getRunningTaskInfo(int taskId) {
+        List<RunningTaskInfo> runningTaskInfos;
+        try {
+            runningTaskInfos = mActivityTaskManager.getTasks(
+                    /* maxNum= */ Integer.MAX_VALUE,
+                    /* filterOnlyVisibleRecents= */ false,
+                    /* keepIntentExtra= */ false);
+        } catch (RemoteException ex) {
+            Slog.w(TAG, "Failed to fetch running tasks");
+            return null;
+        }
+
+        for (RunningTaskInfo taskInfo : runningTaskInfos) {
+            if (taskInfo.taskId == taskId) {
+                return taskInfo;
+            }
+        }
+
+        return null;
+    }
+
+    private GameTaskInfo generateGameInfo(int taskId, @NonNull ComponentName componentName) {
+        final GameTaskInfo gameTaskInfo = new GameTaskInfo(taskId,
+                mGameClassifier.isGame(componentName.getPackageName(), mUserHandle), componentName);
+
+        synchronized (mLock) {
+            mGameTaskInfoCache.put(taskId, gameTaskInfo);
+        }
+
+        return gameTaskInfo;
+    }
+}
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index e145270..dbe4fb8 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -862,8 +862,8 @@
     }
 
      /*package*/ void disconnectLeAudio(int device) {
-        if (device != AudioSystem.DEVICE_OUT_BLE_HEADSET ||
-                    device != AudioSystem.DEVICE_OUT_BLE_BROADCAST) {
+        if (device != AudioSystem.DEVICE_OUT_BLE_HEADSET
+                && device != AudioSystem.DEVICE_OUT_BLE_BROADCAST) {
             Log.e(TAG, "disconnectLeAudio: Can't disconnect not LE Audio device " + device);
             return;
         }
@@ -879,6 +879,8 @@
             new MediaMetrics.Item(mMetricsId + "disconnectLeAudio")
                     .record();
             if (toRemove.size() > 0) {
+                final int delay = checkSendBecomingNoisyIntentInt(device, 0,
+                        AudioSystem.DEVICE_NONE);
                 toRemove.stream().forEach(deviceAddress ->
                         makeLeAudioDeviceUnavailable(deviceAddress, device)
                 );
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index d10ed55..0aa9a2b 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -462,6 +462,7 @@
         mDeviceBroker.postBtProfileDisconnected(BluetoothProfile.HEADSET);
         mDeviceBroker.postBtProfileDisconnected(BluetoothProfile.HEARING_AID);
         mDeviceBroker.postBtProfileDisconnected(BluetoothProfile.LE_AUDIO);
+        mDeviceBroker.postBtProfileDisconnected(BluetoothProfile.LE_AUDIO_BROADCAST);
     }
 
     // @GuardedBy("AudioDeviceBroker.mSetModeLock")
@@ -687,6 +688,7 @@
                         case BluetoothProfile.HEADSET:
                         case BluetoothProfile.HEARING_AID:
                         case BluetoothProfile.LE_AUDIO:
+                        case BluetoothProfile.LE_AUDIO_BROADCAST:
                             mDeviceBroker.postBtProfileDisconnected(profile);
                             break;
 
diff --git a/services/core/java/com/android/server/biometrics/sensors/CoexCoordinator.java b/services/core/java/com/android/server/biometrics/sensors/CoexCoordinator.java
index 5aa9b79..c8a90e7 100644
--- a/services/core/java/com/android/server/biometrics/sensors/CoexCoordinator.java
+++ b/services/core/java/com/android/server/biometrics/sensors/CoexCoordinator.java
@@ -92,7 +92,7 @@
         void sendHapticFeedback();
     }
 
-    private static CoexCoordinator sInstance;
+    private static final CoexCoordinator sInstance = new CoexCoordinator();
 
     @VisibleForTesting
     public static class SuccessfulAuth {
@@ -147,14 +147,9 @@
         }
     }
 
-    /**
-     * @return a singleton instance.
-     */
+    /** The singleton instance. */
     @NonNull
     public static CoexCoordinator getInstance() {
-        if (sInstance == null) {
-            sInstance = new CoexCoordinator();
-        }
         return sInstance;
     }
 
@@ -339,18 +334,8 @@
                         auth.mCallback.sendHapticFeedback();
                         auth.mCallback.sendAuthenticationResult(true /* addAuthTokenIfStrong */);
                         auth.mCallback.handleLifecycleAfterAuth();
-                    } else if (isFaceScanning()) {
-                        // UDFPS rejected but face is still scanning
-                        Slog.d(TAG, "UDFPS rejected in multi-sensor auth, face: " + face);
-                        callback.handleLifecycleAfterAuth();
-
-                        // TODO(b/193089985): Enforce/ensure that face auth finishes (whether
-                        //  accept/reject) within X amount of time. Otherwise users will be stuck
-                        //  waiting with their finger down for a long time.
                     } else {
-                        // Face not scanning, and was not found in the queue. Most likely, face
-                        // auth was too long ago.
-                        Slog.d(TAG, "UDFPS rejected in multi-sensor auth, face not scanning");
+                        Slog.d(TAG, "UDFPS rejected in multi-sensor auth");
                         callback.sendHapticFeedback();
                         callback.handleLifecycleAfterAuth();
                     }
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 698f41f..80ff834 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -1389,12 +1389,10 @@
                 // Brightness throttling is needed, so do so quickly.
                 // Later, when throttling is removed, we let other mechanisms decide on speed.
                 slowChange = false;
-                updateScreenBrightnessSetting = true;
             }
             mAppliedThrottling = true;
         } else if (mAppliedThrottling) {
             mAppliedThrottling = false;
-            updateScreenBrightnessSetting = true;
         }
 
         if (updateScreenBrightnessSetting) {
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 0309ddf..0c11d8f 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -252,6 +252,7 @@
 import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.SparseBooleanArray;
 import android.util.StatsEvent;
 import android.util.TypedXmlPullParser;
 import android.util.TypedXmlSerializer;
@@ -284,6 +285,7 @@
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.XmlUtils;
 import com.android.internal.util.function.TriPredicate;
+import com.android.internal.widget.LockPatternUtils;
 import com.android.server.DeviceIdleInternal;
 import com.android.server.EventLogTags;
 import com.android.server.IoThread;
@@ -1923,6 +1925,54 @@
     private SettingsObserver mSettingsObserver;
     protected ZenModeHelper mZenModeHelper;
 
+    protected class StrongAuthTracker extends LockPatternUtils.StrongAuthTracker {
+
+        SparseBooleanArray mUserInLockDownMode = new SparseBooleanArray();
+        boolean mIsInLockDownMode = false;
+
+        StrongAuthTracker(Context context) {
+            super(context);
+        }
+
+        private boolean containsFlag(int haystack, int needle) {
+            return (haystack & needle) != 0;
+        }
+
+        public boolean isInLockDownMode() {
+            return mIsInLockDownMode;
+        }
+
+        @Override
+        public synchronized void onStrongAuthRequiredChanged(int userId) {
+            boolean userInLockDownModeNext = containsFlag(getStrongAuthForUser(userId),
+                    STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
+            mUserInLockDownMode.put(userId, userInLockDownModeNext);
+            boolean isInLockDownModeNext = mUserInLockDownMode.indexOfValue(true) != -1;
+
+            if (mIsInLockDownMode == isInLockDownModeNext) {
+                return;
+            }
+
+            if (isInLockDownModeNext) {
+                cancelNotificationsWhenEnterLockDownMode();
+            }
+
+            // When the mIsInLockDownMode is true, both notifyPostedLocked and
+            // notifyRemovedLocked will be dismissed. So we shall call
+            // cancelNotificationsWhenEnterLockDownMode before we set mIsInLockDownMode
+            // as true and call postNotificationsWhenExitLockDownMode after we set
+            // mIsInLockDownMode as false.
+            mIsInLockDownMode = isInLockDownModeNext;
+
+            if (!isInLockDownModeNext) {
+                postNotificationsWhenExitLockDownMode();
+            }
+        }
+    }
+
+    private LockPatternUtils mLockPatternUtils;
+    private StrongAuthTracker mStrongAuthTracker;
+
     public NotificationManagerService(Context context) {
         this(context,
                 new NotificationRecordLoggerImpl(),
@@ -1952,6 +2002,11 @@
     }
 
     @VisibleForTesting
+    void setStrongAuthTracker(StrongAuthTracker strongAuthTracker) {
+        mStrongAuthTracker = strongAuthTracker;
+    }
+
+    @VisibleForTesting
     void setKeyguardManager(KeyguardManager keyguardManager) {
         mKeyguardManager = keyguardManager;
     }
@@ -2145,6 +2200,8 @@
         mPlatformCompat = IPlatformCompat.Stub.asInterface(
                 ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
 
+        mLockPatternUtils = new LockPatternUtils(getContext());
+        mStrongAuthTracker = new StrongAuthTracker(getContext());
         mUiHandler = new Handler(UiThread.get().getLooper());
         String[] extractorNames;
         try {
@@ -2641,6 +2698,7 @@
                 bubbsExtractor.setShortcutHelper(mShortcutHelper);
             }
             registerNotificationPreferencesPullers();
+            mLockPatternUtils.registerStrongAuthTracker(mStrongAuthTracker);
         } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
             // This observer will force an update when observe is called, causing us to
             // bind to listener services.
@@ -9537,6 +9595,29 @@
         }
     }
 
+    private void cancelNotificationsWhenEnterLockDownMode() {
+        synchronized (mNotificationLock) {
+            int numNotifications = mNotificationList.size();
+            for (int i = 0; i < numNotifications; i++) {
+                NotificationRecord rec = mNotificationList.get(i);
+                mListeners.notifyRemovedLocked(rec, REASON_CANCEL_ALL,
+                        rec.getStats());
+            }
+
+        }
+    }
+
+    private void postNotificationsWhenExitLockDownMode() {
+        synchronized (mNotificationLock) {
+            int numNotifications = mNotificationList.size();
+            for (int i = 0; i < numNotifications; i++) {
+                NotificationRecord rec = mNotificationList.get(i);
+                mListeners.notifyPostedLocked(rec, rec);
+            }
+
+        }
+    }
+
     private void updateNotificationPulse() {
         synchronized (mNotificationLock) {
             updateLightsLocked();
@@ -9753,6 +9834,10 @@
                 rankings.toArray(new NotificationListenerService.Ranking[0]));
     }
 
+    boolean isInLockDownMode() {
+        return mStrongAuthTracker.isInLockDownMode();
+    }
+
     boolean hasCompanionDevice(ManagedServiceInfo info) {
         if (mCompanionManager == null) {
             mCompanionManager = getCompanionManager();
@@ -10804,8 +10889,12 @@
          *                           targetting <= O_MR1
          */
         @GuardedBy("mNotificationLock")
-        private void notifyPostedLocked(NotificationRecord r, NotificationRecord old,
+        void notifyPostedLocked(NotificationRecord r, NotificationRecord old,
                 boolean notifyAllListeners) {
+            if (isInLockDownMode()) {
+                return;
+            }
+
             try {
                 // Lazily initialized snapshots of the notification.
                 StatusBarNotification sbn = r.getSbn();
@@ -10908,6 +10997,10 @@
         @GuardedBy("mNotificationLock")
         public void notifyRemovedLocked(NotificationRecord r, int reason,
                 NotificationStats notificationStats) {
+            if (isInLockDownMode()) {
+                return;
+            }
+
             final StatusBarNotification sbn = r.getSbn();
 
             // make a copy in case changes are made to the underlying Notification object
@@ -10953,6 +11046,10 @@
          */
         @GuardedBy("mNotificationLock")
         public void notifyRankingUpdateLocked(List<NotificationRecord> changedHiddenNotifications) {
+            if (isInLockDownMode()) {
+                return;
+            }
+
             boolean isHiddenRankingUpdate = changedHiddenNotifications != null
                     && changedHiddenNotifications.size() > 0;
             // TODO (b/73052211): if the ranking update changed the notification type,
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 8bd1da9..2d8d4f5 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -2545,7 +2545,6 @@
         ArrayList<String>[] components;
         int size = 0;
         int[] uids;
-        Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
 
         synchronized (mPm.mLock) {
             final SparseArray<ArrayMap<String, ArrayList<String>>> userIdToPackagesToComponents =
@@ -2584,7 +2583,6 @@
             mPm.sendPackageChangedBroadcast(snapshot, packages[i], true /* dontKillApp */,
                     components[i], uids[i], null /* reason */);
         }
-        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
     }
 
     void handlePackagePostInstall(PackageInstalledInfo res, InstallArgs installArgs,
diff --git a/services/core/java/com/android/server/pm/PackageHandler.java b/services/core/java/com/android/server/pm/PackageHandler.java
index e8faca9..0dfa31c 100644
--- a/services/core/java/com/android/server/pm/PackageHandler.java
+++ b/services/core/java/com/android/server/pm/PackageHandler.java
@@ -75,7 +75,7 @@
         try {
             doHandleMessage(msg);
         } finally {
-            Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+            Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
         }
     }
 
@@ -136,19 +136,13 @@
                 }
             } break;
             case WRITE_SETTINGS: {
-                Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
                 mPm.writeSettings();
-                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
             } break;
             case WRITE_PACKAGE_RESTRICTIONS: {
-                Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
                 mPm.writePendingRestrictions();
-                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
             } break;
             case WRITE_PACKAGE_LIST: {
-                Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
                 mPm.writePackageList(msg.arg1);
-                Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
             } break;
             case CHECK_PENDING_VERIFICATION: {
                 final int verificationId = msg.arg1;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 88564aa..2cef35f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1413,7 +1413,9 @@
         t.traceBegin("create package manager");
         final PackageManagerTracedLock lock = new PackageManagerTracedLock();
         final Object installLock = new Object();
-        HandlerThread backgroundThread = new HandlerThread("PackageManagerBg");
+
+        HandlerThread backgroundThread = new ServiceThread("PackageManagerBg",
+                Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
         backgroundThread.start();
         Handler backgroundHandler = new Handler(backgroundThread.getLooper());
 
@@ -1467,7 +1469,7 @@
                 (i, pm) -> domainVerificationService,
                 (i, pm) -> {
                     HandlerThread thread = new ServiceThread(TAG,
-                            Process.THREAD_PRIORITY_BACKGROUND, true /*allowIo*/);
+                            Process.THREAD_PRIORITY_DEFAULT, true /*allowIo*/);
                     thread.start();
                     return new PackageHandler(thread.getLooper(), pm);
                 },
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 78a600e..6b10d4c 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -159,13 +159,14 @@
     private static final Map<String, Integer> SUPPORTED_PERMISSION_FLAGS = new ArrayMap<>();
     private static final List<String> SUPPORTED_PERMISSION_FLAGS_LIST;
     static {
+        SUPPORTED_PERMISSION_FLAGS_LIST = List.of("review-required", "revoked-compat",
+                "revoke-when-requested", "user-fixed", "user-set");
         SUPPORTED_PERMISSION_FLAGS.put("user-set", FLAG_PERMISSION_USER_SET);
         SUPPORTED_PERMISSION_FLAGS.put("user-fixed", FLAG_PERMISSION_USER_FIXED);
         SUPPORTED_PERMISSION_FLAGS.put("revoked-compat", FLAG_PERMISSION_REVOKED_COMPAT);
         SUPPORTED_PERMISSION_FLAGS.put("review-required", FLAG_PERMISSION_REVIEW_REQUIRED);
         SUPPORTED_PERMISSION_FLAGS.put("revoke-when-requested",
                 FLAG_PERMISSION_REVOKE_WHEN_REQUESTED);
-        SUPPORTED_PERMISSION_FLAGS_LIST = new ArrayList<>(SUPPORTED_PERMISSION_FLAGS.keySet());
     }
 
     final IPackageManager mInterface;
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index a1b4b30..ba4d09f 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -164,6 +164,7 @@
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Objects;
+import java.util.Random;
 import java.util.Set;
 import java.util.UUID;
 import java.util.function.Consumer;
@@ -633,8 +634,8 @@
                 runtimePermissionsPersistence, new Consumer<Integer>() {
             @Override
             public void accept(Integer userId) {
-                mRuntimePermissionsPersistence.writeStateForUser(userId,
-                        mPermissionDataProvider, mPackages, mSharedUsers, mHandler, mLock);
+                mRuntimePermissionsPersistence.writeStateForUser(userId, mPermissionDataProvider,
+                        mPackages, mSharedUsers, mHandler, mLock, /*sync=*/false);
             }
         });
         mPermissionDataProvider = permissionDataProvider;
@@ -5292,7 +5293,7 @@
     public void writePermissionStateForUserLPr(int userId, boolean sync) {
         if (sync) {
             mRuntimePermissionsPersistence.writeStateForUser(userId, mPermissionDataProvider,
-                    mPackages, mSharedUsers, /*handler=*/null, mLock);
+                    mPackages, mSharedUsers, /*handler=*/null, mLock, /*sync=*/true);
         } else {
             mRuntimePermissionsPersistence.writeStateForUserAsync(userId);
         }
@@ -5370,12 +5371,17 @@
     }
 
     private static final class RuntimePermissionPersistence {
-        private static final long WRITE_PERMISSIONS_DELAY_MILLIS = 200;
+        // 200-400ms delay to avoid monopolizing PMS lock when written for multiple users.
+        private static final long WRITE_PERMISSIONS_DELAY_MILLIS = 300;
+        private static final double WRITE_PERMISSIONS_DELAY_JITTER = 0.3;
+
         private static final long MAX_WRITE_PERMISSIONS_DELAY_MILLIS = 2000;
 
         private static final int UPGRADE_VERSION = -1;
         private static final int INITIAL_VERSION = 0;
 
+        private static final Random sRandom = new Random();
+
         private String mExtendedFingerprint;
 
         @GuardedBy("mPersistenceLock")
@@ -5397,6 +5403,11 @@
         private final SparseLongArray mLastNotWrittenMutationTimesMillis = new SparseLongArray();
 
         @GuardedBy("mLock")
+        // Tracking the mutations that haven't yet been written to legacy state.
+        // This avoids unnecessary work when writing settings for multiple users.
+        private boolean mIsLegacyPermissionStateStale = false;
+
+        @GuardedBy("mLock")
         // The mapping keys are user ids.
         private final SparseIntArray mVersions = new SparseIntArray();
 
@@ -5472,9 +5483,22 @@
             return PackagePartitions.FINGERPRINT + "?pc_version=" + version;
         }
 
+        private static long uniformRandom(double low, double high) {
+            double mag = high - low;
+            return (long) (sRandom.nextDouble() * mag + low);
+        }
+
+        private static long nextWritePermissionDelayMillis() {
+            final long delay = WRITE_PERMISSIONS_DELAY_MILLIS;
+            final double jitter = WRITE_PERMISSIONS_DELAY_JITTER;
+            return delay + uniformRandom(-jitter * delay, jitter * delay);
+        }
+
         public void writeStateForUserAsync(int userId) {
             synchronized (mLock) {
+                mIsLegacyPermissionStateStale = true;
                 final long currentTimeMillis = SystemClock.uptimeMillis();
+                final long writePermissionDelayMillis = nextWritePermissionDelayMillis();
 
                 if (mWriteScheduled.get(userId)) {
                     mAsyncHandler.removeMessages(userId);
@@ -5493,7 +5517,7 @@
                     // Hold off a bit more as settings are frequently changing.
                     final long maxDelayMillis = Math.max(lastNotWrittenMutationTimeMillis
                             + MAX_WRITE_PERMISSIONS_DELAY_MILLIS - currentTimeMillis, 0);
-                    final long writeDelayMillis = Math.min(WRITE_PERMISSIONS_DELAY_MILLIS,
+                    final long writeDelayMillis = Math.min(writePermissionDelayMillis,
                             maxDelayMillis);
 
                     Message message = mAsyncHandler.obtainMessage(userId);
@@ -5501,7 +5525,7 @@
                 } else {
                     mLastNotWrittenMutationTimesMillis.put(userId, currentTimeMillis);
                     Message message = mAsyncHandler.obtainMessage(userId);
-                    mAsyncHandler.sendMessageDelayed(message, WRITE_PERMISSIONS_DELAY_MILLIS);
+                    mAsyncHandler.sendMessageDelayed(message, writePermissionDelayMillis);
                     mWriteScheduled.put(userId, true);
                 }
             }
@@ -5511,21 +5535,27 @@
                 legacyPermissionDataProvider,
                 @NonNull WatchedArrayMap<String, ? extends PackageStateInternal> packageStates,
                 @NonNull WatchedArrayMap<String, SharedUserSetting> sharedUsers,
-                @Nullable Handler pmHandler, @NonNull Object pmLock) {
+                @Nullable Handler pmHandler, @NonNull Object pmLock,
+                boolean sync) {
             final int version;
             final String fingerprint;
+            final boolean isLegacyPermissionStateStale;
             synchronized (mLock) {
                 mAsyncHandler.removeMessages(userId);
                 mWriteScheduled.delete(userId);
 
                 version = mVersions.get(userId, INITIAL_VERSION);
                 fingerprint = mFingerprints.get(userId);
+                isLegacyPermissionStateStale = mIsLegacyPermissionStateStale;
+                mIsLegacyPermissionStateStale = false;
             }
 
             Runnable writer = () -> {
                 final RuntimePermissionsState runtimePermissions;
                 synchronized (pmLock) {
-                    legacyPermissionDataProvider.writeLegacyPermissionStateTEMP();
+                    if (sync || isLegacyPermissionStateStale) {
+                        legacyPermissionDataProvider.writeLegacyPermissionStateTEMP();
+                    }
 
                     Map<String, List<RuntimePermissionsState.PermissionState>> packagePermissions =
                             new ArrayMap<>();
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 0311524..284c29e 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -21,6 +21,7 @@
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.app.DownloadManager;
 import android.app.SearchManager;
@@ -1093,6 +1094,14 @@
         }
     }
 
+    public void grantDefaultPermissionsToCarrierServiceApp(@NonNull String packageName,
+            @UserIdInt int userId) {
+        Log.i(TAG, "Grant permissions to Carrier Service app " + packageName + " for user:"
+                + userId);
+        grantPermissionsToPackage(NO_PM_CACHE, packageName, userId, /* ignoreSystemPackage */ false,
+               /* whitelistRestricted */ true, NOTIFICATION_PERMISSIONS);
+    }
+
     private String getDefaultSystemHandlerActivityPackage(PackageManagerWrapper pm,
             String intentAction, int userId) {
         return getDefaultSystemHandlerActivityPackage(pm, new Intent(intentAction), userId);
diff --git a/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java b/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java
index ea554d3..360a04f 100644
--- a/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/LegacyPermissionManagerService.java
@@ -18,6 +18,7 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UserIdInt;
 import android.app.AppOpsManager;
 import android.app.admin.DevicePolicyManager;
 import android.content.Context;
@@ -248,6 +249,15 @@
     }
 
     @Override
+    public void grantDefaultPermissionsToCarrierServiceApp(@NonNull String packageName,
+            @UserIdInt int userId) {
+        PackageManagerServiceUtils.enforceSystemOrRoot(
+                "grantDefaultPermissionsForCarrierServiceApp");
+        Binder.withCleanCallingIdentity(() -> mDefaultPermissionGrantPolicy
+                .grantDefaultPermissionsToCarrierServiceApp(packageName, userId));
+    }
+
+    @Override
     public void grantDefaultPermissionsToActiveLuiApp(String packageName, int userId) {
         final int callingUid = Binder.getCallingUid();
         PackageManagerServiceUtils.enforceSystemOrPhoneCaller(
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
index 092f3be..d9e74f8 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerServiceImpl.java
@@ -767,8 +767,8 @@
             flagValues &= ~FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT;
             flagValues &= ~FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT;
             flagValues &= ~PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION;
-            // REVIEW_REQUIRED can only be set by non-system apps for POST_NOTIFICATIONS, or by the
-            // shell or root UID.
+            // REVIEW_REQUIRED can be set on any permission by the shell or the root uid, or by
+            // any app for the POST_NOTIFICATIONS permission specifically.
             if (!POST_NOTIFICATIONS.equals(permName) && callingUid != Process.SHELL_UID
                     && callingUid != Process.ROOT_UID) {
                 flagValues &= ~PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED;
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 89ac9e7..14abc9a 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -66,11 +66,13 @@
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
+import android.permission.LegacyPermissionManager;
 import android.permission.PermissionControllerManager;
 import android.permission.PermissionManager;
 import android.provider.Settings;
 import android.provider.Telephony;
 import android.telecom.TelecomManager;
+import android.telephony.TelephonyManager;
 import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Log;
@@ -106,6 +108,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Set;
 import java.util.concurrent.ExecutionException;
 
 /**
@@ -163,6 +166,7 @@
     private PackageManagerInternal mPackageManagerInternal;
     private PermissionManagerServiceInternal mPermissionManagerInternal;
     private NotificationManagerInternal mNotificationManager;
+    private TelephonyManager mTelephonyManager;
     private final KeyguardManager mKeyguardManager;
     private final PackageManager mPackageManager;
     private final Handler mHandler;
@@ -384,6 +388,13 @@
     public void onBootPhase(int phase) {
         if (DEBUG) Slog.i(LOG_TAG, "onBootPhase(" + phase + ")");
 
+        if (phase == PHASE_DEVICE_SPECIFIC_SERVICES_READY) {
+            registerCarrierPrivilegesCallbacks();
+            IntentFilter filter =
+                    new IntentFilter(TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED);
+            mContext.registerReceiver(mSimConfigBroadcastReceiver, filter);
+        }
+
         if (phase == PHASE_ACTIVITY_MANAGER_READY) {
             final UserManagerInternal um = LocalServices.getService(UserManagerInternal.class);
 
@@ -408,6 +419,94 @@
 
     }
 
+    private void initTelephonyManagerIfNeeded() {
+        if (mTelephonyManager == null) {
+            mTelephonyManager = TelephonyManager.from(mContext);
+        }
+    }
+
+    private void registerCarrierPrivilegesCallbacks() {
+        initTelephonyManagerIfNeeded();
+        if (mTelephonyManager == null) {
+            return;
+        }
+
+        int numPhones = mTelephonyManager.getActiveModemCount();
+        for (int i = 0; i < numPhones; i++) {
+            PhoneCarrierPrivilegesCallback callback = new PhoneCarrierPrivilegesCallback(i);
+            mPhoneCarrierPrivilegesCallbacks.add(callback);
+            mTelephonyManager.registerCarrierPrivilegesCallback(i, mContext.getMainExecutor(),
+                    callback);
+        }
+    }
+
+    private void unregisterCarrierPrivilegesCallback() {
+        initTelephonyManagerIfNeeded();
+        if (mTelephonyManager == null) {
+            return;
+        }
+
+        for (int i = 0; i < mPhoneCarrierPrivilegesCallbacks.size(); i++) {
+            PhoneCarrierPrivilegesCallback callback = mPhoneCarrierPrivilegesCallbacks.get(i);
+            if (callback != null) {
+                mTelephonyManager.unregisterCarrierPrivilegesCallback(callback);
+            }
+        }
+        mPhoneCarrierPrivilegesCallbacks.clear();
+    }
+
+    private final class PhoneCarrierPrivilegesCallback
+            implements TelephonyManager.CarrierPrivilegesCallback {
+        private int mPhoneId;
+
+        PhoneCarrierPrivilegesCallback(int phoneId) {
+            mPhoneId = phoneId;
+        }
+        @Override
+        public void onCarrierPrivilegesChanged(
+                @NonNull Set<String> privilegedPackageNames,
+                @NonNull Set<Integer> privilegedUids) {
+            initTelephonyManagerIfNeeded();
+            if (mTelephonyManager == null) {
+                Log.e(LOG_TAG, "Cannot grant default permissions to Carrier Service app. "
+                        + "TelephonyManager is null");
+                return;
+            }
+
+            String servicePkg = mTelephonyManager.getCarrierServicePackageNameForLogicalSlot(
+                    mPhoneId);
+            if (servicePkg == null) {
+                return;
+            }
+            int[] users = LocalServices.getService(UserManagerInternal.class).getUserIds();
+            LegacyPermissionManager legacyPermManager =
+                    mContext.getSystemService(LegacyPermissionManager.class);
+            for (int i = 0; i < users.length; i++) {
+                try {
+                    mPackageManager.getPackageInfoAsUser(servicePkg, 0, users[i]);
+                    legacyPermManager.grantDefaultPermissionsToCarrierServiceApp(
+                            servicePkg, users[i]);
+                } catch (PackageManager.NameNotFoundException e) {
+                    // Do nothing if the package does not exist for the specified user
+                }
+            }
+        }
+    }
+
+    private final ArrayList<PhoneCarrierPrivilegesCallback> mPhoneCarrierPrivilegesCallbacks =
+            new ArrayList<>();
+
+    private final BroadcastReceiver mSimConfigBroadcastReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (!TelephonyManager.ACTION_MULTI_SIM_CONFIG_CHANGED.equals(intent.getAction())) {
+                return;
+            }
+            unregisterCarrierPrivilegesCallback();
+            registerCarrierPrivilegesCallbacks();
+        }
+    };
+
     /**
      * @return Whether the user is started but not yet stopped
      */
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index b142141..f14bdca 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -4547,7 +4547,6 @@
                                     pmWakeReason)) + ")");
         }
 
-        mActivityTaskManagerInternal.notifyWakingUp();
         mDefaultDisplayPolicy.setAwake(true);
 
         // Since goToSleep performs these functions synchronously, we must
diff --git a/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java b/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java
index ae23b9e..5db4a7b 100644
--- a/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java
+++ b/services/core/java/com/android/server/speech/SpeechRecognitionManagerServiceImpl.java
@@ -268,9 +268,17 @@
     }
 
     private boolean componentMapsToRecognitionService(@NonNull ComponentName serviceComponent) {
-        List<ResolveInfo> resolveInfos =
-                getContext().getPackageManager().queryIntentServicesAsUser(
-                        new Intent(RecognitionService.SERVICE_INTERFACE), 0, getUserId());
+        List<ResolveInfo> resolveInfos;
+
+        final long identityToken = Binder.clearCallingIdentity();
+        try {
+            resolveInfos =
+                    getContext().getPackageManager().queryIntentServicesAsUser(
+                            new Intent(RecognitionService.SERVICE_INTERFACE), 0, getUserId());
+        } finally {
+            Binder.restoreCallingIdentity(identityToken);
+        }
+
         if (resolveInfos == null) {
             return false;
         }
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index f48c453..df2be8c 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -661,10 +661,19 @@
 
     /**
      * The activity is opaque and fills the entire space of this task.
-     * @see WindowContainer#fillsParent()
+     * @see #occludesParent()
      */
     private boolean mOccludesParent;
 
+    /**
+     * Unlike {@link #mOccludesParent} which can be changed at runtime. This is a static attribute
+     * from the style of activity. Because we don't want {@link WindowContainer#getOrientation()}
+     * to be affected by the temporal state of {@link ActivityClientController#convertToTranslucent}
+     * when running ANIM_SCENE_TRANSITION.
+     * @see WindowContainer#fillsParent()
+     */
+    private final boolean mFillsParent;
+
     // The input dispatching timeout for this application token in milliseconds.
     long mInputDispatchingTimeoutMillis = DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
 
@@ -1956,8 +1965,10 @@
                     // This style is propagated to the main window attributes with
                     // FLAG_SHOW_WALLPAPER from PhoneWindow#generateLayout.
                     || ent.array.getBoolean(R.styleable.Window_windowShowWallpaper, false);
+            mFillsParent = mOccludesParent;
             noDisplay = ent.array.getBoolean(R.styleable.Window_windowNoDisplay, false);
         } else {
+            mFillsParent = mOccludesParent = true;
             noDisplay = false;
         }
 
@@ -2852,7 +2863,7 @@
 
     @Override
     boolean fillsParent() {
-        return occludesParent(true /* includingFinishing */);
+        return mFillsParent;
     }
 
     /** Returns true if this activity is not finishing, is opaque and fills the entire space of
@@ -9647,6 +9658,10 @@
     @Override
     boolean isSyncFinished() {
         if (!super.isSyncFinished()) return false;
+        if (mDisplayContent != null && mDisplayContent.mUnknownAppVisibilityController
+                .isVisibilityUnknown(this)) {
+            return false;
+        }
         if (!isVisibleRequested()) return true;
         // Wait for attach. That is the earliest time where we know if there will be an associated
         // display rotation. If we don't wait, the starting-window can finishDrawing first and
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
index a4b216f..938e0ed 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerInternal.java
@@ -666,9 +666,6 @@
     public abstract boolean hasSystemAlertWindowPermission(int callingUid, int callingPid,
             String callingPackage);
 
-    /** Called when the device is waking up */
-    public abstract void notifyWakingUp();
-
     /**
      * Registers a callback which can intercept activity starts.
      * @throws IllegalArgumentException if duplicate ids are provided
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index d254aaf..350cb7a 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -64,7 +64,6 @@
 import static android.provider.Settings.System.FONT_SCALE;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
-import static android.view.WindowManager.TRANSIT_WAKE;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_CONFIGURATION;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
@@ -6628,15 +6627,6 @@
         }
 
         @Override
-        public void notifyWakingUp() {
-            synchronized (mGlobalLock) {
-                // Start a transition for waking. This is needed for showWhenLocked activities.
-                getTransitionController().requestTransitionIfNeeded(TRANSIT_WAKE, 0 /* flags */,
-                        null /* trigger */, mRootWindowContainer.getDefaultDisplay());
-            }
-        }
-
-        @Override
         public void registerActivityStartInterceptor(
                 @ActivityInterceptorCallback.OrderedId int id,
                 ActivityInterceptorCallback callback) {
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index 68a09a6..4f015d8 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -683,6 +683,9 @@
         } else if (mNextAppTransitionType == NEXT_TRANSIT_TYPE_CUSTOM) {
             a = mTransitionAnimation.loadAppTransitionAnimation(mNextAppTransitionPackage,
                     enter ? mNextAppTransitionEnter : mNextAppTransitionExit);
+            if (mNextAppTransitionBackgroundColor != 0) {
+                a.setBackdropColor(mNextAppTransitionBackgroundColor);
+            }
             ProtoLog.v(WM_DEBUG_APP_TRANSITIONS_ANIM,
                     "applyAnimation: anim=%s nextAppTransition=ANIM_CUSTOM transit=%s "
                             + "isEntrance=%b Callers=%s",
@@ -842,10 +845,6 @@
         }
         setAppTransitionFinishedCallbackIfNeeded(a);
 
-        if (mNextAppTransitionBackgroundColor != 0) {
-            a.setBackdropColor(mNextAppTransitionBackgroundColor);
-        }
-
         return a;
     }
 
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 014bb9f..d1ba77d 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -61,6 +61,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION;
 import static android.view.WindowManager.LayoutParams.TYPE_VOICE_INTERACTION_STARTING;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
+import static android.view.WindowManager.TRANSIT_WAKE;
 import static android.view.WindowManagerGlobal.ADD_OKAY;
 import static android.view.WindowManagerPolicyConstants.ACTION_HDMI_PLUGGED;
 import static android.view.WindowManagerPolicyConstants.ALT_BAR_BOTTOM;
@@ -300,10 +301,6 @@
     // 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;
-
     /**
      * A collection of {@link AppearanceRegion} to indicate that which region of status bar applies
      * which appearance.
@@ -780,7 +777,22 @@
     }
 
     public void setAwake(boolean awake) {
+        if (awake == mAwake) {
+            return;
+        }
         mAwake = awake;
+        synchronized (mService.mGlobalLock) {
+            if (!mDisplayContent.isDefaultDisplay) {
+                return;
+            }
+            if (mAwake) {
+                // Start a transition for waking. This is needed for showWhenLocked activities.
+                mDisplayContent.mTransitionController.requestTransitionIfNeeded(TRANSIT_WAKE,
+                        0 /* flags */, null /* trigger */, mDisplayContent);
+            }
+            mService.mAtmService.mKeyguardController.updateDeferWakeTransition(
+                    mAwake /* waiting */);
+        }
     }
 
     public boolean isAwake() {
@@ -970,16 +982,10 @@
             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;
+        final InsetsSourceProvider provider = win.getControllableInsetProvider();
+        if (provider != null && provider.getSource().getInsetsRoundedCornerFrame()
+                != attrs.insetsRoundedCornerFrame) {
+            provider.getSource().setInsetsRoundedCornerFrame(attrs.insetsRoundedCornerFrame);
         }
     }
 
@@ -1326,9 +1332,6 @@
         if (mLastFocusedWindow == win) {
             mLastFocusedWindow = null;
         }
-        if (mRoundedCornerWindow == win) {
-            mRoundedCornerWindow = null;
-        }
 
         mInsetsSourceWindowsExceptIme.remove(win);
     }
@@ -1360,10 +1363,6 @@
         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
diff --git a/services/core/java/com/android/server/wm/DisplayRotation.java b/services/core/java/com/android/server/wm/DisplayRotation.java
index 5aacb09..f833773 100644
--- a/services/core/java/com/android/server/wm/DisplayRotation.java
+++ b/services/core/java/com/android/server/wm/DisplayRotation.java
@@ -702,17 +702,17 @@
     }
 
     boolean canRotateSeamlessly(int oldRotation, int newRotation) {
+        // If the navigation bar can't change sides, then it will jump when we change orientations
+        // and we don't rotate seamlessly - unless that is allowed, eg. with gesture navigation
+        // where the navbar is low-profile enough that this isn't very noticeable.
+        if (mAllowSeamlessRotationDespiteNavBarMoving || mDisplayPolicy.navigationBarCanMove()) {
+            return true;
+        }
         // For the upside down rotation we don't rotate seamlessly as the navigation bar moves
         // position. Note most apps (using orientation:sensor or user as opposed to fullSensor)
         // will not enter the reverse portrait orientation, so actually the orientation won't change
         // at all.
-        if (oldRotation == mUpsideDownRotation || newRotation == mUpsideDownRotation) {
-            return false;
-        }
-        // If the navigation bar can't change sides, then it will jump when we change orientations
-        // and we don't rotate seamlessly - unless that is allowed, eg. with gesture navigation
-        // where the navbar is low-profile enough that this isn't very noticeable.
-        return mAllowSeamlessRotationDespiteNavBarMoving || mDisplayPolicy.navigationBarCanMove();
+        return oldRotation != Surface.ROTATION_180 && newRotation != Surface.ROTATION_180;
     }
 
     void markForSeamlessRotation(WindowState w, boolean seamlesslyRotated) {
@@ -1224,16 +1224,8 @@
                 || orientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
             // Otherwise, use sensor only if requested by the application or enabled
             // by default for USER or UNSPECIFIED modes.  Does not apply to NOSENSOR.
-            if (mAllowAllRotations == ALLOW_ALL_ROTATIONS_UNDEFINED) {
-                // Can't read this during init() because the context doesn't have display metrics at
-                // that time so we cannot determine tablet vs. phone then.
-                mAllowAllRotations = mContext.getResources().getBoolean(
-                        R.bool.config_allowAllRotations)
-                                ? ALLOW_ALL_ROTATIONS_ENABLED
-                                : ALLOW_ALL_ROTATIONS_DISABLED;
-            }
             if (sensorRotation != Surface.ROTATION_180
-                    || mAllowAllRotations == ALLOW_ALL_ROTATIONS_ENABLED
+                    || getAllowAllRotations() == ALLOW_ALL_ROTATIONS_ENABLED
                     || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR
                     || orientation == ActivityInfo.SCREEN_ORIENTATION_FULL_USER) {
                 preferredRotation = sensorRotation;
@@ -1322,6 +1314,19 @@
         }
     }
 
+    private int getAllowAllRotations() {
+        if (mAllowAllRotations == ALLOW_ALL_ROTATIONS_UNDEFINED) {
+            // Can't read this during init() because the context doesn't have display metrics at
+            // that time so we cannot determine tablet vs. phone then.
+            mAllowAllRotations = mContext.getResources().getBoolean(
+                    R.bool.config_allowAllRotations)
+                    ? ALLOW_ALL_ROTATIONS_ENABLED
+                    : ALLOW_ALL_ROTATIONS_DISABLED;
+        }
+
+        return mAllowAllRotations;
+    }
+
     private boolean isLandscapeOrSeascape(int rotation) {
         return rotation == mLandscapeRotation || rotation == mSeascapeRotation;
     }
@@ -1349,6 +1354,11 @@
 
             case ActivityInfo.SCREEN_ORIENTATION_USER:
             case ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED:
+                // When all rotations enabled it works with any of the 4 rotations
+                if (getAllowAllRotations() == ALLOW_ALL_ROTATIONS_ENABLED) {
+                    return preferredRotation >= 0;
+                }
+
                 // Works with any rotation except upside down.
                 return (preferredRotation >= 0) && (preferredRotation != Surface.ROTATION_180);
         }
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index 6162f12..5c8cfff 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -46,7 +46,6 @@
 import android.app.ActivityTaskManager;
 import android.app.StatusBarManager;
 import android.app.WindowConfiguration;
-import android.graphics.Insets;
 import android.graphics.Rect;
 import android.util.ArrayMap;
 import android.util.IntArray;
@@ -461,22 +460,10 @@
 
     private InsetsState adjustInsetsForRoundedCorners(WindowState w, InsetsState originalState,
             boolean copyState) {
-        final WindowState roundedCornerWindow = mPolicy.getRoundedCornerWindow();
         final Task task = w.getTask();
-        if (task != null && !task.getWindowConfiguration().tasksAreFloating()
-                && (roundedCornerWindow != null || task.inSplitScreen())) {
-            // 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.
+        if (task != null && !task.getWindowConfiguration().tasksAreFloating()) {
+            // Use task bounds to calculating rounded corners if the task is not floating.
             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;
diff --git a/services/core/java/com/android/server/wm/InsetsSourceProvider.java b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
index 8413c54..9853d13 100644
--- a/services/core/java/com/android/server/wm/InsetsSourceProvider.java
+++ b/services/core/java/com/android/server/wm/InsetsSourceProvider.java
@@ -170,6 +170,7 @@
         if (windowContainer == null) {
             setServerVisible(false);
             mSource.setVisibleFrame(null);
+            mSource.setInsetsRoundedCornerFrame(false);
             mSourceFrame.setEmpty();
         } else {
             mWindowContainer.getProvidedInsetsSources().put(mSource.getType(), mSource);
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index 2ebb597..ddcaed7 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -70,6 +70,8 @@
 
     static final String KEYGUARD_SLEEP_TOKEN_TAG = "keyguard";
 
+    private static final int DEFER_WAKE_TRANSITION_TIMEOUT_MS = 5000;
+
     private final ActivityTaskSupervisor mTaskSupervisor;
     private WindowManagerService mWindowManager;
 
@@ -77,7 +79,7 @@
     private final ActivityTaskManagerService mService;
     private RootWindowContainer mRootWindowContainer;
     private final ActivityTaskManagerInternal.SleepTokenAcquirer mSleepTokenAcquirer;
-
+    private boolean mWaitingForWakeTransition;
 
     KeyguardController(ActivityTaskManagerService service,
             ActivityTaskSupervisor taskSupervisor) {
@@ -169,6 +171,9 @@
         // Do not reset keyguardChanged status if this is aodChanged.
         final boolean keyguardChanged = (keyguardShowing != state.mKeyguardShowing)
                 || (state.mKeyguardGoingAway && keyguardShowing && !aodChanged);
+        if (aodChanged && !aodShowing) {
+            updateDeferWakeTransition(false /* waiting */);
+        }
         if (!keyguardChanged && !aodChanged) {
             setWakeTransitionReady();
             return;
@@ -197,10 +202,6 @@
 
         state.mKeyguardShowing = keyguardShowing;
         state.mAodShowing = aodShowing;
-        if (aodChanged) {
-            // Ensure the new state takes effect.
-            mWindowManager.mWindowPlacerLocked.performSurfacePlacement();
-        }
 
         if (keyguardChanged) {
             // Irrelevant to AOD.
@@ -218,6 +219,10 @@
         mRootWindowContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
         InputMethodManagerInternal.get().updateImeWindowStatus(false /* disableImeIcon */);
         setWakeTransitionReady();
+        if (aodChanged) {
+            // Ensure the new state takes effect.
+            mWindowManager.mWindowPlacerLocked.performSurfacePlacement();
+        }
     }
 
     private void setWakeTransitionReady() {
@@ -520,6 +525,33 @@
         }
     }
 
+    private final Runnable mResetWaitTransition = () -> {
+        synchronized (mWindowManager.mGlobalLock) {
+            updateDeferWakeTransition(false /* waiting */);
+        }
+    };
+
+    void updateDeferWakeTransition(boolean waiting) {
+        if (waiting == mWaitingForWakeTransition) {
+            return;
+        }
+        if (!mWindowManager.mAtmService.getTransitionController().isShellTransitionsEnabled()) {
+            return;
+        }
+        // if aod is showing, defer the wake transition until aod state changed.
+        if (waiting && isAodShowing(DEFAULT_DISPLAY)) {
+            mWaitingForWakeTransition = true;
+            mWindowManager.mAtmService.getTransitionController().deferTransitionReady();
+            mWindowManager.mH.postDelayed(mResetWaitTransition, DEFER_WAKE_TRANSITION_TIMEOUT_MS);
+        } else if (!waiting) {
+            // dismiss the deferring if the aod state change or cancel awake.
+            mWaitingForWakeTransition = false;
+            mWindowManager.mAtmService.getTransitionController().continueTransitionReady();
+            mWindowManager.mH.removeCallbacks(mResetWaitTransition);
+        }
+    }
+
+
     /** Represents Keyguard state per individual display. */
     private static class KeyguardDisplayState {
         private final int mDisplayId;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index f97f768..17e1dd2 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -1724,8 +1724,8 @@
     /** Returns {@code true} if this task is currently in split-screen. */
     boolean inSplitScreen() {
         return getWindowingMode() == WINDOWING_MODE_MULTI_WINDOW
-                && getRootTask() != null
-                && getRootTask().getAdjacentTaskFragment() != null;
+                && getCreatedByOrganizerTask() != null
+                && getCreatedByOrganizerTask().getAdjacentTaskFragment() != null;
     }
 
     private boolean supportsSplitScreenWindowingModeInner(@Nullable TaskDisplayArea tda) {
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index b5d2472..fdb88312 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -965,7 +965,7 @@
         } else if (candidateTask != null) {
             final int position = onTop ? POSITION_TOP : POSITION_BOTTOM;
             final Task launchRootTask = getLaunchRootTask(resolvedWindowingMode, activityType,
-                    options, sourceTask, launchFlags);
+                    options, sourceTask, launchFlags, candidateTask);
             if (launchRootTask != null) {
                 if (candidateTask.getParent() == null) {
                     launchRootTask.addChild(candidateTask, position);
@@ -1119,6 +1119,13 @@
     @Nullable
     Task getLaunchRootTask(int windowingMode, int activityType, @Nullable ActivityOptions options,
             @Nullable Task sourceTask, int launchFlags) {
+        return getLaunchRootTask(windowingMode, activityType, options, sourceTask, launchFlags,
+                null /* candidateTask */);
+    }
+
+    @Nullable
+    Task getLaunchRootTask(int windowingMode, int activityType, @Nullable ActivityOptions options,
+            @Nullable Task sourceTask, int launchFlags, @Nullable Task candidateTask) {
         // Try to use the launch root task in options if available.
         if (options != null) {
             final Task launchRootTask = Task.fromWindowContainerToken(options.getLaunchRootTask());
@@ -1159,9 +1166,19 @@
         }
 
         // For a better split UX, If a task is launching from a created-by-organizer task, it should
-        // be launched into the same created-by-organizer task as well.
-        if (sourceTask != null) {
-            return sourceTask.getCreatedByOrganizerTask();
+        // be launched into the same created-by-organizer task as well. Unless, the candidate task
+        // is already positioned in the split.
+        Task preferredRootInSplit = sourceTask != null && sourceTask.inSplitScreen()
+                ? sourceTask.getCreatedByOrganizerTask() : null;
+        if (preferredRootInSplit != null) {
+            if (candidateTask != null) {
+                final Task candidateRoot = candidateTask.getCreatedByOrganizerTask();
+                if (candidateRoot != null && candidateRoot != preferredRootInSplit
+                        && preferredRootInSplit == candidateRoot.getAdjacentTaskFragment()) {
+                    preferredRootInSplit = candidateRoot;
+                }
+            }
+            return preferredRootInSplit;
         }
 
         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 4cb4e91..56e96fa 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -2156,7 +2156,8 @@
         if (applicationType != ACTIVITY_TYPE_UNDEFINED || !hasChild()) {
             return applicationType;
         }
-        return getTopChild().getActivityType();
+        final ActivityRecord activity = getTopNonFinishingActivity();
+        return activity != null ? activity.getActivityType() : getTopChild().getActivityType();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 454424c..dfbeb55 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -490,7 +490,6 @@
         }
 
         // Commit all going-invisible containers
-        boolean activitiesWentInvisible = false;
         for (int i = 0; i < mParticipants.size(); ++i) {
             final ActivityRecord ar = mParticipants.valueAt(i).asActivityRecord();
             if (ar != null) {
@@ -541,7 +540,6 @@
                         }
                         ar.commitVisibility(false /* visible */, false /* performLayout */,
                                 true /* fromTransition */);
-                        activitiesWentInvisible = true;
                     }
                 }
                 if (mChanges.get(ar).mVisible != visibleAtTransitionEnd) {
@@ -568,12 +566,10 @@
                 mController.dispatchLegacyAppTransitionFinished(ar);
             }
         }
-        if (activitiesWentInvisible) {
-            // Always schedule stop processing when transition finishes because activities don't
-            // stop while they are in a transition thus their stop could still be pending.
-            mController.mAtm.mTaskSupervisor
-                    .scheduleProcessStoppingAndFinishingActivitiesIfNeeded();
-        }
+        // Always schedule stop processing when transition finishes because activities don't
+        // stop while they are in a transition thus their stop could still be pending.
+        mController.mAtm.mTaskSupervisor
+                .scheduleProcessStoppingAndFinishingActivitiesIfNeeded();
 
         sendRemoteCallback(mClientAnimationFinishCallback);
 
diff --git a/services/core/java/com/android/server/wm/UnknownAppVisibilityController.java b/services/core/java/com/android/server/wm/UnknownAppVisibilityController.java
index 5e963cc..41c1e79 100644
--- a/services/core/java/com/android/server/wm/UnknownAppVisibilityController.java
+++ b/services/core/java/com/android/server/wm/UnknownAppVisibilityController.java
@@ -69,6 +69,10 @@
         return mUnknownApps.isEmpty();
     }
 
+    boolean isVisibilityUnknown(ActivityRecord r) {
+        return mUnknownApps.containsKey(r);
+    }
+
     void clear() {
         mUnknownApps.clear();
     }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 36e6654..38eaaa0 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -423,7 +423,7 @@
             "persist.wm.enable_remote_keyguard_animation";
 
     private static final int sEnableRemoteKeyguardAnimation =
-            SystemProperties.getInt(ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY, 1);
+            SystemProperties.getInt(ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY, 2);
 
     /**
      * @see #ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY
diff --git a/services/tests/mockingservicestests/Android.bp b/services/tests/mockingservicestests/Android.bp
index 670c159..08c68b9 100644
--- a/services/tests/mockingservicestests/Android.bp
+++ b/services/tests/mockingservicestests/Android.bp
@@ -42,6 +42,8 @@
     static_libs: [
         "androidx.test.core",
         "androidx.test.runner",
+        "androidx.test.espresso.core",
+        "androidx.test.espresso.contrib",
         "androidx.test.ext.truth",
         "frameworks-base-testutils",
         "hamcrest-library",
diff --git a/services/tests/mockingservicestests/AndroidManifest.xml b/services/tests/mockingservicestests/AndroidManifest.xml
index 7714cf0..07b763d 100644
--- a/services/tests/mockingservicestests/AndroidManifest.xml
+++ b/services/tests/mockingservicestests/AndroidManifest.xml
@@ -32,6 +32,8 @@
     <uses-permission
         android:name="android.permission.OVERRIDE_COMPAT_CHANGE_CONFIG_ON_RELEASE_BUILD"/>
     <uses-permission android:name="android.permission.STATUS_BAR_SERVICE" />
+    <uses-permission android:name="android.permission.MANAGE_GAME_ACTIVITY" />
+    <uses-permission android:name="android.permission.SET_ALWAYS_FINISH" />
 
     <!-- needed by MasterClearReceiverTest to display a system dialog -->
     <uses-permission android:name="android.permission.INTERNAL_SYSTEM_WINDOW"/>
@@ -39,6 +41,8 @@
     <application android:testOnly="true"
                  android:debuggable="true">
         <uses-library android:name="android.test.runner" />
+        <activity
+            android:name="android.service.games.GameSessionTrampolineActivityTest$TestActivity" />
     </application>
 
     <instrumentation
diff --git a/services/tests/mockingservicestests/src/android/service/games/GameSessionTrampolineActivityTest.java b/services/tests/mockingservicestests/src/android/service/games/GameSessionTrampolineActivityTest.java
new file mode 100644
index 0000000..d68b517
--- /dev/null
+++ b/services/tests/mockingservicestests/src/android/service/games/GameSessionTrampolineActivityTest.java
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2022 The Android Open 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.service.games;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isClickable;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+import static androidx.test.ext.truth.content.IntentSubject.assertThat;
+import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.hamcrest.Matchers.allOf;
+
+import android.app.Activity;
+import android.app.ActivityManager;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.RemoteException;
+import android.platform.test.annotations.Presubmit;
+import android.testing.AndroidTestingRunner;
+import android.widget.Button;
+import android.widget.LinearLayout;
+import android.widget.TextView;
+
+import androidx.test.espresso.NoActivityResumedException;
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.infra.AndroidFuture;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Unit tests for the {@link GameSessionTrampolineActivity}.
+ */
+@RunWith(AndroidTestingRunner.class)
+@SmallTest
+@Presubmit
+public class GameSessionTrampolineActivityTest {
+
+    @Before
+    public void setUp() {
+        setAlwaysFinishActivities(false);
+    }
+
+    @After
+    public void tearDown() {
+        setAlwaysFinishActivities(false);
+    }
+
+    @Test
+    public void launch_launchesTargetActivity() {
+        AndroidFuture<GameSessionActivityResult> unusedResultFuture =
+                startTestActivityViaGameSessionTrampolineActivity();
+
+        TestActivityPage.assertPageIsLaunched();
+    }
+
+    @Test
+    public void launch_targetActivityFinishesSuccessfully_futureCompletedWithSameResults() {
+        AndroidFuture<GameSessionActivityResult> resultFuture =
+                startTestActivityViaGameSessionTrampolineActivity();
+
+        TestActivityPage.assertPageIsLaunched();
+        TestActivityPage.clickFinish();
+
+        GameSessionActivityResult expectedResult =
+                new GameSessionActivityResult(Activity.RESULT_OK, TestActivity.RESULT_INTENT);
+
+        assertEquals(resultFuture, expectedResult);
+
+        TestActivityPage.assertPageIsNotLaunched();
+    }
+
+    @Test
+    public void launch_trampolineActivityProcessDeath_futureCompletedWithSameResults() {
+        setAlwaysFinishActivities(true);
+
+        AndroidFuture<GameSessionActivityResult> resultFuture =
+                startTestActivityViaGameSessionTrampolineActivity();
+
+        TestActivityPage.assertPageIsLaunched();
+        TestActivityPage.clickFinish();
+
+        GameSessionActivityResult expectedResult =
+                new GameSessionActivityResult(Activity.RESULT_OK, TestActivity.RESULT_INTENT);
+
+        assertEquals(resultFuture, expectedResult);
+
+        TestActivityPage.assertPageIsNotLaunched();
+    }
+
+    private static void assertEquals(
+            AndroidFuture<GameSessionActivityResult> actualFuture,
+            GameSessionActivityResult expected) {
+        try {
+            assertEquals(actualFuture.get(20, TimeUnit.SECONDS), expected);
+        } catch (Exception ex) {
+            throw new IllegalStateException(ex);
+        }
+    }
+
+    private static void assertEquals(
+            GameSessionActivityResult actual,
+            GameSessionActivityResult expected) {
+        assertThat(actual.getResultCode()).isEqualTo(expected.getResultCode());
+        assertThat(actual.getData()).filtersEquallyTo(actual.getData());
+    }
+
+    private static void setAlwaysFinishActivities(boolean isEnabled) {
+        try {
+            ActivityManager.getService().setAlwaysFinish(isEnabled);
+        } catch (RemoteException ex) {
+            throw new IllegalStateException(ex);
+        }
+    }
+
+    private static AndroidFuture<GameSessionActivityResult>
+            startTestActivityViaGameSessionTrampolineActivity() {
+        Intent testActivityIntent = new Intent();
+        testActivityIntent.setClass(getInstrumentation().getTargetContext(), TestActivity.class);
+
+        return startGameSessionTrampolineActivity(testActivityIntent);
+    }
+
+    private static AndroidFuture<GameSessionActivityResult> startGameSessionTrampolineActivity(
+            Intent targetIntent) {
+        AndroidFuture<GameSessionActivityResult> resultFuture = new AndroidFuture<>();
+        Intent trampolineActivityIntent = GameSessionTrampolineActivity.createIntent(targetIntent,
+                null, resultFuture);
+        trampolineActivityIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        getInstrumentation().getTargetContext().startActivity(trampolineActivityIntent);
+        getInstrumentation().waitForIdleSync();
+
+        return resultFuture;
+    }
+
+
+    private static class TestActivityPage {
+        private TestActivityPage() {}
+
+        public static void assertPageIsLaunched() {
+            onView(withText(TestActivity.PAGE_TITLE_TEXT)).check(matches(isDisplayed()));
+        }
+
+        public static void assertPageIsNotLaunched() {
+            try {
+                onView(withText(TestActivity.PAGE_TITLE_TEXT)).check(doesNotExist());
+            } catch (NoActivityResumedException ex) {
+                // Do nothing
+            }
+        }
+
+        public static void clickFinish() {
+            onView(allOf(withText(TestActivity.FINISH_BUTTON_TEXT), isClickable())).perform(
+                    click());
+            getInstrumentation().waitForIdleSync();
+        }
+    }
+
+    public static class TestActivity extends Activity {
+        private static final String PAGE_TITLE_TEXT = "GameSessionTestActivity";
+        private static final String FINISH_BUTTON_TEXT = "Finish Test Activity";
+        private static final Intent RESULT_INTENT = new Intent("com.test.action.VIEW");
+
+        @Override
+        protected void onCreate(Bundle savedInstanceState) {
+            super.onCreate(savedInstanceState);
+
+            LinearLayout contentLayout = new LinearLayout(this);
+            contentLayout.setOrientation(LinearLayout.VERTICAL);
+
+            TextView titleTextView = new TextView(this);
+            titleTextView.setText(PAGE_TITLE_TEXT);
+            contentLayout.addView(titleTextView);
+
+            Button finishActivityButton = new Button(this);
+            finishActivityButton.setText(FINISH_BUTTON_TEXT);
+            finishActivityButton.setOnClickListener((unused) -> {
+                setResult(Activity.RESULT_OK, RESULT_INTENT);
+                finish();
+            });
+
+
+            contentLayout.addView(finishActivityButton);
+            setContentView(contentLayout);
+        }
+    }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/app/GameServiceProviderInstanceImplTest.java b/services/tests/mockingservicestests/src/com/android/server/app/GameServiceProviderInstanceImplTest.java
index 319a769..5b551b1 100644
--- a/services/tests/mockingservicestests/src/com/android/server/app/GameServiceProviderInstanceImplTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/app/GameServiceProviderInstanceImplTest.java
@@ -216,11 +216,12 @@
                 mRunningTaskInfos);
 
 
+        final UserHandle userHandle = new UserHandle(USER_ID);
         mGameServiceProviderInstance = new GameServiceProviderInstanceImpl(
-                new UserHandle(USER_ID),
+                userHandle,
                 ConcurrentUtils.DIRECT_EXECUTOR,
                 mMockContext,
-                mFakeGameClassifier,
+                new GameTaskInfoProvider(userHandle, mMockActivityTaskManager, mFakeGameClassifier),
                 mMockActivityManager,
                 mMockActivityManagerInternal,
                 mMockActivityTaskManager,
@@ -788,6 +789,36 @@
     }
 
     @Test
+    public void gameTaskFocusedWithCreateAfterRemoved_gameSessionRecreated() throws Exception {
+        mGameServiceProviderInstance.start();
+
+        startTask(10, GAME_A_MAIN_ACTIVITY);
+        mockPermissionGranted(Manifest.permission.MANAGE_GAME_ACTIVITY);
+        mFakeGameService.requestCreateGameSession(10);
+
+        FakeGameSession gameSession10 = new FakeGameSession();
+        SurfacePackage mockSurfacePackage10 = Mockito.mock(SurfacePackage.class);
+        mFakeGameSessionService.removePendingFutureForTaskId(10)
+                .complete(new CreateGameSessionResult(gameSession10, mockSurfacePackage10));
+
+        stopTask(10);
+
+        assertThat(gameSession10.mIsDestroyed).isTrue();
+
+        // If the game task is restored via the Recents UI, the task will be running again but
+        // we would not expect any call to TaskStackListener#onTaskCreated.
+        addRunningTaskInfo(10, GAME_A_MAIN_ACTIVITY);
+
+        // We now receive a task focused event for the task. This will occur if the game task is
+        // restored via the Recents UI.
+        dispatchTaskFocused(10, /*focused=*/ true);
+        mFakeGameService.requestCreateGameSession(10);
+
+        // Verify that a new pending game session is created for the game's taskId.
+        assertNotNull(mFakeGameSessionService.removePendingFutureForTaskId(10));
+    }
+
+    @Test
     public void gameTaskRemoved_removesTaskOverlay() throws Exception {
         mGameServiceProviderInstance.start();
 
@@ -1144,13 +1175,18 @@
     }
 
     private void startTask(int taskId, ComponentName componentName) {
+        addRunningTaskInfo(taskId, componentName);
+
+        dispatchTaskCreated(taskId, componentName);
+    }
+
+    private void addRunningTaskInfo(int taskId, ComponentName componentName) {
         RunningTaskInfo runningTaskInfo = new RunningTaskInfo();
         runningTaskInfo.taskId = taskId;
+        runningTaskInfo.baseActivity = componentName;
         runningTaskInfo.displayId = 1;
         runningTaskInfo.configuration.windowConfiguration.setBounds(new Rect(0, 0, 500, 800));
         mRunningTaskInfos.add(runningTaskInfo);
-
-        dispatchTaskCreated(taskId, componentName);
     }
 
     private void stopTask(int taskId) {
diff --git a/services/tests/servicestests/src/com/android/server/biometrics/sensors/CoexCoordinatorTest.java b/services/tests/servicestests/src/com/android/server/biometrics/sensors/CoexCoordinatorTest.java
index f40b31a..abf992b 100644
--- a/services/tests/servicestests/src/com/android/server/biometrics/sensors/CoexCoordinatorTest.java
+++ b/services/tests/servicestests/src/com/android/server/biometrics/sensors/CoexCoordinatorTest.java
@@ -415,7 +415,7 @@
         // Auth was attempted
         when(mUdfpsClient.getState())
                 .thenReturn(AuthenticationClient.STATE_STARTED_PAUSED_ATTEMPTED);
-        verify(mCallback, never()).sendHapticFeedback();
+        verify(mCallback).sendHapticFeedback();
         verify(mCallback).handleLifecycleAfterAuth();
 
         // Then face rejected. Note that scheduler leaves UDFPS in the CoexCoordinator since
@@ -425,7 +425,7 @@
                 LockoutTracker.LOCKOUT_NONE, faceCallback);
         verify(faceCallback).sendHapticFeedback();
         verify(faceCallback).sendAuthenticationResult(eq(false) /* addAuthTokenIfStrong */);
-        verify(mCallback, never()).sendHapticFeedback();
+        verify(mCallback).sendHapticFeedback();
     }
 
     @Test
diff --git a/services/tests/servicestests/src/com/android/server/display/TEST_MAPPING b/services/tests/servicestests/src/com/android/server/display/TEST_MAPPING
new file mode 100644
index 0000000..9f1a209
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/display/TEST_MAPPING
@@ -0,0 +1,21 @@
+{
+  "presubmit": [
+    {
+      "name": "FrameworksServicesTests",
+      "options": [
+        {
+          "include-filter": "com.android.server.display."
+        },
+        {
+          "include-annotation": "android.platform.test.annotations.Presubmit"
+        },
+        {
+          "exclude-annotation": "androidx.test.filters.FlakyTest"
+        },
+        {
+          "exclude-annotation": "org.junit.Ignore"
+        }
+      ]
+    }
+  ]
+}
diff --git a/services/tests/uiservicestests/AndroidManifest.xml b/services/tests/uiservicestests/AndroidManifest.xml
index 767857b..e8e3a8f 100644
--- a/services/tests/uiservicestests/AndroidManifest.xml
+++ b/services/tests/uiservicestests/AndroidManifest.xml
@@ -33,6 +33,7 @@
     <uses-permission android:name="android.permission.OBSERVE_ROLE_HOLDERS" />
     <uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT"/>
     <uses-permission android:name="android.permission.WRITE_DEVICE_CONFIG" />
+    <uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" />
 
     <application android:debuggable="true">
         <uses-library android:name="android.test.runner" />
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java
index 4a13050..c5131c8 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java
@@ -31,8 +31,11 @@
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.nullable;
+import static org.mockito.Mockito.atLeast;
 import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -42,18 +45,16 @@
 import android.app.NotificationChannel;
 import android.app.NotificationManager;
 import android.content.ComponentName;
-import android.content.Context;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
 import android.content.pm.ServiceInfo;
 import android.content.pm.VersionedPackage;
 import android.os.Bundle;
-import android.os.IBinder;
-import android.os.IInterface;
 import android.os.UserHandle;
 import android.service.notification.NotificationListenerFilter;
 import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationRankingUpdate;
+import android.service.notification.NotificationStats;
 import android.service.notification.StatusBarNotification;
 import android.testing.TestableContext;
 import android.util.ArraySet;
@@ -70,6 +71,7 @@
 import org.junit.Test;
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
+import org.mockito.internal.util.reflection.FieldSetter;
 
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
@@ -430,4 +432,66 @@
         verify(mPmi).grantImplicitAccess(sbn.getUserId(), null, UserHandle.getAppId(33),
                 sbn.getUid(), false, false);
     }
+
+    @Test
+    public void testNotifyPostedLockedInLockdownMode() {
+        NotificationRecord r = mock(NotificationRecord.class);
+        NotificationRecord old = mock(NotificationRecord.class);
+
+        // before the lockdown mode
+        when(mNm.isInLockDownMode()).thenReturn(false);
+        mListeners.notifyPostedLocked(r, old, true);
+        mListeners.notifyPostedLocked(r, old, false);
+        verify(r, atLeast(2)).getSbn();
+
+        // in the lockdown mode
+        reset(r);
+        reset(old);
+        when(mNm.isInLockDownMode()).thenReturn(true);
+        mListeners.notifyPostedLocked(r, old, true);
+        mListeners.notifyPostedLocked(r, old, false);
+        verify(r, never()).getSbn();
+    }
+
+    @Test
+    public void testnotifyRankingUpdateLockedInLockdownMode() {
+        List chn = mock(List.class);
+
+        // before the lockdown mode
+        when(mNm.isInLockDownMode()).thenReturn(false);
+        mListeners.notifyRankingUpdateLocked(chn);
+        verify(chn, atLeast(1)).size();
+
+        // in the lockdown mode
+        reset(chn);
+        when(mNm.isInLockDownMode()).thenReturn(true);
+        mListeners.notifyRankingUpdateLocked(chn);
+        verify(chn, never()).size();
+    }
+
+    @Test
+    public void testNotifyRemovedLockedInLockdownMode() throws NoSuchFieldException {
+        NotificationRecord r = mock(NotificationRecord.class);
+        NotificationStats rs = mock(NotificationStats.class);
+        StatusBarNotification sbn = mock(StatusBarNotification.class);
+        FieldSetter.setField(mNm,
+                NotificationManagerService.class.getDeclaredField("mHandler"),
+                mock(NotificationManagerService.WorkerHandler.class));
+
+        // before the lockdown mode
+        when(mNm.isInLockDownMode()).thenReturn(false);
+        when(r.getSbn()).thenReturn(sbn);
+        mListeners.notifyRemovedLocked(r, 0, rs);
+        mListeners.notifyRemovedLocked(r, 0, rs);
+        verify(r, atLeast(2)).getSbn();
+
+        // in the lockdown mode
+        reset(r);
+        reset(rs);
+        when(mNm.isInLockDownMode()).thenReturn(true);
+        when(r.getSbn()).thenReturn(sbn);
+        mListeners.notifyRemovedLocked(r, 0, rs);
+        mListeners.notifyRemovedLocked(r, 0, rs);
+        verify(r, never()).getSbn();
+    }
 }
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 b987c69..348e015 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -63,10 +63,13 @@
 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ALERTING;
 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_CONVERSATIONS;
 import static android.service.notification.NotificationListenerService.FLAG_FILTER_TYPE_ONGOING;
+import static android.service.notification.NotificationListenerService.REASON_CANCEL_ALL;
 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
 import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
 
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static junit.framework.Assert.assertEquals;
@@ -352,6 +355,7 @@
     MultiRateLimiter mToastRateLimiter;
     BroadcastReceiver mPackageIntentReceiver;
     NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake();
+    TestableNotificationManagerService.StrongAuthTrackerFake mStrongAuthTracker;
     private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake(
             1 << 30);
     @Mock
@@ -508,6 +512,9 @@
 
         mService.setAudioManager(mAudioManager);
 
+        mStrongAuthTracker = mService.new StrongAuthTrackerFake(mContext);
+        mService.setStrongAuthTracker(mStrongAuthTracker);
+
         mShortcutHelper = mService.getShortcutHelper();
         mShortcutHelper.setLauncherApps(mLauncherApps);
         mShortcutHelper.setShortcutServiceInternal(mShortcutServiceInternal);
@@ -9247,4 +9254,44 @@
         // make sure the summary was removed and not re-posted
         assertThat(mService.getNotificationRecordCount()).isEqualTo(0);
     }
+
+    @Test
+    public void testStrongAuthTracker_isInLockDownMode() {
+        mStrongAuthTracker.setGetStrongAuthForUserReturnValue(
+                STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
+        mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId());
+        assertTrue(mStrongAuthTracker.isInLockDownMode());
+        mStrongAuthTracker.setGetStrongAuthForUserReturnValue(0);
+        mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId());
+        assertFalse(mStrongAuthTracker.isInLockDownMode());
+    }
+
+    @Test
+    public void testCancelAndPostNotificationsWhenEnterAndExitLockDownMode() {
+        // post 2 notifications from 2 packages
+        NotificationRecord pkgA = new NotificationRecord(mContext,
+                generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
+        mService.addNotification(pkgA);
+        NotificationRecord pkgB = new NotificationRecord(mContext,
+                generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
+        mService.addNotification(pkgB);
+
+        // when entering the lockdown mode, cancel the 2 notifications.
+        mStrongAuthTracker.setGetStrongAuthForUserReturnValue(
+                STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
+        mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId());
+        assertTrue(mStrongAuthTracker.isInLockDownMode());
+
+        // the notifyRemovedLocked function is called twice due to REASON_CANCEL_ALL.
+        ArgumentCaptor<Integer> captor = ArgumentCaptor.forClass(Integer.class);
+        verify(mListeners, times(2)).notifyRemovedLocked(any(), captor.capture(), any());
+        assertEquals(REASON_CANCEL_ALL, captor.getValue().intValue());
+
+        // exit lockdown mode.
+        mStrongAuthTracker.setGetStrongAuthForUserReturnValue(0);
+        mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId());
+
+        // the notifyPostedLocked function is called twice.
+        verify(mListeners, times(2)).notifyPostedLocked(any(), any());
+    }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java b/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java
index bde0485..4ed7d35 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/TestableNotificationManagerService.java
@@ -113,4 +113,20 @@
     protected void doChannelWarningToast(int uid, CharSequence toastText) {
         mChannelToastsSent.add(uid);
     }
+
+    public class StrongAuthTrackerFake extends NotificationManagerService.StrongAuthTracker {
+        private int mGetStrongAuthForUserReturnValue = 0;
+        StrongAuthTrackerFake(Context context) {
+            super(context);
+        }
+
+        public void setGetStrongAuthForUserReturnValue(int val) {
+            mGetStrongAuthForUserReturnValue = val;
+        }
+
+        @Override
+        public int getStrongAuthForUser(int userId) {
+            return mGetStrongAuthForUserReturnValue;
+        }
+    }
 }
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 d65e27d..533540e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -757,6 +757,8 @@
         final ActivityRecord activity = createActivityWithTask();
         ActivityRecord topActivity = new ActivityBuilder(mAtm).setTask(activity.getTask()).build();
         topActivity.setOccludesParent(false);
+        // The requested occluding state doesn't affect whether it fills parent.
+        assertTrue(topActivity.fillsParent());
         activity.setState(STOPPED, "Testing");
         activity.setVisibility(true);
         activity.makeActiveIfNeeded(null /* activeActivity */);
@@ -1218,7 +1220,7 @@
         task.setPausingActivity(currentTop);
         currentTop.finishing = true;
         currentTop.setState(PAUSED, "test");
-        currentTop.completeFinishing("completePauseLocked");
+        currentTop.completeFinishing(false /* updateVisibility */, "completePause");
 
         // Current top becomes stopping because it is visible and the next is invisible.
         assertEquals(STOPPING, currentTop.getState());
@@ -3139,7 +3141,7 @@
         final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
 
         InsetsSource imeSource = new InsetsSource(ITYPE_IME);
-        app.getInsetsState().addSource(imeSource);
+        app.mAboveInsetsState.addSource(imeSource);
         mDisplayContent.setImeLayeringTarget(app);
         mDisplayContent.updateImeInputAndControlTarget(app);
 
@@ -3156,10 +3158,12 @@
         // Simulate app re-start input or turning screen off/on then unlocked by un-secure
         // keyguard to back to the app, expect IME insets is not frozen
         mDisplayContent.updateImeInputAndControlTarget(app);
+        app.mActivityRecord.commitVisibility(true, false);
         assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
+
+        imeSource.setVisible(true);
         imeSource.setFrame(new Rect(100, 400, 500, 500));
-        app.getInsetsState().addSource(imeSource);
-        app.getInsetsState().setSourceVisible(ITYPE_IME, true);
+        app.mAboveInsetsState.addSource(imeSource);
 
         // Verify when IME is visible and the app can receive the right IME insets from policy.
         makeWindowVisibleAndDrawn(app, mImeWindow);
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 33b7024..67f02c7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppTransitionControllerTest.java
@@ -46,7 +46,6 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.clearInvocations;
-import static org.mockito.Mockito.doCallRealMethod;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.verify;
@@ -89,14 +88,6 @@
         mAppTransitionController = new AppTransitionController(mWm, mDisplayContent);
     }
 
-    @Override
-    ActivityRecord createActivityRecord(DisplayContent dc, int windowingMode, int activityType) {
-        final ActivityRecord r = super.createActivityRecord(dc, windowingMode, activityType);
-        // Ensure that ActivityRecord#setOccludesParent takes effect.
-        doCallRealMethod().when(r).fillsParent();
-        return r;
-    }
-
     @Test
     public void testSkipOccludedActivityCloseTransition() {
         final ActivityRecord behind = createActivityRecord(mDisplayContent,
@@ -135,7 +126,7 @@
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
         final ActivityRecord translucentOpening = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        translucentOpening.setOccludesParent(false);
+        doReturn(false).when(translucentOpening).fillsParent();
         translucentOpening.setVisible(false);
         mDisplayContent.prepareAppTransition(TRANSIT_OPEN);
         mDisplayContent.mOpeningApps.add(behind);
@@ -153,7 +144,7 @@
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
         final ActivityRecord translucentClosing = createActivityRecord(mDisplayContent,
                 WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
-        translucentClosing.setOccludesParent(false);
+        doReturn(false).when(translucentClosing).fillsParent();
         mDisplayContent.prepareAppTransition(TRANSIT_CLOSE);
         mDisplayContent.mClosingApps.add(translucentClosing);
         assertEquals(WindowManager.TRANSIT_OLD_TRANSLUCENT_ACTIVITY_CLOSE,
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
index 25cff61c..e4eb98e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationTests.java
@@ -40,7 +40,9 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.clearInvocations;
 
+import android.app.WindowConfiguration;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
@@ -515,6 +517,69 @@
     }
 
     @Test
+    public void testAllowAllRotations_allowsUpsideDownSuggestion()
+            throws Exception {
+        mBuilder.build();
+        mTarget.updateOrientation(SCREEN_ORIENTATION_UNSPECIFIED, true);
+        configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+        when(mMockRes.getBoolean(com.android.internal.R.bool.config_allowAllRotations))
+                .thenReturn(true);
+        freezeRotation(Surface.ROTATION_0);
+        enableOrientationSensor();
+
+        mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180));
+        assertTrue(waitForUiHandler());
+
+        verify(mMockStatusBarManagerInternal)
+                .onProposedRotationChanged(Surface.ROTATION_180, true);
+    }
+
+    @Test
+    public void testDoNotAllowAllRotations_doesNotAllowUpsideDownSuggestion()
+            throws Exception {
+        mBuilder.build();
+        mTarget.updateOrientation(SCREEN_ORIENTATION_UNSPECIFIED, true);
+        configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+        when(mMockRes.getBoolean(com.android.internal.R.bool.config_allowAllRotations))
+                .thenReturn(false);
+        freezeRotation(Surface.ROTATION_0);
+        enableOrientationSensor();
+
+        mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180));
+        assertTrue(waitForUiHandler());
+
+        verify(mMockStatusBarManagerInternal)
+                .onProposedRotationChanged(Surface.ROTATION_180, false);
+    }
+
+    @Test
+    public void testAllowAllRotations_allowAllRotationsBecomesDisabled_forbidsUpsideDownSuggestion()
+            throws Exception {
+        mBuilder.build();
+        mTarget.updateOrientation(SCREEN_ORIENTATION_UNSPECIFIED, true);
+        configureDisplayRotation(SCREEN_ORIENTATION_LANDSCAPE, false, false);
+        when(mMockRes.getBoolean(com.android.internal.R.bool.config_allowAllRotations))
+                .thenReturn(true);
+        freezeRotation(Surface.ROTATION_0);
+        enableOrientationSensor();
+        mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_0));
+        assertTrue(waitForUiHandler());
+
+        // Change resource to disallow all rotations.
+        // Reset "allowAllRotations".
+        mTarget.applyCurrentRotation(Surface.ROTATION_0);
+        clearInvocations(mMockStatusBarManagerInternal);
+        when(mMockRes.getBoolean(com.android.internal.R.bool.config_allowAllRotations))
+                .thenReturn(false);
+        mTarget.resetAllowAllRotations();
+        mOrientationSensorListener.onSensorChanged(createSensorEvent(Surface.ROTATION_180));
+        assertTrue(waitForUiHandler());
+
+        verify(mMockStatusBarManagerInternal)
+                .onProposedRotationChanged(Surface.ROTATION_180, false);
+    }
+
+    @Test
     public void testReturnsCompatibleRotation_SensorEnabled_RotationThawed() throws Exception {
         mBuilder.build();
         configureDisplayRotation(SCREEN_ORIENTATION_PORTRAIT, false, false);
@@ -721,14 +786,20 @@
         doReturn(true).when(mMockDisplayPolicy).navigationBarCanMove();
         doReturn(win).when(mMockDisplayPolicy).getTopFullscreenOpaqueWindow();
         mMockDisplayContent.mCurrentFocus = win;
-        mTarget.mUpsideDownRotation = Surface.ROTATION_180;
+        // This should not affect the condition of shouldRotateSeamlessly.
+        mTarget.mUpsideDownRotation = Surface.ROTATION_90;
 
         doReturn(true).when(win.mActivityRecord).matchParentBounds();
         // The focused fullscreen opaque window without override bounds should be able to be
         // rotated seamlessly.
         assertTrue(mTarget.shouldRotateSeamlessly(
                 Surface.ROTATION_0, Surface.ROTATION_90, false /* forceUpdate */));
+        // Reject any 180 degree because non-movable navbar will be placed in a different position.
+        doReturn(false).when(mMockDisplayPolicy).navigationBarCanMove();
+        assertFalse(mTarget.shouldRotateSeamlessly(
+                Surface.ROTATION_90, Surface.ROTATION_180, false /* forceUpdate */));
 
+        doReturn(true).when(mMockDisplayPolicy).navigationBarCanMove();
         doReturn(false).when(win.mActivityRecord).matchParentBounds();
         // No seamless rotation if the window may be positioned with offset after rotation.
         assertFalse(mTarget.shouldRotateSeamlessly(
@@ -935,6 +1006,8 @@
                     .thenReturn(WmDisplayCutout.NO_CUTOUT);
             when(mMockDisplayContent.getDefaultTaskDisplayArea())
                     .thenReturn(mock(TaskDisplayArea.class));
+            when(mMockDisplayContent.getWindowConfiguration())
+                    .thenReturn(new WindowConfiguration());
 
             mMockDisplayPolicy = mock(DisplayPolicy.class);
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
index 80f6bce..e5e0145 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskDisplayAreaTests.java
@@ -741,4 +741,35 @@
         assertEquals(isAssistantOnTop ? topPosition : topPosition - 4,
                 getTaskIndexOf(taskDisplayArea, assistRootTask));
     }
+
+    /**
+     * This test verifies proper launch root based on source and candidate task for split screen.
+     * If a task is launching from a created-by-organizer task, it should be launched into the
+     * same created-by-organizer task as well. Unless, the candidate task is already positioned in
+     * the split.
+     */
+    @Test
+    public void getLaunchRootTaskInSplit() {
+        final Task rootTask = createTask(
+                mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
+        rootTask.mCreatedByOrganizer = true;
+        final Task adjacentRootTask = createTask(
+                mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
+        adjacentRootTask.mCreatedByOrganizer = true;
+        final Task candidateTask = createTaskInRootTask(rootTask, 0 /* userId*/);
+        final TaskDisplayArea taskDisplayArea = rootTask.getDisplayArea();
+        adjacentRootTask.setAdjacentTaskFragment(rootTask, false /* moveTogether */);
+
+        // Verify the launch root with candidate task
+        Task actualRootTask = taskDisplayArea.getLaunchRootTask(WINDOWING_MODE_UNDEFINED,
+                ACTIVITY_TYPE_STANDARD, null /* options */, adjacentRootTask /* sourceTask */,
+                0 /* launchFlags */, candidateTask);
+        assertSame(rootTask, actualRootTask.getRootTask());
+
+        // Verify the launch root task without candidate task
+        actualRootTask = taskDisplayArea.getLaunchRootTask(WINDOWING_MODE_UNDEFINED,
+                ACTIVITY_TYPE_STANDARD, null /* options */, adjacentRootTask /* sourceTask */,
+                0 /* launchFlags */);
+        assertSame(adjacentRootTask, actualRootTask.getRootTask());
+    }
 }
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 c672b91..7507df6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -1156,10 +1156,6 @@
 
             spyOn(activity);
             if (mTask != null) {
-                // fullscreen value is normally read from resources in ctor, so for testing we need
-                // to set it somewhere else since we can't mock resources.
-                doReturn(true).when(activity).occludesParent();
-                doReturn(true).when(activity).fillsParent();
                 mTask.addChild(activity);
                 if (mOnTop) {
                     // Move the task to front after activity is added.
diff --git a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 8cbbe94..f31cdcb 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -1824,6 +1824,32 @@
             }
         }
 
+        public void setSessionWindowVisible(IBinder token, boolean visible) {
+            synchronized (this) {
+                if (mImpl == null) {
+                    Slog.w(TAG, "setSessionWindowVisible called without running voice interaction "
+                            + "service");
+                    return;
+                }
+                if (mImpl.mActiveSession == null || token != mImpl.mActiveSession.mToken) {
+                    Slog.w(TAG, "setSessionWindowVisible does not match active session");
+                    return;
+                }
+                final long caller = Binder.clearCallingIdentity();
+                try {
+                    mVoiceInteractionSessionListeners.broadcast(listener -> {
+                        try {
+                            listener.onVoiceSessionWindowVisibilityChanged(visible);
+                        } catch (RemoteException e) {
+                            Slog.e(TAG, "Error delivering window visibility event to listener.", e);
+                        }
+                    });
+                } finally {
+                    Binder.restoreCallingIdentity(caller);
+                }
+            }
+        }
+
         @Override
         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java
index c56cc62..235ed84 100644
--- a/telephony/java/android/telephony/data/ApnSetting.java
+++ b/telephony/java/android/telephony/data/ApnSetting.java
@@ -1293,8 +1293,8 @@
                 && Objects.equals(this.mOperatorNumeric, other.mOperatorNumeric)
                 && Objects.equals(this.mProtocol, other.mProtocol)
                 && Objects.equals(this.mRoamingProtocol, other.mRoamingProtocol)
-                && xorEqualsInt(this.mMtuV4, other.mMtuV4)
-                && xorEqualsInt(this.mMtuV6, other.mMtuV6)
+                && mtuUnsetOrEquals(this.mMtuV4, other.mMtuV4)
+                && mtuUnsetOrEquals(this.mMtuV6, other.mMtuV6)
                 && Objects.equals(this.mCarrierEnabled, other.mCarrierEnabled)
                 && Objects.equals(this.mNetworkTypeBitmask, other.mNetworkTypeBitmask)
                 && Objects.equals(this.mLingeringNetworkTypeBitmask,
@@ -1322,7 +1322,12 @@
     // Equal or one is not specified.
     private boolean xorEqualsInt(int first, int second) {
         return first == UNSPECIFIED_INT || second == UNSPECIFIED_INT
-            || Objects.equals(first, second);
+                || first == second;
+    }
+
+    // Equal or one is not specified. Specific to MTU where <= 0 indicates unset.
+    private boolean mtuUnsetOrEquals(int first, int second) {
+        return first <= 0 || second <= 0 || first == second;
     }
 
     private String nullToEmpty(String stringValue) {
diff --git a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/NotificationTest.java b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/NotificationTest.java
index 90fd08b..47f87d6 100644
--- a/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/NotificationTest.java
+++ b/tests/InputMethodStressTest/src/com/android/inputmethod/stresstest/NotificationTest.java
@@ -95,6 +95,8 @@
         PackageManager pm = mContext.getPackageManager();
         // Do not run on Automotive.
         assumeFalse(pm.hasSystemFeature(PackageManager.FEATURE_AUTOMOTIVE));
+        // Do not run on TV. Direct Reply isn't supported on TV.
+        assumeFalse(pm.hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY));
     }
 
     @After