Merge "Update icon for Calendar permission."
diff --git a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
index 2fdba0a..c121bd9 100644
--- a/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
+++ b/apct-tests/perftests/multiuser/src/android/multiuser/UserLifecycleTests.java
@@ -27,6 +27,7 @@
 import android.os.RemoteException;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.util.Log;
 
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.LargeTest;
@@ -130,6 +131,47 @@
         }
     }
 
+    /** Tests switching to an already-created, but no-longer-running, user. */
+    @Test
+    public void switchUser_stopped() throws Exception {
+        while (mRunner.keepRunning()) {
+            mRunner.pauseTiming();
+            final int startUser = mAm.getCurrentUser();
+            final int testUser = initializeNewUserAndSwitchBack(/* stopNewUser */ true);
+            final CountDownLatch latch = new CountDownLatch(1);
+            registerBroadcastReceiver(Intent.ACTION_USER_UNLOCKED, latch, testUser);
+            mRunner.resumeTiming();
+
+            mAm.switchUser(testUser);
+            boolean success = latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
+
+            mRunner.pauseTiming();
+            attestTrue("Failed to achieve 2nd ACTION_USER_UNLOCKED for user " + testUser, success);
+            switchUser(startUser);
+            removeUser(testUser);
+            mRunner.resumeTiming();
+        }
+    }
+
+    /** Tests switching to an already-created already-running non-owner user. */
+    @Test
+    public void switchUser_running() throws Exception {
+        while (mRunner.keepRunning()) {
+            mRunner.pauseTiming();
+            final int startUser = mAm.getCurrentUser();
+            final int testUser = initializeNewUserAndSwitchBack(/* stopNewUser */ false);
+            mRunner.resumeTiming();
+
+            switchUser(testUser);
+
+            mRunner.pauseTiming();
+            attestTrue("Failed to switch to user " + testUser, mAm.isUserRunning(testUser));
+            switchUser(startUser);
+            removeUser(testUser);
+            mRunner.resumeTiming();
+        }
+    }
+
     @Test
     public void stopUser() throws Exception {
         while (mRunner.keepRunning()) {
@@ -188,6 +230,34 @@
         }
     }
 
+    /** Tests starting an already-created, but no-longer-running, profile. */
+    @Test
+    public void managedProfileUnlock_stopped() throws Exception {
+        while (mRunner.keepRunning()) {
+            mRunner.pauseTiming();
+            final UserInfo userInfo = mUm.createProfileForUser("TestUser",
+                    UserInfo.FLAG_MANAGED_PROFILE, mAm.getCurrentUser());
+            // Start the profile initially, then stop it. Similar to setQuietModeEnabled.
+            final CountDownLatch latch1 = new CountDownLatch(1);
+            registerBroadcastReceiver(Intent.ACTION_USER_UNLOCKED, latch1, userInfo.id);
+            mIam.startUserInBackground(userInfo.id);
+            latch1.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
+            stopUser(userInfo.id, true);
+
+            // Now we restart the profile.
+            final CountDownLatch latch2 = new CountDownLatch(1);
+            registerBroadcastReceiver(Intent.ACTION_USER_UNLOCKED, latch2, userInfo.id);
+            mRunner.resumeTiming();
+
+            mIam.startUserInBackground(userInfo.id);
+            latch2.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
+
+            mRunner.pauseTiming();
+            removeUser(userInfo.id);
+            mRunner.resumeTiming();
+        }
+    }
+
     @Test
     public void ephemeralUserStopped() throws Exception {
         while (mRunner.keepRunning()) {
@@ -262,6 +332,35 @@
         latch.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS);
     }
 
+    /**
+     * Creates a user and waits for its ACTION_USER_UNLOCKED.
+     * Then switches to back to the original user and waits for its switchUser() to finish.
+     *
+     * @param stopNewUser whether to stop the new user after switching to otherUser.
+     * @return userId of the newly created user.
+     */
+    private int initializeNewUserAndSwitchBack(boolean stopNewUser) throws Exception {
+        final int origUser = mAm.getCurrentUser();
+        // First, create and switch to testUser, waiting for its ACTION_USER_UNLOCKED
+        final int testUser = mUm.createUser("TestUser", 0).id;
+        final CountDownLatch latch1 = new CountDownLatch(1);
+        registerBroadcastReceiver(Intent.ACTION_USER_UNLOCKED, latch1, testUser);
+        mAm.switchUser(testUser);
+        attestTrue("Failed to achieve initial ACTION_USER_UNLOCKED for user " + testUser,
+                latch1.await(TIMEOUT_IN_SECOND, TimeUnit.SECONDS));
+
+        // Second, switch back to origUser, waiting merely for switchUser() to finish
+        switchUser(origUser);
+        attestTrue("Didn't switch back to user, " + origUser, origUser == mAm.getCurrentUser());
+
+        if (stopNewUser) {
+            stopUser(testUser, true);
+            attestFalse("Failed to stop user " + testUser, mAm.isUserRunning(testUser));
+        }
+
+        return testUser;
+    }
+
     private void registerUserSwitchObserver(final CountDownLatch switchLatch,
             final CountDownLatch bootCompleteLatch, final int userId) throws Exception {
         ActivityManager.getService().registerUserSwitchObserver(
@@ -313,4 +412,14 @@
             mUsersToRemove.add(userId);
         }
     }
+
+    private void attestTrue(String message, boolean attestion) {
+        if (!attestion) {
+            Log.w(TAG, message);
+        }
+    }
+
+    private void attestFalse(String message, boolean attestion) {
+        attestTrue(message, !attestion);
+    }
 }
diff --git a/api/current.txt b/api/current.txt
index d4a1554..9776a11 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11452,6 +11452,7 @@
     method public long getSize();
     method public int getStagedSessionErrorCode();
     method @NonNull public String getStagedSessionErrorMessage();
+    method public long getUpdatedMillis();
     method @NonNull public android.os.UserHandle getUser();
     method public boolean isActive();
     method public boolean isCommitted();
@@ -11606,7 +11607,7 @@
     method @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryBroadcastReceivers(@NonNull android.content.Intent, int);
     method @NonNull public abstract java.util.List<android.content.pm.ProviderInfo> queryContentProviders(@Nullable String, int, int);
     method @NonNull public abstract java.util.List<android.content.pm.InstrumentationInfo> queryInstrumentation(@NonNull String, int);
-    method @Nullable public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentActivities(@NonNull android.content.Intent, int);
+    method @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentActivities(@NonNull android.content.Intent, int);
     method @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentActivityOptions(@Nullable android.content.ComponentName, @Nullable android.content.Intent[], @NonNull android.content.Intent, int);
     method @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentContentProviders(@NonNull android.content.Intent, int);
     method @NonNull public abstract java.util.List<android.content.pm.ResolveInfo> queryIntentServices(@NonNull android.content.Intent, int);
@@ -45108,6 +45109,7 @@
     method public boolean canChangeDtmfToneLength();
     method @Nullable public android.telephony.TelephonyManager createForPhoneAccountHandle(android.telecom.PhoneAccountHandle);
     method public android.telephony.TelephonyManager createForSubscriptionId(int);
+    method @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean doesSwitchMultiSimConfigTriggerReboot();
     method @RequiresPermission(android.Manifest.permission.ACCESS_FINE_LOCATION) public java.util.List<android.telephony.CellInfo> getAllCellInfo();
     method public int getCallState();
     method public int getCardIdForDefaultEuicc();
diff --git a/api/system-current.txt b/api/system-current.txt
index d1018be..3f74596 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -8063,7 +8063,6 @@
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isOffhook();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isPotentialEmergencyNumber(@NonNull String);
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRadioOn();
-    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public boolean isRebootRequiredForModemConfigChange();
     method @Deprecated @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isRinging();
     method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public boolean isVideoCallingEnabled();
     method @Deprecated @RequiresPermission(android.Manifest.permission.READ_PHONE_STATE) public boolean isVisualVoicemailEnabled(android.telecom.PhoneAccountHandle);
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index dc4413f..cbb78bf 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -1406,7 +1406,7 @@
     // Currently is last two bytes of a hash of a device level ID and
     // the mac address of the bluetooth device that is connected.
     // Deprecated: use obfuscated_id instead, this one is always 0 for Q+
-    optional int32 OBSOLETE_obfuscated_id = 2 [deprecated = true];
+    optional int32 obfuscated_id = 2 [deprecated = true];
     // The profile that is connected. Eg. GATT, A2DP, HEADSET.
     // From android.bluetooth.BluetoothAdapter.java
     // Default: 0 when not used
@@ -1417,7 +1417,7 @@
     // Hash algorithm: HMAC-SHA256
     // Size: 32 byte
     // Default: null or empty if the device identifier is not known
-    optional bytes obfuscated_id = 4 [(android.os.statsd.log_mode) = MODE_BYTES];
+    optional bytes new_obfuscated_id = 4 [(android.os.statsd.log_mode) = MODE_BYTES];
 }
 
 /**
diff --git a/core/java/android/app/ApplicationLoaders.java b/core/java/android/app/ApplicationLoaders.java
index faa30f3..2e59b90 100644
--- a/core/java/android/app/ApplicationLoaders.java
+++ b/core/java/android/app/ApplicationLoaders.java
@@ -145,8 +145,7 @@
      */
     public void createAndCacheNonBootclasspathSystemClassLoaders(SharedLibraryInfo[] libs) {
         if (mSystemLibsCacheMap != null) {
-            Log.wtf(TAG, "Already cached.");
-            return;
+            throw new IllegalStateException("Already cached.");
         }
 
         mSystemLibsCacheMap = new HashMap<String, CachedClassLoader>();
@@ -159,7 +158,8 @@
     /**
      * Caches a single non-bootclasspath class loader.
      *
-     * All of this library's dependencies must have previously been cached.
+     * All of this library's dependencies must have previously been cached. Otherwise, an exception
+     * is thrown.
      */
     private void createAndCacheNonBootclasspathSystemClassLoader(SharedLibraryInfo lib) {
         String path = lib.getPath();
@@ -174,9 +174,8 @@
                 CachedClassLoader cached = mSystemLibsCacheMap.get(dependencyPath);
 
                 if (cached == null) {
-                    Log.e(TAG, "Failed to find dependency " + dependencyPath
-                            + " of cached library " + path);
-                    return;
+                    throw new IllegalStateException("Failed to find dependency " + dependencyPath
+                            + " of cachedlibrary " + path);
                 }
 
                 sharedLibraries.add(cached.loader);
@@ -189,8 +188,8 @@
                 null /*cacheKey*/, null /*classLoaderName*/, sharedLibraries /*sharedLibraries*/);
 
         if (classLoader == null) {
-            Log.e(TAG, "Failed to cache " + path);
-            return;
+            // bad configuration or break in classloading code
+            throw new IllegalStateException("Failed to cache " + path);
         }
 
         CachedClassLoader cached = new CachedClassLoader();
@@ -215,7 +214,7 @@
      *
      * If there is an error or the cache is not available, this returns null.
      */
-    private ClassLoader getCachedNonBootclasspathSystemLib(String zip, ClassLoader parent,
+    public ClassLoader getCachedNonBootclasspathSystemLib(String zip, ClassLoader parent,
             String classLoaderName, List<ClassLoader> sharedLibraries) {
         if (mSystemLibsCacheMap == null) {
             return null;
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 5328dda..deb181f 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -687,6 +687,13 @@
      */
     public static final int PRIVATE_FLAG_ALLOW_EXTERNAL_STORAGE_SANDBOX = 1 << 29;
 
+    /**
+     * Value for {@link #privateFlags}: whether this app is pre-installed on the
+     * ODM partition of the system image.
+     * @hide
+     */
+    public static final int PRIVATE_FLAG_ODM = 1 << 30;
+
     /** @hide */
     @IntDef(flag = true, prefix = { "PRIVATE_FLAG_" }, value = {
             PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE,
@@ -717,6 +724,7 @@
             PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE,
             PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE,
             PRIVATE_FLAG_ALLOW_EXTERNAL_STORAGE_SANDBOX,
+            PRIVATE_FLAG_ODM,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ApplicationInfoPrivateFlags {}
@@ -1093,6 +1101,18 @@
     public String appComponentFactory;
 
     /**
+     * Resource id of {@link com.android.internal.R.styleable.AndroidManifestProvider_icon}
+     * @hide
+     */
+    public int iconRes;
+
+    /**
+     * Resource id of {@link com.android.internal.R.styleable.AndroidManifestProvider_roundIcon}
+     * @hide
+     */
+    public int roundIconRes;
+
+    /**
      * The category of this app. Categories are used to cluster multiple apps
      * together into meaningful groups, such as when summarizing battery,
      * network, or disk usage. Apps should only define this value when they fit
@@ -1571,6 +1591,8 @@
         classLoaderName = orig.classLoaderName;
         splitClassLoaderNames = orig.splitClassLoaderNames;
         appComponentFactory = orig.appComponentFactory;
+        iconRes = orig.iconRes;
+        roundIconRes = orig.roundIconRes;
         compileSdkVersion = orig.compileSdkVersion;
         compileSdkVersionCodename = orig.compileSdkVersionCodename;
         mHiddenApiPolicy = orig.mHiddenApiPolicy;
@@ -1650,6 +1672,8 @@
         dest.writeInt(compileSdkVersion);
         dest.writeString(compileSdkVersionCodename);
         dest.writeString(appComponentFactory);
+        dest.writeInt(iconRes);
+        dest.writeInt(roundIconRes);
         dest.writeInt(mHiddenApiPolicy);
         dest.writeInt(hiddenUntilInstalled ? 1 : 0);
         dest.writeString(zygotePreloadName);
@@ -1724,6 +1748,8 @@
         compileSdkVersion = source.readInt();
         compileSdkVersionCodename = source.readString();
         appComponentFactory = source.readString();
+        iconRes = source.readInt();
+        roundIconRes = source.readInt();
         mHiddenApiPolicy = source.readInt();
         hiddenUntilInstalled = source.readInt() != 0;
         zygotePreloadName = source.readString();
@@ -1970,6 +1996,11 @@
     }
 
     /** @hide */
+    public boolean isOdm() {
+        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_ODM) != 0;
+    }
+
+    /** @hide */
     public boolean isPartiallyDirectBootAware() {
         return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE) != 0;
     }
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index a96316b..ec2e8ca 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -17,6 +17,7 @@
 package android.content.pm;
 
 import android.Manifest;
+import android.annotation.CurrentTimeMillisLong;
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -1817,6 +1818,9 @@
         public boolean isCommitted;
 
         /** {@hide} */
+        public long updatedMillis;
+
+        /** {@hide} */
         @UnsupportedAppUsage
         public SessionInfo() {
         }
@@ -2237,6 +2241,15 @@
             return isCommitted;
         }
 
+        /**
+         * The timestamp of the last update that occurred to the session, including changing of
+         * states in case of staged sessions.
+         */
+        @CurrentTimeMillisLong
+        public long getUpdatedMillis() {
+            return updatedMillis;
+        }
+
         @Override
         public int describeContents() {
             return 0;
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index f0539c49..025d8f9 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -4423,7 +4423,7 @@
      *         {@link #resolveActivity}. If there are no matching activities, an
      *         empty list is returned.
      */
-    @Nullable
+    @NonNull
     public abstract List<ResolveInfo> queryIntentActivities(@NonNull Intent intent,
             @ResolveInfoFlags int flags);
 
@@ -4444,7 +4444,7 @@
      *         empty list is returned.
      * @hide
      */
-    @Nullable
+    @NonNull
     @UnsupportedAppUsage
     public abstract List<ResolveInfo> queryIntentActivitiesAsUser(@NonNull Intent intent,
             @ResolveInfoFlags int flags, @UserIdInt int userId);
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 93bc6d7..8981000 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -49,6 +49,8 @@
 import android.annotation.TestApi;
 import android.annotation.UnsupportedAppUsage;
 import android.app.ActivityTaskManager;
+import android.app.ActivityThread;
+import android.app.ResourcesManager;
 import android.content.ComponentName;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -69,6 +71,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.PatternMatcher;
+import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.SystemProperties;
 import android.os.Trace;
@@ -92,6 +95,7 @@
 import android.util.SparseArray;
 import android.util.TypedValue;
 import android.util.apk.ApkSignatureVerifier;
+import android.view.Display;
 import android.view.Gravity;
 
 import com.android.internal.R;
@@ -320,6 +324,8 @@
     private int mParseError = PackageManager.INSTALL_SUCCEEDED;
 
     private static boolean sCompatibilityModeEnabled = true;
+    private static boolean sUseRoundIcon = false;
+
     private static final int PARSE_DEFAULT_INSTALL_LOCATION =
             PackageInfo.INSTALL_LOCATION_UNSPECIFIED;
     private static final int PARSE_DEFAULT_TARGET_SANDBOX = 1;
@@ -3437,6 +3443,11 @@
         TypedArray sa = res.obtainAttributes(parser,
                 com.android.internal.R.styleable.AndroidManifestApplication);
 
+        ai.iconRes = sa.getResourceId(
+            com.android.internal.R.styleable.AndroidManifestApplication_icon, 0);
+        ai.roundIconRes = sa.getResourceId(
+            com.android.internal.R.styleable.AndroidManifestApplication_roundIcon, 0);
+
         if (!parsePackageItemInfo(owner, ai, outError,
                 "<application>", sa, false /*nameRequired*/,
                 com.android.internal.R.styleable.AndroidManifestApplication_name,
@@ -4240,9 +4251,7 @@
             }
         }
 
-        final boolean useRoundIcon =
-                Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon);
-        int roundIconVal = useRoundIcon ? sa.getResourceId(roundIconRes, 0) : 0;
+        int roundIconVal = sUseRoundIcon ? sa.getResourceId(roundIconRes, 0) : 0;
         if (roundIconVal != 0) {
             outInfo.icon = roundIconVal;
             outInfo.nonLocalizedLabel = null;
@@ -5750,9 +5759,7 @@
             outInfo.nonLocalizedLabel = v.coerceToString();
         }
 
-        final boolean useRoundIcon =
-                Resources.getSystem().getBoolean(com.android.internal.R.bool.config_useRoundIcon);
-        int roundIconVal = useRoundIcon ? sa.getResourceId(
+        int roundIconVal = sUseRoundIcon ? sa.getResourceId(
                 com.android.internal.R.styleable.AndroidManifestIntentFilter_roundIcon, 0) : 0;
         if (roundIconVal != 0) {
             outInfo.icon = roundIconVal;
@@ -6920,6 +6927,11 @@
         }
 
         /** @hide */
+        public boolean isOdm() {
+            return applicationInfo.isOdm();
+        }
+
+        /** @hide */
         public boolean isPrivileged() {
             return applicationInfo.isPrivilegedApp();
         }
@@ -7739,6 +7751,7 @@
         }
         ai.seInfoUser = SELinuxUtil.assignSeinfoUser(state);
         ai.resourceDirs = state.overlayPaths;
+        ai.icon = (sUseRoundIcon && ai.roundIconRes != 0) ? ai.roundIconRes : ai.iconRes;
     }
 
     @UnsupportedAppUsage
@@ -8344,6 +8357,39 @@
         sCompatibilityModeEnabled = compatibilityModeEnabled;
     }
 
+    /**
+     * @hide
+     */
+    public static void readConfigUseRoundIcon(Resources r) {
+        if (r != null) {
+            sUseRoundIcon = r.getBoolean(com.android.internal.R.bool.config_useRoundIcon);
+            return;
+        }
+
+        ApplicationInfo androidAppInfo;
+        try {
+            androidAppInfo = ActivityThread.getPackageManager().getApplicationInfo(
+                    "android", 0 /* flags */,
+                UserHandle.myUserId());
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+        Resources systemResources = Resources.getSystem();
+
+        // Create in-flight as this overlayable resource is only used when config changes
+        Resources overlayableRes = ResourcesManager.getInstance().getResources(null,
+                null,
+                null,
+                androidAppInfo.resourceDirs,
+                androidAppInfo.sharedLibraryFiles,
+                Display.DEFAULT_DISPLAY,
+                null,
+                systemResources.getCompatibilityInfo(),
+                systemResources.getClassLoader());
+
+        sUseRoundIcon = overlayableRes.getBoolean(com.android.internal.R.bool.config_useRoundIcon);
+    }
+
     public static class PackageParserException extends Exception {
         public final int error;
 
diff --git a/core/java/android/hardware/Camera.java b/core/java/android/hardware/Camera.java
index 81abdea0..10fe52a 100644
--- a/core/java/android/hardware/Camera.java
+++ b/core/java/android/hardware/Camera.java
@@ -812,7 +812,10 @@
      *
      * @throws RuntimeException if starting preview fails; usually this would be
      *    because of a hardware or other low-level error, or because release()
-     *    has been called on this Camera instance.
+     *    has been called on this Camera instance. The QCIF (176x144) exception
+     *    mentioned in {@link Parameters#setPreviewSize setPreviewSize} and
+     *    {@link Parameters#setPictureSize setPictureSize} can also cause this
+     *    exception be thrown.
      */
     public native final void startPreview();
 
@@ -2863,6 +2866,16 @@
          * orientation should also be considered while setting picture size and
          * thumbnail size.
          *
+         * Exception on 176x144 (QCIF) resolution:
+         * Camera devices usually have a fixed capability for downscaling from
+         * larger resolution to smaller, and the QCIF resolution sometimes
+         * is not fully supported due to this limitation on devices with
+         * high-resolution image sensors. Therefore, trying to configure a QCIF
+         * preview size with any picture or video size larger than 1920x1080
+         * (either width or height) might not be supported, and
+         * {@link #setParameters(Camera.Parameters)} might throw a
+         * RuntimeException if it is not.
+         *
          * @param width  the width of the pictures, in pixels
          * @param height the height of the pictures, in pixels
          * @see #setDisplayOrientation(int)
@@ -2908,6 +2921,16 @@
          * preview can be different from the resolution of the recorded video
          * during video recording.</p>
          *
+         * <p>Exception on 176x144 (QCIF) resolution:
+         * Camera devices usually have a fixed capability for downscaling from
+         * larger resolution to smaller, and the QCIF resolution sometimes
+         * is not fully supported due to this limitation on devices with
+         * high-resolution image sensors. Therefore, trying to configure a QCIF
+         * video resolution with any preview or picture size larger than
+         * 1920x1080  (either width or height) might not be supported, and
+         * {@link #setParameters(Camera.Parameters)} will throw a
+         * RuntimeException if it is not.</p>
+         *
          * @return a list of Size object if camera has separate preview and
          *         video output; otherwise, null is returned.
          * @see #getPreferredPreviewSizeForVideo()
@@ -3202,6 +3225,16 @@
          * <p>Applications need to consider the display orientation. See {@link
          * #setPreviewSize(int,int)} for reference.</p>
          *
+         * <p>Exception on 176x144 (QCIF) resolution:
+         * Camera devices usually have a fixed capability for downscaling from
+         * larger resolution to smaller, and the QCIF resolution sometimes
+         * is not fully supported due to this limitation on devices with
+         * high-resolution image sensors. Therefore, trying to configure a QCIF
+         * picture size with any preview or video size larger than 1920x1080
+         * (either width or height) might not be supported, and
+         * {@link #setParameters(Camera.Parameters)} might throw a
+         * RuntimeException if it is not.</p>
+         *
          * @param width  the width for pictures, in pixels
          * @param height the height for pictures, in pixels
          * @see #setPreviewSize(int,int)
diff --git a/core/java/android/hardware/camera2/CameraCharacteristics.java b/core/java/android/hardware/camera2/CameraCharacteristics.java
index 6a2d8d8..48588e6 100644
--- a/core/java/android/hardware/camera2/CameraCharacteristics.java
+++ b/core/java/android/hardware/camera2/CameraCharacteristics.java
@@ -2396,6 +2396,12 @@
      * </table>
      * <p>Refer to {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} for additional
      * mandatory stream configurations on a per-capability basis.</p>
+     * <p>Exception on 176x144 (QCIF) resolution: camera devices usually have a fixed capability for
+     * downscaling from larger resolution to smaller, and the QCIF resolution sometimes is not
+     * fully supported due to this limitation on devices with high-resolution image sensors.
+     * Therefore, trying to configure a QCIF resolution stream together with any other
+     * stream larger than 1920x1080 resolution (either width or height) might not be supported,
+     * and capture session creation will fail if it is not.</p>
      * <p>This key is available on all devices.</p>
      *
      * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
@@ -2592,6 +2598,12 @@
      * ratio 4:3, and the JPEG encoder alignment requirement is 16, the maximum JPEG size will be
      * 3264x2448.</li>
      * </ul>
+     * <p>Exception on 176x144 (QCIF) resolution: camera devices usually have a fixed capability on
+     * downscaling from larger resolution to smaller ones, and the QCIF resolution can sometimes
+     * not be fully supported due to this limitation on devices with high-resolution image
+     * sensors. Therefore, trying to configure a QCIF resolution stream together with any other
+     * stream larger than 1920x1080 resolution (either width or height) might not be supported,
+     * and capture session creation will fail if it is not.</p>
      * <p>This key is available on all devices.</p>
      *
      * @see CameraCharacteristics#INFO_SUPPORTED_HARDWARE_LEVEL
@@ -3580,7 +3592,7 @@
      * <li><code>LEVEL_3</code> devices additionally support YUV reprocessing and RAW image capture, along
      *   with additional output stream configurations.</li>
      * <li><code>EXTERNAL</code> devices are similar to <code>LIMITED</code> devices with exceptions like some sensor or
-     *   lens information not reorted or less stable framerates.</li>
+     *   lens information not reported or less stable framerates.</li>
      * </ul>
      * <p>See the individual level enums for full descriptions of the supported capabilities.  The
      * {@link CameraCharacteristics#REQUEST_AVAILABLE_CAPABILITIES android.request.availableCapabilities} entry describes the device's capabilities at a
diff --git a/core/java/android/hardware/camera2/CameraDevice.java b/core/java/android/hardware/camera2/CameraDevice.java
index 20fc53f..bac6522 100644
--- a/core/java/android/hardware/camera2/CameraDevice.java
+++ b/core/java/android/hardware/camera2/CameraDevice.java
@@ -449,6 +449,14 @@
      * by calling {@link #isSessionConfigurationSupported} or attempting to create a session with
      * such targets.</p>
      *
+     * <p>Exception on 176x144 (QCIF) resolution:
+     * Camera devices usually have a fixed capability for downscaling from larger resolution to
+     * smaller, and the QCIF resolution sometimes is not fully supported due to this
+     * limitation on devices with high-resolution image sensors. Therefore, trying to configure a
+     * QCIF resolution stream together with any other stream larger than 1920x1080 resolution
+     * (either width or height) might not be supported, and capture session creation will fail if it
+     * is not.</p>
+     *
      * @param outputs The new set of Surfaces that should be made available as
      *                targets for captured image data.
      * @param callback The callback to notify about the status of the new capture session.
diff --git a/core/java/android/hardware/display/ColorDisplayManager.java b/core/java/android/hardware/display/ColorDisplayManager.java
index 0c07a67..ce71db6 100644
--- a/core/java/android/hardware/display/ColorDisplayManager.java
+++ b/core/java/android/hardware/display/ColorDisplayManager.java
@@ -392,6 +392,26 @@
     }
 
     /**
+     * Enables or disables display white balance.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS)
+    public boolean setDisplayWhiteBalanceEnabled(boolean enabled) {
+        return mManager.setDisplayWhiteBalanceEnabled(enabled);
+    }
+
+    /**
+     * Returns whether display white balance is currently enabled. Even if enabled, it may or may
+     * not be active, if another transform with higher priority is active.
+     *
+     * @hide
+     */
+    public boolean isDisplayWhiteBalanceEnabled() {
+        return mManager.isDisplayWhiteBalanceEnabled();
+    }
+
+    /**
      * Returns {@code true} if Night Display is supported by the device.
      *
      * @hide
@@ -616,6 +636,22 @@
             }
         }
 
+        boolean isDisplayWhiteBalanceEnabled() {
+            try {
+                return mCdm.isDisplayWhiteBalanceEnabled();
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        boolean setDisplayWhiteBalanceEnabled(boolean enabled) {
+            try {
+                return mCdm.setDisplayWhiteBalanceEnabled(enabled);
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
         int getColorMode() {
             try {
                 return mCdm.getColorMode();
diff --git a/core/java/android/hardware/display/IColorDisplayManager.aidl b/core/java/android/hardware/display/IColorDisplayManager.aidl
index 88b59a6..7b1033d 100644
--- a/core/java/android/hardware/display/IColorDisplayManager.aidl
+++ b/core/java/android/hardware/display/IColorDisplayManager.aidl
@@ -42,4 +42,7 @@
 
     int getColorMode();
     void setColorMode(int colorMode);
+
+    boolean isDisplayWhiteBalanceEnabled();
+    boolean setDisplayWhiteBalanceEnabled(boolean enabled);
 }
\ No newline at end of file
diff --git a/core/java/android/hardware/face/FaceManager.java b/core/java/android/hardware/face/FaceManager.java
index 3e8c334..6035f40 100644
--- a/core/java/android/hardware/face/FaceManager.java
+++ b/core/java/android/hardware/face/FaceManager.java
@@ -45,6 +45,7 @@
 import android.util.Slog;
 
 import com.android.internal.R;
+import com.android.internal.os.SomeArgs;
 
 import java.util.List;
 
@@ -63,6 +64,8 @@
     private static final int MSG_AUTHENTICATION_FAILED = 103;
     private static final int MSG_ERROR = 104;
     private static final int MSG_REMOVED = 105;
+    private static final int MSG_GET_FEATURE_COMPLETED = 106;
+    private static final int MSG_SET_FEATURE_COMPLETED = 107;
 
     private IFaceService mService;
     private final Context mContext;
@@ -70,6 +73,8 @@
     private AuthenticationCallback mAuthenticationCallback;
     private EnrollmentCallback mEnrollmentCallback;
     private RemovalCallback mRemovalCallback;
+    private SetFeatureCallback mSetFeatureCallback;
+    private GetFeatureCallback mGetFeatureCallback;
     private CryptoObject mCryptoObject;
     private Face mRemovalFace;
     private Handler mHandler;
@@ -112,6 +117,20 @@
         public void onEnumerated(long deviceId, int faceId, int remaining) {
             // TODO: Finish. Low priority since it's not used.
         }
+
+        @Override
+        public void onFeatureSet(boolean success, int feature) {
+            mHandler.obtainMessage(MSG_SET_FEATURE_COMPLETED, feature, 0, success).sendToTarget();
+        }
+
+        @Override
+        public void onFeatureGet(boolean success, int feature, boolean value) {
+            SomeArgs args = SomeArgs.obtain();
+            args.arg1 = success;
+            args.argi1 = feature;
+            args.arg2 = value;
+            mHandler.obtainMessage(MSG_GET_FEATURE_COMPLETED, args).sendToTarget();
+        }
     };
 
     /**
@@ -286,31 +305,31 @@
      * @hide
      */
     @RequiresPermission(MANAGE_BIOMETRIC)
-    public boolean setFeature(int feature, boolean enabled, byte[] token) {
+    public void setFeature(int feature, boolean enabled, byte[] token,
+            SetFeatureCallback callback) {
         if (mService != null) {
             try {
-                return mService.setFeature(feature, enabled, token);
+                mSetFeatureCallback = callback;
+                mService.setFeature(feature, enabled, token, mServiceReceiver);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
         }
-        return false;
     }
 
     /**
      * @hide
      */
     @RequiresPermission(MANAGE_BIOMETRIC)
-    public boolean getFeature(int feature) {
-        boolean result = true;
+    public void getFeature(int feature, GetFeatureCallback callback) {
         if (mService != null) {
             try {
-                result = mService.getFeature(feature);
+                mGetFeatureCallback = callback;
+                mService.getFeature(feature, mServiceReceiver);
             } catch (RemoteException e) {
                 throw e.rethrowFromSystemServer();
             }
         }
-        return result;
     }
 
     /**
@@ -874,6 +893,20 @@
         }
     }
 
+    /**
+     * @hide
+     */
+    public abstract static class SetFeatureCallback {
+        public abstract void onCompleted(boolean success, int feature);
+    }
+
+    /**
+     * @hide
+     */
+    public abstract static class GetFeatureCallback {
+        public abstract void onCompleted(boolean success, int feature, boolean value);
+    }
+
     private class OnEnrollCancelListener implements OnCancelListener {
         @Override
         public void onCancel() {
@@ -926,9 +959,36 @@
                 case MSG_REMOVED:
                     sendRemovedResult((Face) msg.obj, msg.arg1 /* remaining */);
                     break;
+                case MSG_SET_FEATURE_COMPLETED:
+                    sendSetFeatureCompleted((boolean) msg.obj /* success */,
+                            msg.arg1 /* feature */);
+                    break;
+                case MSG_GET_FEATURE_COMPLETED:
+                    SomeArgs args = (SomeArgs) msg.obj;
+                    sendGetFeatureCompleted((boolean) args.arg1 /* success */,
+                            args.argi1 /* feature */,
+                            (boolean) args.arg2 /* value */);
+                    args.recycle();
+                    break;
+                default:
+                    Log.w(TAG, "Unknown message: " + msg.what);
             }
         }
-    };
+    }
+
+    private void sendSetFeatureCompleted(boolean success, int feature) {
+        if (mSetFeatureCallback == null) {
+            return;
+        }
+        mSetFeatureCallback.onCompleted(success, feature);
+    }
+
+    private void sendGetFeatureCompleted(boolean success, int feature, boolean value) {
+        if (mGetFeatureCallback == null) {
+            return;
+        }
+        mGetFeatureCallback.onCompleted(success, feature, value);
+    }
 
     private void sendRemovedResult(Face face, int remaining) {
         if (mRemovalCallback == null) {
diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl
index 5043d4c..601be75 100644
--- a/core/java/android/hardware/face/IFaceService.aidl
+++ b/core/java/android/hardware/face/IFaceService.aidl
@@ -51,7 +51,7 @@
 
     // Start face enrollment
     void enroll(IBinder token, in byte [] cryptoToken, IFaceServiceReceiver receiver,
-                String opPackageName, in int [] disabledFeatures);
+            String opPackageName, in int [] disabledFeatures);
 
     // Cancel enrollment in progress
     void cancelEnrollment(IBinder token);
@@ -98,9 +98,10 @@
     // Enumerate all faces
     void enumerate(IBinder token, int userId, IFaceServiceReceiver receiver);
 
-    boolean setFeature(int feature, boolean enabled, in byte [] token);
+    void setFeature(int feature, boolean enabled, in byte [] token,
+            IFaceServiceReceiver receiver);
 
-    boolean getFeature(int feature);
+    void getFeature(int feature, IFaceServiceReceiver receiver);
 
     void userActivity();
 }
diff --git a/core/java/android/hardware/face/IFaceServiceReceiver.aidl b/core/java/android/hardware/face/IFaceServiceReceiver.aidl
index cec9fd8..2176902 100644
--- a/core/java/android/hardware/face/IFaceServiceReceiver.aidl
+++ b/core/java/android/hardware/face/IFaceServiceReceiver.aidl
@@ -29,4 +29,6 @@
     void onError(long deviceId, int error, int vendorCode);
     void onRemoved(long deviceId, int faceId, int remaining);
     void onEnumerated(long deviceId, int faceId, int remaining);
+    void onFeatureSet(boolean success, int feature);
+    void onFeatureGet(boolean success, int feature, boolean value);
 }
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 00d522b..ecd16dd 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -266,8 +266,11 @@
      *   - Fixed bug in min learned capacity updating process.
      * New in version 34:
      *   - Deprecated STATS_SINCE_UNPLUGGED and STATS_CURRENT.
+     * New in version 35:
+     *   - Fixed bug that was not reporting high cellular tx power correctly
+     *   - Added out of service and emergency service modes to data connection types
      */
-    static final int CHECKIN_VERSION = 34;
+    static final int CHECKIN_VERSION = 35;
 
     /**
      * Old version, we hit 9 and ran out of room, need to remove.
@@ -2371,18 +2374,21 @@
      */
     public abstract int getMobileRadioActiveUnknownCount(int which);
 
-    public static final int DATA_CONNECTION_NONE = 0;
-    public static final int DATA_CONNECTION_OTHER = TelephonyManager.MAX_NETWORK_TYPE + 1;
+    public static final int DATA_CONNECTION_OUT_OF_SERVICE = 0;
+    public static final int DATA_CONNECTION_EMERGENCY_SERVICE =
+            TelephonyManager.MAX_NETWORK_TYPE + 1;
+    public static final int DATA_CONNECTION_OTHER = DATA_CONNECTION_EMERGENCY_SERVICE + 1;
+
 
     static final String[] DATA_CONNECTION_NAMES = {
-        "none", "gprs", "edge", "umts", "cdma", "evdo_0", "evdo_A",
+        "oos", "gprs", "edge", "umts", "cdma", "evdo_0", "evdo_A",
         "1xrtt", "hsdpa", "hsupa", "hspa", "iden", "evdo_b", "lte",
         "ehrpd", "hspap", "gsm", "td_scdma", "iwlan", "lte_ca", "nr",
-        "other"
+        "emngcy", "other"
     };
 
     @UnsupportedAppUsage
-    public static final int NUM_DATA_CONNECTION_TYPES = DATA_CONNECTION_OTHER+1;
+    public static final int NUM_DATA_CONNECTION_TYPES = DATA_CONNECTION_OTHER + 1;
 
     /**
      * Returns the time in microseconds that the phone has been running with
@@ -6564,6 +6570,10 @@
                 }
                 oldState = rec.states;
                 oldState2 = rec.states2;
+                // Clear High Tx Power Flag for volta positioning
+                if ((rec.states2 & HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG) != 0) {
+                    rec.states2 &= ~HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
+                }
             }
 
             return item.toString();
@@ -7865,9 +7875,9 @@
         // Phone data connection (DATA_CONNECTION_TIME_DATA and DATA_CONNECTION_COUNT_DATA)
         for (int i = 0; i < NUM_DATA_CONNECTION_TYPES; ++i) {
             // Map OTHER to TelephonyManager.NETWORK_TYPE_UNKNOWN and mark NONE as a boolean.
-            boolean isNone = (i == DATA_CONNECTION_NONE);
+            boolean isNone = (i == DATA_CONNECTION_OUT_OF_SERVICE);
             int telephonyNetworkType = i;
-            if (i == DATA_CONNECTION_OTHER) {
+            if (i == DATA_CONNECTION_OTHER || i == DATA_CONNECTION_EMERGENCY_SERVICE) {
                 telephonyNetworkType = TelephonyManager.NETWORK_TYPE_UNKNOWN;
             }
             final long pdcToken = proto.start(SystemProto.DATA_CONNECTION);
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 5d33b49..336c2e5 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -38,7 +38,8 @@
     public static final String HEARING_AID_SETTINGS = "settings_bluetooth_hearing_aid";
     public static final String SAFETY_HUB = "settings_safety_hub";
     public static final String SCREENRECORD_LONG_PRESS = "settings_screenrecord_long_press";
-    public static final String GLOBAL_ACTIONS_GRID_ENABLED = "settings_global_actions_grid_enabled";
+    public static final String FORCE_GLOBAL_ACTIONS_GRID_ENABLED =
+            "settings_global_actions_force_grid_enabled";
     public static final String GLOBAL_ACTIONS_PANEL_ENABLED =
             "settings_global_actions_panel_enabled";
     public static final String DYNAMIC_SYSTEM = "settings_dynamic_system";
@@ -58,7 +59,7 @@
         DEFAULT_FLAGS.put(HEARING_AID_SETTINGS, "false");
         DEFAULT_FLAGS.put(SAFETY_HUB, "true");
         DEFAULT_FLAGS.put(SCREENRECORD_LONG_PRESS, "false");
-        DEFAULT_FLAGS.put(GLOBAL_ACTIONS_GRID_ENABLED, "true");
+        DEFAULT_FLAGS.put(FORCE_GLOBAL_ACTIONS_GRID_ENABLED, "false");
         DEFAULT_FLAGS.put(GLOBAL_ACTIONS_PANEL_ENABLED, "true");
         DEFAULT_FLAGS.put("settings_wifi_details_saved_screen", "true");
         DEFAULT_FLAGS.put("settings_wifi_details_datausage_header", "false");
diff --git a/core/java/android/util/HashedStringCache.java b/core/java/android/util/HashedStringCache.java
new file mode 100644
index 0000000..8ce8514
--- /dev/null
+++ b/core/java/android/util/HashedStringCache.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.util;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.os.Environment;
+import android.os.storage.StorageManager;
+import android.text.TextUtils;
+
+import java.io.File;
+import java.nio.charset.Charset;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+
+/**
+ * HashedStringCache provides hashing functionality with an underlying LRUCache and expiring salt.
+ * Salt and expiration time are being stored under the tag passed in by the calling package --
+ * intended usage is the calling package name.
+ * TODO: Add unit tests b/129870147
+ * @hide
+ */
+public class HashedStringCache {
+    private static HashedStringCache sHashedStringCache = null;
+    private static final Charset UTF_8 = Charset.forName("UTF-8");
+    private static final int HASH_CACHE_SIZE = 100;
+    private static final int HASH_LENGTH = 8;
+    private static final String HASH_SALT = "_hash_salt";
+    private static final String HASH_SALT_DATE = "_hash_salt_date";
+    private static final String HASH_SALT_GEN = "_hash_salt_gen";
+    // For privacy we need to rotate the salt regularly
+    private static final long DAYS_TO_MILLIS = 1000 * 60 * 60 * 24;
+    private static final int MAX_SALT_DAYS = 100;
+    private final LruCache<String, String> mHashes;
+    private final SecureRandom mSecureRandom;
+    private final Object mPreferenceLock = new Object();
+    private final MessageDigest mDigester;
+    private byte[] mSalt;
+    private int mSaltGen;
+    private SharedPreferences mSharedPreferences;
+
+    private static final String TAG = "HashedStringCache";
+    private static final boolean DEBUG = false;
+
+    private HashedStringCache() {
+        mHashes = new LruCache<>(HASH_CACHE_SIZE);
+        mSecureRandom = new SecureRandom();
+        try {
+            mDigester = MessageDigest.getInstance("MD5");
+        } catch (NoSuchAlgorithmException impossible) {
+            // this can't happen - MD5 is always present
+            throw new RuntimeException(impossible);
+        }
+    }
+
+    /**
+     * @return - instance of the HashedStringCache
+     * @hide
+     */
+    public static HashedStringCache getInstance() {
+        if (sHashedStringCache == null) {
+            sHashedStringCache = new HashedStringCache();
+        }
+        return sHashedStringCache;
+    }
+
+    /**
+     * Take the string and context and create a hash of the string. Trigger refresh on salt if salt
+     * is more than 7 days old
+     * @param context - callers context to retrieve SharedPreferences
+     * @param clearText - string that needs to be hashed
+     * @param tag - class name to use for storing values in shared preferences
+     * @param saltExpirationDays - number of days we may keep the same salt
+     *                           special value -1 will short-circuit and always return null.
+     * @return - HashResult containing the hashed string and the generation of the hash salt, null
+     *      if clearText string is empty
+     *
+     * @hide
+     */
+    public HashResult hashString(Context context, String tag, String clearText,
+            int saltExpirationDays) {
+        if (TextUtils.isEmpty(clearText) || saltExpirationDays == -1) {
+            return null;
+        }
+
+        populateSaltValues(context, tag, saltExpirationDays);
+        String hashText = mHashes.get(clearText);
+        if (hashText != null) {
+            return new HashResult(hashText, mSaltGen);
+        }
+
+        mDigester.reset();
+        mDigester.update(mSalt);
+        mDigester.update(clearText.getBytes(UTF_8));
+        byte[] bytes = mDigester.digest();
+        int len = Math.min(HASH_LENGTH, bytes.length);
+        hashText = Base64.encodeToString(bytes, 0, len, Base64.NO_PADDING | Base64.NO_WRAP);
+        mHashes.put(clearText, hashText);
+
+        return new HashResult(hashText, mSaltGen);
+    }
+
+    /**
+     * Populates the mSharedPreferences and checks if there is a salt present and if it's older than
+     * 7 days
+     * @param tag - class name to use for storing values in shared preferences
+     * @param saltExpirationDays - number of days we may keep the same salt
+     * @param saltDate - the date retrieved from configuration
+     * @return - true if no salt or salt is older than 7 days
+     */
+    private boolean checkNeedsNewSalt(String tag, int saltExpirationDays, long saltDate) {
+        if (saltDate == 0 || saltExpirationDays < -1) {
+            return true;
+        }
+        if (saltExpirationDays > MAX_SALT_DAYS) {
+            saltExpirationDays = MAX_SALT_DAYS;
+        }
+        long now = System.currentTimeMillis();
+        long delta = now - saltDate;
+        // Check for delta < 0 to make sure we catch if someone puts their phone far in the
+        // future and then goes back to normal time.
+        return delta >= saltExpirationDays * DAYS_TO_MILLIS || delta < 0;
+    }
+
+    /**
+     * Populate the salt and saltGen member variables if they aren't already set / need refreshing.
+     * @param context - to get sharedPreferences
+     * @param tag - class name to use for storing values in shared preferences
+     * @param saltExpirationDays - number of days we may keep the same salt
+     */
+    private void populateSaltValues(Context context, String tag, int saltExpirationDays) {
+        synchronized (mPreferenceLock) {
+            // check if we need to refresh the salt
+            mSharedPreferences = getHashSharedPreferences(context);
+            long saltDate = mSharedPreferences.getLong(tag + HASH_SALT_DATE, 0);
+            boolean needsNewSalt = checkNeedsNewSalt(tag, saltExpirationDays, saltDate);
+            if (needsNewSalt) {
+                mHashes.evictAll();
+            }
+            if (mSalt == null || needsNewSalt) {
+                String saltString = mSharedPreferences.getString(tag + HASH_SALT, null);
+                mSaltGen = mSharedPreferences.getInt(tag + HASH_SALT_GEN, 0);
+                if (saltString == null || needsNewSalt) {
+                    mSaltGen++;
+                    byte[] saltBytes = new byte[16];
+                    mSecureRandom.nextBytes(saltBytes);
+                    saltString = Base64.encodeToString(saltBytes,
+                            Base64.NO_PADDING | Base64.NO_WRAP);
+                    mSharedPreferences.edit()
+                            .putString(tag + HASH_SALT, saltString)
+                            .putInt(tag + HASH_SALT_GEN, mSaltGen)
+                            .putLong(tag + HASH_SALT_DATE, System.currentTimeMillis()).apply();
+                    if (DEBUG) {
+                        Log.d(TAG, "created a new salt: " + saltString);
+                    }
+                }
+                mSalt = saltString.getBytes(UTF_8);
+            }
+        }
+    }
+
+    /**
+     * Android:ui doesn't have persistent preferences, so need to fall back on this hack originally
+     * from ChooserActivity.java
+     * @param context
+     * @return
+     */
+    private SharedPreferences getHashSharedPreferences(Context context) {
+        final File prefsFile = new File(new File(
+                Environment.getDataUserCePackageDirectory(
+                        StorageManager.UUID_PRIVATE_INTERNAL,
+                        context.getUserId(), context.getPackageName()),
+                "shared_prefs"),
+                "hashed_cache.xml");
+        return context.getSharedPreferences(prefsFile, Context.MODE_PRIVATE);
+    }
+
+    /**
+     * Helper class to hold hashed string and salt generation.
+     */
+    public class HashResult {
+        public String hashedString;
+        public int saltGeneration;
+
+        public HashResult(String hString, int saltGen) {
+            hashedString = hString;
+            saltGeneration = saltGen;
+        }
+    }
+}
diff --git a/core/java/android/view/LayoutInflater.java b/core/java/android/view/LayoutInflater.java
index 35cf129..f9b629c8 100644
--- a/core/java/android/view/LayoutInflater.java
+++ b/core/java/android/view/LayoutInflater.java
@@ -566,7 +566,7 @@
         String layout = res.getResourceEntryName(resource);
 
         try {
-            Class clazz = mPrecompiledClassLoader.loadClass("" + pkg + ".CompiledView");
+            Class clazz = Class.forName("" + pkg + ".CompiledView", false, mPrecompiledClassLoader);
             Method inflater = clazz.getMethod(layout, Context.class, int.class);
             View view = (View) inflater.invoke(null, mContext, resource);
 
@@ -827,8 +827,8 @@
 
             if (constructor == null) {
                 // Class not found in the cache, see if it's real, and try to add it
-                clazz = mContext.getClassLoader().loadClass(
-                        prefix != null ? (prefix + name) : name).asSubclass(View.class);
+                clazz = Class.forName(prefix != null ? (prefix + name) : name, false,
+                        mContext.getClassLoader()).asSubclass(View.class);
 
                 if (mFilter != null && clazz != null) {
                     boolean allowed = mFilter.onLoadClass(clazz);
@@ -846,8 +846,8 @@
                     Boolean allowedState = mFilterMap.get(name);
                     if (allowedState == null) {
                         // New class -- remember whether it is allowed
-                        clazz = mContext.getClassLoader().loadClass(
-                                prefix != null ? (prefix + name) : name).asSubclass(View.class);
+                        clazz = Class.forName(prefix != null ? (prefix + name) : name, false,
+                                mContext.getClassLoader()).asSubclass(View.class);
 
                         boolean allowed = clazz != null && mFilter.onLoadClass(clazz);
                         mFilterMap.put(name, allowed);
diff --git a/core/java/android/view/RenderNodeAnimator.java b/core/java/android/view/RenderNodeAnimator.java
index 7ab9534..04ac922 100644
--- a/core/java/android/view/RenderNodeAnimator.java
+++ b/core/java/android/view/RenderNodeAnimator.java
@@ -26,6 +26,7 @@
 import android.graphics.RenderNode;
 import android.os.Build;
 import android.os.Handler;
+import android.os.Looper;
 import android.util.SparseIntArray;
 
 import com.android.internal.util.VirtualRefBasePtr;
@@ -191,6 +192,9 @@
         }
 
         mState = STATE_DELAYED;
+        if (mHandler == null) {
+            mHandler = new Handler(true);
+        }
         applyInterpolator();
 
         if (mNativePtr == null) {
@@ -224,9 +228,6 @@
     private void moveToRunningState() {
         mState = STATE_RUNNING;
         if (mNativePtr != null) {
-            if (mHandler == null) {
-                mHandler = new Handler();
-            }
             nStart(mNativePtr.get());
         }
         notifyStartListeners();
@@ -503,7 +504,11 @@
     // Called by native
     @UnsupportedAppUsage
     private static void callOnFinished(RenderNodeAnimator animator) {
-        animator.mHandler.post(animator::onFinished);
+        if (animator.mHandler != null) {
+            animator.mHandler.post(animator::onFinished);
+        } else {
+            new Handler(Looper.getMainLooper(), null, true).post(animator::onFinished);
+        }
     }
 
     @Override
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index bd38327..c2aec6a 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1746,7 +1746,7 @@
          * what the other flags are.
          * @hide
          */
-        public static final int PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND = 0x00020000;
+        public static final int PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS = 0x00020000;
 
         /**
          * Flag to indicate that this window needs Sustained Performance Mode if
@@ -1877,8 +1877,8 @@
                         equals = PRIVATE_FLAG_LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME,
                         name = "LAYOUT_CHILD_WINDOW_IN_PARENT_FRAME"),
                 @ViewDebug.FlagToString(
-                        mask = PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND,
-                        equals = PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND,
+                        mask = PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS,
+                        equals = PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS,
                         name = "FORCE_DRAW_STATUS_BAR_BACKGROUND"),
                 @ViewDebug.FlagToString(
                         mask = PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE,
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index a1d0cdc..d553c6c 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -74,6 +74,7 @@
 import android.os.ResultReceiver;
 import android.os.UserHandle;
 import android.os.UserManager;
+import android.provider.DeviceConfig;
 import android.provider.DocumentsContract;
 import android.provider.Downloads;
 import android.provider.OpenableColumns;
@@ -83,6 +84,7 @@
 import android.service.chooser.IChooserTargetService;
 import android.text.TextUtils;
 import android.util.AttributeSet;
+import android.util.HashedStringCache;
 import android.util.Log;
 import android.util.Size;
 import android.util.Slog;
@@ -106,6 +108,7 @@
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.config.sysui.SystemUiDeviceConfigFlags;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.util.ImageUtils;
@@ -170,6 +173,11 @@
     private static final int QUERY_TARGET_SERVICE_LIMIT = 5;
     private static final int WATCHDOG_TIMEOUT_MILLIS = 3000;
 
+    private static final int DEFAULT_SALT_EXPIRATION_DAYS = 7;
+    private int mMaxHashSaltDays = DeviceConfig.getInt(DeviceConfig.NAMESPACE_SYSTEMUI,
+            SystemUiDeviceConfigFlags.HASH_SALT_MAX_DAYS,
+            DEFAULT_SALT_EXPIRATION_DAYS);
+
     private Bundle mReplacementExtras;
     private IntentSender mChosenComponentSender;
     private IntentSender mRefinementIntentSender;
@@ -201,7 +209,8 @@
     private static final int SHORTCUT_MANAGER_SHARE_TARGET_RESULT_COMPLETED = 4;
     private static final int LIST_VIEW_UPDATE_MESSAGE = 5;
 
-    private static final int LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS = 250;
+    @VisibleForTesting
+    public static final int LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS = 250;
 
     private boolean mListViewDataChanged = false;
 
@@ -991,6 +1000,7 @@
             // Lower values mean the ranking was better.
             int cat = 0;
             int value = which;
+            HashedStringCache.HashResult directTargetHashed = null;
             switch (mChooserListAdapter.getPositionTargetType(which)) {
                 case ChooserListAdapter.TARGET_CALLER:
                     cat = MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_APP_TARGET;
@@ -998,6 +1008,17 @@
                     break;
                 case ChooserListAdapter.TARGET_SERVICE:
                     cat = MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET;
+                    value -= mChooserListAdapter.getCallerTargetCount();
+                    // Log the package name + target name to answer the question if most users
+                    // share to mostly the same person or to a bunch of different people.
+                    ChooserTarget target =
+                            mChooserListAdapter.mServiceTargets.get(value).getChooserTarget();
+                    directTargetHashed = HashedStringCache.getInstance().hashString(
+                            this,
+                            TAG,
+                            target.getComponentName().getPackageName()
+                                    + target.getTitle().toString(),
+                            mMaxHashSaltDays);
                     break;
                 case ChooserListAdapter.TARGET_STANDARD:
                     cat = MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_STANDARD_TARGET;
@@ -1007,6 +1028,15 @@
             }
 
             if (cat != 0) {
+                LogMaker targetLogMaker = new LogMaker(cat).setSubtype(value);
+                if (directTargetHashed != null) {
+                    targetLogMaker.addTaggedData(
+                            MetricsEvent.FIELD_HASHED_TARGET_NAME, directTargetHashed.hashedString);
+                    targetLogMaker.addTaggedData(
+                                    MetricsEvent.FIELD_HASHED_TARGET_SALT_GEN,
+                                    directTargetHashed.saltGeneration);
+                }
+                getMetricsLogger().write(targetLogMaker);
                 MetricsLogger.action(this, cat, value);
             }
 
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index 114d31f..9f860e2 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -106,7 +106,7 @@
     void notePhoneOn();
     void notePhoneOff();
     void notePhoneSignalStrength(in SignalStrength signalStrength);
-    void notePhoneDataConnectionState(int dataType, boolean hasData);
+    void notePhoneDataConnectionState(int dataType, boolean hasData, int serviceType);
     void notePhoneState(int phoneState);
     void noteWifiOn();
     void noteWifiOff();
diff --git a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
index fd74c04..495a5fb 100644
--- a/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
+++ b/core/java/com/android/internal/config/sysui/SystemUiDeviceConfigFlags.java
@@ -95,5 +95,10 @@
     public static final String COMPACT_MEDIA_SEEKBAR_ENABLED =
             "compact_media_notification_seekbar_enabled";
 
+    /**
+     * (int) Maximum number of days to retain the salt for hashing direct share targets in logging
+     */
+    public static final String HASH_SALT_MAX_DAYS = "hash_salt_max_days";
+
     private SystemUiDeviceConfigFlags() { }
 }
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 1fc7635..8f37d81 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -907,8 +907,6 @@
     @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
     protected StopwatchTimer mBluetoothScanTimer;
 
-    boolean mIsCellularTxPowerHigh = false;
-
     int mMobileRadioPowerState = DataConnectionRealTimeInfo.DC_POWER_STATE_LOW;
     long mMobileRadioActiveStartTime;
     StopwatchTimer mMobileRadioActiveTimer;
@@ -5275,16 +5273,26 @@
     }
 
     @UnsupportedAppUsage
-    public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData) {
+    public void notePhoneDataConnectionStateLocked(int dataType, boolean hasData, int serviceType) {
         // BatteryStats uses 0 to represent no network type.
         // Telephony does not have a concept of no network type, and uses 0 to represent unknown.
         // Unknown is included in DATA_CONNECTION_OTHER.
-        int bin = DATA_CONNECTION_NONE;
+        int bin = DATA_CONNECTION_OUT_OF_SERVICE;
         if (hasData) {
             if (dataType > 0 && dataType <= TelephonyManager.MAX_NETWORK_TYPE) {
                 bin = dataType;
             } else {
-                bin = DATA_CONNECTION_OTHER;
+                switch (serviceType) {
+                    case ServiceState.STATE_OUT_OF_SERVICE:
+                        bin = DATA_CONNECTION_OUT_OF_SERVICE;
+                        break;
+                    case ServiceState.STATE_EMERGENCY_ONLY:
+                        bin = DATA_CONNECTION_EMERGENCY_SERVICE;
+                        break;
+                    default:
+                        bin = DATA_CONNECTION_OTHER;
+                        break;
+                }
             }
         }
         if (DEBUG) Log.i(TAG, "Phone Data Connection -> " + dataType + " = " + hasData);
@@ -11198,19 +11206,9 @@
             }
         }
         if (levelMaxTimeSpent == ModemActivityInfo.TX_POWER_LEVELS - 1) {
-            if (!mIsCellularTxPowerHigh) {
-                mHistoryCur.states2 |= HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
-                addHistoryRecordLocked(elapsedRealtime, uptime);
-                mIsCellularTxPowerHigh = true;
-            }
-            return;
-        }
-        if (mIsCellularTxPowerHigh) {
-            mHistoryCur.states2 &= ~HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
+            mHistoryCur.states2 |= HistoryItem.STATE2_CELLULAR_HIGH_TX_POWER_FLAG;
             addHistoryRecordLocked(elapsedRealtime, uptime);
-            mIsCellularTxPowerHigh = false;
         }
-        return;
     }
 
     private final class BluetoothActivityInfoCache {
@@ -13670,7 +13668,6 @@
         mCameraOnTimer.readSummaryFromParcelLocked(in);
         mBluetoothScanNesting = 0;
         mBluetoothScanTimer.readSummaryFromParcelLocked(in);
-        mIsCellularTxPowerHigh = false;
 
         int NRPMS = in.readInt();
         if (NRPMS > 10000) {
@@ -14654,7 +14651,6 @@
         mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase, in);
         mBluetoothScanNesting = 0;
         mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase, in);
-        mIsCellularTxPowerHigh = false;
         mDischargeUnplugLevel = in.readInt();
         mDischargePlugLevel = in.readInt();
         mDischargeCurrentLevel = in.readInt();
diff --git a/core/java/com/android/internal/os/Zygote.java b/core/java/com/android/internal/os/Zygote.java
index 8ca0bd1..afdeb1b 100644
--- a/core/java/com/android/internal/os/Zygote.java
+++ b/core/java/com/android/internal/os/Zygote.java
@@ -197,9 +197,6 @@
 
     private Zygote() {}
 
-    /** Called for some security initialization before any fork. */
-    static native void nativeSecurityInit();
-
     /**
      * Forks a new VM instance.  The current VM must have been started
      * with the -Xzygote flag. <b>NOTE: new instance keeps all
@@ -384,22 +381,19 @@
     native protected static void nativeInstallSeccompUidGidFilter(int uidGidMin, int uidGidMax);
 
     /**
-     * Zygote unmount storage space on initializing.
-     * This method is called once.
-     */
-    protected static native void nativeUnmountStorageOnInit();
-
-    /**
-     * Get socket file descriptors (opened by init) from the environment and
-     * store them for access from native code later.
+     * Initialize the native state of the Zygote.  This inclues
+     *   - Fetching socket FDs from the environment
+     *   - Initializing security properties
+     *   - Unmounting storage as appropriate
+     *   - Loading necessary performance profile information
      *
      * @param isPrimary  True if this is the zygote process, false if it is zygote_secondary
      */
-    public static void getSocketFDs(boolean isPrimary) {
-        nativeGetSocketFDs(isPrimary);
+    static void initNativeState(boolean isPrimary) {
+        nativeInitNativeState(isPrimary);
     }
 
-    protected static native void nativeGetSocketFDs(boolean isPrimary);
+    protected static native void nativeInitNativeState(boolean isPrimary);
 
     /**
      * Returns the raw string value of a system property.
diff --git a/core/java/com/android/internal/os/ZygoteInit.java b/core/java/com/android/internal/os/ZygoteInit.java
index 7cca7b7..bb7b09a 100644
--- a/core/java/com/android/internal/os/ZygoteInit.java
+++ b/core/java/com/android/internal/os/ZygoteInit.java
@@ -20,10 +20,10 @@
 import static android.system.OsConstants.S_IRWXO;
 
 import android.annotation.UnsupportedAppUsage;
-import android.content.res.Resources;
-import android.content.res.TypedArray;
 import android.app.ApplicationLoaders;
 import android.content.pm.SharedLibraryInfo;
+import android.content.res.Resources;
+import android.content.res.TypedArray;
 import android.os.Build;
 import android.os.Environment;
 import android.os.IInstalld;
@@ -863,8 +863,6 @@
                 throw new RuntimeException("No ABI list supplied.");
             }
 
-            Zygote.getSocketFDs(isPrimaryZygote);
-
             // In some configurations, we avoid preloading resources and classes eagerly.
             // In such cases, we will preload things prior to our first fork.
             if (!enableLazyPreload) {
@@ -889,10 +887,8 @@
             // Zygote.
             Trace.setTracingEnabled(false, 0);
 
-            Zygote.nativeSecurityInit();
 
-            // Zygote process unmounts root storage spaces.
-            Zygote.nativeUnmountStorageOnInit();
+            Zygote.initNativeState(isPrimaryZygote);
 
             ZygoteHooks.stopZygoteNoThreadCreation();
 
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 625814d..66a6329 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -38,7 +38,6 @@
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
 import static android.view.WindowManager.LayoutParams.TYPE_DRAWN_APPLICATION;
-
 import static com.android.internal.policy.PhoneWindow.FEATURE_OPTIONS_PANEL;
 
 import android.animation.Animator;
@@ -53,6 +52,7 @@
 import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.graphics.Color;
+import android.graphics.Insets;
 import android.graphics.LinearGradient;
 import android.graphics.Outline;
 import android.graphics.Paint;
@@ -205,8 +205,8 @@
     private final Interpolator mShowInterpolator;
     private final Interpolator mHideInterpolator;
     private final int mBarEnterExitDuration;
-    final boolean mForceWindowDrawsStatusBarBackground;
-    private final int mSemiTransparentStatusBarColor;
+    final boolean mForceWindowDrawsBarBackgrounds;
+    private final int mSemiTransparentBarColor;
 
     private final BackgroundFallback mBackgroundFallback = new BackgroundFallback();
 
@@ -242,6 +242,8 @@
     private boolean mWindowResizeCallbacksAdded = false;
     private Drawable.Callback mLastBackgroundDrawableCb = null;
     private BackdropFrameRenderer mBackdropFrameRenderer = null;
+    private Drawable mOriginalBackgroundDrawable;
+    private Drawable mLastOriginalBackgroundDrawable;
     private Drawable mResizingBackgroundDrawable;
     private Drawable mCaptionBackgroundDrawable;
     private Drawable mUserCaptionBackgroundDrawable;
@@ -257,6 +259,8 @@
     private final int mResizeShadowSize;
     private final Paint mVerticalResizeShadowPaint = new Paint();
     private final Paint mHorizontalResizeShadowPaint = new Paint();
+    private Insets mBackgroundInsets = Insets.NONE;
+    private Insets mLastBackgroundInsets = Insets.NONE;
 
     DecorView(Context context, int featureId, PhoneWindow window,
             WindowManager.LayoutParams params) {
@@ -270,10 +274,10 @@
 
         mBarEnterExitDuration = context.getResources().getInteger(
                 R.integer.dock_enter_exit_duration);
-        mForceWindowDrawsStatusBarBackground = context.getResources().getBoolean(
+        mForceWindowDrawsBarBackgrounds = context.getResources().getBoolean(
                 R.bool.config_forceWindowDrawsStatusBarBackground)
                 && context.getApplicationInfo().targetSdkVersion >= N;
-        mSemiTransparentStatusBarColor = context.getResources().getColor(
+        mSemiTransparentBarColor = context.getResources().getColor(
                 R.color.system_bar_background_semi_transparent, null /* theme */);
 
         updateAvailableWidth();
@@ -948,8 +952,9 @@
     }
 
     public void setWindowBackground(Drawable drawable) {
-        if (getBackground() != drawable) {
-            setBackgroundDrawable(drawable);
+        if (mOriginalBackgroundDrawable != drawable) {
+            mOriginalBackgroundDrawable = drawable;
+            updateBackgroundDrawable();
             if (drawable != null) {
                 mResizingBackgroundDrawable = enforceNonTranslucentBackground(drawable,
                         mWindow.isTranslucent() || mWindow.isShowingWallpaper());
@@ -1114,9 +1119,10 @@
             boolean navBarToLeftEdge = isNavBarToLeftEdge(mLastBottomInset, mLastLeftInset);
             int navBarSize = getNavBarSize(mLastBottomInset, mLastRightInset, mLastLeftInset);
             updateColorViewInt(mNavigationColorViewState, sysUiVisibility,
-                    mWindow.mNavigationBarColor, mWindow.mNavigationBarDividerColor, navBarSize,
+                    calculateNavigationBarColor(), mWindow.mNavigationBarDividerColor, navBarSize,
                     navBarToRightEdge || navBarToLeftEdge, navBarToLeftEdge,
-                    0 /* sideInset */, animate && !disallowAnimate, false /* force */);
+                    0 /* sideInset */, animate && !disallowAnimate,
+                    mForceWindowDrawsBarBackgrounds);
 
             boolean statusBarNeedsRightInset = navBarToRightEdge
                     && mNavigationColorViewState.present;
@@ -1128,24 +1134,34 @@
                     calculateStatusBarColor(), 0, mLastTopInset,
                     false /* matchVertical */, statusBarNeedsLeftInset, statusBarSideInset,
                     animate && !disallowAnimate,
-                    mForceWindowDrawsStatusBarBackground);
+                    mForceWindowDrawsBarBackgrounds);
         }
 
-        // When we expand the window with FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, we still need
-        // to ensure that the rest of the view hierarchy doesn't notice it, unless they've
-        // explicitly asked for it.
-        boolean consumingNavBar =
-                (attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
+        // When we expand the window with FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS or
+        // mForceWindowDrawsBarBackgrounds, we still need to ensure that the rest of the view
+        // hierarchy doesn't notice it, unless they've explicitly asked for it.
+        //
+        // Note: We don't need to check for IN_SCREEN or INSET_DECOR because unlike the status bar,
+        // these flags wouldn't make the window draw behind the navigation bar, unless
+        // LAYOUT_HIDE_NAVIGATION was set.
+        boolean forceConsumingNavBar = (mForceWindowDrawsBarBackgrounds
+                        && (attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
                         && (sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0
-                        && (sysUiVisibility & SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
+                        && (sysUiVisibility & SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0)
                 || mLastShouldAlwaysConsumeSystemBars;
 
+        boolean consumingNavBar =
+                ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
+                        && (sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0
+                        && (sysUiVisibility & SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0)
+                || forceConsumingNavBar;
+
         // If we didn't request fullscreen layout, but we still got it because of the
-        // mForceWindowDrawsStatusBarBackground flag, also consume top inset.
+        // mForceWindowDrawsBarBackgrounds flag, also consume top inset.
         boolean consumingStatusBar = (sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) == 0
                 && (attrs.flags & FLAG_LAYOUT_IN_SCREEN) == 0
                 && (attrs.flags & FLAG_LAYOUT_INSET_DECOR) == 0
-                && mForceWindowDrawsStatusBarBackground
+                && mForceWindowDrawsBarBackgrounds
                 && mLastTopInset != 0
                 || mLastShouldAlwaysConsumeSystemBars;
 
@@ -1176,21 +1192,63 @@
             }
         }
 
+        if (forceConsumingNavBar) {
+            mBackgroundInsets = Insets.of(mLastLeftInset, 0, mLastRightInset, mLastBottomInset);
+        } else {
+            mBackgroundInsets = Insets.NONE;
+        }
+        updateBackgroundDrawable();
+
         if (insets != null) {
             insets = insets.consumeStableInsets();
         }
         return insets;
     }
 
-    private int calculateStatusBarColor() {
-        return calculateStatusBarColor(mWindow.getAttributes().flags,
-                mSemiTransparentStatusBarColor, mWindow.mStatusBarColor);
+    /**
+     * Updates the background drawable, applying padding to it in case we {@link #mBackgroundInsets}
+     * are set.
+     */
+    private void updateBackgroundDrawable() {
+        if (mBackgroundInsets.equals(mLastBackgroundInsets)
+                && mLastOriginalBackgroundDrawable == mOriginalBackgroundDrawable) {
+            return;
+        }
+        if (mBackgroundInsets.equals(Insets.NONE)) {
+            setBackground(mOriginalBackgroundDrawable);
+        } else {
+            setBackground(new InsetDrawable(mOriginalBackgroundDrawable,
+                    mBackgroundInsets.left, mBackgroundInsets.top,
+                    mBackgroundInsets.right, mBackgroundInsets.bottom) {
+
+                /**
+                 * Return inner padding so we don't apply the padding again in
+                 * {@link DecorView#drawableChanged()}
+                 */
+                @Override
+                public boolean getPadding(Rect padding) {
+                    return getDrawable().getPadding(padding);
+                }
+            });
+        }
+        mLastBackgroundInsets = mBackgroundInsets;
+        mLastOriginalBackgroundDrawable = mOriginalBackgroundDrawable;
     }
 
-    public static int calculateStatusBarColor(int flags, int semiTransparentStatusBarColor,
-            int statusBarColor) {
-        return (flags & FLAG_TRANSLUCENT_STATUS) != 0 ? semiTransparentStatusBarColor
-                : (flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 ? statusBarColor
+    private int calculateStatusBarColor() {
+        return calculateBarColor(mWindow.getAttributes().flags, FLAG_TRANSLUCENT_STATUS,
+                mSemiTransparentBarColor, mWindow.mStatusBarColor);
+    }
+
+    private int calculateNavigationBarColor() {
+        return calculateBarColor(mWindow.getAttributes().flags, FLAG_TRANSLUCENT_NAVIGATION,
+                mSemiTransparentBarColor, mWindow.mNavigationBarColor);
+    }
+
+    public static int calculateBarColor(int flags, int translucentFlag, int semiTransparentBarColor,
+            int barColor) {
+        return (flags & translucentFlag) != 0 ? semiTransparentBarColor
+                : (flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0 ? barColor
                 : Color.BLACK;
     }
 
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 890ee86..04559e4 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -31,7 +31,7 @@
 import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
 
 import android.annotation.NonNull;
 import android.annotation.UnsupportedAppUsage;
@@ -2469,8 +2469,8 @@
                 setFlags(FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS,
                         FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS & ~getForcedWindowFlags());
             }
-            if (mDecor.mForceWindowDrawsStatusBarBackground) {
-                params.privateFlags |= PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
+            if (mDecor.mForceWindowDrawsBarBackgrounds) {
+                params.privateFlags |= PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
             }
         }
         if (a.getBoolean(R.styleable.Window_windowLightStatusBar, false)) {
diff --git a/core/jni/Android.bp b/core/jni/Android.bp
index 000c044..0e31ab9 100644
--- a/core/jni/Android.bp
+++ b/core/jni/Android.bp
@@ -204,7 +204,6 @@
         "android_content_res_Configuration.cpp",
         "android_animation_PropertyValuesHolder.cpp",
         "android_security_Scrypt.cpp",
-        "com_android_internal_net_NetworkStatsFactory.cpp",
         "com_android_internal_os_AtomicDirectory.cpp",
         "com_android_internal_os_ClassLoaderFactory.cpp",
         "com_android_internal_os_FuseAppLoop.cpp",
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index ccd0b66..967abce 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -227,7 +227,6 @@
 extern int register_android_animation_PropertyValuesHolder(JNIEnv *env);
 extern int register_android_security_Scrypt(JNIEnv *env);
 extern int register_com_android_internal_content_NativeLibraryHelper(JNIEnv *env);
-extern int register_com_android_internal_net_NetworkStatsFactory(JNIEnv *env);
 extern int register_com_android_internal_os_AtomicDirectory(JNIEnv *env);
 extern int register_com_android_internal_os_ClassLoaderFactory(JNIEnv* env);
 extern int register_com_android_internal_os_FuseAppLoop(JNIEnv* env);
@@ -1569,7 +1568,6 @@
     REG_JNI(register_android_animation_PropertyValuesHolder),
     REG_JNI(register_android_security_Scrypt),
     REG_JNI(register_com_android_internal_content_NativeLibraryHelper),
-    REG_JNI(register_com_android_internal_net_NetworkStatsFactory),
     REG_JNI(register_com_android_internal_os_AtomicDirectory),
     REG_JNI(register_com_android_internal_os_FuseAppLoop),
 };
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index bf56ef4..d3f9196 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -163,7 +163,7 @@
       }
 
       // Generic idmap parameters
-      const char* argv[8];
+      const char* argv[9];
       int argc = 0;
       struct stat st;
 
@@ -199,6 +199,10 @@
         argv[argc++] = AssetManager::PRODUCT_SERVICES_OVERLAY_DIR;
       }
 
+      if (stat(AssetManager::ODM_OVERLAY_DIR, &st) == 0) {
+        argv[argc++] = AssetManager::ODM_OVERLAY_DIR;
+      }
+
       // Finally, invoke idmap (if any overlay directory exists)
       if (argc > 5) {
         execv(AssetManager::IDMAP_BIN, (char* const*)argv);
@@ -233,6 +237,10 @@
     input_dirs.push_back(AssetManager::PRODUCT_SERVICES_OVERLAY_DIR);
   }
 
+  if (stat(AssetManager::ODM_OVERLAY_DIR, &st) == 0) {
+    input_dirs.push_back(AssetManager::ODM_OVERLAY_DIR);
+  }
+
   if (input_dirs.empty()) {
     LOG(WARNING) << "no directories for idmap2 to scan";
     return env->NewObjectArray(0, g_stringClass, nullptr);
diff --git a/core/jni/com_android_internal_os_Zygote.cpp b/core/jni/com_android_internal_os_Zygote.cpp
index 8dd7e8e..430b9c5 100644
--- a/core/jni/com_android_internal_os_Zygote.cpp
+++ b/core/jni/com_android_internal_os_Zygote.cpp
@@ -126,7 +126,7 @@
 static jclass gZygoteInitClass;
 static jmethodID gCreateSystemServerClassLoader;
 
-static bool g_is_security_enforced = true;
+static bool gIsSecurityEnforced = true;
 
 /**
  * The maximum number of characters (not including a null terminator) that a
@@ -510,7 +510,7 @@
 }
 
 static void SetUpSeccompFilter(uid_t uid, bool is_child_zygote) {
-  if (!g_is_security_enforced) {
+  if (!gIsSecurityEnforced) {
     ALOGI("seccomp disabled by setenforce 0");
     return;
   }
@@ -1626,18 +1626,48 @@
   return fd_vec;
 }
 
+static void UnmountStorageOnInit(JNIEnv* env) {
+  // Zygote process unmount root storage space initially before every child processes are forked.
+  // Every forked child processes (include SystemServer) only mount their own root storage space
+  // and no need unmount storage operation in MountEmulatedStorage method.
+  // Zygote process does not utilize root storage spaces and unshares its mount namespace below.
+
+  // See storage config details at http://source.android.com/tech/storage/
+  // Create private mount namespace shared by all children
+  if (unshare(CLONE_NEWNS) == -1) {
+    RuntimeAbort(env, __LINE__, "Failed to unshare()");
+    return;
+  }
+
+  // Mark rootfs as being a slave so that changes from default
+  // namespace only flow into our children.
+  if (mount("rootfs", "/", nullptr, (MS_SLAVE | MS_REC), nullptr) == -1) {
+    RuntimeAbort(env, __LINE__, "Failed to mount() rootfs as MS_SLAVE");
+    return;
+  }
+
+  // Create a staging tmpfs that is shared by our children; they will
+  // bind mount storage into their respective private namespaces, which
+  // are isolated from each other.
+  const char* target_base = getenv("EMULATED_STORAGE_TARGET");
+  if (target_base != nullptr) {
+#define STRINGIFY_UID(x) __STRING(x)
+    if (mount("tmpfs", target_base, "tmpfs", MS_NOSUID | MS_NODEV,
+              "uid=0,gid=" STRINGIFY_UID(AID_SDCARD_R) ",mode=0751") == -1) {
+      ALOGE("Failed to mount tmpfs to %s", target_base);
+      RuntimeAbort(env, __LINE__, "Failed to mount tmpfs");
+      return;
+    }
+#undef STRINGIFY_UID
+  }
+
+  UnmountTree("/storage");
+}
+
 }  // anonymous namespace
 
 namespace android {
 
-static void com_android_internal_os_Zygote_nativeSecurityInit(JNIEnv*, jclass) {
-  // security_getenforce is not allowed on app process. Initialize and cache
-  // the value before zygote forks.
-  g_is_security_enforced = security_getenforce();
-
-  selinux_android_seapp_context_init();
-}
-
 static void com_android_internal_os_Zygote_nativePreApplicationInit(JNIEnv*, jclass) {
   PreApplicationInit();
 }
@@ -1791,47 +1821,9 @@
     FileDescriptorWhitelist::Get()->Allow(path_cstr);
 }
 
-static void com_android_internal_os_Zygote_nativeUnmountStorageOnInit(JNIEnv* env, jclass) {
-    // Zygote process unmount root storage space initially before every child processes are forked.
-    // Every forked child processes (include SystemServer) only mount their own root storage space
-    // and no need unmount storage operation in MountEmulatedStorage method.
-    // Zygote process does not utilize root storage spaces and unshares its mount namespace below.
-
-    // See storage config details at http://source.android.com/tech/storage/
-    // Create private mount namespace shared by all children
-    if (unshare(CLONE_NEWNS) == -1) {
-        RuntimeAbort(env, __LINE__, "Failed to unshare()");
-        return;
-    }
-
-    // Mark rootfs as being a slave so that changes from default
-    // namespace only flow into our children.
-    if (mount("rootfs", "/", nullptr, (MS_SLAVE | MS_REC), nullptr) == -1) {
-        RuntimeAbort(env, __LINE__, "Failed to mount() rootfs as MS_SLAVE");
-        return;
-    }
-
-    // Create a staging tmpfs that is shared by our children; they will
-    // bind mount storage into their respective private namespaces, which
-    // are isolated from each other.
-    const char* target_base = getenv("EMULATED_STORAGE_TARGET");
-    if (target_base != nullptr) {
-#define STRINGIFY_UID(x) __STRING(x)
-        if (mount("tmpfs", target_base, "tmpfs", MS_NOSUID | MS_NODEV,
-                  "uid=0,gid=" STRINGIFY_UID(AID_SDCARD_R) ",mode=0751") == -1) {
-            ALOGE("Failed to mount tmpfs to %s", target_base);
-            RuntimeAbort(env, __LINE__, "Failed to mount tmpfs");
-            return;
-        }
-#undef STRINGIFY_UID
-    }
-
-    UnmountTree("/storage");
-}
-
 static void com_android_internal_os_Zygote_nativeInstallSeccompUidGidFilter(
         JNIEnv* env, jclass, jint uidGidMin, jint uidGidMax) {
-  if (!g_is_security_enforced) {
+  if (!gIsSecurityEnforced) {
     ALOGI("seccomp disabled by setenforce 0");
     return;
   }
@@ -1883,8 +1875,12 @@
  * @param is_primary  If this process is the primary or secondary Zygote; used to compute the name
  * of the environment variable storing the file descriptors.
  */
-static void com_android_internal_os_Zygote_nativeGetSocketFDs(JNIEnv* env, jclass,
-                                                              jboolean is_primary) {
+static void com_android_internal_os_Zygote_nativeInitNativeState(JNIEnv* env, jclass,
+                                                                 jboolean is_primary) {
+  /*
+   * Obtain file descriptors created by init from the environment.
+   */
+
   std::string android_socket_prefix(ANDROID_SOCKET_PREFIX);
   std::string env_var_name = android_socket_prefix + (is_primary ? "zygote" : "zygote_secondary");
   char* env_var_val = getenv(env_var_name.c_str());
@@ -1905,6 +1901,30 @@
   } else {
     ALOGE("Unable to fetch USAP pool socket file descriptor");
   }
+
+  /*
+   * Security Initialization
+   */
+
+  // security_getenforce is not allowed on app process. Initialize and cache
+  // the value before zygote forks.
+  gIsSecurityEnforced = security_getenforce();
+
+  selinux_android_seapp_context_init();
+
+  /*
+   * Storage Initialization
+   */
+
+  UnmountStorageOnInit(env);
+
+  /*
+   * Performance Initialization
+   */
+
+  if (!SetTaskProfiles(0, {})) {
+    ZygoteFailure(env, "zygote", nullptr, "Zygote SetTaskProfiles failed");
+  }
 }
 
 /**
@@ -2001,8 +2021,6 @@
 }
 
 static const JNINativeMethod gMethods[] = {
-    { "nativeSecurityInit", "()V",
-      (void *) com_android_internal_os_Zygote_nativeSecurityInit },
     { "nativeForkAndSpecialize",
       "(II[II[[IILjava/lang/String;Ljava/lang/String;[I[IZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)I",
       (void *) com_android_internal_os_Zygote_nativeForkAndSpecialize },
@@ -2010,8 +2028,6 @@
       (void *) com_android_internal_os_Zygote_nativeForkSystemServer },
     { "nativeAllowFileAcrossFork", "(Ljava/lang/String;)V",
       (void *) com_android_internal_os_Zygote_nativeAllowFileAcrossFork },
-    { "nativeUnmountStorageOnInit", "()V",
-      (void *) com_android_internal_os_Zygote_nativeUnmountStorageOnInit },
     { "nativePreApplicationInit", "()V",
       (void *) com_android_internal_os_Zygote_nativePreApplicationInit },
     { "nativeInstallSeccompUidGidFilter", "(II)V",
@@ -2021,8 +2037,8 @@
     { "nativeSpecializeAppProcess",
       "(II[II[[IILjava/lang/String;Ljava/lang/String;ZLjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;)V",
       (void *) com_android_internal_os_Zygote_nativeSpecializeAppProcess },
-    { "nativeGetSocketFDs", "(Z)V",
-      (void *) com_android_internal_os_Zygote_nativeGetSocketFDs },
+    { "nativeInitNativeState", "(Z)V",
+      (void *) com_android_internal_os_Zygote_nativeInitNativeState },
     { "nativeGetUsapPipeFDs", "()[I",
       (void *) com_android_internal_os_Zygote_nativeGetUsapPipeFDs },
     { "nativeRemoveUsapTableEntry", "(I)Z",
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index d8d4656..0996352 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -102,6 +102,8 @@
   static const char* kProductOverlayDir = "/product/overlay";
   static const char* kSystemProductServicesOverlayDir = "/system/product_services/overlay/";
   static const char* kProductServicesOverlayDir = "/product_services/overlay";
+  static const char* kSystemOdmOverlayDir = "/system/odm/overlay";
+  static const char* kOdmOverlayDir = "/odm/overlay";
   static const char* kApkSuffix = ".apk";
 
   if ((android::base::StartsWith(path, kOverlayDir)
@@ -110,7 +112,9 @@
        || android::base::StartsWith(path, kSystemProductOverlayDir)
        || android::base::StartsWith(path, kProductOverlayDir)
        || android::base::StartsWith(path, kSystemProductServicesOverlayDir)
-       || android::base::StartsWith(path, kProductServicesOverlayDir))
+       || android::base::StartsWith(path, kProductServicesOverlayDir)
+       || android::base::StartsWith(path, kSystemOdmOverlayDir)
+       || android::base::StartsWith(path, kOdmOverlayDir))
       && android::base::EndsWith(path, kApkSuffix)
       && path.find("/../") == std::string::npos) {
     return true;
diff --git a/core/proto/android/app/settings_enums.proto b/core/proto/android/app/settings_enums.proto
index d029527..ace88f5 100644
--- a/core/proto/android/app/settings_enums.proto
+++ b/core/proto/android/app/settings_enums.proto
@@ -2331,4 +2331,9 @@
 
     // Open: Settings > app > bubble settings > confirmation dialog
     DIALOG_APP_BUBBLE_SETTINGS = 1702;
+
+    // ACTION: Display white balance setting enabled or disabled.
+    // CATEGORY: SETTINGS
+    // OS: Q
+    ACTION_DISPLAY_WHITE_BALANCE_SETTING_CHANGED = 1703;
 }
diff --git a/core/res/Android.bp b/core/res/Android.bp
index e66f1a2..4e60f8c 100644
--- a/core/res/Android.bp
+++ b/core/res/Android.bp
@@ -39,3 +39,12 @@
     // PRODUCT-agnostic resource data like IDs and type definitions.
     export_package_resources: true,
 }
+
+// This logic can be removed once robolectric's transition to binary resources is complete
+filegroup {
+    name: "robolectric_framework_raw_res_files",
+    srcs: [
+        "assets/**/*",
+        "res/**/*",
+    ],
+}
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index ec2a6ae..21f5acb 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1302,12 +1302,6 @@
     <!-- Disable lockscreen rotation by default -->
     <bool name="config_enableLockScreenRotation">false</bool>
 
-    <!-- Enable lockscreen translucent decor by default -->
-    <bool name="config_enableLockScreenTranslucentDecor">true</bool>
-
-    <!-- Enable translucent decor by default -->
-    <bool name="config_enableTranslucentDecor">true</bool>
-
     <!-- Is the device capable of hot swapping an UICC Card -->
     <bool name="config_hotswapCapable">false</bool>
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 4b8a96c..6f3adfd 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1434,7 +1434,7 @@
     <string name="permdesc_mediaLocation">Allows the app to read locations from your media collection.</string>
 
     <!-- Title shown when the system-provided biometric dialog is shown, asking the user to authenticate. [CHAR LIMIT=40] -->
-    <string name="biometric_dialog_default_title">Application <xliff:g id="app" example="Gmail">%s</xliff:g> wants to authenticate.</string>
+    <string name="biometric_dialog_default_title">Verify it\u2018s you</string>
     <!-- Message shown when biometric hardware is not available [CHAR LIMIT=50] -->
     <string name="biometric_error_hw_unavailable">Biometric hardware unavailable</string>
     <!-- Message shown when biometric authentication was canceled by the user [CHAR LIMIT=50] -->
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 3e23640..fb7be77 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1717,8 +1717,6 @@
   <java-symbol type="bool" name="config_enableCarDockHomeLaunch" />
   <java-symbol type="bool" name="config_enableLockBeforeUnlockScreen" />
   <java-symbol type="bool" name="config_enableLockScreenRotation" />
-  <java-symbol type="bool" name="config_enableLockScreenTranslucentDecor" />
-  <java-symbol type="bool" name="config_enableTranslucentDecor" />
   <java-symbol type="bool" name="config_forceShowSystemBars" />
   <java-symbol type="bool" name="config_lidControlsScreenLock" />
   <java-symbol type="bool" name="config_lidControlsSleep" />
diff --git a/core/tests/BroadcastRadioTests/Android.bp b/core/tests/BroadcastRadioTests/Android.bp
new file mode 100644
index 0000000..0aebaaa
--- /dev/null
+++ b/core/tests/BroadcastRadioTests/Android.bp
@@ -0,0 +1,35 @@
+// Copyright (C) 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+android_test {
+    name: "BroadcastRadioTests",
+    privileged: true,
+    certificate: "platform",
+    // TODO(b/13282254): uncomment when b/13282254 is fixed
+    // sdk_version: "current"
+    platform_apis: true,
+    static_libs: [
+        "compatibility-device-util-axt",
+        "androidx.test.rules",
+        "testng",
+    ],
+    libs: ["android.test.base"],
+    srcs: ["src/**/*.java"],
+    dex_preopt: {
+        enabled: false,
+    },
+    optimize: {
+        enabled: false,
+    },
+}
diff --git a/core/tests/BroadcastRadioTests/Android.mk b/core/tests/BroadcastRadioTests/Android.mk
deleted file mode 100644
index faffc4b..0000000
--- a/core/tests/BroadcastRadioTests/Android.mk
+++ /dev/null
@@ -1,38 +0,0 @@
-# Copyright (C) 2017 The Android Open Source Project
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-LOCAL_PATH:= $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_PACKAGE_NAME := BroadcastRadioTests
-
-LOCAL_PRIVILEGED_MODULE := true
-LOCAL_CERTIFICATE := platform
-LOCAL_MODULE_TAGS := tests
-# TODO(b/13282254): uncomment when b/13282254 is fixed
-# LOCAL_SDK_VERSION := current
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_STATIC_JAVA_LIBRARIES := compatibility-device-util-axt androidx.test.rules testng
-
-LOCAL_JAVA_LIBRARIES := android.test.base
-
-LOCAL_MODULE_PATH := $(TARGET_OUT_DATA_APPS)
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-
-LOCAL_DEX_PREOPT := false
-LOCAL_PROGUARD_ENABLED := disabled
-
-include $(BUILD_PACKAGE)
diff --git a/core/tests/coretests/src/android/app/ApplicationLoadersTest.java b/core/tests/coretests/src/android/app/ApplicationLoadersTest.java
new file mode 100644
index 0000000..4b9910c
--- /dev/null
+++ b/core/tests/coretests/src/android/app/ApplicationLoadersTest.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.app;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+import android.content.pm.SharedLibraryInfo;
+
+import androidx.test.filters.SmallTest;
+import androidx.test.runner.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class ApplicationLoadersTest {
+
+    // a library installed onto the device with no dependencies
+    private static final String LIB_A = "/system/framework/android.hidl.base-V1.0-java.jar";
+    // a library installed onto the device which only depends on A
+    private static final String LIB_DEP_A = "/system/framework/android.hidl.manager-V1.0-java.jar";
+
+    private static SharedLibraryInfo createLib(String zip) {
+        return new SharedLibraryInfo(
+                zip, null /*packageName*/, null /*codePaths*/, null /*name*/, 0 /*version*/,
+                SharedLibraryInfo.TYPE_BUILTIN, null /*declaringPackage*/,
+                null /*dependentPackages*/, null /*dependencies*/);
+    }
+
+    @Test
+    public void testGetNonExistantLib() {
+        ApplicationLoaders loaders = new ApplicationLoaders();
+        assertEquals(null, loaders.getCachedNonBootclasspathSystemLib(
+                "/system/framework/nonexistantlib.jar", null, null, null));
+    }
+
+    @Test
+    public void testCacheExistantLib() {
+        ApplicationLoaders loaders = new ApplicationLoaders();
+        SharedLibraryInfo libA = createLib(LIB_A);
+
+        loaders.createAndCacheNonBootclasspathSystemClassLoaders(new SharedLibraryInfo[]{libA});
+
+        assertNotEquals(null, loaders.getCachedNonBootclasspathSystemLib(
+                LIB_A, null, null, null));
+    }
+
+    @Test
+    public void testNonNullParent() {
+        ApplicationLoaders loaders = new ApplicationLoaders();
+        SharedLibraryInfo libA = createLib(LIB_A);
+
+        ClassLoader parent = ClassLoader.getSystemClassLoader();
+        assertNotEquals(null, parent);
+
+        loaders.createAndCacheNonBootclasspathSystemClassLoaders(new SharedLibraryInfo[]{libA});
+
+        assertEquals(null, loaders.getCachedNonBootclasspathSystemLib(
+                LIB_A, parent, null, null));
+    }
+
+    @Test
+    public void testNonNullClassLoaderNamespace() {
+        ApplicationLoaders loaders = new ApplicationLoaders();
+        SharedLibraryInfo libA = createLib(LIB_A);
+
+        loaders.createAndCacheNonBootclasspathSystemClassLoaders(new SharedLibraryInfo[]{libA});
+
+        assertEquals(null, loaders.getCachedNonBootclasspathSystemLib(
+                LIB_A, null, "other classloader", null));
+    }
+
+    @Test
+    public void testDifferentSharedLibraries() {
+        ApplicationLoaders loaders = new ApplicationLoaders();
+        SharedLibraryInfo libA = createLib(LIB_A);
+
+        // any other existant lib
+        ClassLoader dep = ClassLoader.getSystemClassLoader();
+        ArrayList<ClassLoader> sharedLibraries = new ArrayList<>();
+        sharedLibraries.add(dep);
+
+        loaders.createAndCacheNonBootclasspathSystemClassLoaders(new SharedLibraryInfo[]{libA});
+
+        assertEquals(null, loaders.getCachedNonBootclasspathSystemLib(
+                LIB_A, null, null, sharedLibraries));
+    }
+
+    @Test
+    public void testDependentLibs() {
+        ApplicationLoaders loaders = new ApplicationLoaders();
+        SharedLibraryInfo libA = createLib(LIB_A);
+        SharedLibraryInfo libB = createLib(LIB_DEP_A);
+        libB.addDependency(libA);
+
+        loaders.createAndCacheNonBootclasspathSystemClassLoaders(
+                new SharedLibraryInfo[]{libA, libB});
+
+        ClassLoader loadA = loaders.getCachedNonBootclasspathSystemLib(
+                LIB_A, null, null, null);
+        assertNotEquals(null, loadA);
+
+        ArrayList<ClassLoader> sharedLibraries = new ArrayList<>();
+        sharedLibraries.add(loadA);
+
+        assertNotEquals(null, loaders.getCachedNonBootclasspathSystemLib(
+                LIB_DEP_A, null, null, sharedLibraries));
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void testDependentLibsWrongOrder() {
+        ApplicationLoaders loaders = new ApplicationLoaders();
+        SharedLibraryInfo libA = createLib(LIB_A);
+        SharedLibraryInfo libB = createLib(LIB_DEP_A);
+        libB.addDependency(libA);
+
+        loaders.createAndCacheNonBootclasspathSystemClassLoaders(
+                new SharedLibraryInfo[]{libB, libA});
+    }
+}
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
index 185fa07..00b4a22 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserActivityTest.java
@@ -39,6 +39,7 @@
 import android.content.ClipData;
 import android.content.ClipDescription;
 import android.content.ClipboardManager;
+import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ResolveInfo;
@@ -47,8 +48,10 @@
 import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Paint;
+import android.graphics.drawable.Icon;
 import android.metrics.LogMaker;
 import android.net.Uri;
+import android.service.chooser.ChooserTarget;
 
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.platform.app.InstrumentationRegistry;
@@ -735,6 +738,120 @@
         onView(withId(R.id.content_preview_file_icon)).check(matches(isDisplayed()));
     }
 
+    // This test is too long and too slow and should not be taken as an example for future tests.
+    // This is necessary because it tests that multiple calls result in the same result but
+    // normally a test this long should be broken into smaller tests testing individual components.
+    @Test
+    public void testDirectTargetSelectionLogging() throws InterruptedException {
+        Intent sendIntent = createSendTextIntent();
+        // We need app targets for direct targets to get displayed
+        List<ResolvedComponentInfo> resolvedComponentInfos = createResolvedComponentsForTest(2);
+        when(sOverrides.resolverListController.getResolversForIntent(Mockito.anyBoolean(),
+                Mockito.anyBoolean(),
+                Mockito.isA(List.class))).thenReturn(resolvedComponentInfos);
+
+        // Set up resources
+        MetricsLogger mockLogger = sOverrides.metricsLogger;
+        ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
+        // Create direct share target
+        List<ChooserTarget> serviceTargets = createDirectShareTargets(1);
+        ResolveInfo ri = ResolverDataProvider.createResolveInfo(3, 0);
+
+        // Start activity
+        final ChooserWrapperActivity activity = mActivityRule
+                .launchActivity(Intent.createChooser(sendIntent, null));
+
+        // Insert the direct share target
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(
+                () -> activity.getAdapter().addServiceResults(
+                        activity.createTestDisplayResolveInfo(sendIntent,
+                                ri,
+                                "testLabel",
+                                "testInfo",
+                                sendIntent),
+                        serviceTargets,
+                        false)
+        );
+        // Thread.sleep shouldn't be a thing in an integration test but it's
+        // necessary here because of the way the code is structured
+        // TODO: restructure the tests b/129870719
+        Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);
+
+        assertThat("Chooser should have 3 targets (2apps, 1 direct)",
+                activity.getAdapter().getCount(), is(3));
+        assertThat("Chooser should have exactly one selectable direct target",
+                activity.getAdapter().getSelectableServiceTargetCount(), is(1));
+        assertThat("The resolver info must match the resolver info used to create the target",
+                activity.getAdapter().getItem(0).getResolveInfo(), is(ri));
+
+        // Click on the direct target
+        String name = serviceTargets.get(0).getTitle().toString();
+        onView(withText(name))
+                .perform(click());
+        waitForIdle();
+
+        // Currently we're seeing 3 invocations
+        //      1. ChooserActivity.onCreate()
+        //      2. ChooserActivity$ChooserRowAdapter.createContentPreviewView()
+        //      3. ChooserActivity.startSelected -- which is the one we're after
+        verify(mockLogger, Mockito.times(3)).write(logMakerCaptor.capture());
+        assertThat(logMakerCaptor.getAllValues().get(2).getCategory(),
+                is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET));
+        String hashedName = (String) logMakerCaptor
+                .getAllValues().get(2).getTaggedData(MetricsEvent.FIELD_HASHED_TARGET_NAME);
+        assertThat("Hash is not predictable but must be obfuscated",
+                hashedName, is(not(name)));
+
+        // Running the same again to check if the hashed name is the same as before.
+
+        Intent sendIntent2 = createSendTextIntent();
+
+        // Start activity
+        final ChooserWrapperActivity activity2 = mActivityRule
+                .launchActivity(Intent.createChooser(sendIntent2, null));
+        waitForIdle();
+
+        // Insert the direct share target
+        InstrumentationRegistry.getInstrumentation().runOnMainSync(
+                () -> activity2.getAdapter().addServiceResults(
+                        activity2.createTestDisplayResolveInfo(sendIntent,
+                                ri,
+                                "testLabel",
+                                "testInfo",
+                                sendIntent),
+                        serviceTargets,
+                        false)
+        );
+        // Thread.sleep shouldn't be a thing in an integration test but it's
+        // necessary here because of the way the code is structured
+        // TODO: restructure the tests b/129870719
+        Thread.sleep(ChooserActivity.LIST_VIEW_UPDATE_INTERVAL_IN_MILLIS);
+
+        assertThat("Chooser should have 3 targets (2apps, 1 direct)",
+                activity2.getAdapter().getCount(), is(3));
+        assertThat("Chooser should have exactly one selectable direct target",
+                activity2.getAdapter().getSelectableServiceTargetCount(), is(1));
+        assertThat("The resolver info must match the resolver info used to create the target",
+                activity2.getAdapter().getItem(0).getResolveInfo(), is(ri));
+
+        // Click on the direct target
+        onView(withText(name))
+                .perform(click());
+        waitForIdle();
+
+        // Currently we're seeing 6 invocations (3 from above, doubled up)
+        //      4. ChooserActivity.onCreate()
+        //      5. ChooserActivity$ChooserRowAdapter.createContentPreviewView()
+        //      6. ChooserActivity.startSelected -- which is the one we're after
+        verify(mockLogger, Mockito.times(6)).write(logMakerCaptor.capture());
+        assertThat(logMakerCaptor.getAllValues().get(5).getCategory(),
+                is(MetricsEvent.ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET));
+        String hashedName2 = (String) logMakerCaptor
+                .getAllValues().get(5).getTaggedData(MetricsEvent.FIELD_HASHED_TARGET_NAME);
+        assertThat("Hashing the same name should result in the same hashed value",
+                hashedName2, is(hashedName));
+    }
+
     private Intent createSendTextIntent() {
         Intent sendIntent = new Intent();
         sendIntent.setAction(Intent.ACTION_SEND);
@@ -798,6 +915,23 @@
         return infoList;
     }
 
+    private List<ChooserTarget> createDirectShareTargets(int numberOfResults) {
+        Icon icon = Icon.createWithBitmap(createBitmap());
+        String testTitle = "testTitle";
+        List<ChooserTarget> targets = new ArrayList<>();
+        for (int i = 0; i < numberOfResults; i++) {
+            ComponentName componentName = ResolverDataProvider.createComponentName(i);
+            ChooserTarget tempTarget = new ChooserTarget(
+                    testTitle + i,
+                    icon,
+                    (float) (1 - ((i + 1) / 10.0)),
+                    componentName,
+                    null);
+            targets.add(tempTarget);
+        }
+        return targets;
+    }
+
     private void waitForIdle() {
         InstrumentationRegistry.getInstrumentation().waitForIdleSync();
     }
diff --git a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
index 5e71129..44e56ea 100644
--- a/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
+++ b/core/tests/coretests/src/com/android/internal/app/ChooserWrapperActivity.java
@@ -21,7 +21,9 @@
 import android.app.usage.UsageStatsManager;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.database.Cursor;
 import android.graphics.Bitmap;
 import android.net.Uri;
@@ -121,6 +123,11 @@
         return super.isWorkProfile();
     }
 
+    public DisplayResolveInfo createTestDisplayResolveInfo(Intent originalIntent, ResolveInfo pri,
+            CharSequence pLabel, CharSequence pInfo, Intent pOrigIntent) {
+        return new DisplayResolveInfo(originalIntent, pri, pLabel, pInfo, pOrigIntent);
+    }
+
     /**
      * We cannot directly mock the activity created since instrumentation creates it.
      * <p>
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index 626bbf00..072beae 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -100,36 +100,6 @@
         <font weight="400" style="normal">CarroisGothicSC-Regular.ttf</font>
     </family>
 
-    <family name="arbutus-slab">
-        <font weight="400" style="normal">ArbutusSlab-Regular.ttf</font>
-    </family>
-
-    <family name="arvo">
-        <font weight="400" style="normal">Arvo-Regular.ttf</font>
-        <font weight="400" style="italic">Arvo-Italic.ttf</font>
-        <font weight="700" style="normal">Arvo-Bold.ttf</font>
-        <font weight="700" style="italic">Arvo-BoldItalic.ttf</font>
-    </family>
-    <alias name="arvo-bold" to="arvo" weight="700" />
-
-    <family name="lato">
-        <font weight="400" style="normal">Lato-Regular.ttf</font>
-        <font weight="400" style="italic">Lato-Italic.ttf</font>
-        <font weight="700" style="normal">Lato-Bold.ttf</font>
-        <font weight="700" style="italic">Lato-BoldItalic.ttf</font>
-    </family>
-    <alias name="lato-bold" to="lato" weight="700" />
-
-    <family name="rubik">
-        <font weight="400" style="normal">Rubik-Regular.ttf</font>
-        <font weight="400" style="italic">Rubik-Italic.ttf</font>
-        <font weight="500" style="normal">Rubik-Medium.ttf</font>
-        <font weight="500" style="italic">Rubik-MediumItalic.ttf</font>
-        <font weight="700" style="normal">Rubik-Bold.ttf</font>
-        <font weight="700" style="italic">Rubik-BoldItalic.ttf</font>
-    </family>
-    <alias name="rubik-medium" to="rubik" weight="500" />
-
     <family name="source-sans-pro">
         <font weight="400" style="normal">SourceSansPro-Regular.ttf</font>
         <font weight="400" style="italic">SourceSansPro-Italic.ttf</font>
diff --git a/libs/androidfw/Asset.cpp b/libs/androidfw/Asset.cpp
index 9a95fdf..92125c9 100644
--- a/libs/androidfw/Asset.cpp
+++ b/libs/androidfw/Asset.cpp
@@ -253,8 +253,10 @@
 
     pAsset = new _FileAsset;
     result = pAsset->openChunk(NULL, fd, offset, length);
-    if (result != NO_ERROR)
+    if (result != NO_ERROR) {
+        delete pAsset;
         return NULL;
+    }
 
     pAsset->mAccessMode = mode;
     return pAsset;
@@ -273,8 +275,10 @@
     pAsset = new _CompressedAsset;
     result = pAsset->openChunk(fd, offset, compressionMethod,
                 uncompressedLen, compressedLen);
-    if (result != NO_ERROR)
+    if (result != NO_ERROR) {
+        delete pAsset;
         return NULL;
+    }
 
     pAsset->mAccessMode = mode;
     return pAsset;
@@ -328,8 +332,10 @@
 
     pAsset = new _CompressedAsset;
     result = pAsset->openChunk(dataMap, uncompressedLen);
-    if (result != NO_ERROR)
+    if (result != NO_ERROR) {
+        delete pAsset;
         return NULL;
+    }
 
     pAsset->mAccessMode = mode;
     return pAsset;
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index 365be10..21609d3 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -75,6 +75,7 @@
 const char* AssetManager::VENDOR_OVERLAY_DIR = "/vendor/overlay";
 const char* AssetManager::PRODUCT_OVERLAY_DIR = "/product/overlay";
 const char* AssetManager::PRODUCT_SERVICES_OVERLAY_DIR = "/product_services/overlay";
+const char* AssetManager::ODM_OVERLAY_DIR = "/odm/overlay";
 const char* AssetManager::OVERLAY_THEME_DIR_PROPERTY = "ro.boot.vendor.overlay.theme";
 const char* AssetManager::TARGET_PACKAGE_NAME = "android";
 const char* AssetManager::TARGET_APK_PATH = "/system/framework/framework-res.apk";
diff --git a/libs/androidfw/OWNERS b/libs/androidfw/OWNERS
index f1903a5..87b1467 100644
--- a/libs/androidfw/OWNERS
+++ b/libs/androidfw/OWNERS
@@ -1,3 +1,5 @@
 set noparent
 toddke@google.com
-rtmitchell@google.com
\ No newline at end of file
+rtmitchell@google.com
+
+per-file CursorWindow.cpp=omakoto@google.com
diff --git a/libs/androidfw/include/androidfw/AssetManager.h b/libs/androidfw/include/androidfw/AssetManager.h
index e22e2d2..a015eab 100644
--- a/libs/androidfw/include/androidfw/AssetManager.h
+++ b/libs/androidfw/include/androidfw/AssetManager.h
@@ -62,6 +62,7 @@
     static const char* VENDOR_OVERLAY_DIR;
     static const char* PRODUCT_OVERLAY_DIR;
     static const char* PRODUCT_SERVICES_OVERLAY_DIR;
+    static const char* ODM_OVERLAY_DIR;
     /*
      * If OVERLAY_THEME_DIR_PROPERTY is set, search for runtime resource overlay
      * APKs in VENDOR_OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in
diff --git a/media/java/android/media/AudioAttributes.java b/media/java/android/media/AudioAttributes.java
index a3eee0a..55f1911 100644
--- a/media/java/android/media/AudioAttributes.java
+++ b/media/java/android/media/AudioAttributes.java
@@ -388,9 +388,10 @@
      */
     public static final int FLAG_NO_SYSTEM_CAPTURE = 0x1 << 12;
 
-    private final static int FLAG_ALL = FLAG_AUDIBILITY_ENFORCED | FLAG_SECURE | FLAG_SCO |
-            FLAG_BEACON | FLAG_HW_AV_SYNC | FLAG_HW_HOTWORD | FLAG_BYPASS_INTERRUPTION_POLICY |
-            FLAG_BYPASS_MUTE | FLAG_LOW_LATENCY | FLAG_DEEP_BUFFER | FLAG_MUTE_HAPTIC;
+    private static final int FLAG_ALL = FLAG_AUDIBILITY_ENFORCED | FLAG_SECURE | FLAG_SCO
+            | FLAG_BEACON | FLAG_HW_AV_SYNC | FLAG_HW_HOTWORD | FLAG_BYPASS_INTERRUPTION_POLICY
+            | FLAG_BYPASS_MUTE | FLAG_LOW_LATENCY | FLAG_DEEP_BUFFER | FLAG_NO_MEDIA_PROJECTION
+            | FLAG_MUTE_HAPTIC | FLAG_NO_SYSTEM_CAPTURE;
     private final static int FLAG_ALL_PUBLIC = FLAG_AUDIBILITY_ENFORCED |
             FLAG_HW_AV_SYNC | FLAG_LOW_LATENCY;
 
diff --git a/native/android/libandroid.map.txt b/native/android/libandroid.map.txt
index 1f2480b..177f2b8 100644
--- a/native/android/libandroid.map.txt
+++ b/native/android/libandroid.map.txt
@@ -248,16 +248,21 @@
     ASystemFontIterator_open; # introduced=29
     ASystemFontIterator_close; # introduced=29
     ASystemFontIterator_next; # introduced=29
-    ASystemFont_close; # introduced=29
-    ASystemFont_getFontFilePath; # introduced=29
-    ASystemFont_getWeight; # introduced=29
-    ASystemFont_isItalic; # introduced=29
-    ASystemFont_getLocale; # introduced=29
-    ASystemFont_getCollectionIndex; # introduced=29
-    ASystemFont_getAxisCount; # introduced=29
-    ASystemFont_getAxisTag; # introduced=29
-    ASystemFont_getAxisValue; # introduced=29
-    ASystemFont_matchFamilyStyleCharacter; # introduced=29
+    AFont_close; # introduced=29
+    AFont_getFontFilePath; # introduced=29
+    AFont_getWeight; # introduced=29
+    AFont_isItalic; # introduced=29
+    AFont_getLocale; # introduced=29
+    AFont_getCollectionIndex; # introduced=29
+    AFont_getAxisCount; # introduced=29
+    AFont_getAxisTag; # introduced=29
+    AFont_getAxisValue; # introduced=29
+    AFontMatcher_create; # introduced=29
+    AFontMatcher_destroy; # introduced=29
+    AFontMatcher_setStyle; # introduced=29
+    AFontMatcher_setLocales; # introduced=29
+    AFontMatcher_setFamilyVariant; # introduced=29
+    AFontMatcher_match; # introduced=29
     ATrace_beginSection; # introduced=23
     ATrace_endSection; # introduced=23
     ATrace_isEnabled; # introduced=23
diff --git a/native/android/system_fonts.cpp b/native/android/system_fonts.cpp
index 4d3d1d6..302cbd1 100644
--- a/native/android/system_fonts.cpp
+++ b/native/android/system_fonts.cpp
@@ -16,6 +16,8 @@
 
 #include <jni.h>
 
+#include <android/font.h>
+#include <android/font_matcher.h>
 #include <android/system_fonts.h>
 
 #include <memory>
@@ -53,7 +55,7 @@
     XmlDocUniquePtr mCustomizationXmlDoc;
 };
 
-struct ASystemFont {
+struct AFont {
     std::string mFilePath;
     std::unique_ptr<std::string> mLocale;
     uint16_t mWeight;
@@ -62,6 +64,19 @@
     std::vector<std::pair<uint32_t, float>> mAxes;
 };
 
+struct AFontMatcher {
+    minikin::FontStyle mFontStyle;
+    uint32_t mLocaleListId = 0;  // 0 is reserved for empty locale ID.
+    bool mFamilyVariant = AFAMILY_VARIANT_DEFAULT;
+};
+
+static_assert(static_cast<uint32_t>(AFAMILY_VARIANT_DEFAULT) ==
+              static_cast<uint32_t>(minikin::FamilyVariant::DEFAULT));
+static_assert(static_cast<uint32_t>(AFAMILY_VARIANT_COMPACT) ==
+              static_cast<uint32_t>(minikin::FamilyVariant::COMPACT));
+static_assert(static_cast<uint32_t>(AFAMILY_VARIANT_ELEGANT) ==
+              static_cast<uint32_t>(minikin::FamilyVariant::ELEGANT));
+
 namespace {
 
 std::string xmlTrim(const std::string& in) {
@@ -101,7 +116,7 @@
     return nullptr;
 }
 
-void copyFont(const XmlDocUniquePtr& xmlDoc, xmlNode* fontNode, ASystemFont* out,
+void copyFont(const XmlDocUniquePtr& xmlDoc, xmlNode* fontNode, AFont* out,
               const std::string& pathPrefix) {
     const xmlChar* LOCALE_ATTR_NAME = BAD_CAST("lang");
     XmlCharUniquePtr filePathStr(
@@ -197,24 +212,48 @@
     delete ite;
 }
 
-ASystemFont* ASystemFont_matchFamilyStyleCharacter(
-        const char* _Nonnull familyName,
+AFontMatcher* _Nonnull AFontMatcher_create() {
+    return new AFontMatcher();
+}
+
+void AFontMatcher_destroy(AFontMatcher* matcher) {
+    delete matcher;
+}
+
+void AFontMatcher_setStyle(
+        AFontMatcher* _Nonnull matcher,
         uint16_t weight,
-        bool italic,
-        const char* _Nonnull languageTags,
+        bool italic) {
+    matcher->mFontStyle = minikin::FontStyle(
+            weight, static_cast<minikin::FontStyle::Slant>(italic));
+}
+
+void AFontMatcher_setLocales(
+        AFontMatcher* _Nonnull matcher,
+        const char* _Nonnull languageTags) {
+    matcher->mLocaleListId = minikin::registerLocaleList(languageTags);
+}
+
+void AFontMatcher_setFamilyVariant(AFontMatcher* _Nonnull matcher, uint32_t familyVariant) {
+    matcher->mFamilyVariant = familyVariant;
+}
+
+AFont* _Nonnull AFontMatcher_match(
+        const AFontMatcher* _Nonnull matcher,
+        const char* _Nonnull familyName,
         const uint16_t* _Nonnull text,
-        uint32_t textLength,
+        const uint32_t textLength,
         uint32_t* _Nullable runLength) {
     std::shared_ptr<minikin::FontCollection> fc =
             minikin::SystemFonts::findFontCollection(familyName);
-    std::vector<minikin::FontCollection::Run> runs =
-            fc->itemize(minikin::U16StringPiece(text, textLength),
-                        minikin::FontStyle(weight, static_cast<minikin::FontStyle::Slant>(italic)),
-                        minikin::registerLocaleList(languageTags),
-                        minikin::FamilyVariant::DEFAULT);
+    std::vector<minikin::FontCollection::Run> runs = fc->itemize(
+                minikin::U16StringPiece(text, textLength),
+                matcher->mFontStyle,
+                matcher->mLocaleListId,
+                static_cast<minikin::FamilyVariant>(matcher->mFamilyVariant));
 
     const minikin::Font* font = runs[0].fakedFont.font;
-    std::unique_ptr<ASystemFont> result = std::make_unique<ASystemFont>();
+    std::unique_ptr<AFont> result = std::make_unique<AFont>();
     const android::MinikinFontSkia* minikinFontSkia =
             reinterpret_cast<android::MinikinFontSkia*>(font->typeface().get());
     result->mFilePath = minikinFontSkia->getFilePath();
@@ -253,7 +292,7 @@
     }
 }
 
-ASystemFont* ASystemFontIterator_next(ASystemFontIterator* ite) {
+AFont* ASystemFontIterator_next(ASystemFontIterator* ite) {
     LOG_ALWAYS_FATAL_IF(ite == nullptr, "nullptr has passed as iterator argument");
     if (ite->mXmlDoc) {
         ite->mFontNode = findNextFontNode(ite->mXmlDoc, ite->mFontNode);
@@ -262,7 +301,7 @@
             ite->mXmlDoc.reset();
             ite->mFontNode = nullptr;
         } else {
-            std::unique_ptr<ASystemFont> font = std::make_unique<ASystemFont>();
+            std::unique_ptr<AFont> font = std::make_unique<AFont>();
             copyFont(ite->mXmlDoc, ite->mFontNode, font.get(), "/system/fonts/");
             if (!isFontFileAvailable(font->mFilePath)) {
                 return ASystemFontIterator_next(ite);
@@ -279,7 +318,7 @@
             ite->mFontNode = nullptr;
             return nullptr;
         } else {
-            std::unique_ptr<ASystemFont> font = std::make_unique<ASystemFont>();
+            std::unique_ptr<AFont> font = std::make_unique<AFont>();
             copyFont(ite->mCustomizationXmlDoc, ite->mFontNode, font.get(), "/product/fonts/");
             if (!isFontFileAvailable(font->mFilePath)) {
                 return ASystemFontIterator_next(ite);
@@ -290,48 +329,48 @@
     return nullptr;
 }
 
-void ASystemFont_close(ASystemFont* font) {
+void AFont_close(AFont* font) {
     delete font;
 }
 
-const char* ASystemFont_getFontFilePath(const ASystemFont* font) {
+const char* AFont_getFontFilePath(const AFont* font) {
     LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed as font argument");
     return font->mFilePath.c_str();
 }
 
-uint16_t ASystemFont_getWeight(const ASystemFont* font) {
+uint16_t AFont_getWeight(const AFont* font) {
     LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed as font argument");
     return font->mWeight;
 }
 
-bool ASystemFont_isItalic(const ASystemFont* font) {
+bool AFont_isItalic(const AFont* font) {
     LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed as font argument");
     return font->mItalic;
 }
 
-const char* ASystemFont_getLocale(const ASystemFont* font) {
+const char* AFont_getLocale(const AFont* font) {
     LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed to font argument");
     return font->mLocale ? nullptr : font->mLocale->c_str();
 }
 
-size_t ASystemFont_getCollectionIndex(const ASystemFont* font) {
+size_t AFont_getCollectionIndex(const AFont* font) {
     LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed to font argument");
     return font->mCollectionIndex;
 }
 
-size_t ASystemFont_getAxisCount(const ASystemFont* font) {
+size_t AFont_getAxisCount(const AFont* font) {
     LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed to font argument");
     return font->mAxes.size();
 }
 
-uint32_t ASystemFont_getAxisTag(const ASystemFont* font, uint32_t axisIndex) {
+uint32_t AFont_getAxisTag(const AFont* font, uint32_t axisIndex) {
     LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed to font argument");
     LOG_ALWAYS_FATAL_IF(axisIndex >= font->mAxes.size(),
                         "given axis index is out of bounds. (< %zd", font->mAxes.size());
     return font->mAxes[axisIndex].first;
 }
 
-float ASystemFont_getAxisValue(const ASystemFont* font, uint32_t axisIndex) {
+float AFont_getAxisValue(const AFont* font, uint32_t axisIndex) {
     LOG_ALWAYS_FATAL_IF(font == nullptr, "nullptr has passed to font argument");
     LOG_ALWAYS_FATAL_IF(axisIndex >= font->mAxes.size(),
                         "given axis index is out of bounds. (< %zd", font->mAxes.size());
diff --git a/packages/NetworkStack/tests/Android.bp b/packages/NetworkStack/tests/Android.bp
index 0535af3..d0f419c 100644
--- a/packages/NetworkStack/tests/Android.bp
+++ b/packages/NetworkStack/tests/Android.bp
@@ -42,6 +42,7 @@
         "libbinder",
         "libbinderthreadstate",
         "libc++",
+        "libcgrouprc",
         "libcrypto",
         "libcutils",
         "libdexfile",
diff --git a/packages/SettingsLib/HelpUtils/res/drawable/ic_help_actionbar.xml b/packages/SettingsLib/HelpUtils/res/drawable/ic_help_actionbar.xml
index 9089a93..1a4b1c3 100644
--- a/packages/SettingsLib/HelpUtils/res/drawable/ic_help_actionbar.xml
+++ b/packages/SettingsLib/HelpUtils/res/drawable/ic_help_actionbar.xml
@@ -20,6 +20,7 @@
         android:height="24dp"
         android:viewportWidth="24.0"
         android:viewportHeight="24.0"
+        android:autoMirrored="true"
         android:tint="?android:attr/colorControlNormal">
     <path
         android:fillColor="#FFFFFFFF"
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java
index 9feacac..eeb6cb0 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java
@@ -75,20 +75,32 @@
             return true;
         }
 
+        if (isDefaultActiveApp(pkg)) {
+            return true;
+        }
+
+        return false;
+    }
+
+    /**
+     * Check if it is default active app in multiple area(i.e. SMS, Dialer, Device admin..)
+     */
+    public boolean isDefaultActiveApp(String pkg) {
         // Additionally, check if pkg is default dialer/sms. They are considered essential apps and
         // should be automatically whitelisted (otherwise user may be able to set restriction on
         // them, leading to bad device behavior.)
-        if (!mAppContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY)) {
-            return false;
-        }
+
+        final boolean hasTelephony = mAppContext.getPackageManager().hasSystemFeature(
+                PackageManager.FEATURE_TELEPHONY);
         final ComponentName defaultSms = SmsApplication.getDefaultSmsApplication(mAppContext,
                 true /* updateIfNeeded */);
-        if (defaultSms != null && TextUtils.equals(pkg, defaultSms.getPackageName())) {
+        if (hasTelephony && defaultSms != null && TextUtils.equals(pkg,
+                defaultSms.getPackageName())) {
             return true;
         }
 
         final String defaultDialer = DefaultDialerManager.getDefaultDialerApplication(mAppContext);
-        if (TextUtils.equals(pkg, defaultDialer)) {
+        if (hasTelephony && TextUtils.equals(pkg, defaultDialer)) {
             return true;
         }
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt b/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt
index 239b1d4..eff02d2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt
+++ b/packages/SettingsLib/src/com/android/settingslib/graph/ThemedBatteryDrawable.kt
@@ -173,6 +173,7 @@
     }
 
     override fun draw(c: Canvas) {
+        c.saveLayer(null, null)
         unifiedPath.reset()
         levelPath.reset()
         levelRect.set(fillRect)
@@ -243,6 +244,7 @@
             // And draw the plus sign on top of the fill
             c.drawPath(scaledPlus, errorPaint)
         }
+        c.restore()
     }
 
     private fun batteryColorForLevel(level: Int): Int {
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
index bbf807d2..44ee423 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
@@ -118,6 +118,7 @@
         ShadowSmsApplication.setDefaultSmsApplication(new ComponentName(testSms, "receiver"));
 
         assertThat(mPowerWhitelistBackend.isWhitelisted(testSms)).isTrue();
+        assertThat(mPowerWhitelistBackend.isDefaultActiveApp(testSms)).isTrue();
     }
 
     @Test
@@ -126,6 +127,7 @@
         ShadowDefaultDialerManager.setDefaultDialerApplication(testDialer);
 
         assertThat(mPowerWhitelistBackend.isWhitelisted(testDialer)).isTrue();
+        assertThat(mPowerWhitelistBackend.isDefaultActiveApp(testDialer)).isTrue();
     }
 
     @Test
@@ -133,6 +135,7 @@
         doReturn(true).when(mDevicePolicyManager).packageHasActiveAdmins(PACKAGE_ONE);
 
         assertThat(mPowerWhitelistBackend.isWhitelisted(PACKAGE_ONE)).isTrue();
+        assertThat(mPowerWhitelistBackend.isDefaultActiveApp(PACKAGE_ONE)).isTrue();
     }
 
     @Test
diff --git a/packages/SystemUI/res-keyguard/values/alias.xml b/packages/SystemUI/res-keyguard/values/alias.xml
index 1c63c79..6d49b1f 100644
--- a/packages/SystemUI/res-keyguard/values/alias.xml
+++ b/packages/SystemUI/res-keyguard/values/alias.xml
@@ -28,9 +28,6 @@
     <!-- Alias used to reference framework configuration for screen rotation.  -->
     <item type="bool" name="config_enableLockScreenRotation">@*android:bool/config_enableLockScreenRotation</item>
 
-    <!-- Alias used to reference framework configuration for translucent decor.  -->
-    <item type="bool" name="config_enableLockScreenTranslucentDecor">@*android:bool/config_enableLockScreenTranslucentDecor</item>
-
     <!-- Alias used to reference framework activity duration.  -->
     <item type="integer" name="config_activityDefaultDur">@*android:integer/config_activityDefaultDur</item>
 
diff --git a/packages/SystemUI/res/drawable/ic_notification_gentle.xml b/packages/SystemUI/res/drawable/ic_notification_gentle.xml
new file mode 100644
index 0000000..7074130
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_notification_gentle.xml
@@ -0,0 +1,40 @@
+<!--
+Copyright (C) 2019 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:id="@+id/back">
+        <shape android:shape="oval">
+            <solid
+                android:color="@color/GM2_green_500" />
+            <size
+                android:height="36dp"
+                android:width="36dp"/>
+        </shape>
+    </item>
+    <item
+        android:id="@+id/fore"
+        android:gravity="center">
+        <vector
+                android:width="32dp"
+                android:height="32dp"
+                android:viewportWidth="24"
+                android:viewportHeight="24">
+            <path
+                android:fillColor="#FFFFFFFF"
+                android:pathData="M15,14.5c-1.38,0 -2.5,-1.12 -2.5,-2.5c0,-0.28 -0.22,-0.5 -0.5,-0.5s-0.5,0.22 -0.5,0.5c0,1.38 -1.12,2.5 -2.5,2.5S6.5,13.38 6.5,12c0,-0.28 -0.22,-0.5 -0.5,-0.5c-0.24,0 -0.46,0.18 -0.49,0.42C5.41,12.55 4.89,13 4.27,13H2v-2h1.71C4.1,10.11 5,9.5 6,9.5c1.38,0 2.5,1.12 2.5,2.5c0,0.28 0.22,0.5 0.5,0.5s0.5,-0.22 0.5,-0.5c0,-1.38 1.12,-2.5 2.5,-2.5s2.5,1.12 2.5,2.5c0,0.28 0.22,0.5 0.5,0.5s0.5,-0.22 0.5,-0.5c0,-1.38 1.12,-2.5 2.5,-2.5c1.02,0 1.91,0.6 2.29,1.5H22v2h-2.27c-0.62,0 -1.14,-0.45 -1.23,-1.08c-0.04,-0.24 -0.25,-0.42 -0.49,-0.42c-0.28,0 -0.5,0.22 -0.5,0.5C17.5,13.38 16.38,14.5 15,14.5z"/>
+        </vector>
+    </item>
+</layer-list>
diff --git a/packages/SystemUI/res/drawable/ic_notification_interruptive.xml b/packages/SystemUI/res/drawable/ic_notification_interruptive.xml
new file mode 100644
index 0000000..0a8b3b8
--- /dev/null
+++ b/packages/SystemUI/res/drawable/ic_notification_interruptive.xml
@@ -0,0 +1,41 @@
+<!--
+Copyright (C) 2019 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+
+<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:id="@+id/back">
+        <shape android:shape="oval">
+            <solid
+                android:color="@color/GM2_yellow_500" />
+            <size
+                android:height="36dp"
+                android:width="36dp"/>
+        </shape>
+    </item>
+    <item
+        android:id="@+id/fore"
+        android:gravity="center">
+        <vector
+                android:width="32dp"
+                android:height="32dp"
+                android:viewportWidth="24"
+                android:viewportHeight="24">
+            <path
+                android:fillColor="#FFFFFFFF"
+                android:pathData="M8.98,16.65c-0.47,0 -0.91,-0.27 -1.12,-0.69l-1.93,-4.61L5.46,12.3c-0.21,0.43 -0.64,0.69 -1.12,0.69H2v-2h1.88l1,-2C5.1,8.56 5.52,8.3 6,8.3s0.9,0.26 1.12,0.69l1.73,4.14l2,-7c0.2,-0.46 0.65,-0.76 1.15,-0.76s0.95,0.3 1.15,0.76l0.04,0.12l1.96,6.88l1.7,-4.08c0.49,-0.98 1.84,-0.91 2.26,-0.06l1,2H22v2h-2.35c-0.47,0 -0.91,-0.27 -1.12,-0.7l-0.47,-0.95l-1.9,4.55c-0.25,0.5 -0.69,0.77 -1.18,0.75c-0.48,-0.01 -0.92,-0.31 -1.11,-0.76l-0.04,-0.12L12,9.37l-1.87,6.52c-0.19,0.45 -0.63,0.74 -1.11,0.76C9.01,16.65 9,16.65 8.98,16.65zM20.32,11.4L20.32,11.4C20.32,11.4 20.32,11.4 20.32,11.4z" />
+        </vector>
+    </item>
+</layer-list>
diff --git a/packages/SystemUI/res/layout/contextual.xml b/packages/SystemUI/res/layout/contextual.xml
index c8f0a24..9b6ccae 100644
--- a/packages/SystemUI/res/layout/contextual.xml
+++ b/packages/SystemUI/res/layout/contextual.xml
@@ -37,16 +37,10 @@
         android:paddingStart="@dimen/navigation_key_padding"
         android:paddingEnd="@dimen/navigation_key_padding"
     />
-    <com.android.systemui.statusbar.policy.KeyButtonView
-        android:id="@+id/ime_switcher"
+    <include layout="@layout/ime_switcher"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:layout_weight="0"
-        android:scaleType="center"
         android:visibility="invisible"
-        android:contentDescription="@string/accessibility_ime_switch_button"
-        android:paddingStart="@dimen/navigation_key_padding"
-        android:paddingEnd="@dimen/navigation_key_padding"
     />
     <com.android.systemui.statusbar.policy.KeyButtonView
         android:id="@+id/rotate_suggestion"
diff --git a/packages/SystemUI/res/layout/home_handle.xml b/packages/SystemUI/res/layout/home_handle.xml
index d950f39..7c5db10 100644
--- a/packages/SystemUI/res/layout/home_handle.xml
+++ b/packages/SystemUI/res/layout/home_handle.xml
@@ -21,5 +21,7 @@
     android:layout_width="@dimen/navigation_home_handle_width"
     android:layout_height="match_parent"
     android:layout_weight="0"
+    android:paddingStart="@dimen/navigation_key_padding"
+    android:paddingEnd="@dimen/navigation_key_padding"
     />
 
diff --git a/packages/SystemUI/res/layout/ime_switcher.xml b/packages/SystemUI/res/layout/ime_switcher.xml
new file mode 100644
index 0000000..7710b25
--- /dev/null
+++ b/packages/SystemUI/res/layout/ime_switcher.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+
+<com.android.systemui.statusbar.policy.KeyButtonView
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:id="@+id/ime_switcher"
+    android:layout_width="@dimen/navigation_key_width"
+    android:layout_height="match_parent"
+    android:layout_weight="0"
+    android:contentDescription="@string/accessibility_ime_switch_button"
+    android:scaleType="center"
+    android:paddingStart="@dimen/navigation_key_padding"
+    android:paddingEnd="@dimen/navigation_key_padding"
+    />
diff --git a/packages/SystemUI/res/layout/menu_ime.xml b/packages/SystemUI/res/layout/menu_ime.xml
index 8a3a0b1..24374e8 100644
--- a/packages/SystemUI/res/layout/menu_ime.xml
+++ b/packages/SystemUI/res/layout/menu_ime.xml
@@ -35,13 +35,13 @@
         android:visibility="invisible"
         android:contentDescription="@string/accessibility_menu"
         />
-    <com.android.systemui.statusbar.policy.KeyButtonView
-        android:id="@+id/ime_switcher"
+    <include layout="@layout/ime_switcher"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:visibility="invisible"
-        android:contentDescription="@string/accessibility_ime_switch_button"
         android:scaleType="centerInside"
+        android:visibility="invisible"
+        android:paddingStart="0dp"
+        android:paddingEnd="0dp"
         />
     <com.android.systemui.statusbar.policy.KeyButtonView
         android:id="@+id/rotate_suggestion"
diff --git a/packages/SystemUI/res/layout/notification_info.xml b/packages/SystemUI/res/layout/notification_info.xml
index 0d44931..f7c6c43 100644
--- a/packages/SystemUI/res/layout/notification_info.xml
+++ b/packages/SystemUI/res/layout/notification_info.xml
@@ -24,6 +24,7 @@
     android:clipChildren="false"
     android:clipToPadding="false"
     android:orientation="vertical"
+    android:paddingStart="@*android:dimen/notification_content_margin_start"
     android:background="@color/notification_guts_bg_color">
 
     <!-- Package Info -->
@@ -31,7 +32,6 @@
         android:id="@+id/header"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
-        android:layout_marginStart="@*android:dimen/notification_content_margin_start"
         android:clipChildren="false"
         android:clipToPadding="false">
         <ImageView
@@ -44,7 +44,7 @@
             android:id="@+id/pkgname"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Info"
+            style="@style/TextAppearance.NotificationInfo.Primary"
             android:layout_marginStart="3dp"
             android:layout_marginEnd="2dp"
             android:singleLine="true"
@@ -54,7 +54,7 @@
             android:id="@+id/pkg_divider"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Info"
+            style="@style/TextAppearance.NotificationInfo.Primary"
             android:layout_marginStart="2dp"
             android:layout_marginEnd="2dp"
             android:text="@*android:string/notification_header_divider_symbol"
@@ -64,7 +64,7 @@
             android:id="@+id/delegate_name"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Info"
+            style="@style/TextAppearance.NotificationInfo.Primary"
             android:layout_marginStart="2dp"
             android:layout_marginEnd="2dp"
             android:ellipsize="end"
@@ -77,286 +77,284 @@
             android:layout_height="wrap_content"
             android:layout_centerVertical="true"
             android:layout_alignParentEnd="true"
-            android:paddingHorizontal="16dp"
+
             android:orientation="horizontal">
             <!-- Optional link to app. Only appears if the channel is not disabled and the app
 asked for it -->
             <ImageButton
                 android:id="@+id/app_settings"
-                android:layout_width="40dp"
-                android:layout_height="56dp"
+                android:layout_width="48dp"
+                android:layout_height="48dp"
                 android:layout_centerVertical="true"
-                android:paddingRight="16dp"
                 android:visibility="gone"
                 android:background="@drawable/ripple_drawable"
                 android:contentDescription="@string/notification_app_settings"
-                android:src="@drawable/ic_settings"
-                android:tint="?android:attr/colorAccent" />
+                android:src="@drawable/ic_info"
+                android:tint="@color/notification_guts_link_icon_tint" />
             <!-- 24 dp icon with 16 dp padding all around to mirror notification content margins -->
             <ImageButton
                 android:id="@+id/info"
-                android:layout_width="24dp"
-                android:layout_height="56dp"
+                android:layout_width="48dp"
+                android:layout_height="48dp"
                 android:layout_centerVertical="true"
                 android:background="@drawable/ripple_drawable"
                 android:contentDescription="@string/notification_more_settings"
-                android:src="@drawable/ic_info"
-                android:tint="?android:attr/colorAccent" />
+                android:src="@drawable/ic_settings"
+                android:tint="@color/notification_guts_link_icon_tint" />
         </LinearLayout>
     </RelativeLayout>
 
+    <!-- Channel Info Block -->
     <LinearLayout
-        android:id="@+id/prompt"
+        android:id="@+id/channel_info"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginBottom="@dimen/notification_guts_button_spacing"
+        android:paddingEnd="@*android:dimen/notification_content_margin_end"
+        android:orientation="vertical">
+        <RelativeLayout
+            android:id="@+id/names"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content">
+            <TextView
+                android:id="@+id/group_name"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                style="@style/TextAppearance.NotificationInfo.Primary"
+                android:layout_marginStart="2dp"
+                android:layout_marginEnd="2dp"
+                android:ellipsize="end"
+                android:maxLines="1"
+                android:layout_centerVertical="true" />
+            <TextView
+                android:id="@+id/pkg_group_divider"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                style="@style/TextAppearance.NotificationInfo.Primary"
+                android:layout_marginStart="2dp"
+                android:layout_marginEnd="2dp"
+                android:text="@*android:string/notification_header_divider_symbol"
+                android:layout_centerVertical="true"
+                android:layout_toEndOf="@id/group_name" />
+            <!-- Channel Name -->
+            <TextView
+                android:id="@+id/channel_name"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_weight="1"
+                style="@style/TextAppearance.NotificationInfo.Primary"
+                android:layout_toEndOf="@id/pkg_group_divider"/>
+        </RelativeLayout>
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/blocking_helper"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="@dimen/notification_guts_button_spacing"
+        android:paddingEnd="@*android:dimen/notification_content_margin_end"
+        android:clipChildren="false"
+        android:clipToPadding="false"
+        android:orientation="vertical">
+        <!-- blocking helper text. no need for non-configurable check b/c controls won't be
+        activated in that case -->
+        <TextView
+            android:id="@+id/blocking_helper_text"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="2dp"
+            android:text="@string/inline_blocking_helper"
+            style="@*android:style/TextAppearance.DeviceDefault.Notification" />
+        <RelativeLayout
+            android:id="@+id/block_buttons"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:layout_marginTop="@dimen/notification_guts_button_spacing">
+            <TextView
+                android:id="@+id/blocking_helper_turn_off_notifications"
+                android:text="@string/inline_turn_off_notifications"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_centerVertical="true"
+                android:layout_alignParentStart="true"
+                android:width="110dp"
+                android:paddingEnd="15dp"
+                android:breakStrategy="simple"
+                style="@style/TextAppearance.NotificationInfo.Button"/>
+            <TextView
+                android:id="@+id/deliver_silently"
+                android:text="@string/inline_deliver_silently_button"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_centerVertical="true"
+                android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
+                android:paddingEnd="15dp"
+                android:width="110dp"
+                android:breakStrategy="simple"
+                android:layout_toStartOf="@+id/keep_showing"
+                style="@style/TextAppearance.NotificationInfo.Button"/>
+            <TextView
+                android:id="@+id/keep_showing"
+                android:text="@string/inline_keep_button"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_centerVertical="true"
+                android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
+                android:width="110dp"
+                android:breakStrategy="simple"
+                android:layout_alignParentEnd="true"
+                style="@style/TextAppearance.NotificationInfo.Button"/>
+        </RelativeLayout>
+
+    </LinearLayout>
+
+    <LinearLayout
+        android:id="@+id/inline_controls"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="@dimen/notification_guts_button_spacing"
+        android:paddingEnd="@*android:dimen/notification_content_margin_end"
         android:clipChildren="false"
         android:clipToPadding="false"
         android:orientation="vertical">
 
-        <!-- Channel Info Block -->
-        <LinearLayout
+        <!-- Non configurable app/channel text. appears instead of @+id/interruptiveness_settings-->
+        <TextView
+            android:id="@+id/non_configurable_text"
+            android:text="@string/notification_unblockable_desc"
+            android:visibility="gone"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginStart="@*android:dimen/notification_content_margin_start"
-            android:layout_marginEnd="@*android:dimen/notification_content_margin_start"
+            android:paddingTop="@dimen/notification_guts_option_vertical_padding"
+            style="@*android:style/TextAppearance.DeviceDefault.Notification" />
+
+        <!-- Non configurable multichannel text. appears instead of @+id/interruptiveness_settings-->
+        <TextView
+            android:id="@+id/non_configurable_multichannel_text"
+            android:text="@string/notification_multichannel_desc"
+            android:visibility="gone"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingTop="@dimen/notification_guts_option_vertical_padding"
+            style="@*android:style/TextAppearance.DeviceDefault.Notification" />
+
+        <LinearLayout
+            android:id="@+id/interruptiveness_settings"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
             android:orientation="vertical">
-            <RelativeLayout
-                android:id="@+id/names"
+            <!-- Interruptive row -->
+            <LinearLayout
+                android:id="@+id/alert_row"
                 android:layout_width="match_parent"
-                android:layout_height="wrap_content">
-                <TextView
-                    android:id="@+id/group_name"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
-                    android:layout_marginStart="2dp"
-                    android:layout_marginEnd="2dp"
-                    android:ellipsize="end"
-                    android:maxLines="1"
-                    android:layout_centerVertical="true" />
-                <TextView
-                    android:id="@+id/pkg_group_divider"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
-                    android:layout_marginStart="2dp"
-                    android:layout_marginEnd="2dp"
-                    android:text="@*android:string/notification_header_divider_symbol"
-                    android:layout_centerVertical="true"
-                    android:layout_toEndOf="@id/group_name" />
-                <!-- Channel Name -->
-                <TextView
-                    android:id="@+id/channel_name"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_weight="1"
-                    style="@*android:style/TextAppearance.DeviceDefault.Notification.Title"
-                    android:layout_toEndOf="@id/pkg_group_divider"/>
-            </RelativeLayout>
-            <!-- Question prompt -->
-            <TextView
-                android:id="@+id/block_prompt"
-                android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                style="@*android:style/TextAppearance.DeviceDefault.Notification" />
+                android:paddingTop="@dimen/notification_guts_option_vertical_padding"
+                android:paddingBottom="@dimen/notification_guts_option_vertical_padding"
+                android:paddingStart="@dimen/notification_guts_option_horizontal_padding"
+                android:orientation="horizontal">
+
+                <ImageView
+                    android:id="@+id/int_alert"
+                    android:src="@drawable/ic_notification_interruptive"
+                    android:background="@android:color/transparent"
+                    android:layout_gravity="center"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:contentDescription="@string/inline_silent_button_alert"/>
+
+                <LinearLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:paddingStart="@dimen/notification_guts_option_horizontal_padding"
+                    android:paddingEnd="@dimen/notification_guts_option_horizontal_padding"
+                    android:orientation="vertical">
+                    <TextView
+                        android:id="@+id/int_alert_label"
+                        android:text="@string/inline_silent_button_alert"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:ellipsize="end"
+                        android:maxLines="1"
+                        style="@style/TextAppearance.NotificationInfo.Primary"/>
+                    <TextView
+                        android:id="@+id/int_alert_summary"
+                        android:text="@string/hint_text_alert"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:ellipsize="end"
+                        style="@style/TextAppearance.NotificationInfo.Secondary"/>
+                </LinearLayout>
+            </LinearLayout>
+
+            <!-- Gentle row -->
+            <LinearLayout
+                android:id="@+id/silent_row"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:paddingTop="@dimen/notification_guts_option_vertical_padding"
+                android:paddingBottom="@dimen/notification_guts_option_vertical_padding"
+                android:paddingStart="@dimen/notification_guts_option_horizontal_padding"
+                android:layout_marginTop="@dimen/notification_guts_option_vertical_margin"
+                android:orientation="horizontal">
+                <ImageView
+                    android:id="@+id/int_silent"
+                    android:src="@drawable/ic_notification_gentle"
+                    android:layout_gravity="center"
+                    android:layout_width="36dp"
+                    android:layout_height="36dp"
+                    android:background="@android:color/transparent"
+                    android:contentDescription="@string/inline_silent_button_silent"/>
+                <LinearLayout
+                    android:layout_width="match_parent"
+                    android:layout_height="wrap_content"
+                    android:orientation="vertical"
+                    android:paddingStart="@dimen/notification_guts_option_horizontal_padding"
+                    android:paddingEnd="@dimen/notification_guts_option_horizontal_padding">
+                    <TextView
+                        android:id="@+id/int_silent_label"
+                        android:text="@string/inline_silent_button_silent"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:ellipsize="end"
+                        android:maxLines="1"
+                        style="@style/TextAppearance.NotificationInfo.Primary"/>
+                    <TextView
+                        android:id="@+id/int_silent_summary"
+                        android:text="@string/hint_text_silent"
+                        android:layout_width="match_parent"
+                        android:layout_height="wrap_content"
+                        android:ellipsize="end"
+                        style="@style/TextAppearance.NotificationInfo.Secondary"/>
+                </LinearLayout>
+            </LinearLayout>
         </LinearLayout>
 
-        <!-- Settings and Done buttons -->
         <RelativeLayout
-            android:id="@+id/block_or_minimize"
+            android:id="@+id/bottom_buttons"
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_marginTop="@dimen/notification_guts_button_spacing"
-            android:layout_marginStart="@dimen/notification_guts_button_side_margin"
-            android:layout_marginEnd="@dimen/notification_guts_button_side_margin"
-            android:clipChildren="false"
-            android:clipToPadding="false">
+            android:paddingTop="@dimen/notification_guts_button_spacing"
+            android:paddingBottom="@dimen/notification_guts_button_spacing">
+            <TextView
+                android:id="@+id/turn_off_notifications"
+                android:text="@string/inline_turn_off_notifications"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_centerVertical="true"
+                android:layout_alignParentStart="true"
+                android:maxWidth="200dp"
+                style="@style/TextAppearance.NotificationInfo.Button"/>
             <TextView
                 android:id="@+id/done"
                 android:text="@string/inline_ok_button"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_centerVertical="true"
-                android:maxWidth="100dp"
-                style="@style/TextAppearance.NotificationInfo.Button"/>
-
-            <LinearLayout
-                android:id="@+id/block_buttons"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_centerVertical="true"
+                android:maxWidth="125dp"
                 android:layout_alignParentEnd="true"
-                android:maxWidth="200dp"
-                android:orientation="horizontal">
-                <TextView
-                    android:id="@+id/deliver_silently"
-                    android:text="@string/inline_silent_button_silent"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_centerVertical="true"
-                    android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
-                    android:paddingRight="24dp"
-                    android:maxWidth="125dp"
-                    style="@style/TextAppearance.NotificationInfo.Button"/>
-                <TextView
-                    android:id="@+id/block"
-                    android:text="@string/inline_block_button"
-                    android:minWidth="48dp"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_centerVertical="true"
-                    android:maxWidth="75dp"
-                    android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
-                    style="@style/TextAppearance.NotificationInfo.Button"/>
-                <TextView
-                    android:id="@+id/minimize"
-                    android:text="@string/inline_minimize_button"
-                    android:minWidth="48dp"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_centerVertical="true"
-                    android:maxWidth="75dp"
-                    android:layout_marginStart="@dimen/notification_guts_button_horizontal_spacing"
-                    style="@style/TextAppearance.NotificationInfo.Button"/>
-            </LinearLayout>
+                style="@style/TextAppearance.NotificationInfo.Button"/>
         </RelativeLayout>
-        <LinearLayout
-            android:id="@+id/interruptiveness_settings"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:orientation="vertical"
-            android:visibility="gone">
-            <LinearLayout
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_marginTop="2dp"
-                android:layout_marginStart="@dimen/notification_guts_button_side_margin"
-                android:layout_marginEnd="@dimen/notification_guts_button_side_margin"
-                android:gravity="center"
-                android:orientation="horizontal">
-                <LinearLayout
-                    android:layout_width="0dp"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:gravity="center_horizontal"
-                    android:orientation="vertical">
-                    <FrameLayout
-                        android:id="@+id/int_block_wrapper"
-                        android:padding="4dp"
-                        android:layout_width="48dp"
-                        android:layout_height="48dp"
-                        android:gravity="center">
-                        <ImageButton
-                            android:id="@+id/int_block"
-                            android:background="@drawable/circle_white_40dp"
-                            android:src="@drawable/ic_notification_block"
-                            android:layout_gravity="center"
-                            android:layout_width="40dp"
-                            android:layout_height="40dp"
-                            android:clickable="false"
-                            android:contentDescription="@string/inline_block_button"
-                            android:tint="@color/GM2_grey_400"
-                            style="@style/TextAppearance.NotificationInfo.Button"/>
-                    </FrameLayout>
-                    <TextView
-                        android:id="@+id/int_block_label"
-                        android:text="@string/inline_block_button"
-                        android:layout_gravity="center_horizontal"
-                        android:gravity="center"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:ellipsize="end"
-                        android:maxLines="1"
-                        style="@style/TextAppearance.NotificationInfo.ButtonLabel"/>
-                </LinearLayout>
-                <LinearLayout
-                    android:layout_width="0dp"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:gravity="center_horizontal"
-                    android:orientation="vertical">
-                    <FrameLayout
-                        android:id="@+id/int_silent_wrapper"
-                        android:padding="4dp"
-                        android:layout_width="48dp"
-                        android:layout_height="48dp"
-                        android:gravity="center">
-                        <ImageButton
-                            android:id="@+id/int_silent"
-                            android:background="@drawable/circle_white_40dp"
-                            android:src="@drawable/ic_notifications_silence"
-                            android:layout_gravity="center"
-                            android:layout_width="40dp"
-                            android:layout_height="40dp"
-                            android:clickable="false"
-                            android:contentDescription="@string/inline_silent_button_silent"
-                            android:tint="@color/GM2_grey_400"
-                            style="@style/TextAppearance.NotificationInfo.Button"/>
-                    </FrameLayout>
-                    <TextView
-                        android:id="@+id/int_silent_label"
-                        android:text="@string/inline_silent_button_silent"
-                        android:layout_gravity="center_horizontal"
-                        android:gravity="center"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:ellipsize="end"
-                        android:maxLines="1"
-                        style="@style/TextAppearance.NotificationInfo.ButtonLabel"/>
-                </LinearLayout>
-                <LinearLayout
-                    android:layout_width="0dp"
-                    android:layout_height="match_parent"
-                    android:layout_weight="1"
-                    android:gravity="center_horizontal"
-                    android:orientation="vertical">
-                    <FrameLayout
-                        android:id="@+id/int_alert_wrapper"
-                        android:padding="4dp"
-                        android:layout_width="48dp"
-                        android:layout_height="48dp"
-                        android:gravity="center">
-                        <ImageButton
-                            android:id="@+id/int_alert"
-                            android:background="@drawable/circle_white_40dp"
-                            android:src="@drawable/ic_notifications_alert"
-                            android:layout_gravity="center"
-                            android:layout_width="40dp"
-                            android:layout_height="40dp"
-                            android:contentDescription="@string/inline_silent_button_alert"
-                            android:clickable="false"
-                            android:tint="@color/GM2_grey_400"
-                            style="@style/TextAppearance.NotificationInfo.Button"/>
-                    </FrameLayout>
-                    <TextView
-                        android:id="@+id/int_alert_label"
-                        android:text="@string/inline_silent_button_alert"
-                        android:layout_gravity="center_horizontal"
-                        android:gravity="center"
-                        android:layout_width="match_parent"
-                        android:layout_height="wrap_content"
-                        android:ellipsize="end"
-                        android:maxLines="1"
-                        style="@style/TextAppearance.NotificationInfo.ButtonLabel"/>
-                </LinearLayout>
-            </LinearLayout>
-            <TextView
-                android:id="@+id/hint_text"
-                android:layout_marginStart="@*android:dimen/notification_content_margin_start"
-                android:layout_marginEnd="@*android:dimen/notification_content_margin_start"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                style="@style/TextAppearance.NotificationInfo.HintText" />
-            <TextView
-                android:id="@+id/done_button"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_gravity="right"
-                android:paddingRight="24dp"
-                android:text="@string/inline_done_button"
-                style="@style/TextAppearance.NotificationInfo.Button" />
-        </LinearLayout>
+
     </LinearLayout>
 
     <com.android.systemui.statusbar.notification.row.NotificationUndoLayout
diff --git a/packages/SystemUI/res/values-night/colors.xml b/packages/SystemUI/res/values-night/colors.xml
index d74d258..8a0aaea 100644
--- a/packages/SystemUI/res/values-night/colors.xml
+++ b/packages/SystemUI/res/values-night/colors.xml
@@ -42,6 +42,10 @@
     <!-- The color of the text inside a notification -->
     <color name="notification_primary_text_color">@*android:color/notification_primary_text_color_dark</color>
 
+    <color name="notification_guts_selection_bg">#202124</color>
+    <color name="notification_guts_selection_border">#669DF6</color>
+    <color name="notification_guts_link_icon_tint">@color/GM2_grey_200</color>
+
     <!-- The color of the background in the top part of QSCustomizer -->
     <color name="qs_customize_background">@color/GM2_grey_900</color>
 
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 290d75b..b2a5075 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -88,6 +88,10 @@
     <!-- The "inside" of a notification, reached via longpress -->
     <color name="notification_guts_bg_color">@color/GM2_grey_50</color>
 
+    <color name="notification_guts_selection_bg">#FFFFFF</color>
+    <color name="notification_guts_selection_border">#4285F4</color>
+    <color name="notification_guts_link_icon_tint">@color/GM2_grey_900</color>
+
     <color name="assist_orb_color">#ffffff</color>
 
     <color name="keyguard_user_switcher_background_gradient_color">#77000000</color>
@@ -163,4 +167,7 @@
 
     <color name="GM2_red_300">#F28B82</color>
     <color name="GM2_red_500">#B71C1C</color>
+
+    <color name="GM2_yellow_500">#FFFBBC04</color>
+    <color name="GM2_green_500">#FF34A853</color>
 </resources>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index f8295eb..ce04638 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -109,12 +109,12 @@
 
     <!-- The default tiles to display in QuickSettings -->
     <string name="quick_settings_tiles_default" translatable="false">
-        wifi,bt,dnd,flashlight,rotation,battery,cell,airplane,cast,sensorprivacy
+        wifi,bt,dnd,flashlight,rotation,battery,cell,airplane,cast
     </string>
 
     <!-- Tiles native to System UI. Order should match "quick_settings_tiles_default" -->
     <string name="quick_settings_tiles_stock" translatable="false">
-        wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,work,cast,night,sensorprivacy
+        wifi,cell,battery,dnd,flashlight,rotation,bt,airplane,location,hotspot,inversion,saver,work,cast,night
     </string>
 
     <!-- The tiles to display in QuickSettings -->
@@ -330,7 +330,7 @@
     <!-- Nav bar button default ordering/layout -->
     <string name="config_navBarLayout" translatable="false">left[.5W],back[1WC];home;recent[1WC],right[.5W]</string>
     <string name="config_navBarLayoutQuickstep" translatable="false">back[1.7WC];home;contextual[1.7WC]</string>
-    <string name="config_navBarLayoutHandle" translatable="false">";home_handle;"</string>
+    <string name="config_navBarLayoutHandle" translatable="false">back[1.7WC];home_handle;ime_switcher[1.7WC]</string>
 
     <bool name="quick_settings_show_full_alarm">false</bool>
 
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index bea0365..a02469e 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -179,7 +179,7 @@
     <dimen name="notification_menu_icon_padding">20dp</dimen>
 
     <!-- The vertical space around the buttons in the inline settings -->
-    <dimen name="notification_guts_button_spacing">6dp</dimen>
+    <dimen name="notification_guts_button_spacing">12dp</dimen>
 
     <!-- Extra horizontal space for properly aligning guts buttons with the notification content -->
     <dimen name="notification_guts_button_side_margin">8dp</dimen>
@@ -196,6 +196,18 @@
     <!-- The height of the header in inline settings -->
     <dimen name="notification_guts_header_height">24dp</dimen>
 
+    <!-- The text size of the header in inline settings -->
+    <dimen name="notification_guts_header_text_size">16sp</dimen>
+
+    <!-- The horizontal space between items in the alert selections in the inline settings -->
+    <dimen name="notification_guts_option_horizontal_padding">15dp</dimen>
+
+    <!-- The vertical space between items in the alert selections in the inline settings -->
+    <dimen name="notification_guts_option_vertical_padding">15dp</dimen>
+
+    <!-- The vertical space between the alert selections in the inline settings -->
+    <dimen name="notification_guts_option_vertical_margin">6dp</dimen>
+
     <!-- The minimum height for the snackbar shown after the snooze option has been chosen. -->
     <dimen name="snooze_snackbar_min_height">56dp</dimen>
 
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index cd286fc..f47d4b5 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1602,7 +1602,7 @@
     <string name="inline_done_button">Done</string>
 
     <!-- Notification Inline controls: button to dismiss the blocking helper [CHAR_LIMIT=20] -->
-    <string name="inline_ok_button">OK</string>
+    <string name="inline_ok_button">Apply</string>
 
     <!-- Notification Inline controls: continue receiving notifications prompt, channel level -->
     <string name="inline_keep_showing">Keep showing these notifications?</string>
@@ -1623,17 +1623,20 @@
     <string name="inline_minimize_button">Minimize</string>
 
     <!-- Notification inline controls: button to show notifications silently, without alerting the user [CHAR_LIMIT=35] -->
-    <string name="inline_silent_button_silent">Show silently</string>
+    <string name="inline_silent_button_silent">Gentle</string>
 
     <!-- Notification inline controls: button to continue showing notifications silently [CHAR_LIMIT=35] -->
     <string name="inline_silent_button_stay_silent">Stay silent</string>
 
     <!-- Notification inline controls: button to make notifications alert the user [CHAR_LIMIT=35] -->
-    <string name="inline_silent_button_alert">Alert</string>
+    <string name="inline_silent_button_alert">Interruptive</string>
 
     <!-- Notification inline controls: button to continue alerting the user when notifications arrive [CHAR_LIMIT=35] -->
     <string name="inline_silent_button_keep_alerting">Keep alerting</string>
 
+    <!-- Notification inline controls: button to show block screen [CHAR_LIMIT=35] -->
+    <string name="inline_turn_off_notifications">Turn off notifications</string>
+
     <!-- Notification Inline controls: continue receiving notifications prompt, app level -->
     <string name="inline_keep_showing_app">Keep showing notifications from this app?</string>
 
@@ -1644,11 +1647,14 @@
     <string name="hint_text_silent">Silent notifications appear in the shade, but do not appear on the lock screen, present a banner, or play a sound.</string>
 
     <!-- Hint text for alert button in the interruptiveness settings [CHAR_LIMIT=NONE]-->
-    <string name="hint_text_alert">Alerted notifications appear in the shade, on the lock screen, present a banner, and play a sound.</string>
+    <string name="hint_text_alert">These notifications will make a sound and show in the notification drawer, status bar, and lock screen</string>
 
     <!-- Notification: Control panel: Label that displays when the app's notifications cannot be blocked. -->
     <string name="notification_unblockable_desc">These notifications can\'t be turned off</string>
 
+    <!-- Notification: Control panel: label that displays when viewing settings for a group of notifications posted to multiple channels. -->
+    <string name="notification_multichannel_desc">This group of notifications cannot be configured here</string>
+
     <!-- Notification: Control panel: Label for the app that posted this notification, if it's not the package that the notification was posted for -->
     <string name="notification_delegate_header">via <xliff:g id="app_name" example="YouTube">%1$s</xliff:g></string>
 
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 7c123ef..2ff481f 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -435,6 +435,7 @@
     </style>
 
     <style name="TextAppearance.NotificationInfo.Primary">
+        <item name="android:fontFamily">@*android:string/config_bodyFontFamilyMedium</item>
         <item name="android:textSize">16sp</item>
         <item name="android:alpha">0.87</item>
     </style>
@@ -471,16 +472,12 @@
     </style>
 
     <style name="TextAppearance.NotificationInfo.Button">
-        <item name="android:fontFamily">@*android:string/config_bodyFontFamilyMedium</item>
-        <item name="android:textSize">14sp</item>
+        <item name="android:fontFamily">@*android:string/config_bodyFontFamily</item>
+        <item name="android:textSize">16sp</item>
         <item name="android:textColor">?android:attr/colorAccent</item>
         <item name="android:background">@drawable/btn_borderless_rect</item>
         <item name="android:gravity">center</item>
         <item name="android:focusable">true</item>
-        <item name="android:paddingTop">@dimen/notification_guts_button_vertical_padding</item>
-        <item name="android:paddingBottom">@dimen/notification_guts_button_vertical_padding</item>
-        <item name="android:paddingLeft">@dimen/notification_guts_button_horizontal_padding</item>
-        <item name="android:paddingRight">@dimen/notification_guts_button_horizontal_padding</item>
     </style>
 
     <style name="TextAppearance.HeadsUpStatusBarText"
diff --git a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
index 0075327..04701bc 100644
--- a/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
+++ b/packages/SystemUI/shared/src/com/android/systemui/shared/recents/IOverviewProxy.aidl
@@ -123,4 +123,10 @@
      * Sent when the assistant changes how visible it is to the user.
      */
     void onAssistantVisibilityChanged(float visibility) = 14;
+
+    /*
+     * Sent when back is triggered.
+     */
+    void onBackAction(boolean completed, int downX, int downY, boolean isButton,
+            boolean gestureSwipeLeft) = 15;
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
index 8ebe1ae..c1bf4d4 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardSliceView.java
@@ -20,6 +20,8 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
 
+import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
+
 import android.animation.LayoutTransition;
 import android.animation.ObjectAnimator;
 import android.animation.PropertyValuesHolder;
@@ -60,6 +62,7 @@
 import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.keyguard.KeyguardSliceProvider;
+import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.util.wakelock.KeepAwakeAnimationListener;
@@ -70,6 +73,9 @@
 import java.util.HashMap;
 import java.util.List;
 
+import javax.inject.Inject;
+import javax.inject.Named;
+
 /**
  * View visible under the clock on the lock screen and AoD.
  */
@@ -80,6 +86,8 @@
     public static final int DEFAULT_ANIM_DURATION = 550;
 
     private final HashMap<View, PendingIntent> mClickActions;
+    private final ActivityStarter mActivityStarter;
+    private final ConfigurationController mConfigurationController;
     private Uri mKeyguardSliceUri;
     @VisibleForTesting
     TextView mTitle;
@@ -99,16 +107,10 @@
     private final int mRowWithHeaderPadding;
     private final int mRowPadding;
 
-    public KeyguardSliceView(Context context) {
-        this(context, null, 0);
-    }
-
-    public KeyguardSliceView(Context context, AttributeSet attrs) {
-        this(context, attrs, 0);
-    }
-
-    public KeyguardSliceView(Context context, AttributeSet attrs, int defStyle) {
-        super(context, attrs, defStyle);
+    @Inject
+    public KeyguardSliceView(@Named(VIEW_CONTEXT) Context context, AttributeSet attrs,
+            ActivityStarter activityStarter, ConfigurationController configurationController) {
+        super(context, attrs);
 
         TunerService tunerService = Dependency.get(TunerService.class);
         tunerService.addTunable(this, Settings.Secure.KEYGUARD_SLICE_URI);
@@ -117,6 +119,8 @@
         mRowPadding = context.getResources().getDimensionPixelSize(R.dimen.subtitle_clock_padding);
         mRowWithHeaderPadding = context.getResources()
                 .getDimensionPixelSize(R.dimen.header_subtitle_padding);
+        mActivityStarter = activityStarter;
+        mConfigurationController = configurationController;
 
         LayoutTransition transition = new LayoutTransition();
         transition.setStagger(LayoutTransition.CHANGE_APPEARING, DEFAULT_ANIM_DURATION / 2);
@@ -137,6 +141,7 @@
         mRow = findViewById(R.id.row);
         mTextColor = Utils.getColorAttrDefaultColor(mContext, R.attr.wallpaperTextColor);
         mIconSize = (int) mContext.getResources().getDimension(R.dimen.widget_icon_size);
+        mTitle.setOnClickListener(this);
     }
 
     @Override
@@ -146,7 +151,7 @@
         mDisplayId = getDisplay().getDisplayId();
         // Make sure we always have the most current slice
         mLiveData.observeForever(this);
-        Dependency.get(ConfigurationController.class).addCallback(this);
+        mConfigurationController.addCallback(this);
     }
 
     @Override
@@ -157,7 +162,7 @@
         if (mDisplayId == DEFAULT_DISPLAY) {
             mLiveData.removeObserver(this);
         }
-        Dependency.get(ConfigurationController.class).removeCallback(this);
+        mConfigurationController.removeCallback(this);
     }
 
     /**
@@ -179,6 +184,7 @@
             Trace.endSection();
             return;
         }
+        mClickActions.clear();
 
         ListContent lc = new ListContent(getContext(), mSlice);
         SliceContent headerContent = lc.getHeader();
@@ -201,9 +207,12 @@
             SliceItem mainTitle = header.getTitleItem();
             CharSequence title = mainTitle != null ? mainTitle.getText() : null;
             mTitle.setText(title);
+            if (header.getPrimaryAction() != null
+                    && header.getPrimaryAction().getAction() != null) {
+                mClickActions.put(mTitle, header.getPrimaryAction().getAction());
+            }
         }
 
-        mClickActions.clear();
         final int subItemsCount = subItems.size();
         final int blendedColor = getTextColor();
         final int startIndex = mHasHeader ? 1 : 0; // First item is header; skip it
@@ -289,11 +298,7 @@
     public void onClick(View v) {
         final PendingIntent action = mClickActions.get(v);
         if (action != null) {
-            try {
-                action.send();
-            } catch (PendingIntent.CanceledException e) {
-                Log.i(TAG, "Pending intent cancelled, nothing to launch", e);
-            }
+            mActivityStarter.startPendingIntentDismissingKeyguard(action);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
index 62b0542..de64cf8 100644
--- a/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
+++ b/packages/SystemUI/src/com/android/systemui/BatteryMeterView.java
@@ -176,10 +176,6 @@
         setClipChildren(false);
         setClipToPadding(false);
         Dependency.get(ConfigurationController.class).observe(viewAttachLifecycle(this), this);
-
-        // Needed for PorderDuff.Mode.CLEAR operations to work properly, but redraws don't happen
-        // enough to justify a hardware layer.
-        setLayerType(LAYER_TYPE_SOFTWARE, null);
     }
 
     private void setupLayoutTransition() {
diff --git a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
index 72ab02c..822538b 100644
--- a/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/HardwareUiLayout.java
@@ -561,4 +561,29 @@
         inoutInfo.contentInsets.set(mList.getLeft(), mList.getTop(),
                 0, getBottom() - mList.getBottom());
     };
+
+    private float getAnimationDistance() {
+        return getContext().getResources().getDimension(
+                com.android.systemui.R.dimen.global_actions_panel_width) / 2;
+    }
+
+    @Override
+    public float getAnimationOffsetX() {
+        if (RotationUtils.getRotation(mContext) == ROTATION_NONE) {
+            return getAnimationDistance();
+        }
+        return 0;
+    }
+
+    @Override
+    public float getAnimationOffsetY() {
+        switch (RotationUtils.getRotation(getContext())) {
+            case RotationUtils.ROTATION_LANDSCAPE:
+                return -getAnimationDistance();
+            case RotationUtils.ROTATION_SEASCAPE:
+                return getAnimationDistance();
+            default: // Portrait
+                return 0;
+        }
+    }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/MultiListLayout.java b/packages/SystemUI/src/com/android/systemui/MultiListLayout.java
index d063a0f..a30b681 100644
--- a/packages/SystemUI/src/com/android/systemui/MultiListLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/MultiListLayout.java
@@ -148,6 +148,16 @@
     }
 
     /**
+     * Get the X offset in pixels for use when animating the view onto or off of the screen.
+     */
+    public abstract float getAnimationOffsetX();
+
+    /**
+     * Get the Y offset in pixels for use when animating the view onto or off of the screen.
+     */
+    public abstract float getAnimationOffsetY();
+
+    /**
      * Adapter class for converting items into child views for MultiListLayout and handling
      * callbacks for input events.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
index de4605b..d850dbc 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleStackView.java
@@ -64,6 +64,8 @@
 
 import java.math.BigDecimal;
 import java.math.RoundingMode;
+import java.util.Collections;
+import java.util.List;
 
 /**
  * Renders bubbles in a stack and handles animating expanded and collapsed states.
@@ -164,6 +166,8 @@
     int[] mTempLoc = new int[2];
     RectF mTempRect = new RectF();
 
+    private final List<Rect> mSystemGestureExclusionRects = Collections.singletonList(new Rect());
+
     private ViewTreeObserver.OnPreDrawListener mViewUpdater =
             new ViewTreeObserver.OnPreDrawListener() {
                 @Override
@@ -175,6 +179,9 @@
                 }
             };
 
+    private ViewTreeObserver.OnDrawListener mSystemGestureExcludeUpdater =
+            this::updateSystemGestureExcludeRects;
+
     private ViewClippingUtil.ClippingParameters mClippingParameters =
             new ViewClippingUtil.ClippingParameters() {
 
@@ -361,6 +368,19 @@
         return false;
     }
 
+    private void updateSystemGestureExcludeRects() {
+        // Exclude the region occupied by the first BubbleView in the stack
+        Rect excludeZone = mSystemGestureExclusionRects.get(0);
+        if (mBubbleContainer.getChildCount() > 0) {
+            View firstBubble = mBubbleContainer.getChildAt(0);
+            excludeZone.set(firstBubble.getLeft(), firstBubble.getTop(), firstBubble.getRight(),
+                    firstBubble.getBottom());
+        } else {
+            excludeZone.setEmpty();
+        }
+        mBubbleContainer.setSystemGestureExclusionRects(mSystemGestureExclusionRects);
+    }
+
     /**
      * Updates the visibility of the 'dot' indicating an update on the bubble.
      * @param key the {@link NotificationEntry#key} associated with the bubble.
@@ -669,12 +689,17 @@
             updateExpandedBubble();
             applyCurrentState();
 
+            // This must be a separate OnDrawListener since it should be called for every draw.
+            getViewTreeObserver().addOnDrawListener(mSystemGestureExcludeUpdater);
+
             mIsExpansionAnimating = true;
 
             Runnable updateAfter = () -> {
                 applyCurrentState();
                 mIsExpansionAnimating = false;
                 requestUpdate();
+                getViewTreeObserver().removeOnDrawListener(mSystemGestureExcludeUpdater);
+                updateSystemGestureExcludeRects();
             };
 
             if (shouldExpand) {
diff --git a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java
index 0d8cb63..baeedaa 100644
--- a/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/bubbles/BubbleTouchHandler.java
@@ -97,11 +97,13 @@
             case MotionEvent.ACTION_DOWN:
                 trackMovement(event);
 
-                mDismissViewController.createDismissTarget();
-                mHandler.postDelayed(mShowDismissAffordance, SHOW_TARGET_DELAY);
-
                 mTouchDown.set(rawX, rawY);
 
+                if (!isFlyout) {
+                    mDismissViewController.createDismissTarget();
+                    mHandler.postDelayed(mShowDismissAffordance, SHOW_TARGET_DELAY);
+                }
+
                 if (isStack) {
                     mViewPositionOnTouchDown.set(mStack.getStackPosition());
                     mStack.onDragStart();
@@ -148,7 +150,7 @@
                     mController.dismissStack(BubbleController.DISMISS_USER_GESTURE);
                 } else if (isFlyout) {
                     // TODO(b/129768381): Expand if tapped, dismiss if swiped away.
-                    if (!mStack.isExpanded()) {
+                    if (!mStack.isExpanded() && !mMovedEnough) {
                         mStack.expandStack();
                     }
                 } else if (mMovedEnough) {
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index dcacd0f..e22b24e 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -1127,10 +1127,7 @@
         }
 
         protected int getActionLayoutId(Context context) {
-            if (isGridEnabled(context)) {
-                return com.android.systemui.R.layout.global_actions_grid_item;
-            }
-            return com.android.systemui.R.layout.global_actions_item;
+            return com.android.systemui.R.layout.global_actions_grid_item;
         }
 
         public View create(
@@ -1540,26 +1537,28 @@
             initializeLayout();
         }
 
-        private boolean initializePanel() {
+        private boolean shouldUsePanel() {
             if (!isPanelEnabled(mContext) || mPanelController == null) {
                 return false;
             }
-            View panelView = mPanelController.getPanelContent();
-            if (panelView == null) {
+            if (mPanelController.getPanelContent() == null) {
                 return false;
             }
+            return true;
+        }
+
+        private void initializePanel() {
             FrameLayout panelContainer = new FrameLayout(mContext);
             FrameLayout.LayoutParams panelParams =
                     new FrameLayout.LayoutParams(
                             FrameLayout.LayoutParams.MATCH_PARENT,
                             FrameLayout.LayoutParams.WRAP_CONTENT);
-            panelContainer.addView(panelView, panelParams);
+            panelContainer.addView(mPanelController.getPanelContent(), panelParams);
             addContentView(
                     panelContainer,
                     new ViewGroup.LayoutParams(
                             ViewGroup.LayoutParams.MATCH_PARENT,
                             ViewGroup.LayoutParams.MATCH_PARENT));
-            return true;
         }
 
         private void initializeLayout() {
@@ -1578,8 +1577,7 @@
             mGlobalActionsLayout.setRotationListener(this::onRotate);
             mGlobalActionsLayout.setAdapter(mAdapter);
 
-            boolean panelEnabled = initializePanel();
-            if (!panelEnabled) {
+            if (!shouldUsePanel()) {
                 if (mBackgroundDrawable == null) {
                     mBackgroundDrawable = new GradientDrawable(mContext);
                 }
@@ -1589,12 +1587,12 @@
                         com.android.systemui.R.drawable.global_action_panel_scrim);
                 mScrimAlpha = 1f;
             }
-            mGlobalActionsLayout.setSnapToEdge(panelEnabled);
+            mGlobalActionsLayout.setSnapToEdge(true);
             getWindow().setBackgroundDrawable(mBackgroundDrawable);
         }
 
         private int getGlobalActionsLayoutId(Context context) {
-            if (isGridEnabled(context)) {
+            if (isForceGridEnabled(context) || shouldUsePanel()) {
                 if (RotationUtils.getRotation(context) == RotationUtils.ROTATION_SEASCAPE) {
                     return com.android.systemui.R.layout.global_actions_grid_seascape;
                 }
@@ -1653,11 +1651,13 @@
             super.show();
             mShowing = true;
             mBackgroundDrawable.setAlpha(0);
-            mGlobalActionsLayout.setTranslationX(getAnimTranslation());
+            mGlobalActionsLayout.setTranslationX(mGlobalActionsLayout.getAnimationOffsetX());
+            mGlobalActionsLayout.setTranslationY(mGlobalActionsLayout.getAnimationOffsetY());
             mGlobalActionsLayout.setAlpha(0);
             mGlobalActionsLayout.animate()
                     .alpha(1)
                     .translationX(0)
+                    .translationY(0)
                     .setDuration(300)
                     .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
                     .setUpdateListener(animation -> {
@@ -1675,10 +1675,12 @@
             }
             mShowing = false;
             mGlobalActionsLayout.setTranslationX(0);
+            mGlobalActionsLayout.setTranslationY(0);
             mGlobalActionsLayout.setAlpha(1);
             mGlobalActionsLayout.animate()
                     .alpha(0)
-                    .translationX(getAnimTranslation())
+                    .translationX(mGlobalActionsLayout.getAnimationOffsetX())
+                    .translationY(mGlobalActionsLayout.getAnimationOffsetY())
                     .setDuration(300)
                     .withEndAction(super::dismiss)
                     .setInterpolator(new LogAccelerateInterpolator())
@@ -1701,11 +1703,6 @@
             }
         }
 
-        private float getAnimTranslation() {
-            return getContext().getResources().getDimension(
-                    com.android.systemui.R.dimen.global_actions_panel_width) / 2;
-        }
-
         @Override
         public void onColorsChanged(ColorExtractor extractor, int which) {
             if (mKeyguardShowing) {
@@ -1731,17 +1728,19 @@
         }
 
         public void onRotate(int from, int to) {
-            if (mShowing && isGridEnabled(mContext)) {
+            if (mShowing && (shouldUsePanel() || isForceGridEnabled(mContext))) {
                 refreshDialog();
             }
         }
     }
 
     /**
-     * Determines whether or not the Global Actions menu should use the newer grid-style layout.
+     * Determines whether or not the Global Actions menu should be forced to
+     * use the newer grid-style layout.
      */
-    private static boolean isGridEnabled(Context context) {
-        return FeatureFlagUtils.isEnabled(context, FeatureFlagUtils.GLOBAL_ACTIONS_GRID_ENABLED);
+    private static boolean isForceGridEnabled(Context context) {
+        return FeatureFlagUtils.isEnabled(context,
+                FeatureFlagUtils.FORCE_GLOBAL_ACTIONS_GRID_ENABLED);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java
index 9a0759c..f882569 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsGridLayout.java
@@ -16,6 +16,10 @@
 
 package com.android.systemui.globalactions;
 
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE;
+import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
+
 import android.content.Context;
 import android.text.TextUtils;
 import android.util.AttributeSet;
@@ -85,8 +89,8 @@
         int rotation = RotationUtils.getRotation(mContext);
 
         boolean reverse = false; // should we add items to parents in the reverse order?
-        if (rotation == RotationUtils.ROTATION_NONE
-                || rotation == RotationUtils.ROTATION_SEASCAPE) {
+        if (rotation == ROTATION_NONE
+                || rotation == ROTATION_SEASCAPE) {
             reverse = !reverse; // if we're in portrait or seascape, reverse items
         }
         if (TextUtils.getLayoutDirectionFromLocale(Locale.getDefault())
@@ -125,9 +129,9 @@
     private void updateSnapPosition() {
         if (mSnapToEdge) {
             setPadding(0, 0, 0, 0);
-            if (mRotation == RotationUtils.ROTATION_LANDSCAPE) {
+            if (mRotation == ROTATION_LANDSCAPE) {
                 setGravity(Gravity.RIGHT);
-            } else if (mRotation == RotationUtils.ROTATION_SEASCAPE) {
+            } else if (mRotation == ROTATION_SEASCAPE) {
                 setGravity(Gravity.LEFT);
             } else {
                 setGravity(Gravity.BOTTOM);
@@ -157,9 +161,9 @@
             return getSeparatedView();
         } else {
             switch (rotation) {
-                case RotationUtils.ROTATION_LANDSCAPE:
+                case ROTATION_LANDSCAPE:
                     return getListView().getParentView(index, false, true);
-                case RotationUtils.ROTATION_SEASCAPE:
+                case ROTATION_SEASCAPE:
                     return getListView().getParentView(index, true, true);
                 default:
                     return getListView().getParentView(index, false, false);
@@ -174,4 +178,31 @@
     public void setDivisionView(View v) {
         // do nothing
     }
+
+    private float getAnimationDistance() {
+        int rows = getListView().getRowCount();
+        float gridItemSize = getContext().getResources().getDimension(
+                com.android.systemui.R.dimen.global_actions_grid_item_height);
+        return rows * gridItemSize / 2;
+    }
+
+    @Override
+    public float getAnimationOffsetX() {
+        switch (RotationUtils.getRotation(getContext())) {
+            case ROTATION_LANDSCAPE:
+                return getAnimationDistance();
+            case ROTATION_SEASCAPE:
+                return -getAnimationDistance();
+            default: // Portrait
+                return 0;
+        }
+    }
+
+    @Override
+    public float getAnimationOffsetY() {
+        if (RotationUtils.getRotation(mContext) == ROTATION_NONE) {
+            return getAnimationDistance();
+        }
+        return 0;
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/ListGridLayout.java b/packages/SystemUI/src/com/android/systemui/globalactions/ListGridLayout.java
index 048f801..9c71ffc 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/ListGridLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/ListGridLayout.java
@@ -109,7 +109,10 @@
         }
     }
 
-    private int getRowCount() {
+    /**
+     * Get the number of rows which will be used to render children.
+     */
+    public int getRowCount() {
         // special case for 3 to use a single row
         if (mExpectedCount == 3) {
             return 1;
@@ -117,7 +120,10 @@
         return (int) Math.round(Math.sqrt(mExpectedCount));
     }
 
-    private int getColumnCount() {
+    /**
+     * Get the number of columns which will be used to render children.
+     */
+    public int getColumnCount() {
         // special case for 3 to use a single row
         if (mExpectedCount == 3) {
             return 3;
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 3140e6d..3ec6cb7 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -795,7 +795,10 @@
                 ? mExpandedMovementBounds
                 : mNormalMovementBounds;
         try {
-            mPinnedStackController.setMinEdgeSize(isMenuExpanded ? mExpandedShortestEdgeSize : 0);
+            if (mPinnedStackController != null) {
+                mPinnedStackController.setMinEdgeSize(
+                        isMenuExpanded ? mExpandedShortestEdgeSize : 0);
+            }
         } catch (RemoteException e) {
             Log.e(TAG, "Could not set minimized state", e);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 2b361f8..4d6693f 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -444,6 +444,17 @@
         }
     }
 
+    public void notifyBackAction(boolean completed, int downX, int downY, boolean isButton,
+            boolean gestureSwipeLeft) {
+        try {
+            if (mOverviewProxy != null) {
+                mOverviewProxy.onBackAction(completed, downX, downY, isButton, gestureSwipeLeft);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG_OPS, "Failed to notify back action", e);
+        }
+    }
+
     /**
      * Sets the navbar region which can receive touch inputs
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
index 580e702..2c15e87 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManager.java
@@ -85,11 +85,13 @@
         // - User sentiment is negative (DEBUG flag can bypass)
         // - The notification shade is fully expanded (guarantees we're not touching a HUN).
         // - The row is blockable (i.e. not non-blockable)
-        // - The dismissed row is a valid group (>1 or 0 children) or the only child in the group
+        // - The dismissed row is a valid group (>1 or 0 children from the same channel)
+        // or the only child in the group
         if ((row.getEntry().userSentiment == USER_SENTIMENT_NEGATIVE || DEBUG)
                 && mIsShadeExpanded
                 && !row.getIsNonblockable()
-                && (!row.isChildInGroup() || row.isOnlyChildInGroup())) {
+                && ((!row.isChildInGroup() || row.isOnlyChildInGroup())
+                        && row.getNumUniqueChannels() <= 1)) {
             // Dismiss any current blocking helper before continuing forward (only one can be shown
             // at a given time).
             dismissCurrentBlockingHelper();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 54bdaa2..69e6120 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -309,7 +309,6 @@
                 mDeviceProvisionedController.isDeviceProvisioned(),
                 row.getIsNonblockable(),
                 isForBlockingHelper,
-                row.getEntry().userSentiment == USER_SENTIMENT_NEGATIVE,
                 row.getEntry().importance,
                 row.getEntry().isHighPriority());
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
index 2e4325b..622b869 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationInfo.java
@@ -39,6 +39,7 @@
 import android.content.pm.ResolveInfo;
 import android.graphics.Color;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.GradientDrawable;
 import android.metrics.LogMaker;
 import android.os.Handler;
 import android.os.RemoteException;
@@ -82,9 +83,13 @@
 
     public static final int ACTION_NONE = 0;
     static final int ACTION_UNDO = 1;
+    // standard controls
     static final int ACTION_TOGGLE_SILENT = 2;
+    // unused
     static final int ACTION_BLOCK = 3;
+    // blocking helper
     static final int ACTION_DELIVER_SILENTLY = 4;
+    // standard controls
     private static final int ACTION_ALERT = 5;
 
     private INotificationManager mINotificationManager;
@@ -99,7 +104,6 @@
     private NotificationChannel mSingleNotificationChannel;
     private int mStartingChannelImportance;
     private boolean mWasShownHighPriority;
-    private int mNotificationBlockState = ACTION_NONE;
     /**
      * The last importance level chosen by the user.  Null if the user has not chosen an importance
      * level; non-null once the user takes an action which indicates an explicit preference.
@@ -109,13 +113,13 @@
     private boolean mIsNonblockable;
     private StatusBarNotification mSbn;
     private AnimatorSet mExpandAnimation;
-    private boolean mIsForeground;
     private boolean mIsDeviceProvisioned;
 
     private CheckSaveListener mCheckSaveListener;
     private OnSettingsClickListener mOnSettingsClickListener;
     private OnAppSettingsClickListener mAppSettingsClickListener;
     private NotificationGuts mGutsContainer;
+    private GradientDrawable mSelectedBackground;
 
     /** Whether this view is being shown as part of the blocking helper. */
     private boolean mIsForBlockingHelper;
@@ -125,40 +129,39 @@
      */
     private String mExitReason = NotificationCounters.BLOCKING_HELPER_DISMISSED;
 
-    private OnClickListener mOnKeepShowing = v -> {
-        mExitReason = NotificationCounters.BLOCKING_HELPER_KEEP_SHOWING;
-        if (mIsForBlockingHelper) {
-            closeControls(v);
-            mMetricsLogger.write(getLogMaker().setCategory(
-                    MetricsEvent.NOTIFICATION_BLOCKING_HELPER)
-                    .setType(MetricsEvent.TYPE_ACTION)
-                    .setSubtype(MetricsEvent.BLOCKING_HELPER_CLICK_STAY_SILENT));
-        }
-    };
-
+    // used by standard ui
     private OnClickListener mOnAlert = v -> {
         mExitReason = NotificationCounters.BLOCKING_HELPER_KEEP_SHOWING;
         mChosenImportance = IMPORTANCE_DEFAULT;
-        updateButtonsAndHelpText(ACTION_ALERT);
+        updateButtons(ACTION_ALERT);
     };
 
+    // used by standard ui
+    private OnClickListener mOnSilent = v -> {
+        mExitReason = NotificationCounters.BLOCKING_HELPER_DELIVER_SILENTLY;
+        mChosenImportance = IMPORTANCE_LOW;
+        updateButtons(ACTION_TOGGLE_SILENT);
+    };
+
+    // used by standard ui
     private OnClickListener mOnDismissSettings = v -> {
         closeControls(v);
     };
 
+    // used by blocking helper
+    private OnClickListener mOnKeepShowing = v -> {
+        mExitReason = NotificationCounters.BLOCKING_HELPER_KEEP_SHOWING;
+        closeControls(v);
+        mMetricsLogger.write(getLogMaker().setCategory(
+                MetricsEvent.NOTIFICATION_BLOCKING_HELPER)
+                .setType(MetricsEvent.TYPE_ACTION)
+                .setSubtype(MetricsEvent.BLOCKING_HELPER_CLICK_STAY_SILENT));
+    };
+
+    // used by blocking helper
     private OnClickListener mOnDeliverSilently = v -> {
         handleSaveImportance(
                 ACTION_DELIVER_SILENTLY, MetricsEvent.BLOCKING_HELPER_CLICK_STAY_SILENT);
-        if (!mIsForBlockingHelper) {
-            updateButtonsAndHelpText(ACTION_DELIVER_SILENTLY);
-        }
-    };
-
-    private OnClickListener mOnStopOrMinimizeNotifications = v -> {
-        handleSaveImportance(ACTION_BLOCK, MetricsEvent.BLOCKING_HELPER_CLICK_BLOCKED);
-        if (!mIsForBlockingHelper) {
-            updateButtonsAndHelpText(ACTION_BLOCK);
-        }
     };
 
     private void handleSaveImportance(int action, int metricsSubtype) {
@@ -189,6 +192,7 @@
                     .setType(MetricsEvent.TYPE_DISMISS)
                     .setSubtype(MetricsEvent.BLOCKING_HELPER_CLICK_UNDO));
         } else {
+            // TODO: this can't happen?
             mMetricsLogger.write(importanceChangeLogMaker().setType(MetricsEvent.TYPE_DISMISS));
         }
         saveImportanceAndExitReason(ACTION_UNDO);
@@ -233,7 +237,7 @@
         bindNotification(pm, iNotificationManager, pkg, notificationChannel,
                 numUniqueChannelsInRow, sbn, checkSaveListener, onSettingsClick,
                 onAppSettingsClick, isDeviceProvisioned, isNonblockable,
-                false /* isBlockingHelper */, false /* isUserSentimentNegative */,
+                false /* isBlockingHelper */,
                 importance, wasShownHighPriority);
     }
 
@@ -250,7 +254,6 @@
             boolean isDeviceProvisioned,
             boolean isNonblockable,
             boolean isForBlockingHelper,
-            boolean isUserSentimentNegative,
             int importance,
             boolean wasShownHighPriority)
             throws RemoteException {
@@ -268,13 +271,20 @@
         mStartingChannelImportance = mSingleNotificationChannel.getImportance();
         mWasShownHighPriority = wasShownHighPriority;
         mIsNonblockable = isNonblockable;
-        mIsForeground =
-                (mSbn.getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE) != 0;
         mIsForBlockingHelper = isForBlockingHelper;
         mAppUid = mSbn.getUid();
         mDelegatePkg = mSbn.getOpPkg();
         mIsDeviceProvisioned = isDeviceProvisioned;
 
+        mSelectedBackground = new GradientDrawable();
+        mSelectedBackground.setShape(GradientDrawable.RECTANGLE);
+        mSelectedBackground.setColor(mContext.getColor(R.color.notification_guts_selection_bg));
+        final float cornerRadii = getResources().getDisplayMetrics().density * 8;
+        mSelectedBackground.setCornerRadii(new float[]{cornerRadii, cornerRadii, cornerRadii,
+                cornerRadii, cornerRadii, cornerRadii, cornerRadii, cornerRadii});
+        mSelectedBackground.setStroke((int) (getResources().getDisplayMetrics().density * 2),
+                mContext.getColor(R.color.notification_guts_selection_border));
+
         int numTotalChannels = mINotificationManager.getNumNotificationChannelsForPackage(
                 pkg, mAppUid, false /* includeDeleted */);
         if (mNumUniqueChannelsInRow == 0) {
@@ -288,13 +298,74 @@
         }
 
         bindHeader();
-        bindPrompt();
-        bindButtons();
+        bindChannelDetails();
+
+        if (mIsForBlockingHelper) {
+            bindBlockingHelper();
+        } else {
+            bindInlineControls();
+        }
 
         mMetricsLogger.write(notificationControlsLogMaker());
     }
 
-    private void bindHeader() throws RemoteException {
+    private void bindBlockingHelper() {
+        findViewById(R.id.inline_controls).setVisibility(GONE);
+        findViewById(R.id.blocking_helper).setVisibility(VISIBLE);
+
+        findViewById(R.id.undo).setOnClickListener(mOnUndo);
+
+        View turnOffButton = findViewById(R.id.blocking_helper_turn_off_notifications);
+        turnOffButton.setOnClickListener(getSettingsOnClickListener());
+        turnOffButton.setVisibility(turnOffButton.hasOnClickListeners() ? VISIBLE : GONE);
+
+        TextView keepShowing = findViewById(R.id.keep_showing);
+        keepShowing.setOnClickListener(mOnKeepShowing);
+
+        View deliverSilently = findViewById(R.id.deliver_silently);
+        deliverSilently.setOnClickListener(mOnDeliverSilently);
+    }
+
+    private void bindInlineControls() {
+        findViewById(R.id.inline_controls).setVisibility(VISIBLE);
+        findViewById(R.id.blocking_helper).setVisibility(GONE);
+
+        if (mIsNonblockable) {
+            findViewById(R.id.non_configurable_text).setVisibility(VISIBLE);
+            findViewById(R.id.non_configurable_multichannel_text).setVisibility(GONE);
+            findViewById(R.id.interruptiveness_settings).setVisibility(GONE);
+        } else if (mNumUniqueChannelsInRow > 1) {
+            findViewById(R.id.non_configurable_text).setVisibility(GONE);
+            findViewById(R.id.interruptiveness_settings).setVisibility(GONE);
+            findViewById(R.id.non_configurable_multichannel_text).setVisibility(VISIBLE);
+        } else {
+            findViewById(R.id.non_configurable_text).setVisibility(GONE);
+            findViewById(R.id.non_configurable_multichannel_text).setVisibility(GONE);
+            findViewById(R.id.interruptiveness_settings).setVisibility(VISIBLE);
+        }
+
+        View turnOffButton = findViewById(R.id.turn_off_notifications);
+        turnOffButton.setOnClickListener(getSettingsOnClickListener());
+        turnOffButton.setVisibility(turnOffButton.hasOnClickListeners() && !mIsNonblockable
+                ? VISIBLE : GONE);
+
+        View done = findViewById(R.id.done);
+        done.setOnClickListener(mOnDismissSettings);
+
+
+        View silent = findViewById(R.id.silent_row);
+        View alert = findViewById(R.id.alert_row);
+        silent.setOnClickListener(mOnSilent);
+        alert.setOnClickListener(mOnAlert);
+
+        if (mWasShownHighPriority) {
+            updateButtons(ACTION_ALERT);
+        } else {
+            updateButtons(ACTION_TOGGLE_SILENT);
+        }
+    }
+
+    private void bindHeader() {
         // Package name
         Drawable pkgicon = null;
         ApplicationInfo info;
@@ -319,31 +390,44 @@
         // Delegate
         bindDelegate();
 
-        // Settings button.
-        final View settingsButton = findViewById(R.id.info);
-        if (mAppUid >= 0 && mOnSettingsClickListener != null && mIsDeviceProvisioned) {
-            settingsButton.setVisibility(View.VISIBLE);
-            final int appUidF = mAppUid;
-            settingsButton.setOnClickListener(
-                    (View view) -> {
-                        logBlockingHelperCounter(
-                                NotificationCounters.BLOCKING_HELPER_NOTIF_SETTINGS);
-                        mOnSettingsClickListener.onClick(view,
-                                mNumUniqueChannelsInRow > 1 ? null : mSingleNotificationChannel,
-                                appUidF);
-                    });
+        // Set up app settings link (i.e. Customize)
+        View settingsLinkView = findViewById(R.id.app_settings);
+        Intent settingsIntent = getAppSettingsIntent(mPm, mPackageName,
+                mSingleNotificationChannel,
+                mSbn.getId(), mSbn.getTag());
+        if (settingsIntent != null
+                && !TextUtils.isEmpty(mSbn.getNotification().getSettingsText())) {
+            settingsLinkView.setVisibility(VISIBLE);
+            settingsLinkView.setOnClickListener((View view) -> {
+                mAppSettingsClickListener.onClick(view, settingsIntent);
+            });
         } else {
-            settingsButton.setVisibility(View.GONE);
+            settingsLinkView.setVisibility(View.GONE);
         }
+
+        // System Settings button.
+        final View settingsButton = findViewById(R.id.info);
+        settingsButton.setOnClickListener(getSettingsOnClickListener());
+        settingsButton.setVisibility(settingsButton.hasOnClickListeners() ? VISIBLE : GONE);
     }
 
-    private void bindPrompt() throws RemoteException {
-        final TextView blockPrompt = findViewById(R.id.block_prompt);
+    private OnClickListener getSettingsOnClickListener() {
+        if (mAppUid >= 0 && mOnSettingsClickListener != null && mIsDeviceProvisioned) {
+            final int appUidF = mAppUid;
+            return ((View view) -> {
+                logBlockingHelperCounter(
+                        NotificationCounters.BLOCKING_HELPER_NOTIF_SETTINGS);
+                mOnSettingsClickListener.onClick(view,
+                        mNumUniqueChannelsInRow > 1 ? null : mSingleNotificationChannel,
+                        appUidF);
+            });
+        }
+        return null;
+    }
+
+    private void bindChannelDetails() throws RemoteException {
         bindName();
         bindGroup();
-        if (mIsNonblockable) {
-            blockPrompt.setText(R.string.notification_unblockable_desc);
-        }
     }
 
     private void bindName() {
@@ -450,110 +534,17 @@
         }
     }
 
-    private void bindButtons() {
-        findViewById(R.id.undo).setOnClickListener(mOnUndo);
-
-        boolean showInterruptivenessSettings =
-                !mIsNonblockable
-                        && !mIsForeground
-                        && !mIsForBlockingHelper
-                        && NotificationUtils.useNewInterruptionModel(mContext);
-        if (showInterruptivenessSettings) {
-            findViewById(R.id.block_or_minimize).setVisibility(GONE);
-            findViewById(R.id.interruptiveness_settings).setVisibility(VISIBLE);
-            View done = findViewById(R.id.done_button);
-            done.setOnClickListener(mOnDismissSettings);
-            View block = findViewById(R.id.int_block_wrapper);
-            View silent = findViewById(R.id.int_silent_wrapper);
-            View alert = findViewById(R.id.int_alert_wrapper);
-            block.setOnClickListener(mOnStopOrMinimizeNotifications);
-            silent.setOnClickListener(mOnDeliverSilently);
-            alert.setOnClickListener(mOnAlert);
-            if (mNotificationBlockState != ACTION_NONE) {
-                updateButtonsAndHelpText(mNotificationBlockState);
-            } else if (mWasShownHighPriority) {
-                updateButtonsAndHelpText(ACTION_ALERT);
-            } else {
-                updateButtonsAndHelpText(ACTION_DELIVER_SILENTLY);
-            }
-        } else {
-            findViewById(R.id.block_or_minimize).setVisibility(VISIBLE);
-            findViewById(R.id.interruptiveness_settings).setVisibility(GONE);
-            View block = findViewById(R.id.block);
-            TextView done = findViewById(R.id.done);
-            View minimize = findViewById(R.id.minimize);
-            View deliverSilently = findViewById(R.id.deliver_silently);
-
-
-            block.setOnClickListener(mOnStopOrMinimizeNotifications);
-            done.setOnClickListener(mOnKeepShowing);
-            minimize.setOnClickListener(mOnStopOrMinimizeNotifications);
-            deliverSilently.setOnClickListener(mOnDeliverSilently);
-
-            if (mIsNonblockable) {
-                done.setText(android.R.string.ok);
-                block.setVisibility(GONE);
-                minimize.setVisibility(GONE);
-                deliverSilently.setVisibility(GONE);
-            } else if (mIsForeground) {
-                block.setVisibility(GONE);
-                minimize.setVisibility(VISIBLE);
-            } else {
-                block.setVisibility(VISIBLE);
-                minimize.setVisibility(GONE);
-            }
-
-            // Set up app settings link (i.e. Customize)
-            View settingsLinkView = findViewById(R.id.app_settings);
-            Intent settingsIntent = getAppSettingsIntent(mPm, mPackageName,
-                    mSingleNotificationChannel,
-                    mSbn.getId(), mSbn.getTag());
-            if (!mIsForBlockingHelper
-                    && settingsIntent != null
-                    && !TextUtils.isEmpty(mSbn.getNotification().getSettingsText())) {
-                settingsLinkView.setVisibility(VISIBLE);
-                settingsLinkView.setOnClickListener((View view) -> {
-                    mAppSettingsClickListener.onClick(view, settingsIntent);
-                });
-            } else {
-                settingsLinkView.setVisibility(View.GONE);
-            }
-        }
-    }
-
-    private void updateButtonsAndHelpText(int blockState) {
-        mNotificationBlockState = blockState;
-        ImageView block = findViewById(R.id.int_block);
-        ImageView silent = findViewById(R.id.int_silent);
-        ImageView alert = findViewById(R.id.int_alert);
-        TextView hintText = findViewById(R.id.hint_text);
+    private void updateButtons(int blockState) {
+        View silent = findViewById(R.id.silent_row);
+        View alert = findViewById(R.id.alert_row);
         switch (blockState) {
-            case ACTION_BLOCK:
-                block.setBackgroundResource(R.drawable.circle_blue_40dp);
-                block.setColorFilter(Color.WHITE);
-                silent.setBackgroundResource(R.drawable.circle_white_40dp);
-                silent.setColorFilter(getResources().getColor(R.color.GM2_grey_400));
-                alert.setBackgroundResource(R.drawable.circle_white_40dp);
-                alert.setColorFilter(getResources().getColor(R.color.GM2_grey_400));
-                hintText.setText(R.string.hint_text_block);
-                break;
-            case ACTION_DELIVER_SILENTLY:
-                silent.setBackgroundResource(R.drawable.circle_blue_40dp);
-                silent.setColorFilter(Color.WHITE);
-                block.setBackgroundResource(R.drawable.circle_white_40dp);
-                block.setColorFilter(getResources().getColor(R.color.GM2_grey_400));
-                alert.setBackgroundResource(R.drawable.circle_white_40dp);
-                alert.setColorFilter(getResources().getColor(R.color.GM2_grey_400));
-                hintText.setText(R.string.hint_text_silent);
+            case ACTION_TOGGLE_SILENT:
+                silent.setBackground(mSelectedBackground);
+                alert.setBackground(null);
                 break;
             case ACTION_ALERT:
-                alert.setBackgroundResource(R.drawable.circle_blue_40dp);
-                alert.setColorFilter(Color.WHITE);
-                block.setBackgroundResource(R.drawable.circle_white_40dp);
-                block.setColorFilter(getResources().getColor(R.color.GM2_grey_400));
-                silent.setBackgroundResource(R.drawable.circle_white_40dp);
-                silent.setColorFilter(getResources().getColor(R.color.GM2_grey_400));
-                hintText.setText(R.string.hint_text_alert);
+                alert.setBackground(mSelectedBackground);
+                silent.setBackground(null);
                 break;
         }
     }
@@ -575,28 +566,20 @@
                     mChosenImportance = IMPORTANCE_DEFAULT;
                 }
                 break;
-            case ACTION_BLOCK:
-                mExitReason = NotificationCounters.BLOCKING_HELPER_STOP_NOTIFICATIONS;
-                if (mIsForeground) {
-                    mChosenImportance = IMPORTANCE_MIN;
-                } else {
-                    mChosenImportance = IMPORTANCE_NONE;
-                }
-                break;
             default:
                 throw new IllegalArgumentException();
         }
     }
 
+    // only used for blocking helper
     private void swapContent(@NotificationInfoAction int action, boolean animate) {
         if (mExpandAnimation != null) {
             mExpandAnimation.cancel();
         }
 
-        View prompt = findViewById(R.id.prompt);
+        View blockingHelper = findViewById(R.id.blocking_helper);
         ViewGroup confirmation = findViewById(R.id.confirmation);
         TextView confirmationText = findViewById(R.id.confirmation_text);
-        View header = findViewById(R.id.header);
 
         saveImportanceAndExitReason(action);
 
@@ -606,33 +589,20 @@
             case ACTION_DELIVER_SILENTLY:
                 confirmationText.setText(R.string.notification_channel_silenced);
                 break;
-            case ACTION_TOGGLE_SILENT:
-                if (mWasShownHighPriority) {
-                    confirmationText.setText(R.string.notification_channel_silenced);
-                } else {
-                    confirmationText.setText(R.string.notification_channel_unsilenced);
-                }
-                break;
-            case ACTION_BLOCK:
-                if (mIsForeground) {
-                    confirmationText.setText(R.string.notification_channel_minimized);
-                } else {
-                    confirmationText.setText(R.string.notification_channel_disabled);
-                }
-                break;
             default:
                 throw new IllegalArgumentException();
         }
 
         boolean isUndo = action == ACTION_UNDO;
 
-        prompt.setVisibility(isUndo ? VISIBLE : GONE);
+        blockingHelper.setVisibility(isUndo ? VISIBLE : GONE);
+        findViewById(R.id.channel_info).setVisibility(isUndo ? VISIBLE : GONE);
+        findViewById(R.id.header).setVisibility(isUndo ? VISIBLE : GONE);
         confirmation.setVisibility(isUndo ? GONE : VISIBLE);
-        header.setVisibility(isUndo ? VISIBLE : GONE);
 
         if (animate) {
-            ObjectAnimator promptAnim = ObjectAnimator.ofFloat(prompt, View.ALPHA,
-                    prompt.getAlpha(), isUndo ? 1f : 0f);
+            ObjectAnimator promptAnim = ObjectAnimator.ofFloat(blockingHelper, View.ALPHA,
+                    blockingHelper.getAlpha(), isUndo ? 1f : 0f);
             promptAnim.setInterpolator(isUndo ? Interpolators.ALPHA_IN : Interpolators.ALPHA_OUT);
             ObjectAnimator confirmAnim = ObjectAnimator.ofFloat(confirmation, View.ALPHA,
                     confirmation.getAlpha(), isUndo ? 0f : 1f);
@@ -652,7 +622,7 @@
                 @Override
                 public void onAnimationEnd(Animator animation) {
                     if (!mCancelled) {
-                        prompt.setVisibility(isUndo ? VISIBLE : GONE);
+                        blockingHelper.setVisibility(isUndo ? VISIBLE : GONE);
                         confirmation.setVisibility(isUndo ? GONE : VISIBLE);
                     }
                 }
@@ -674,15 +644,11 @@
         }
         mExitReason = NotificationCounters.BLOCKING_HELPER_DISMISSED;
 
-        View prompt = findViewById(R.id.prompt);
-        ViewGroup confirmation = findViewById(R.id.confirmation);
-        View header = findViewById(R.id.header);
-        prompt.setVisibility(VISIBLE);
-        prompt.setAlpha(1f);
-        confirmation.setVisibility(GONE);
-        confirmation.setAlpha(1f);
-        header.setVisibility(VISIBLE);
-        header.setAlpha(1f);
+        if (mIsForBlockingHelper) {
+            bindBlockingHelper();
+        } else {
+            bindInlineControls();
+        }
 
         mMetricsLogger.write(notificationControlsLogMaker().setType(MetricsEvent.TYPE_CLOSE));
     }
@@ -730,8 +696,8 @@
      * commit the updated importance.
      *
      * <p><b>Note,</b> this will only get called once the view is dismissing. This means that the
-     * user does not have the ability to undo the action anymore. See {@link #swapContent(boolean)}
-     * for where undo is handled.
+     * user does not have the ability to undo the action anymore. See
+     * {@link #swapContent(boolean, boolean)} for where undo is handled.
      */
     @VisibleForTesting
     void closeControls(View v) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButton.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButton.java
index 5dded52..541c142 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButton.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButton.java
@@ -51,6 +51,9 @@
      * Reload the drawable from resource id, should reapply the previous dark intensity.
      */
     public void updateIcon() {
+        if (getCurrentView() == null || !getCurrentView().isAttachedToWindow()) {
+            return;
+        }
         final KeyButtonDrawable currentDrawable = getImageDrawable();
         KeyButtonDrawable drawable = getNewDrawable();
         if (currentDrawable != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButtonGroup.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButtonGroup.java
index 38df17a..02b660f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButtonGroup.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ContextualButtonGroup.java
@@ -112,23 +112,24 @@
      * their icons for their buttons.
      */
     public void updateIcons() {
-        if (getCurrentView() == null || !getCurrentView().isAttachedToWindow()) {
-            return;
-        }
         for (ButtonData data : mButtonData) {
             data.button.updateIcon();
         }
     }
 
     public void dump(PrintWriter pw) {
+        View view = getCurrentView();
         pw.println("ContextualButtonGroup {");
         pw.println("      getVisibleContextButton(): " + getVisibleContextButton());
         pw.println("      isVisible(): " + isVisible());
+        pw.println("      attached(): " + (view != null && view.isAttachedToWindow()));
         pw.println("      mButtonData [ ");
         for (int i = mButtonData.size() - 1; i >= 0; --i) {
             final ButtonData data = mButtonData.get(i);
+            view = data.button.getCurrentView();
             pw.println("            " + i + ": markedVisible=" + data.markedVisible
                     + " visible=" + data.button.getVisibility()
+                    + " attached=" + (view != null && view.isAttachedToWindow())
                     + " alpha=" + data.button.getAlpha());
         }
         pw.println("      ]");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
index 95abb66..212666f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/EdgeBackGestureHandler.java
@@ -46,6 +46,7 @@
 import android.view.WindowManagerGlobal;
 
 import com.android.systemui.R;
+import com.android.systemui.recents.OverviewProxyService;
 import com.android.systemui.shared.system.InputChannelCompat.InputEventReceiver;
 import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.shared.system.WindowManagerWrapper;
@@ -102,6 +103,7 @@
             };
 
     private final Context mContext;
+    private final OverviewProxyService mOverviewProxyService;
 
     private final Point mDisplaySize = new Point();
     private final int mDisplayId;
@@ -137,11 +139,12 @@
     private NavigationBarEdgePanel mEdgePanel;
     private WindowManager.LayoutParams mEdgePanelLp;
 
-    public EdgeBackGestureHandler(Context context) {
+    public EdgeBackGestureHandler(Context context, OverviewProxyService overviewProxyService) {
         mContext = context;
         mDisplayId = context.getDisplayId();
         mMainExecutor = context.getMainExecutor();
         mWm = context.getSystemService(WindowManager.class);
+        mOverviewProxyService = overviewProxyService;
 
         mEdgeWidth = QuickStepContract.getEdgeSensitivityWidth(context);
         mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
@@ -313,11 +316,15 @@
                 float xDiff = ev.getX() - mDownPoint.x;
                 boolean exceedsThreshold = mIsOnLeftEdge
                         ? (xDiff > mSwipeThreshold) : (-xDiff > mSwipeThreshold);
-                if (exceedsThreshold && Math.abs(xDiff) > Math.abs(ev.getY() - mDownPoint.y)) {
+                boolean performAction = exceedsThreshold
+                        && Math.abs(xDiff) > Math.abs(ev.getY() - mDownPoint.y);
+                if (performAction) {
                     // Perform back
                     sendEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_BACK);
                     sendEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_BACK);
                 }
+                mOverviewProxyService.notifyBackAction(performAction, (int) mDownPoint.x,
+                        (int) mDownPoint.y, false /* isButton */, !mIsOnLeftEdge);
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
index 27394d9..6ebd6b3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -263,8 +263,7 @@
             return STATE_BIOMETRICS_ERROR;
         } else if (mUnlockMethodCache.canSkipBouncer()) {
             return STATE_LOCK_OPEN;
-        } else if (mUnlockMethodCache.isFaceUnlockRunning()
-                || updateMonitor.isFaceDetectionRunning()) {
+        } else if (updateMonitor.isFaceDetectionRunning()) {
             return STATE_SCANNING_FACE;
         } else {
             return STATE_LOCKED;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
index 3dcadf1..6729f9f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarFragment.java
@@ -202,7 +202,9 @@
         @Override
         public void onBackButtonAlphaChanged(float alpha, boolean animate) {
             final ButtonDispatcher backButton = mNavigationBarView.getBackButton();
-            if (QuickStepContract.isGesturalMode(getContext())) {
+            final boolean useAltBack =
+                    (mNavigationIconHints & StatusBarManager.NAVIGATION_HINT_BACK_ALT) != 0;
+            if (QuickStepContract.isGesturalMode(getContext()) && !useAltBack) {
                 // If property was changed to hide/show back button, going home will trigger
                 // launcher to to change the back button alpha to reflect property change
                 backButton.setVisibility(View.GONE);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
index 26aa617..a522ed1c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarInflaterView.java
@@ -68,6 +68,7 @@
     public static final String LEFT = "left";
     public static final String RIGHT = "right";
     public static final String CONTEXTUAL = "contextual";
+    public static final String IME_SWITCHER = "ime_switcher";
 
     public static final String GRAVITY_SEPARATOR = ";";
     public static final String BUTTON_SEPARATOR = ",";
@@ -164,17 +165,21 @@
     @Override
     public void onTuningChanged(String key, String newValue) {
         if (NAV_BAR_VIEWS.equals(key)) {
-            if (!Objects.equals(mCurrentLayout, newValue)) {
-                mUsingCustomLayout = newValue != null;
-                clearViews();
-                inflateLayout(newValue);
-            }
+            setNavigationBarLayout(newValue);
         } else if (NAV_BAR_LEFT.equals(key) || NAV_BAR_RIGHT.equals(key)) {
             clearViews();
             inflateLayout(mCurrentLayout);
         }
     }
 
+    public void setNavigationBarLayout(String layoutValue) {
+        if (!Objects.equals(mCurrentLayout, layoutValue)) {
+            mUsingCustomLayout = layoutValue != null;
+            clearViews();
+            inflateLayout(layoutValue);
+        }
+    }
+
     public void onLikelyDefaultLayoutChange() {
         // Don't override custom layouts
         if (mUsingCustomLayout) return;
@@ -401,6 +406,8 @@
             v = inflater.inflate(R.layout.contextual, parent, false);
         } else if (HOME_HANDLE.equals(button)) {
             v = inflater.inflate(R.layout.home_handle, parent, false);
+        } else if (IME_SWITCHER.equals(button)) {
+            v = inflater.inflate(R.layout.ime_switcher, parent, false);
         } else if (button.startsWith(KEY)) {
             String uri = extractImage(button);
             int code = extractKeycode(button);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 4fd6a71..e2a63cc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -21,7 +21,6 @@
 
 import static com.android.systemui.shared.system.NavigationBarCompat.FLAG_SHOW_OVERVIEW_BUTTON;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_OPAQUE;
-import static com.android.systemui.statusbar.phone.NavigationBarInflaterView.NAV_BAR_VIEWS;
 
 import android.animation.LayoutTransition;
 import android.animation.LayoutTransition.TransitionListener;
@@ -35,6 +34,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.pm.ParceledListSlice;
 import android.content.res.Configuration;
 import android.graphics.Canvas;
 import android.graphics.Point;
@@ -48,6 +48,8 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import android.view.Display;
+import android.view.IPinnedStackController;
+import android.view.IPinnedStackListener;
 import android.view.MotionEvent;
 import android.view.Surface;
 import android.view.View;
@@ -133,6 +135,7 @@
     private boolean mUseCarModeUi = false;
     private boolean mInCarMode = false;
     private boolean mDockedStackExists;
+    private boolean mImeVisible;
 
     private final SparseArray<ButtonDispatcher> mButtonDispatchers = new SparseArray<>();
     private final ContextualButtonGroup mContextualButtonGroup;
@@ -234,6 +237,45 @@
         }
     };
 
+    private final IPinnedStackListener.Stub mImeChangedListener = new IPinnedStackListener.Stub() {
+        @Override
+        public void onListenerRegistered(IPinnedStackController controller) {
+        }
+
+        @Override
+        public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
+            post(() -> {
+                // TODO remove this and do below when mNavigationIconHints changes
+                if (imeVisible) {
+                    getBackButton().setVisibility(VISIBLE);
+                    reloadNavIcons();
+                } else {
+                    getImeSwitchButton().setVisibility(GONE);
+                }
+                mImeVisible = imeVisible;
+                updateWindowTouchable();
+            });
+        }
+
+        @Override
+        public void onShelfVisibilityChanged(boolean shelfVisible, int shelfHeight) {
+        }
+
+        @Override
+        public void onMinimizedStateChanged(boolean isMinimized) {
+        }
+
+        @Override
+        public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds,
+                Rect animatingBounds, boolean fromImeAdjustment, boolean fromShelfAdjustment,
+                int displayRotation) {
+        }
+
+        @Override
+        public void onActionsChanged(ParceledListSlice actions) {
+        }
+    };
+
     private BroadcastReceiver mOverlaysChangedReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
@@ -285,7 +327,7 @@
         mButtonDispatchers.put(R.id.menu_container, mContextualButtonGroup);
         mDeadZone = new DeadZone(this);
 
-        mEdgeBackGestureHandler = new EdgeBackGestureHandler(context);
+        mEdgeBackGestureHandler = new EdgeBackGestureHandler(context, mOverviewProxyService);
         mTintController = new NavBarTintController(this, getLightTransitionsController());
 
     }
@@ -472,6 +514,11 @@
             return;
         }
 
+        if (QuickStepContract.isGesturalMode(getContext())) {
+            drawable.setRotation(degrees);
+            return;
+        }
+
         // Animate the back button's rotation to the new degrees and only in portrait move up the
         // back button to line up with the other buttons
         float targetY = !mOverviewProxyService.shouldShowSwipeUpUI() && !mIsVertical && useAltBack
@@ -574,8 +621,8 @@
         // Always disable recents when alternate car mode UI is active and for secondary displays.
         boolean disableRecent = isRecentsButtonDisabled();
 
-        boolean disableBack = QuickStepContract.isGesturalMode(getContext())
-                || (((mDisabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0) && !useAltBack);
+        boolean disableBack = !useAltBack && (QuickStepContract.isGesturalMode(getContext())
+                || ((mDisabledFlags & View.STATUS_BAR_DISABLE_BACK) != 0));
 
         // When screen pinning, don't hide back and home when connected service or back and
         // recents buttons when disconnected from launcher service in screen pinning mode,
@@ -715,6 +762,11 @@
         setWindowFlag(WindowManager.LayoutParams.FLAG_SLIPPERY, slippery);
     }
 
+    public void updateWindowTouchable() {
+        boolean touchable = mImeVisible || !QuickStepContract.isGesturalMode(getContext());
+        setWindowFlag(WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE, !touchable);
+    }
+
     private void setWindowFlag(int flags, boolean enable) {
         final ViewGroup navbarView = ((ViewGroup) getParent());
         if (navbarView == null) {
@@ -734,7 +786,7 @@
     }
 
     private void onOverlaysChanged() {
-        mNavigationInflaterView.onTuningChanged(NAV_BAR_VIEWS, null);
+        mNavigationInflaterView.setNavigationBarLayout(null);
 
         // Color adaption is tied with showing home handle, only avaliable if visible
         if (QuickStepContract.isGesturalMode(getContext())) {
@@ -1062,6 +1114,15 @@
         filter.addDataScheme("package");
         getContext().registerReceiver(mOverlaysChangedReceiver, filter);
         mEdgeBackGestureHandler.onNavBarAttached();
+
+        if (QuickStepContract.isGesturalMode(getContext())) {
+            try {
+                WindowManagerWrapper.getInstance().addPinnedStackListener(mImeChangedListener);
+            } catch (RemoteException e) {
+                Log.e(TAG, "Failed to register pinned stack listener", e);
+            }
+        }
+        updateWindowTouchable();
     }
 
     @Override
@@ -1078,6 +1139,8 @@
 
         getContext().unregisterReceiver(mOverlaysChangedReceiver);
         mEdgeBackGestureHandler.onNavBarDetached();
+
+        WindowManagerWrapper.getInstance().removePinnedStackListener(mImeChangedListener);
     }
 
     private void setUpSwipeUpOnboarding(boolean connectedToOverviewProxy) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
index bdd76c8..44c82c8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
@@ -43,7 +43,6 @@
     /** Whether the unlock method is currently insecure (insecure method or trusted environment) */
     private boolean mCanSkipBouncer;
     private boolean mTrustManaged;
-    private boolean mFaceUnlockRunning;
     private boolean mTrusted;
 
     private UnlockMethodCache(Context ctx) {
@@ -93,16 +92,13 @@
         boolean canSkipBouncer = !secure ||  mKeyguardUpdateMonitor.getUserCanSkipBouncer(user);
         boolean trustManaged = mKeyguardUpdateMonitor.getUserTrustIsManaged(user);
         boolean trusted = mKeyguardUpdateMonitor.getUserHasTrust(user);
-        boolean faceUnlockRunning = mKeyguardUpdateMonitor.isFaceUnlockRunning(user)
-                && trustManaged;
         boolean changed = secure != mSecure || canSkipBouncer != mCanSkipBouncer ||
-                trustManaged != mTrustManaged  || faceUnlockRunning != mFaceUnlockRunning;
+                trustManaged != mTrustManaged;
         if (changed || updateAlways) {
             mSecure = secure;
             mCanSkipBouncer = canSkipBouncer;
             mTrusted = trusted;
             mTrustManaged = trustManaged;
-            mFaceUnlockRunning = faceUnlockRunning;
             notifyListeners();
         }
         Trace.endSection();
@@ -171,10 +167,6 @@
         return mTrustManaged;
     }
 
-    public boolean isFaceUnlockRunning() {
-        return mFaceUnlockRunning;
-    }
-
     public static interface OnUnlockMethodChangedListener {
         void onUnlockMethodStateChanged();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
index 1e05983..06fc745 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyButtonView.java
@@ -308,6 +308,10 @@
         // TODO(b/122195391): Added logs to make sure sysui is sending back button events
         if (mCode == KeyEvent.KEYCODE_BACK && flags != KeyEvent.FLAG_LONG_PRESS) {
             Log.i(TAG, "Back button event: " + KeyEvent.actionToString(action));
+            if (action == MotionEvent.ACTION_UP) {
+                mOverviewProxyService.notifyBackAction((flags & KeyEvent.FLAG_CANCELED) == 0,
+                        -1, -1, true /* isButton */, false /* gestureSwipeLeft */);
+            }
         }
         final int repeatCount = (flags & KeyEvent.FLAG_LONG_PRESS) != 0 ? 1 : 0;
         final KeyEvent ev = new KeyEvent(mDownTime, when, action, mCode, repeatCount,
diff --git a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
index 7705e4e..376c328 100644
--- a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
+++ b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
@@ -24,6 +24,7 @@
 import android.view.View;
 
 import com.android.keyguard.KeyguardClockSwitch;
+import com.android.keyguard.KeyguardSliceView;
 import com.android.systemui.SystemUIFactory;
 import com.android.systemui.qs.QSCarrierGroup;
 import com.android.systemui.qs.QSFooterImpl;
@@ -136,6 +137,11 @@
          * Creates the KeyguardClockSwitch.
          */
         KeyguardClockSwitch createKeyguardClockSwitch();
+
+        /**
+         * Creates the KeyguardSliceView.
+         */
+        KeyguardSliceView createKeyguardSliceView();
     }
 
     /**
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java
index 190ce75..b3accbc 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardSliceViewTest.java
@@ -27,8 +27,10 @@
 import androidx.slice.SliceSpecs;
 import androidx.slice.builders.ListBuilder;
 
+import com.android.systemui.SystemUIFactory;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.keyguard.KeyguardSliceProvider;
+import com.android.systemui.util.InjectionInflationController;
 
 import org.junit.Assert;
 import org.junit.Before;
@@ -49,7 +51,11 @@
     @Before
     public void setUp() throws Exception {
         com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper();
-        mKeyguardSliceView = (KeyguardSliceView) LayoutInflater.from(getContext())
+        InjectionInflationController inflationController = new InjectionInflationController(
+                SystemUIFactory.getInstance().getRootComponent());
+        LayoutInflater layoutInflater = inflationController
+                .injectable(LayoutInflater.from(getContext()));
+        mKeyguardSliceView = (KeyguardSliceView) layoutInflater
                 .inflate(R.layout.keyguard_status_area, null);
         mSliceUri = Uri.parse(KeyguardSliceProvider.KEYGUARD_SLICE_URI);
         SliceProvider.setSpecs(new HashSet<>(Collections.singletonList(SliceSpecs.LIST)));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java
index 4fe364a..3c91b3f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationBlockingHelperManagerTest.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.notification.row;
 
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_POSITIVE;
@@ -24,11 +25,13 @@
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.NotificationChannel;
 import android.content.Context;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
@@ -130,6 +133,21 @@
         verify(mGutsManager).openGuts(row, 0, 0, mMenuItem);
     }
 
+    @Test
+    public void testPerhapsShowBlockingHelper_notShownForMultiChannelGroup() throws Exception {
+        ExpandableNotificationRow groupRow = createBlockableGroupRowSpy(10);
+        int i = 0;
+        for (ExpandableNotificationRow childRow : groupRow.getNotificationChildren()) {
+            childRow.getEntry().channel =
+                    new NotificationChannel(Integer.toString(i++), "", IMPORTANCE_DEFAULT);
+        }
+
+        groupRow.getEntry().userSentiment = USER_SENTIMENT_NEGATIVE;
+
+        assertFalse(mBlockingHelperManager.perhapsShowBlockingHelper(groupRow, mMenuRow));
+
+        verify(mGutsManager, never()).openGuts(groupRow, 0, 0, mMenuItem);
+    }
 
     @Test
     public void testPerhapsShowBlockingHelper_shownForLargeGroup() throws Exception {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
index ff849c3..8380192 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationGutsManagerTest.java
@@ -325,7 +325,6 @@
                 eq(false),
                 eq(false),
                 eq(true) /* isForBlockingHelper */,
-                eq(true) /* isUserSentimentNegative */,
                 eq(0),
                 eq(false) /* wasShownHighPriority */);
     }
@@ -354,7 +353,6 @@
                 eq(false),
                 eq(false),
                 eq(false) /* isForBlockingHelper */,
-                eq(true) /* isUserSentimentNegative */,
                 eq(0),
                 eq(false) /* wasShownHighPriority */);
     }
@@ -385,7 +383,6 @@
                 eq(false),
                 eq(false),
                 eq(true) /* isForBlockingHelper */,
-                eq(true) /* isUserSentimentNegative */,
                 eq(IMPORTANCE_DEFAULT),
                 eq(true) /* wasShownHighPriority */);
     }
@@ -415,7 +412,6 @@
                 eq(true),
                 eq(false),
                 eq(false) /* isForBlockingHelper */,
-                eq(true) /* isUserSentimentNegative */,
                 eq(0),
                 eq(false) /* wasShownHighPriority */);
     }
@@ -444,7 +440,6 @@
                 eq(false),
                 eq(false),
                 eq(true) /* isForBlockingHelper */,
-                eq(true) /* isUserSentimentNegative */,
                 eq(0),
                 eq(false) /* wasShownHighPriority */);
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
index fb4fd31..d2f8e02 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/row/NotificationInfoTest.java
@@ -313,108 +313,20 @@
     }
 
     @Test
-    public void testBindNotification_BlockButton() throws Exception {
+    public void testBindNotification_BlockLink_BlockingHelper() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
-                IMPORTANCE_DEFAULT, true);
-        final View block = mNotificationInfo.findViewById(R.id.int_block);
-        final View minimize = mNotificationInfo.findViewById(R.id.block_or_minimize);
-        assertEquals(VISIBLE, block.getVisibility());
-        assertEquals(GONE, minimize.getVisibility());
-    }
-
-    @Test
-    public void testBindNotification_BlockButton_BlockingHelper() throws Exception {
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
-                true /* isBlockingHelper */, false, IMPORTANCE_DEFAULT, true);
-        final View block = mNotificationInfo.findViewById(R.id.block);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, mock(
+                        NotificationInfo.OnSettingsClickListener.class), null, true, false,
+                true /* isBlockingHelper */, IMPORTANCE_DEFAULT, true);
+        final View block =
+                mNotificationInfo.findViewById(R.id.blocking_helper_turn_off_notifications);
         final View interruptivenessSettings = mNotificationInfo.findViewById(
-                R.id.interruptiveness_settings);
+                R.id.inline_controls);
         assertEquals(VISIBLE, block.getVisibility());
         assertEquals(GONE, interruptivenessSettings.getVisibility());
     }
 
     @Test
-    public void testBindNotification_SilenceButton_CurrentlyAlerting() throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
-                IMPORTANCE_DEFAULT, true);
-        final TextView silent = mNotificationInfo.findViewById(R.id.int_silent_label);
-        assertEquals(VISIBLE, silent.getVisibility());
-        assertEquals(
-                mContext.getString(R.string.inline_silent_button_silent), silent.getText());
-    }
-
-    @Test
-    public void testBindNotification_verifyButtonTexts() throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
-                IMPORTANCE_LOW, false);
-        final TextView block = mNotificationInfo.findViewById(R.id.int_block_label);
-        final TextView alert = mNotificationInfo.findViewById(R.id.int_alert_label);
-        final TextView silent = mNotificationInfo.findViewById(R.id.int_silent_label);
-        assertEquals(VISIBLE, silent.getVisibility());
-        assertEquals(VISIBLE, block.getVisibility());
-        assertEquals(VISIBLE, alert.getVisibility());
-        assertEquals(
-                mContext.getString(R.string.inline_silent_button_silent),
-                silent.getText());
-        assertEquals(
-                mContext.getString(R.string.inline_silent_button_alert), alert.getText());
-        assertEquals(
-                mContext.getString(R.string.inline_block_button), block.getText());
-    }
-
-    @Test
-    public void testBindNotification_verifyHintTextForSilent() throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
-                IMPORTANCE_LOW, false);
-        TextView hintText = mNotificationInfo.findViewById(R.id.hint_text);
-        assertEquals(mContext.getString(R.string.hint_text_silent), hintText.getText());
-    }
-
-    @Test
-    public void testBindNotification_verifyHintTextForBlock() throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
-                IMPORTANCE_LOW, false);
-        View blockWrapper = mNotificationInfo.findViewById(R.id.int_block_wrapper);
-        blockWrapper.performClick();
-        TextView hintText = mNotificationInfo.findViewById(R.id.hint_text);
-        assertEquals(mContext.getString(R.string.hint_text_block), hintText.getText());
-    }
-
-    @Test
-    public void testBindNotification_verifyHintTextForAlert() throws Exception {
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
-                IMPORTANCE_DEFAULT, true);
-        TextView hintText = mNotificationInfo.findViewById(R.id.hint_text);
-        assertEquals(mContext.getString(R.string.hint_text_alert), hintText.getText());
-    }
-
-    @Test
-    public void testBindNotification_MinButton() throws Exception {
-        mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
-                IMPORTANCE_DEFAULT, true);
-        final View block = mNotificationInfo.findViewById(R.id.block);
-        final View interruptivenessSettings = mNotificationInfo.findViewById(
-                R.id.interruptiveness_settings);
-        final View minimize = mNotificationInfo.findViewById(R.id.minimize);
-        assertEquals(GONE, block.getVisibility());
-        assertEquals(GONE, interruptivenessSettings.getVisibility());
-        assertEquals(VISIBLE, minimize.getVisibility());
-    }
-
-    @Test
     public void testBindNotification_SetsOnClickListenerForSettings() throws Exception {
         final CountDownLatch latch = new CountDownLatch(1);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
@@ -484,7 +396,7 @@
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
                 null, null, null,
                 false, true,
-                true, true,
+                true,
                 IMPORTANCE_DEFAULT, true);
         verify(mMetricsLogger).write(argThat(logMaker ->
                 logMaker.getCategory() == MetricsEvent.ACTION_NOTE_CONTROLS
@@ -499,7 +411,7 @@
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
                 null, null, null,
                 false, true,
-                true, true,
+                true,
                 IMPORTANCE_DEFAULT, true);
         mNotificationInfo.logBlockingHelperCounter("HowCanNotifsBeRealIfAppsArent");
         verify(mMetricsLogger).count(eq("HowCanNotifsBeRealIfAppsArent"), eq(1));
@@ -526,7 +438,7 @@
             throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null, null,
-                null, true, true, IMPORTANCE_DEFAULT, true);
+                null, true, false, IMPORTANCE_DEFAULT, true);
         final TextView channelNameView =
                 mNotificationInfo.findViewById(R.id.channel_name);
         assertEquals(GONE, channelNameView.getVisibility());
@@ -537,20 +449,24 @@
     public void testStopInvisibleIfBundleFromDifferentChannels() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, MULTIPLE_CHANNEL_COUNT, mSbn, null, null,
-                null, true, true, IMPORTANCE_DEFAULT, true);
-        final TextView blockView = mNotificationInfo.findViewById(R.id.block);
-        assertEquals(GONE, blockView.getVisibility());
+                null, true, false, IMPORTANCE_DEFAULT, true);
+        assertEquals(GONE, mNotificationInfo.findViewById(
+                R.id.interruptiveness_settings).getVisibility());
+        assertEquals(VISIBLE, mNotificationInfo.findViewById(
+                R.id.non_configurable_multichannel_text).getVisibility());
     }
 
     @Test
-    public void testbindNotification_UnblockableTextVisibleWhenAppUnblockable() throws Exception {
+    public void testBindNotification_whenAppUnblockable() throws Exception {
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
                 IMPORTANCE_DEFAULT, true);
-        final TextView view = mNotificationInfo.findViewById(R.id.block_prompt);
+        final TextView view = mNotificationInfo.findViewById(R.id.non_configurable_text);
         assertEquals(View.VISIBLE, view.getVisibility());
         assertEquals(mContext.getString(R.string.notification_unblockable_desc),
                 view.getText());
+        assertEquals(GONE,
+                mNotificationInfo.findViewById(R.id.interruptiveness_settings).getVisibility());
     }
 
     @Test
@@ -568,23 +484,9 @@
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
-                IMPORTANCE_DEFAULT, false);
+                IMPORTANCE_LOW, false);
 
-        mNotificationInfo.findViewById(R.id.int_block).performClick();
-        mTestableLooper.processAllMessages();
-        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
-                anyString(), eq(TEST_UID), any());
-    }
-
-    @Test
-    public void testDoesNotUpdateNotificationChannelAfterImportanceChangedMin()
-            throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
-                IMPORTANCE_DEFAULT, false);
-
-        mNotificationInfo.findViewById(R.id.minimize).performClick();
+        mNotificationInfo.findViewById(R.id.alert_row).performClick();
         mTestableLooper.processAllMessages();
         verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
                 anyString(), eq(TEST_UID), any());
@@ -598,21 +500,7 @@
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
                 IMPORTANCE_DEFAULT, true);
 
-        mNotificationInfo.findViewById(R.id.int_silent).performClick();
-        mTestableLooper.processAllMessages();
-        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
-                anyString(), eq(TEST_UID), any());
-    }
-
-    @Test
-    public void testDoesNotUpdateNotificationChannelAfterImportanceChangedUnSilenced()
-            throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
-                IMPORTANCE_DEFAULT, false);
-
-        mNotificationInfo.findViewById(R.id.int_alert).performClick();
+        mNotificationInfo.findViewById(R.id.silent_row).performClick();
         mTestableLooper.processAllMessages();
         verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
                 anyString(), eq(TEST_UID), any());
@@ -650,76 +538,6 @@
     }
 
     @Test
-    public void testHandleCloseControls_setsNotificationsDisabledForMultipleChannelNotifications()
-            throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
-                10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
-                null /* onSettingsClick */, null /* onAppSettingsClick */,
-                true, false /* isNonblockable */, IMPORTANCE_DEFAULT, false
-        );
-
-        mNotificationInfo.findViewById(R.id.int_block_wrapper).performClick();
-        mNotificationInfo.findViewById(R.id.done_button).performClick();
-        mNotificationInfo.handleCloseControls(true, false);
-
-        mTestableLooper.processAllMessages();
-        verify(mMockINotificationManager, times(1))
-                .setNotificationsEnabledWithImportanceLockForPackage(
-                        anyString(), eq(TEST_UID), eq(false));
-    }
-
-
-    @Test
-    public void testHandleCloseControls_keepsNotificationsEnabledForMultipleChannelNotifications()
-            throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
-                10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
-                null /* onSettingsClick */, null /* onAppSettingsClick */,
-                true, false /* isNonblockable */, IMPORTANCE_DEFAULT, false
-        );
-
-        mNotificationInfo.findViewById(R.id.int_block_wrapper).performClick();
-        mNotificationInfo.findViewById(R.id.done_button).performClick();
-        mNotificationInfo.handleCloseControls(true, false);
-
-        mTestableLooper.processAllMessages();
-        verify(mMockINotificationManager, times(1))
-                .setNotificationsEnabledWithImportanceLockForPackage(
-                        anyString(), eq(TEST_UID), eq(false));
-    }
-
-    @Test
-    public void testCloseControls_blockingHelperSavesImportanceForMultipleChannelNotifications()
-            throws Exception {
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel /* notificationChannel */,
-                10 /* numUniqueChannelsInRow */, mSbn, null /* checkSaveListener */,
-                null /* onSettingsClick */, null /* onAppSettingsClick */,
-                true /* provisioned */,
-                false /* isNonblockable */, true /* isForBlockingHelper */,
-                true /* isUserSentimentNegative */, IMPORTANCE_DEFAULT, true);
-
-        NotificationGuts guts = spy(new NotificationGuts(mContext, null));
-        when(guts.getWindowToken()).thenReturn(mock(IBinder.class));
-        doNothing().when(guts).animateClose(anyInt(), anyInt(), anyBoolean());
-        doNothing().when(guts).setExposed(anyBoolean(), anyBoolean());
-        guts.setGutsContent(mNotificationInfo);
-        mNotificationInfo.setGutsParent(guts);
-
-        mNotificationInfo.findViewById(R.id.done).performClick();
-
-        verify(mBlockingHelperManager).dismissCurrentBlockingHelper();
-        mTestableLooper.processAllMessages();
-        verify(mMockINotificationManager, times(1))
-                .setNotificationsEnabledWithImportanceLockForPackage(
-                        anyString(), eq(TEST_UID), eq(true));
-    }
-
-    @Test
     public void testCloseControls_nonNullCheckSaveListenerDoesntDelayKeepShowing_BlockingHelper()
             throws Exception {
         NotificationInfo.CheckSaveListener listener =
@@ -729,7 +547,7 @@
                 10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
                 null /* onSettingsClick */, null /* onAppSettingsClick */, true /* provisioned */,
                 false /* isNonblockable */, true /* isForBlockingHelper */,
-                true /* isUserSentimentNegative */, IMPORTANCE_DEFAULT, true);
+                IMPORTANCE_DEFAULT, true);
 
         NotificationGuts guts = spy(new NotificationGuts(mContext, null));
         when(guts.getWindowToken()).thenReturn(mock(IBinder.class));
@@ -738,7 +556,7 @@
         guts.setGutsContent(mNotificationInfo);
         mNotificationInfo.setGutsParent(guts);
 
-        mNotificationInfo.findViewById(R.id.done).performClick();
+        mNotificationInfo.findViewById(R.id.keep_showing).performClick();
 
         verify(mBlockingHelperManager).dismissCurrentBlockingHelper();
         mTestableLooper.processAllMessages();
@@ -757,8 +575,7 @@
                 10 /* numUniqueChannelsInRow */, mSbn, listener /* checkSaveListener */,
                 null /* onSettingsClick */, null /* onAppSettingsClick */,
                 false /* isNonblockable */, true /* isForBlockingHelper */,
-                true, true /* isUserSentimentNegative */,  /* isNoisy */
-                IMPORTANCE_DEFAULT, true);
+                true, IMPORTANCE_DEFAULT, true);
 
         mNotificationInfo.handleCloseControls(true /* save */, false /* force */);
 
@@ -777,9 +594,9 @@
                 null /* onSettingsClick */, null /* onAppSettingsClick */,
                 true /* provisioned */,
                 false /* isNonblockable */, true /* isForBlockingHelper */,
-                true /* isUserSentimentNegative */, IMPORTANCE_DEFAULT, true);
+                IMPORTANCE_DEFAULT, true);
 
-        mNotificationInfo.findViewById(R.id.block).performClick();
+        mNotificationInfo.findViewById(R.id.deliver_silently).performClick();
         mTestableLooper.processAllMessages();
         verify(listener).checkSave(any(Runnable.class), eq(mSbn));
     }
@@ -799,7 +616,6 @@
                 false /* isNonblockable */,
                 true /* isForBlockingHelper */,
                 true,
-                false /* isUserSentimentNegative */,
                 IMPORTANCE_DEFAULT, true);
         NotificationGuts guts = mock(NotificationGuts.class);
         doCallRealMethod().when(guts).closeControls(anyInt(), anyInt(), anyBoolean(), anyBoolean());
@@ -811,129 +627,6 @@
     }
 
     @Test
-    public void testNonBlockableAppDoesNotBecomeBlocked() throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
-                true, false, IMPORTANCE_DEFAULT, false);
-        mNotificationInfo.findViewById(R.id.block).performClick();
-        waitForUndoButton();
-
-        mTestableLooper.processAllMessages();
-        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
-                anyString(), eq(TEST_UID), any());
-    }
-
-    @Test
-    public void testBlockChangedCallsUpdateNotificationChannel_notBlockingHelper()
-            throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
-                null, null, null,
-                true, false,
-                IMPORTANCE_DEFAULT, false);
-
-        mNotificationInfo.findViewById(R.id.int_block_wrapper).performClick();
-        mNotificationInfo.findViewById(R.id.done_button).performClick();
-        mNotificationInfo.handleCloseControls(true, false);
-
-        ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
-        verify(mMetricsLogger, times(2)).write(logMakerCaptor.capture());
-        assertEquals(MetricsProto.MetricsEvent.TYPE_ACTION,
-                logMakerCaptor.getValue().getType());
-        assertEquals(IMPORTANCE_NONE - IMPORTANCE_LOW,
-                logMakerCaptor.getValue().getSubtype());
-
-        mTestableLooper.processAllMessages();
-        ArgumentCaptor<NotificationChannel> updated =
-                ArgumentCaptor.forClass(NotificationChannel.class);
-        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
-                anyString(), eq(TEST_UID), updated.capture());
-        assertTrue((updated.getValue().getUserLockedFields()
-                & USER_LOCKED_IMPORTANCE) != 0);
-        assertEquals(IMPORTANCE_NONE, updated.getValue().getImportance());
-    }
-
-    @Test
-    public void testBlockChangedCallsUpdateNotificationChannel_blockingHelper() throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(
-                mMockPackageManager,
-                mMockINotificationManager,
-                TEST_PACKAGE_NAME,
-                mNotificationChannel,
-                1 /* numChannels */,
-                mSbn,
-                null /* checkSaveListener */,
-                null /* onSettingsClick */,
-                null /* onAppSettingsClick */,
-                true /*provisioned */,
-                false /* isNonblockable */,
-                true /* isForBlockingHelper */,
-                true /* isUserSentimentNegative */,
-                IMPORTANCE_DEFAULT,
-                false);
-
-        mNotificationInfo.findViewById(R.id.block).performClick();
-        waitForUndoButton();
-        mNotificationInfo.handleCloseControls(true, false);
-
-        ArgumentCaptor<LogMaker> logMakerCaptor = ArgumentCaptor.forClass(LogMaker.class);
-        verify(mMetricsLogger, times(3)).write(logMakerCaptor.capture());
-        assertEquals(MetricsProto.MetricsEvent.TYPE_ACTION,
-                logMakerCaptor.getValue().getType());
-        assertEquals(IMPORTANCE_NONE - IMPORTANCE_LOW,
-                logMakerCaptor.getValue().getSubtype());
-
-        mTestableLooper.processAllMessages();
-        ArgumentCaptor<NotificationChannel> updated =
-                ArgumentCaptor.forClass(NotificationChannel.class);
-        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
-                anyString(), eq(TEST_UID), updated.capture());
-        assertTrue((updated.getValue().getUserLockedFields()
-                & USER_LOCKED_IMPORTANCE) != 0);
-        assertEquals(IMPORTANCE_NONE, updated.getValue().getImportance());
-    }
-
-
-    @Test
-    public void testNonBlockableAppDoesNotBecomeMin() throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
-                true, false, IMPORTANCE_DEFAULT, false);
-        mNotificationInfo.findViewById(R.id.minimize).performClick();
-        waitForUndoButton();
-
-        mTestableLooper.processAllMessages();
-        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
-                anyString(), eq(TEST_UID), any());
-    }
-
-    @Test
-    public void testMinChangedCallsUpdateNotificationChannel() throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
-                true, false, IMPORTANCE_DEFAULT, false);
-
-        mNotificationInfo.findViewById(R.id.minimize).performClick();
-        waitForUndoButton();
-        mNotificationInfo.handleCloseControls(true, false);
-
-        mTestableLooper.processAllMessages();
-        ArgumentCaptor<NotificationChannel> updated =
-                ArgumentCaptor.forClass(NotificationChannel.class);
-        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
-                anyString(), eq(TEST_UID), updated.capture());
-        assertTrue((updated.getValue().getUserLockedFields()
-                & USER_LOCKED_IMPORTANCE) != 0);
-        assertEquals(IMPORTANCE_MIN, updated.getValue().getImportance());
-    }
-
-    @Test
     public void testSilentlyChangedCallsUpdateNotificationChannel_blockingHelper()
             throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
@@ -950,7 +643,6 @@
                 true /*provisioned */,
                 false /* isNonblockable */,
                 true /* isForBlockingHelper */,
-                true /* isUserSentimentNegative */,
                 IMPORTANCE_DEFAULT,
                 false);
 
@@ -969,12 +661,13 @@
     }
 
     @Test
-    public void testKeepUpdatesNotificationChannel() throws Exception {
+    public void testKeepUpdatesNotificationChannel_blockingHelper() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
-                IMPORTANCE_DEFAULT, false);
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+                IMPORTANCE_LOW, false);
 
+        mNotificationInfo.findViewById(R.id.keep_showing).performClick();
         mNotificationInfo.handleCloseControls(true, false);
 
         mTestableLooper.processAllMessages();
@@ -987,14 +680,32 @@
     }
 
     @Test
+    public void testNoActionsUpdatesNotificationChannel_blockingHelper() throws Exception {
+        mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
+        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
+                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
+                IMPORTANCE_DEFAULT, false);
+
+        mNotificationInfo.handleCloseControls(true, false);
+
+        mTestableLooper.processAllMessages();
+        ArgumentCaptor<NotificationChannel> updated =
+                ArgumentCaptor.forClass(NotificationChannel.class);
+        verify(mMockINotificationManager, times(1)).updateNotificationChannelForPackage(
+                anyString(), eq(TEST_UID), updated.capture());
+        assertTrue(0 != (mNotificationChannel.getUserLockedFields() & USER_LOCKED_IMPORTANCE));
+        assertEquals(IMPORTANCE_DEFAULT, mNotificationChannel.getImportance());
+    }
+
+    @Test
     public void testSilenceCallsUpdateNotificationChannel() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_DEFAULT);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
                 IMPORTANCE_DEFAULT, true);
 
-        mNotificationInfo.findViewById(R.id.int_silent_wrapper).performClick();
-        mNotificationInfo.findViewById(R.id.done_button).performClick();
+        mNotificationInfo.findViewById(R.id.silent_row).performClick();
+        mNotificationInfo.findViewById(R.id.done).performClick();
         mNotificationInfo.handleCloseControls(true, false);
 
         mTestableLooper.processAllMessages();
@@ -1014,8 +725,8 @@
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
                 IMPORTANCE_DEFAULT, false);
 
-        mNotificationInfo.findViewById(R.id.int_alert_wrapper).performClick();
-        mNotificationInfo.findViewById(R.id.done_button).performClick();
+        mNotificationInfo.findViewById(R.id.alert_row).performClick();
+        mNotificationInfo.findViewById(R.id.done).performClick();
         mNotificationInfo.handleCloseControls(true, false);
 
         mTestableLooper.processAllMessages();
@@ -1036,8 +747,8 @@
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
                 IMPORTANCE_DEFAULT, true);
 
-        mNotificationInfo.findViewById(R.id.int_silent_wrapper).performClick();
-        mNotificationInfo.findViewById(R.id.done_button).performClick();
+        mNotificationInfo.findViewById(R.id.silent_row).performClick();
+        mNotificationInfo.findViewById(R.id.done).performClick();
         mNotificationInfo.handleCloseControls(true, false);
 
         mTestableLooper.processAllMessages();
@@ -1058,8 +769,8 @@
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
                 IMPORTANCE_LOW, false);
 
-        mNotificationInfo.findViewById(R.id.int_alert_wrapper).performClick();
-        mNotificationInfo.findViewById(R.id.done_button).performClick();
+        mNotificationInfo.findViewById(R.id.alert_row).performClick();
+        mNotificationInfo.findViewById(R.id.done).performClick();
         mNotificationInfo.handleCloseControls(true, false);
 
         mTestableLooper.processAllMessages();
@@ -1073,30 +784,14 @@
     }
 
     @Test
-    public void testCloseControlsDoesNotUpdateMinIfSaveIsFalse() throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
-                true, false, IMPORTANCE_DEFAULT, false);
-
-        mNotificationInfo.findViewById(R.id.minimize).performClick();
-        waitForUndoButton();
-        mNotificationInfo.handleCloseControls(false, false);
-
-        mTestableLooper.processAllMessages();
-        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
-                eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel));
-    }
-
-    @Test
     public void testCloseControlsDoesNotUpdateIfSaveIsFalse() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, false,
-                IMPORTANCE_DEFAULT, false);
+                IMPORTANCE_LOW, false);
 
-        mNotificationInfo.findViewById(R.id.int_block_wrapper).performClick();
-        mNotificationInfo.findViewById(R.id.done_button).performClick();
+        mNotificationInfo.findViewById(R.id.alert_row).performClick();
+        mNotificationInfo.findViewById(R.id.done).performClick();
         mNotificationInfo.handleCloseControls(false, false);
 
         mTestableLooper.processAllMessages();
@@ -1105,33 +800,17 @@
     }
 
     @Test
-    public void testBlockDoesNothingIfCheckSaveListenerIsNoOp() throws Exception {
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
-                (Runnable saveImportance, StatusBarNotification sbn) -> {
-                }, null, null, true, true, IMPORTANCE_DEFAULT, false);
-
-        mNotificationInfo.findViewById(R.id.int_block_wrapper).performClick();
-        mTestableLooper.processAllMessages();
-        mNotificationInfo.handleCloseControls(true, false);
-
-        verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
-                eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel));
-    }
-
-    @Test
     public void testCloseControlsUpdatesWhenCheckSaveListenerUsesCallback() throws Exception {
         mNotificationChannel.setImportance(IMPORTANCE_LOW);
         mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
                 TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn,
                 (Runnable saveImportance, StatusBarNotification sbn) -> {
                     saveImportance.run();
-                }, null, null, true, false, IMPORTANCE_DEFAULT, false
+                }, null, null, true, false, IMPORTANCE_LOW, false
         );
 
-        mNotificationInfo.findViewById(R.id.int_block_wrapper).performClick();
-        mNotificationInfo.findViewById(R.id.done_button).performClick();
+        mNotificationInfo.findViewById(R.id.alert_row).performClick();
+        mNotificationInfo.findViewById(R.id.done).performClick();
         mTestableLooper.processAllMessages();
         verify(mMockINotificationManager, never()).updateNotificationChannelForPackage(
                 eq(TEST_PACKAGE_NAME), eq(TEST_UID), eq(mNotificationChannel));
@@ -1147,18 +826,4 @@
     public void testWillBeRemovedReturnsFalseBeforeBind() throws Exception {
         assertFalse(mNotificationInfo.willBeRemoved());
     }
-
-    @Test
-    public void testUndoText_min() throws Exception {
-        mSbn.getNotification().flags = Notification.FLAG_FOREGROUND_SERVICE;
-        mNotificationChannel.setImportance(IMPORTANCE_LOW);
-        mNotificationInfo.bindNotification(mMockPackageManager, mMockINotificationManager,
-                TEST_PACKAGE_NAME, mNotificationChannel, 1, mSbn, null, null, null, true, true,
-                true, false, IMPORTANCE_DEFAULT, false);
-
-        mNotificationInfo.findViewById(R.id.minimize).performClick();
-        waitForUndoButton();
-        TextView confirmationText = mNotificationInfo.findViewById(R.id.confirmation_text);
-        assertTrue(confirmationText.getText().toString().contains("minimized"));
-    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarContextTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarContextTest.java
index 6293b06..e3c081e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarContextTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NavigationBarContextTest.java
@@ -36,6 +36,7 @@
 import com.android.systemui.statusbar.policy.KeyButtonDrawable;
 
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
@@ -173,6 +174,7 @@
     }
 
     @Test
+    @Ignore("b/112934365")
     public void testUpdateIconsDarkIntensity() throws Exception {
         final int unusedColor = 0;
         final Drawable d = mock(Drawable.class);
diff --git a/packages/overlays/NavigationBarModeGesturalOverlay/res/values/config.xml b/packages/overlays/NavigationBarModeGesturalOverlay/res/values/config.xml
index 23d2e7b..704ff2e 100644
--- a/packages/overlays/NavigationBarModeGesturalOverlay/res/values/config.xml
+++ b/packages/overlays/NavigationBarModeGesturalOverlay/res/values/config.xml
@@ -31,6 +31,6 @@
     <bool name="config_navBarTapThrough">true</bool>
 
     <!-- Controls the size of the back gesture inset. -->
-    <dimen name="config_backGestureInset">48dp</dimen>
+    <dimen name="config_backGestureInset">20dp</dimen>
 
 </resources>
diff --git a/proto/src/metrics_constants/metrics_constants.proto b/proto/src/metrics_constants/metrics_constants.proto
index ce39a70..a88ae9e 100644
--- a/proto/src/metrics_constants/metrics_constants.proto
+++ b/proto/src/metrics_constants/metrics_constants.proto
@@ -7162,6 +7162,19 @@
     // Open: Settings > app > bubble settings > confirmation dialog
     DIALOG_APP_BUBBLE_SETTINGS = 1702;
 
+    // ACTION: Display white balance setting enabled or disabled.
+    // CATEGORY: SETTINGS
+    // OS: Q
+    ACTION_DISPLAY_WHITE_BALANCE_SETTING_CHANGED = 1703;
+
+    // Action: ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET
+    // Direct share target hashed with rotating salt
+    FIELD_HASHED_TARGET_NAME = 1704;
+
+    // Action: ACTION_ACTIVITY_CHOOSER_PICKED_SERVICE_TARGET
+    // Salt generation for the above hashed direct share target
+    FIELD_HASHED_TARGET_SALT_GEN = 1705;
+
     // ---- End Q Constants, all Q constants go above this line ----
     // Add new aosp constants above this line.
     // END OF AOSP CONSTANTS
diff --git a/services/core/java/com/android/server/DynamicSystemService.java b/services/core/java/com/android/server/DynamicSystemService.java
index 99bbcf8..7a1697f 100644
--- a/services/core/java/com/android/server/DynamicSystemService.java
+++ b/services/core/java/com/android/server/DynamicSystemService.java
@@ -18,16 +18,23 @@
 
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.gsi.GsiInstallParams;
 import android.gsi.GsiProgress;
 import android.gsi.IGsiService;
+import android.os.Environment;
 import android.os.IBinder;
 import android.os.IBinder.DeathRecipient;
 import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.SystemProperties;
+import android.os.UserHandle;
 import android.os.image.IDynamicSystemService;
+import android.os.storage.StorageManager;
+import android.os.storage.StorageVolume;
 import android.util.Slog;
 
+import java.io.File;
+
 /**
  * DynamicSystemService implements IDynamicSystemService. It provides permission check before
  * passing requests to gsid
@@ -36,7 +43,7 @@
     private static final String TAG = "DynamicSystemService";
     private static final String NO_SERVICE_ERROR = "no gsiservice";
     private static final int GSID_ROUGH_TIMEOUT_MS = 8192;
-
+    private static final String PATH_DEFAULT = "/data/gsi";
     private Context mContext;
     private volatile IGsiService mGsiService;
 
@@ -100,7 +107,32 @@
 
     @Override
     public boolean startInstallation(long systemSize, long userdataSize) throws RemoteException {
-        return getGsiService().startGsiInstall(systemSize, userdataSize, true) == 0;
+        // priority from high to low: sysprop -> sdcard -> /data
+        String path = SystemProperties.get("os.aot.path");
+        if (path.isEmpty()) {
+            final int userId = UserHandle.myUserId();
+            final StorageVolume[] volumes =
+                    StorageManager.getVolumeList(userId, StorageManager.FLAG_FOR_WRITE);
+            for (StorageVolume volume : volumes) {
+                if (volume.isEmulated()) continue;
+                if (!volume.isRemovable()) continue;
+                if (!Environment.MEDIA_MOUNTED.equals(volume.getState())) continue;
+                File sdCard = volume.getPathFile();
+                if (sdCard.isDirectory()) {
+                    path = sdCard.getPath();
+                    break;
+                }
+            }
+            if (path.isEmpty()) {
+                path = PATH_DEFAULT;
+            }
+            Slog.i(TAG, "startInstallation -> " + path);
+        }
+        GsiInstallParams installParams = new GsiInstallParams();
+        installParams.installDir = path;
+        installParams.gsiSize = systemSize;
+        installParams.userdataSize = userdataSize;
+        return getGsiService().beginGsiInstall(installParams) == 0;
     }
 
     @Override
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index d1ae284..3dc8af1 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -89,10 +89,10 @@
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.app.IBatteryStats;
-import com.android.internal.net.NetworkStatsFactory;
 import com.android.internal.util.DumpUtils;
 import com.android.internal.util.HexDump;
 import com.android.internal.util.Preconditions;
+import com.android.server.net.NetworkStatsFactory;
 
 import com.google.android.collect.Maps;
 
diff --git a/services/core/java/com/android/server/ServiceWatcher.java b/services/core/java/com/android/server/ServiceWatcher.java
index a5a515f..e3dc3b7 100644
--- a/services/core/java/com/android/server/ServiceWatcher.java
+++ b/services/core/java/com/android/server/ServiceWatcher.java
@@ -382,7 +382,13 @@
     /**
      * Runs the given function synchronously if currently connected, and returns the default value
      * if not currently connected or if any exception is thrown.
+     *
+     * @deprecated Using this function is an indication that your AIDL API is broken. Calls from
+     * system server to outside MUST be one-way, and so cannot return any result, and this
+     * method should not be needed or used. Use a separate callback interface to allow outside
+     * components to return results back to the system server.
      */
+    @Deprecated
     public final <T> T runOnBinderBlocking(BlockingBinderRunner<T> runner, T defaultValue) {
         try {
             return runOnHandlerBlocking(() -> {
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index 4598d3e..3079192 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -929,13 +929,20 @@
     private void initIfBootedAndConnected() {
         Slog.d(TAG, "Thinking about init, mBootCompleted=" + mBootCompleted
                 + ", mDaemonConnected=" + mDaemonConnected);
-        if (mBootCompleted && mDaemonConnected
-                && !StorageManager.isFileEncryptedNativeOnly()) {
-            // When booting a device without native support, make sure that our
-            // user directories are locked or unlocked based on the current
-            // emulation status.
-            final boolean initLocked = StorageManager.isFileEncryptedEmulatedOnly();
-            Slog.d(TAG, "Setting up emulation state, initlocked=" + initLocked);
+        if (mBootCompleted && mDaemonConnected) {
+            // Tell vold to lock or unlock the user directories based on the
+            // current file-based encryption status.
+            final boolean initLocked;
+            if (StorageManager.isFileEncryptedNativeOrEmulated()) {
+                // For native FBE this is a no-op after reboot, but this is
+                // still needed in case of framework restarts.
+                Slog.d(TAG, "FBE is enabled; ensuring all user directories are locked.");
+                initLocked = true;
+            } else {
+                // This is in case FBE emulation was turned off.
+                Slog.d(TAG, "FBE is disabled; ensuring the FBE emulation state is cleared.");
+                initLocked = false;
+            }
             final List<UserInfo> users = mContext.getSystemService(UserManager.class).getUsers();
             for (UserInfo user : users) {
                 try {
@@ -3840,7 +3847,9 @@
                     uid, packageName, READ_EXTERNAL_STORAGE, OP_READ_EXTERNAL_STORAGE);
             final boolean hasWrite = StorageManager.checkPermissionAndAppOp(mContext, false, 0,
                     uid, packageName, WRITE_EXTERNAL_STORAGE, OP_WRITE_EXTERNAL_STORAGE);
-            final boolean hasStorage = hasRead || hasWrite;
+            // STOPSHIP: remove this temporary hack once we have dynamic runtime
+            // permissions fully enabled again
+            final boolean hasStorage = hasRead || hasWrite || true;
 
             // We're only willing to give out broad access if they also hold
             // runtime permission; this is a firm CDD requirement
diff --git a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
index e42666c..7ab70fa 100644
--- a/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
+++ b/services/core/java/com/android/server/am/ActivityManagerDebugConfig.java
@@ -49,6 +49,7 @@
     static final boolean DEBUG_BROADCAST_BACKGROUND = DEBUG_BROADCAST || false;
     static final boolean DEBUG_BROADCAST_LIGHT = DEBUG_BROADCAST || false;
     static final boolean DEBUG_BROADCAST_DEFERRAL = DEBUG_BROADCAST || false;
+    static final boolean DEBUG_COMPACTION = DEBUG_ALL || false;
     static final boolean DEBUG_LRU = DEBUG_ALL || false;
     static final boolean DEBUG_MU = DEBUG_ALL || false;
     static final boolean DEBUG_NETWORK = DEBUG_ALL || false;
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index a5932cc..1757c98 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -213,6 +213,7 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageManagerInternal.CheckPermissionDelegate;
+import android.content.pm.PackageParser;
 import android.content.pm.ParceledListSlice;
 import android.content.pm.PathPermission;
 import android.content.pm.PermissionInfo;
@@ -18474,7 +18475,9 @@
 
     void updateApplicationInfoLocked(@NonNull List<String> packagesToUpdate, int userId) {
         final boolean updateFrameworkRes = packagesToUpdate.contains("android");
-
+        if (updateFrameworkRes) {
+            PackageParser.readConfigUseRoundIcon(null);
+        }
         mProcessList.updateApplicationInfoLocked(packagesToUpdate, userId, updateFrameworkRes);
 
         if (updateFrameworkRes) {
diff --git a/services/core/java/com/android/server/am/AppCompactor.java b/services/core/java/com/android/server/am/AppCompactor.java
index ac10026..043dc8d 100644
--- a/services/core/java/com/android/server/am/AppCompactor.java
+++ b/services/core/java/com/android/server/am/AppCompactor.java
@@ -18,6 +18,9 @@
 
 import static android.os.Process.THREAD_PRIORITY_FOREGROUND;
 
+import static com.android.server.am.ActivityManagerDebugConfig.DEBUG_COMPACTION;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+
 import android.app.ActivityManager;
 import android.app.ActivityThread;
 import android.os.Debug;
@@ -30,6 +33,7 @@
 import android.provider.DeviceConfig.OnPropertyChangedListener;
 import android.text.TextUtils;
 import android.util.EventLog;
+import android.util.Slog;
 import android.util.StatsLog;
 
 import com.android.internal.annotations.GuardedBy;
@@ -39,7 +43,12 @@
 import java.io.FileOutputStream;
 import java.io.PrintWriter;
 import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.Map;
 import java.util.Random;
+import java.util.Set;
 
 public final class AppCompactor {
 
@@ -55,6 +64,12 @@
     @VisibleForTesting static final String KEY_COMPACT_THROTTLE_6 = "compact_throttle_6";
     @VisibleForTesting static final String KEY_COMPACT_STATSD_SAMPLE_RATE =
             "compact_statsd_sample_rate";
+    @VisibleForTesting static final String KEY_COMPACT_FULL_RSS_THROTTLE_KB =
+            "compact_full_rss_throttle_kb";
+    @VisibleForTesting static final String KEY_COMPACT_FULL_DELTA_RSS_THROTTLE_KB =
+            "compact_full_delta_rss_throttle_kb";
+    @VisibleForTesting static final String KEY_COMPACT_PROC_STATE_THROTTLE =
+            "compact_proc_state_throttle";
 
     // Phenotype sends int configurations and we map them to the strings we'll use on device,
     // preventing a weird string value entering the kernel.
@@ -79,6 +94,11 @@
     @VisibleForTesting static final long DEFAULT_COMPACT_THROTTLE_6 = 10 * 60 * 1000;
     // The sampling rate to push app compaction events into statsd for upload.
     @VisibleForTesting static final float DEFAULT_STATSD_SAMPLE_RATE = 0.1f;
+    @VisibleForTesting static final long DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB = 12_000L;
+    @VisibleForTesting static final long DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB = 8_000L;
+    // Format of this string should be a comma separated list of integers.
+    @VisibleForTesting static final String DEFAULT_COMPACT_PROC_STATE_THROTTLE =
+            String.valueOf(ActivityManager.PROCESS_STATE_RECEIVER);
 
     @VisibleForTesting
     interface PropertyChangedCallbackForTest {
@@ -123,6 +143,12 @@
                             updateCompactionThrottles();
                         } else if (KEY_COMPACT_STATSD_SAMPLE_RATE.equals(name)) {
                             updateStatsdSampleRate();
+                        } else if (KEY_COMPACT_FULL_RSS_THROTTLE_KB.equals(name)) {
+                            updateFullRssThrottle();
+                        } else if (KEY_COMPACT_FULL_DELTA_RSS_THROTTLE_KB.equals(name)) {
+                            updateFullDeltaRssThrottle();
+                        } else if (KEY_COMPACT_PROC_STATE_THROTTLE.equals(name)) {
+                            updateProcStateThrottle();
                         }
                     }
                     if (mTestCallback != null) {
@@ -154,18 +180,42 @@
     @VisibleForTesting volatile long mCompactThrottlePersistent = DEFAULT_COMPACT_THROTTLE_6;
     @GuardedBy("mPhenotypeFlagLock")
     private volatile boolean mUseCompaction = DEFAULT_USE_COMPACTION;
-
     private final Random mRandom = new Random();
     @GuardedBy("mPhenotypeFlagLock")
     @VisibleForTesting volatile float mStatsdSampleRate = DEFAULT_STATSD_SAMPLE_RATE;
+    @GuardedBy("mPhenotypeFlagLock")
+    @VisibleForTesting volatile long mFullAnonRssThrottleKb =
+            DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB;
+    @GuardedBy("mPhenoypeFlagLock")
+    @VisibleForTesting volatile long mFullDeltaRssThrottleKb =
+            DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB;
+    @GuardedBy("mPhenoypeFlagLock")
+    @VisibleForTesting final Set<Integer> mProcStateThrottle;
 
     // Handler on which compaction runs.
     private Handler mCompactionHandler;
 
+    // Maps process ID to last compaction statistics for processes that we've fully compacted. Used
+    // when evaluating throttles that we only consider for "full" compaction, so we don't store
+    // data for "some" compactions.
+    private Map<Integer, LastCompactionStats> mLastCompactionStats =
+            new LinkedHashMap<Integer, LastCompactionStats>() {
+                @Override
+                protected boolean removeEldestEntry(Map.Entry eldest) {
+                    return size() > 100;
+                }
+    };
+
+    private int mSomeCompactionCount;
+    private int mFullCompactionCount;
+    private int mPersistentCompactionCount;
+    private int mBfgsCompactionCount;
+
     public AppCompactor(ActivityManagerService am) {
         mAm = am;
         mCompactionThread = new ServiceThread("CompactionThread",
                 THREAD_PRIORITY_FOREGROUND, true);
+        mProcStateThrottle = new HashSet<>();
     }
 
     @VisibleForTesting
@@ -186,10 +236,12 @@
             updateCompactionActions();
             updateCompactionThrottles();
             updateStatsdSampleRate();
+            updateFullRssThrottle();
+            updateFullDeltaRssThrottle();
+            updateProcStateThrottle();
         }
         Process.setThreadGroupAndCpuset(mCompactionThread.getThreadId(),
                 Process.THREAD_GROUP_SYSTEM);
-
     }
 
     /**
@@ -212,7 +264,33 @@
             pw.println("  " + KEY_COMPACT_THROTTLE_2 + "=" + mCompactThrottleSomeFull);
             pw.println("  " + KEY_COMPACT_THROTTLE_3 + "=" + mCompactThrottleFullSome);
             pw.println("  " + KEY_COMPACT_THROTTLE_4 + "=" + mCompactThrottleFullFull);
+            pw.println("  " + KEY_COMPACT_THROTTLE_5 + "=" + mCompactThrottleBFGS);
+            pw.println("  " + KEY_COMPACT_THROTTLE_6 + "=" + mCompactThrottlePersistent);
             pw.println("  " + KEY_COMPACT_STATSD_SAMPLE_RATE + "=" + mStatsdSampleRate);
+            pw.println("  " + KEY_COMPACT_FULL_RSS_THROTTLE_KB + "="
+                    + mFullAnonRssThrottleKb);
+            pw.println("  " + KEY_COMPACT_FULL_DELTA_RSS_THROTTLE_KB + "="
+                    + mFullDeltaRssThrottleKb);
+            pw.println("  "  + KEY_COMPACT_PROC_STATE_THROTTLE + "="
+                    + Arrays.toString(mProcStateThrottle.toArray(new Integer[0])));
+
+            pw.println("  " + mSomeCompactionCount + " some, " + mFullCompactionCount
+                    + " full, " + mPersistentCompactionCount + " persistent, "
+                    + mBfgsCompactionCount + " BFGS compactions.");
+
+            if (mLastCompactionStats != null) {
+                pw.println("  Tracking last compaction stats for " + mLastCompactionStats.size()
+                        + " processes.");
+                if (DEBUG_COMPACTION) {
+                    for (Map.Entry<Integer, LastCompactionStats> entry
+                            : mLastCompactionStats.entrySet()) {
+                        int pid = entry.getKey();
+                        LastCompactionStats stats = entry.getValue();
+                        pw.println("    " + pid + ": "
+                                + Arrays.toString(stats.getRssAfterCompaction()));
+                    }
+                }
+            }
         }
     }
 
@@ -277,7 +355,7 @@
 
     /**
      * Reads the flag value from DeviceConfig to determine whether app compaction
-     * should be enabled, and starts/stops the compaction thread as needed.
+     * should be enabled, and starts the compaction thread if needed.
      */
     @GuardedBy("mPhenotypeFlagLock")
     private void updateUseCompaction() {
@@ -360,6 +438,58 @@
         mStatsdSampleRate = Math.min(1.0f, Math.max(0.0f, mStatsdSampleRate));
     }
 
+    @GuardedBy("mPhenotypeFlagLock")
+    private void updateFullRssThrottle() {
+        mFullAnonRssThrottleKb = DeviceConfig.getLong(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                KEY_COMPACT_FULL_RSS_THROTTLE_KB, DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB);
+
+        // Don't allow negative values. 0 means don't apply the throttle.
+        if (mFullAnonRssThrottleKb < 0) {
+            mFullAnonRssThrottleKb = DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB;
+        }
+    }
+
+    @GuardedBy("mPhenotypeFlagLock")
+    private void updateFullDeltaRssThrottle() {
+        mFullDeltaRssThrottleKb = DeviceConfig.getLong(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                KEY_COMPACT_FULL_DELTA_RSS_THROTTLE_KB, DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB);
+
+        if (mFullDeltaRssThrottleKb < 0) {
+            mFullDeltaRssThrottleKb = DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB;
+        }
+    }
+
+    @GuardedBy("mPhenotypeFlagLock")
+    private void updateProcStateThrottle() {
+        String procStateThrottleString = DeviceConfig.getString(
+                DeviceConfig.NAMESPACE_ACTIVITY_MANAGER, KEY_COMPACT_PROC_STATE_THROTTLE,
+                DEFAULT_COMPACT_PROC_STATE_THROTTLE);
+        if (!parseProcStateThrottle(procStateThrottleString)) {
+            Slog.w(TAG_AM, "Unable to parse app compact proc state throttle \""
+                    + procStateThrottleString + "\" falling back to default.");
+            if (!parseProcStateThrottle(DEFAULT_COMPACT_PROC_STATE_THROTTLE)) {
+                Slog.wtf(TAG_AM,
+                        "Unable to parse default app compact proc state throttle "
+                                + DEFAULT_COMPACT_PROC_STATE_THROTTLE);
+            }
+        }
+    }
+
+    private boolean parseProcStateThrottle(String procStateThrottleString) {
+        String[] procStates = TextUtils.split(procStateThrottleString, ",");
+        mProcStateThrottle.clear();
+        for (String procState : procStates) {
+            try {
+                mProcStateThrottle.add(Integer.parseInt(procState));
+            } catch (NumberFormatException e) {
+                Slog.e(TAG_AM, "Failed to parse default app compaction proc state: "
+                        + procState);
+                return false;
+            }
+        }
+        return true;
+    }
+
     @VisibleForTesting
     static String compactActionIntToString(int action) {
         switch(action) {
@@ -376,6 +506,22 @@
         }
     }
 
+    @VisibleForTesting static String procStateListToString(Integer... processStates) {
+        return Arrays.toString(processStates);
+    }
+
+    private static final class LastCompactionStats {
+        private final long[] mRssAfterCompaction;
+
+        LastCompactionStats(long[] rss) {
+            mRssAfterCompaction = rss;
+        }
+
+        long[] getRssAfterCompaction() {
+            return mRssAfterCompaction;
+        }
+    }
+
     private final class MemCompactionHandler extends Handler {
         private MemCompactionHandler() {
             super(mCompactionThread.getLooper());
@@ -392,24 +538,34 @@
                     final String name;
                     int pendingAction, lastCompactAction;
                     long lastCompactTime;
+                    LastCompactionStats lastCompactionStats;
+                    int lastOomAdj = msg.arg1;
+                    int procState = msg.arg2;
                     synchronized (mAm) {
                         proc = mPendingCompactionProcesses.remove(0);
 
                         pendingAction = proc.reqCompactAction;
+                        pid = proc.pid;
+                        name = proc.processName;
 
                         // don't compact if the process has returned to perceptible
                         // and this is only a cached/home/prev compaction
                         if ((pendingAction == COMPACT_PROCESS_SOME
                                 || pendingAction == COMPACT_PROCESS_FULL)
                                 && (proc.setAdj <= ProcessList.PERCEPTIBLE_APP_ADJ)) {
+                            if (DEBUG_COMPACTION) {
+                                Slog.d(TAG_AM,
+                                        "Skipping compaction as process " + name + " is "
+                                        + "now perceptible.");
+                            }
                             return;
                         }
 
-                        pid = proc.pid;
-                        name = proc.processName;
-
                         lastCompactAction = proc.lastCompactAction;
                         lastCompactTime = proc.lastCompactTime;
+                        // remove rather than get so that insertion order will be updated when we
+                        // put the post-compaction stats back into the map.
+                        lastCompactionStats = mLastCompactionStats.remove(pid);
                     }
 
                     if (pid == 0) {
@@ -431,6 +587,12 @@
                                     || (lastCompactAction == COMPACT_PROCESS_FULL
                                         && (start - lastCompactTime
                                                 < mCompactThrottleSomeFull))) {
+                                if (DEBUG_COMPACTION) {
+                                    Slog.d(TAG_AM, "Skipping some compaction for " + name
+                                            + ": too soon. throttle=" + mCompactThrottleSomeSome
+                                            + "/" + mCompactThrottleSomeFull + " last="
+                                            + (start - lastCompactTime) + "ms ago");
+                                }
                                 return;
                             }
                         } else if (pendingAction == COMPACT_PROCESS_FULL) {
@@ -439,18 +601,35 @@
                                     || (lastCompactAction == COMPACT_PROCESS_FULL
                                         && (start - lastCompactTime
                                                 < mCompactThrottleFullFull))) {
+                                if (DEBUG_COMPACTION) {
+                                    Slog.d(TAG_AM, "Skipping full compaction for " + name
+                                            + ": too soon. throttle=" + mCompactThrottleFullSome
+                                            + "/" + mCompactThrottleFullFull + " last="
+                                            + (start - lastCompactTime) + "ms ago");
+                                }
                                 return;
                             }
                         } else if (pendingAction == COMPACT_PROCESS_PERSISTENT) {
                             if (start - lastCompactTime < mCompactThrottlePersistent) {
+                                if (DEBUG_COMPACTION) {
+                                    Slog.d(TAG_AM, "Skipping persistent compaction for " + name
+                                            + ": too soon. throttle=" + mCompactThrottlePersistent
+                                            + " last=" + (start - lastCompactTime) + "ms ago");
+                                }
                                 return;
                             }
                         } else if (pendingAction == COMPACT_PROCESS_BFGS) {
                             if (start - lastCompactTime < mCompactThrottleBFGS) {
+                                if (DEBUG_COMPACTION) {
+                                    Slog.d(TAG_AM, "Skipping bfgs compaction for " + name
+                                            + ": too soon. throttle=" + mCompactThrottleBFGS
+                                            + " last=" + (start - lastCompactTime) + "ms ago");
+                                }
                                 return;
                             }
                         }
                     }
+
                     switch (pendingAction) {
                         case COMPACT_PROCESS_SOME:
                             action = mCompactActionSome;
@@ -470,12 +649,77 @@
                         return;
                     }
 
+                    if (mProcStateThrottle.contains(procState)) {
+                        if (DEBUG_COMPACTION) {
+                            Slog.d(TAG_AM, "Skipping full compaction for process " + name
+                                    + "; proc state is " + procState);
+                        }
+                        return;
+                    }
+
+                    long[] rssBefore = Process.getRss(pid);
+                    long anonRssBefore = rssBefore[2];
+
+                    if (rssBefore[0] == 0 && rssBefore[1] == 0 && rssBefore[2] == 0
+                            && rssBefore[3] == 0) {
+                        if (DEBUG_COMPACTION) {
+                            Slog.d(TAG_AM, "Skipping compaction for" + "process " + pid
+                                    + " with no memory usage. Dead?");
+                        }
+                        return;
+                    }
+
+                    if (action.equals(COMPACT_ACTION_FULL) || action.equals(COMPACT_ACTION_ANON)) {
+                        if (mFullAnonRssThrottleKb > 0L
+                                && anonRssBefore < mFullAnonRssThrottleKb) {
+                            if (DEBUG_COMPACTION) {
+                                Slog.d(TAG_AM, "Skipping full compaction for process "
+                                        + name + "; anon RSS is too small: " + anonRssBefore
+                                        + "KB.");
+                            }
+                            return;
+                        }
+
+                        if (lastCompactionStats != null && mFullDeltaRssThrottleKb > 0L) {
+                            long[] lastRss = lastCompactionStats.getRssAfterCompaction();
+                            long absDelta = Math.abs(rssBefore[1] - lastRss[1])
+                                    + Math.abs(rssBefore[2] - lastRss[2])
+                                    + Math.abs(rssBefore[3] - lastRss[3]);
+                            if (absDelta <= mFullDeltaRssThrottleKb) {
+                                if (DEBUG_COMPACTION) {
+                                    Slog.d(TAG_AM, "Skipping full compaction for process "
+                                            + name + "; abs delta is too small: " + absDelta
+                                            + "KB.");
+                                }
+                                return;
+                            }
+                        }
+                    }
+
+                    // Now we've passed through all the throttles and are going to compact, update
+                    // bookkeeping.
+                    switch (pendingAction) {
+                        case COMPACT_PROCESS_SOME:
+                            mSomeCompactionCount++;
+                            break;
+                        case COMPACT_PROCESS_FULL:
+                            mFullCompactionCount++;
+                            break;
+                        case COMPACT_PROCESS_PERSISTENT:
+                            mPersistentCompactionCount++;
+                            break;
+                        case COMPACT_PROCESS_BFGS:
+                            mBfgsCompactionCount++;
+                            break;
+                        default:
+                            break;
+                    }
+
                     try {
                         Trace.traceBegin(Trace.TRACE_TAG_ACTIVITY_MANAGER, "Compact "
                                 + ((pendingAction == COMPACT_PROCESS_SOME) ? "some" : "full")
                                 + ": " + name);
                         long zramFreeKbBefore = Debug.getZramFreeKb();
-                        long[] rssBefore = Process.getRss(pid);
                         FileOutputStream fos = new FileOutputStream("/proc/" + pid + "/reclaim");
                         fos.write(action.getBytes());
                         fos.close();
@@ -487,8 +731,9 @@
                                 rssBefore[0], rssBefore[1], rssBefore[2], rssBefore[3],
                                 rssAfter[0] - rssBefore[0], rssAfter[1] - rssBefore[1],
                                 rssAfter[2] - rssBefore[2], rssAfter[3] - rssBefore[3], time,
-                                lastCompactAction, lastCompactTime, msg.arg1, msg.arg2,
+                                lastCompactAction, lastCompactTime, lastOomAdj, procState,
                                 zramFreeKbBefore, zramFreeKbAfter - zramFreeKbBefore);
+
                         // Note that as above not taking mPhenoTypeFlagLock here to avoid locking
                         // on every single compaction for a flag that will seldom change and the
                         // impact of reading the wrong value here is low.
@@ -496,17 +741,23 @@
                             StatsLog.write(StatsLog.APP_COMPACTED, pid, name, pendingAction,
                                     rssBefore[0], rssBefore[1], rssBefore[2], rssBefore[3],
                                     rssAfter[0], rssAfter[1], rssAfter[2], rssAfter[3], time,
-                                    lastCompactAction, lastCompactTime, msg.arg1,
-                                    ActivityManager.processStateAmToProto(msg.arg2),
+                                    lastCompactAction, lastCompactTime, lastOomAdj,
+                                    ActivityManager.processStateAmToProto(procState),
                                     zramFreeKbBefore, zramFreeKbAfter);
                         }
+
                         synchronized (mAm) {
                             proc.lastCompactTime = end;
                             proc.lastCompactAction = pendingAction;
                         }
-                        Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
+
+                        if (action.equals(COMPACT_ACTION_FULL)
+                                || action.equals(COMPACT_ACTION_ANON)) {
+                            mLastCompactionStats.put(pid, new LastCompactionStats(rssAfter));
+                        }
                     } catch (Exception e) {
                         // nothing to do, presumably the process died
+                    } finally {
                         Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                     }
                     break;
diff --git a/services/core/java/com/android/server/am/BatteryStatsService.java b/services/core/java/com/android/server/am/BatteryStatsService.java
index f86ba27..ae3324c 100644
--- a/services/core/java/com/android/server/am/BatteryStatsService.java
+++ b/services/core/java/com/android/server/am/BatteryStatsService.java
@@ -720,10 +720,10 @@
         }
     }
 
-    public void notePhoneDataConnectionState(int dataType, boolean hasData) {
+    public void notePhoneDataConnectionState(int dataType, boolean hasData, int serviceType) {
         enforceCallingPermission();
         synchronized (mStats) {
-            mStats.notePhoneDataConnectionStateLocked(dataType, hasData);
+            mStats.notePhoneDataConnectionStateLocked(dataType, hasData, serviceType);
         }
     }
 
diff --git a/services/core/java/com/android/server/attention/AttentionManagerService.java b/services/core/java/com/android/server/attention/AttentionManagerService.java
index 1681c5b..bc78d1a 100644
--- a/services/core/java/com/android/server/attention/AttentionManagerService.java
+++ b/services/core/java/com/android/server/attention/AttentionManagerService.java
@@ -19,6 +19,7 @@
 import static android.provider.DeviceConfig.NAMESPACE_ATTENTION_MANAGER_SERVICE;
 import static android.provider.Settings.System.ADAPTIVE_SLEEP;
 import static android.service.attention.AttentionService.ATTENTION_FAILURE_CANCELLED;
+import static android.service.attention.AttentionService.ATTENTION_FAILURE_UNKNOWN;
 
 import android.Manifest;
 import android.annotation.NonNull;
@@ -249,6 +250,7 @@
                 if (userState.mPendingAttentionCheck != null
                         && userState.mPendingAttentionCheck.mCallbackInternal.equals(
                         callbackInternal)) {
+                    userState.mPendingAttentionCheck.cancel(ATTENTION_FAILURE_UNKNOWN);
                     userState.mPendingAttentionCheck = null;
                 }
                 return;
@@ -624,7 +626,7 @@
             if (userState == null) {
                 return;
             }
-            cancel(userState, AttentionService.ATTENTION_FAILURE_UNKNOWN);
+            cancel(userState, ATTENTION_FAILURE_UNKNOWN);
 
             mContext.unbindService(userState.mConnection);
             userState.mConnection.cleanupService();
diff --git a/services/core/java/com/android/server/audio/AudioDeviceInventory.java b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
index 5f624ba..7750bfe 100644
--- a/services/core/java/com/android/server/audio/AudioDeviceInventory.java
+++ b/services/core/java/com/android/server/audio/AudioDeviceInventory.java
@@ -207,7 +207,7 @@
                     mDeviceBroker.setDeviceVolume(
                             streamState, AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP);
                 }
-                makeA2dpDeviceAvailable(address, btDevice.getName(),
+                makeA2dpDeviceAvailable(address, BtHelper.getName(btDevice),
                         "onSetA2dpSinkConnectionState", a2dpCodec);
             }
         }
@@ -257,7 +257,7 @@
             if (isConnected && state != BluetoothProfile.STATE_CONNECTED) {
                 makeHearingAidDeviceUnavailable(address);
             } else if (!isConnected && state == BluetoothProfile.STATE_CONNECTED) {
-                makeHearingAidDeviceAvailable(address, btDevice.getName(),
+                makeHearingAidDeviceAvailable(address, BtHelper.getName(btDevice),
                         "onSetHearingAidConnectionState");
             }
         }
@@ -318,7 +318,7 @@
                 }
             }
             if (AudioSystem.handleDeviceConfigChange(AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, address,
-                    btDevice.getName(), a2dpCodec) != AudioSystem.AUDIO_STATUS_OK) {
+                    BtHelper.getName(btDevice), a2dpCodec) != AudioSystem.AUDIO_STATUS_OK) {
                 int musicDevice = mDeviceBroker.getDeviceForStream(AudioSystem.STREAM_MUSIC);
                 // force A2DP device disconnection in case of error so that AudioService state is
                 // consistent with audio policy manager state
@@ -603,10 +603,9 @@
                 }
                 // A2DP device exists, handle active device change
                 final String existingDevicekey = mConnectedDevices.keyAt(i);
-                final String deviceName = device.getName();
                 mConnectedDevices.remove(existingDevicekey);
                 mConnectedDevices.put(deviceKey, new DeviceInfo(
-                        AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, deviceName,
+                        AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP, BtHelper.getName(device),
                         address, a2dpCodec));
                 mDeviceBroker.postA2dpActiveDeviceChange(
                         new BtHelper.BluetoothA2dpDeviceInfo(
diff --git a/services/core/java/com/android/server/audio/BtHelper.java b/services/core/java/com/android/server/audio/BtHelper.java
index 522a55d..2d9156b 100644
--- a/services/core/java/com/android/server/audio/BtHelper.java
+++ b/services/core/java/com/android/server/audio/BtHelper.java
@@ -152,6 +152,14 @@
         }
     }
 
+    /*package*/ @NonNull static String getName(@NonNull BluetoothDevice device) {
+        final String deviceName = device.getName();
+        if (deviceName == null) {
+            return "";
+        }
+        return deviceName;
+    }
+
     //----------------------------------------------------------------------
     // Interface for AudioDeviceBroker
 
@@ -515,7 +523,7 @@
         if (!BluetoothAdapter.checkBluetoothAddress(address)) {
             address = "";
         }
-        String btDeviceName =  btDevice.getName();
+        String btDeviceName =  getName(btDevice);
         boolean result = false;
         if (isActive) {
             result |= mDeviceBroker.handleDeviceConnection(
diff --git a/services/core/java/com/android/server/biometrics/BiometricService.java b/services/core/java/com/android/server/biometrics/BiometricService.java
index 516844d..a64eacb 100644
--- a/services/core/java/com/android/server/biometrics/BiometricService.java
+++ b/services/core/java/com/android/server/biometrics/BiometricService.java
@@ -19,7 +19,6 @@
 import static android.Manifest.permission.USE_BIOMETRIC;
 import static android.Manifest.permission.USE_BIOMETRIC_INTERNAL;
 import static android.Manifest.permission.USE_FINGERPRINT;
-import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FACE;
 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_FINGERPRINT;
 import static android.hardware.biometrics.BiometricAuthenticator.TYPE_IRIS;
@@ -576,30 +575,9 @@
             if (useDefaultTitle) {
                 checkInternalPermission();
                 // Set the default title if necessary
-                try {
-                    final List<ActivityManager.RunningAppProcessInfo> procs =
-                            ActivityManager.getService().getRunningAppProcesses();
-                    for (int i = 0; i < procs.size(); i++) {
-                        final ActivityManager.RunningAppProcessInfo info = procs.get(i);
-                        if (info.uid == callingUid
-                                && info.importance == IMPORTANCE_FOREGROUND) {
-                            PackageManager pm = getContext().getPackageManager();
-                            final CharSequence label = pm.getApplicationLabel(
-                                    pm.getApplicationInfo(info.processName,
-                                            PackageManager.GET_META_DATA));
-                            final String title = getContext()
-                                    .getString(R.string.biometric_dialog_default_title, label);
-                            if (TextUtils.isEmpty(
-                                    bundle.getCharSequence(BiometricPrompt.KEY_TITLE))) {
-                                bundle.putCharSequence(BiometricPrompt.KEY_TITLE, title);
-                            }
-                            break;
-                        }
-                    }
-                } catch (RemoteException e) {
-                    Slog.e(TAG, "Remote exception", e);
-                } catch (PackageManager.NameNotFoundException e) {
-                    Slog.e(TAG, "Name not found", e);
+                if (TextUtils.isEmpty(bundle.getCharSequence(BiometricPrompt.KEY_TITLE))) {
+                    bundle.putCharSequence(BiometricPrompt.KEY_TITLE,
+                            getContext().getString(R.string.biometric_dialog_default_title));
                 }
             }
 
diff --git a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
index d8e7b7d..c4855c3 100644
--- a/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
+++ b/services/core/java/com/android/server/biometrics/BiometricServiceBase.java
@@ -1045,10 +1045,15 @@
                 }
             } else {
                 currentClient.stop(initiatedByClient);
+
+                // Only post the reset runnable for non-cleanup clients. Cleanup clients should
+                // never be forcibly stopped since they ensure synchronization between HAL and
+                // framework. Thus, we should instead just start the pending client once cleanup
+                // finishes instead of using the reset runnable.
+                mHandler.removeCallbacks(mResetClientState);
+                mHandler.postDelayed(mResetClientState, CANCEL_TIMEOUT_LIMIT);
             }
             mPendingClient = newClient;
-            mHandler.removeCallbacks(mResetClientState);
-            mHandler.postDelayed(mResetClientState, CANCEL_TIMEOUT_LIMIT);
         } else if (newClient != null) {
             // For BiometricPrompt clients, do not start until
             // <Biometric>Service#startPreparedClient is called. BiometricService waits until all
@@ -1225,6 +1230,7 @@
         } else {
             clearEnumerateState();
             if (mPendingClient != null) {
+                Slog.d(getTag(), "Enumerate finished, starting pending client");
                 startClient(mPendingClient, false /* initiatedByClient */);
             }
         }
diff --git a/services/core/java/com/android/server/biometrics/face/FaceService.java b/services/core/java/com/android/server/biometrics/face/FaceService.java
index 5e4bf33..c573bbb 100644
--- a/services/core/java/com/android/server/biometrics/face/FaceService.java
+++ b/services/core/java/com/android/server/biometrics/face/FaceService.java
@@ -397,61 +397,62 @@
         }
 
         @Override
-        public boolean setFeature(int feature, boolean enabled, final byte[] token) {
+        public void setFeature(int feature, boolean enabled, final byte[] token,
+                IFaceServiceReceiver receiver) {
             checkPermission(MANAGE_BIOMETRIC);
 
-            if (!FaceService.this.hasEnrolledBiometrics(mCurrentUserId)) {
-                Slog.e(TAG, "No enrolled biometrics while setting feature: " + feature);
-                return false;
-            }
-
-            final ArrayList<Byte> byteToken = new ArrayList<>();
-            for (int i = 0; i < token.length; i++) {
-                byteToken.add(token[i]);
-            }
-
-            // TODO: Support multiple faces
-            final int faceId = getFirstTemplateForUser(mCurrentUserId);
-
-            if (mDaemon != null) {
-                try {
-                    return mDaemon.setFeature(feature, enabled, byteToken, faceId) == Status.OK;
-                } catch (RemoteException e) {
-                    Slog.e(getTag(), "Unable to set feature: " + feature + " to enabled:" + enabled,
-                            e);
+            mHandler.post(() -> {
+                if (!FaceService.this.hasEnrolledBiometrics(mCurrentUserId)) {
+                    Slog.e(TAG, "No enrolled biometrics while setting feature: " + feature);
+                    return;
                 }
-            }
-            return false;
+
+                final ArrayList<Byte> byteToken = new ArrayList<>();
+                for (int i = 0; i < token.length; i++) {
+                    byteToken.add(token[i]);
+                }
+
+                // TODO: Support multiple faces
+                final int faceId = getFirstTemplateForUser(mCurrentUserId);
+
+                if (mDaemon != null) {
+                    try {
+                        final int result = mDaemon.setFeature(feature, enabled, byteToken, faceId);
+                        receiver.onFeatureSet(result == Status.OK, feature);
+                    } catch (RemoteException e) {
+                        Slog.e(getTag(), "Unable to set feature: " + feature
+                                        + " to enabled:" + enabled, e);
+                    }
+                }
+            });
+
         }
 
         @Override
-        public boolean getFeature(int feature) {
+        public void getFeature(int feature, IFaceServiceReceiver receiver) {
             checkPermission(MANAGE_BIOMETRIC);
 
-            // This should ideally return tri-state, but the user isn't shown settings unless
-            // they are enrolled so it's fine for now.
-            if (!FaceService.this.hasEnrolledBiometrics(mCurrentUserId)) {
-                Slog.e(TAG, "No enrolled biometrics while getting feature: " + feature);
-                return false;
-            }
-
-            // TODO: Support multiple faces
-            final int faceId = getFirstTemplateForUser(mCurrentUserId);
-
-            if (mDaemon != null) {
-                try {
-                    OptionalBool result = mDaemon.getFeature(feature, faceId);
-                    if (result.status == Status.OK) {
-                        return result.value;
-                    } else {
-                        // Same tri-state comment applies here.
-                        return false;
-                    }
-                } catch (RemoteException e) {
-                    Slog.e(getTag(), "Unable to getRequireAttention", e);
+            mHandler.post(() -> {
+                // This should ideally return tri-state, but the user isn't shown settings unless
+                // they are enrolled so it's fine for now.
+                if (!FaceService.this.hasEnrolledBiometrics(mCurrentUserId)) {
+                    Slog.e(TAG, "No enrolled biometrics while getting feature: " + feature);
+                    return;
                 }
-            }
-            return false;
+
+                // TODO: Support multiple faces
+                final int faceId = getFirstTemplateForUser(mCurrentUserId);
+
+                if (mDaemon != null) {
+                    try {
+                        OptionalBool result = mDaemon.getFeature(feature, faceId);
+                        receiver.onFeatureGet(result.status == Status.OK, feature, result.value);
+                    } catch (RemoteException e) {
+                        Slog.e(getTag(), "Unable to getRequireAttention", e);
+                    }
+                }
+            });
+
         }
 
         @Override
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/AnnouncementAggregator.java b/services/core/java/com/android/server/broadcastradio/hal2/AnnouncementAggregator.java
index 0bbaf25..5307697 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/AnnouncementAggregator.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/AnnouncementAggregator.java
@@ -90,7 +90,11 @@
             for (ModuleWatcher watcher : mModuleWatchers) {
                 combined.addAll(watcher.currentList);
             }
-            TunerCallback.dispatch(() -> mListener.onListUpdated(combined));
+            try {
+                mListener.onListUpdated(combined);
+            } catch (RemoteException ex) {
+                Slog.e(TAG, "mListener.onListUpdated() failed: ", ex);
+            }
         }
     }
 
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java b/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java
index 2df8982..5e79c59 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/BroadcastRadioService.java
@@ -54,13 +54,6 @@
     @GuardedBy("mLock")
     private final Map<Integer, RadioModule> mModules = new HashMap<>();
 
-    // Map from module ID to TunerSession created by openSession().
-    //
-    // Because this service currently implements a 1 AIDL to 1 HAL policy, mTunerSessions is used to
-    // enforce the "aggresive open" policy mandated for IBroadcastRadio.openSession(). In the
-    // future, this solution will be replaced with a multiple-AIDL to 1 HAL implementation.
-    private final Map<Integer, TunerSession> mTunerSessions = new HashMap<>();
-
     private IServiceNotification.Stub mServiceListener = new IServiceNotification.Stub() {
         @Override
         public void onRegistration(String fqName, String serviceName, boolean preexisting) {
@@ -81,8 +74,10 @@
                 }
                 Slog.v(TAG, "loaded broadcast radio module " + moduleId + ": " + serviceName
                         + " (HAL 2.0)");
-                closeTunerSessionLocked(moduleId);
-                mModules.put(moduleId, module);
+                RadioModule prevModule = mModules.put(moduleId, module);
+                if (prevModule != null) {
+                    prevModule.closeSessions(RadioTuner.ERROR_HARDWARE_FAILURE);
+                }
 
                 if (newService) {
                     mServiceNameToModuleIdMap.put(serviceName, moduleId);
@@ -105,8 +100,10 @@
             Slog.v(TAG, "serviceDied(" + cookie + ")");
             synchronized (mLock) {
                 int moduleId = (int) cookie;
-                mModules.remove(moduleId);
-                closeTunerSessionLocked(moduleId);
+                RadioModule prevModule = mModules.remove(moduleId);
+                if (prevModule != null) {
+                    prevModule.closeSessions(RadioTuner.ERROR_HARDWARE_FAILURE);
+                }
 
                 for (Map.Entry<String, Integer> entry : mServiceNameToModuleIdMap.entrySet()) {
                     if (entry.getValue() == moduleId) {
@@ -166,13 +163,9 @@
             if (module == null) {
                 throw new IllegalArgumentException("Invalid module ID");
             }
-            closeTunerSessionLocked(moduleId);
         }
 
         TunerSession tunerSession = module.openSession(callback);
-        synchronized (mLock) {
-            mTunerSessions.put(moduleId, tunerSession);
-        }
         if (legacyConfig != null) {
             tunerSession.setConfiguration(legacyConfig);
         }
@@ -198,12 +191,4 @@
         }
         return aggregator;
     }
-
-    private void closeTunerSessionLocked(int moduleId) {
-        TunerSession tunerSession = mTunerSessions.remove(moduleId);
-        if (tunerSession != null) {
-            Slog.d(TAG, "Closing previous TunerSession");
-            tunerSession.close(RadioTuner.ERROR_HARDWARE_FAILURE);
-        }
-    }
 }
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
index 832f8e1..acb0207 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/RadioModule.java
@@ -26,16 +26,26 @@
 import android.hardware.broadcastradio.V2_0.IAnnouncementListener;
 import android.hardware.broadcastradio.V2_0.IBroadcastRadio;
 import android.hardware.broadcastradio.V2_0.ICloseHandle;
+import android.hardware.broadcastradio.V2_0.ITunerCallback;
 import android.hardware.broadcastradio.V2_0.ITunerSession;
+import android.hardware.broadcastradio.V2_0.ProgramInfo;
+import android.hardware.broadcastradio.V2_0.ProgramListChunk;
+import android.hardware.broadcastradio.V2_0.ProgramSelector;
 import android.hardware.broadcastradio.V2_0.Result;
+import android.hardware.broadcastradio.V2_0.VendorKeyValue;
 import android.hardware.radio.RadioManager;
+import android.os.DeadObjectException;
 import android.os.RemoteException;
 import android.util.MutableInt;
 import android.util.Slog;
 
+import com.android.internal.annotations.GuardedBy;
+
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Objects;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 class RadioModule {
@@ -44,8 +54,63 @@
     @NonNull private final IBroadcastRadio mService;
     @NonNull public final RadioManager.ModuleProperties mProperties;
 
+    private final Object mLock = new Object();
+
+    @GuardedBy("mLock")
+    private ITunerSession mHalTunerSession;
+
+    // Tracks antenna state reported by HAL (if any).
+    @GuardedBy("mLock")
+    private Boolean mAntennaConnected = null;
+
+    @GuardedBy("mLock")
+    private RadioManager.ProgramInfo mProgramInfo = null;
+
+    // Callback registered with the HAL to relay callbacks to AIDL clients.
+    private final ITunerCallback mHalTunerCallback = new ITunerCallback.Stub() {
+        @Override
+        public void onTuneFailed(int result, ProgramSelector programSelector) {
+            fanoutAidlCallback(cb -> cb.onTuneFailed(result, Convert.programSelectorFromHal(
+                    programSelector)));
+        }
+
+        @Override
+        public void onCurrentProgramInfoChanged(ProgramInfo halProgramInfo) {
+            RadioManager.ProgramInfo programInfo = Convert.programInfoFromHal(halProgramInfo);
+            synchronized (mLock) {
+                mProgramInfo = programInfo;
+                fanoutAidlCallbackLocked(cb -> cb.onCurrentProgramInfoChanged(programInfo));
+            }
+        }
+
+        @Override
+        public void onProgramListUpdated(ProgramListChunk programListChunk) {
+            // TODO: Cache per-AIDL client filters, send union of filters to HAL, use filters to fan
+            // back out to clients.
+            fanoutAidlCallback(cb -> cb.onProgramListUpdated(Convert.programListChunkFromHal(
+                    programListChunk)));
+        }
+
+        @Override
+        public void onAntennaStateChange(boolean connected) {
+            synchronized (mLock) {
+                mAntennaConnected = connected;
+                fanoutAidlCallbackLocked(cb -> cb.onAntennaState(connected));
+            }
+        }
+
+        @Override
+        public void onParametersUpdated(ArrayList<VendorKeyValue> parameters) {
+            fanoutAidlCallback(cb -> cb.onParametersUpdated(Convert.vendorInfoFromHal(parameters)));
+        }
+    };
+
+    // Collection of active AIDL tuner sessions created through openSession().
+    @GuardedBy("mLock")
+    private final Set<TunerSession> mAidlTunerSessions = new HashSet<>();
+
     private RadioModule(@NonNull IBroadcastRadio service,
-            @NonNull RadioManager.ModuleProperties properties) {
+            @NonNull RadioManager.ModuleProperties properties) throws RemoteException {
         mProperties = Objects.requireNonNull(properties);
         mService = Objects.requireNonNull(service);
     }
@@ -81,21 +146,85 @@
 
     public @NonNull TunerSession openSession(@NonNull android.hardware.radio.ITunerCallback userCb)
             throws RemoteException {
-        TunerCallback cb = new TunerCallback(Objects.requireNonNull(userCb));
-        Mutable<ITunerSession> hwSession = new Mutable<>();
-        MutableInt halResult = new MutableInt(Result.UNKNOWN_ERROR);
+        synchronized (mLock) {
+            if (mHalTunerSession == null) {
+                Mutable<ITunerSession> hwSession = new Mutable<>();
+                mService.openSession(mHalTunerCallback, (result, session) -> {
+                    Convert.throwOnError("openSession", result);
+                    hwSession.value = session;
+                });
+                mHalTunerSession = Objects.requireNonNull(hwSession.value);
+            }
+            TunerSession tunerSession = new TunerSession(this, mHalTunerSession, userCb);
+            mAidlTunerSessions.add(tunerSession);
 
-        synchronized (mService) {
-            mService.openSession(cb, (result, session) -> {
-                hwSession.value = session;
-                halResult.value = result;
-            });
+            // Propagate state to new client. Note: These callbacks are invoked while holding mLock
+            // to prevent race conditions with new callbacks from the HAL.
+            if (mAntennaConnected != null) {
+                userCb.onAntennaState(mAntennaConnected);
+            }
+            if (mProgramInfo != null) {
+                userCb.onCurrentProgramInfoChanged(mProgramInfo);
+            }
+
+            return tunerSession;
         }
+    }
 
-        Convert.throwOnError("openSession", halResult.value);
-        Objects.requireNonNull(hwSession.value);
+    public void closeSessions(Integer error) {
+        // Copy the contents of mAidlTunerSessions into a local array because TunerSession.close()
+        // must be called without mAidlTunerSessions locked because it can call
+        // onTunerSessionClosed().
+        TunerSession[] tunerSessions;
+        synchronized (mLock) {
+            tunerSessions = new TunerSession[mAidlTunerSessions.size()];
+            mAidlTunerSessions.toArray(tunerSessions);
+            mAidlTunerSessions.clear();
+        }
+        for (TunerSession tunerSession : tunerSessions) {
+            tunerSession.close(error);
+        }
+    }
 
-        return new TunerSession(this, hwSession.value, cb);
+    void onTunerSessionClosed(TunerSession tunerSession) {
+        synchronized (mLock) {
+            mAidlTunerSessions.remove(tunerSession);
+            if (mAidlTunerSessions.isEmpty() && mHalTunerSession != null) {
+                Slog.v(TAG, "closing HAL tuner session");
+                try {
+                    mHalTunerSession.close();
+                } catch (RemoteException ex) {
+                    Slog.e(TAG, "mHalTunerSession.close() failed: ", ex);
+                }
+                mHalTunerSession = null;
+            }
+        }
+    }
+
+    interface AidlCallbackRunnable {
+        void run(android.hardware.radio.ITunerCallback callback) throws RemoteException;
+    }
+
+    // Invokes runnable with each TunerSession currently open.
+    void fanoutAidlCallback(AidlCallbackRunnable runnable) {
+        synchronized (mLock) {
+            fanoutAidlCallbackLocked(runnable);
+        }
+    }
+
+    private void fanoutAidlCallbackLocked(AidlCallbackRunnable runnable) {
+        for (TunerSession tunerSession : mAidlTunerSessions) {
+            try {
+                runnable.run(tunerSession.mCallback);
+            } catch (DeadObjectException ex) {
+                // The other side died without calling close(), so just purge it from our
+                // records.
+                Slog.e(TAG, "Removing dead TunerSession");
+                mAidlTunerSessions.remove(tunerSession);
+            } catch (RemoteException ex) {
+                Slog.e(TAG, "Failed to invoke ITunerCallback: ", ex);
+            }
+        }
     }
 
     public android.hardware.radio.ICloseHandle addAnnouncementListener(@NonNull int[] enabledTypes,
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/TunerCallback.java b/services/core/java/com/android/server/broadcastradio/hal2/TunerCallback.java
deleted file mode 100644
index 3c4b49c..0000000
--- a/services/core/java/com/android/server/broadcastradio/hal2/TunerCallback.java
+++ /dev/null
@@ -1,76 +0,0 @@
-/**
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.broadcastradio.hal2;
-
-import android.annotation.NonNull;
-import android.hardware.broadcastradio.V2_0.ITunerCallback;
-import android.hardware.broadcastradio.V2_0.ProgramInfo;
-import android.hardware.broadcastradio.V2_0.ProgramListChunk;
-import android.hardware.broadcastradio.V2_0.ProgramSelector;
-import android.hardware.broadcastradio.V2_0.VendorKeyValue;
-import android.os.RemoteException;
-import android.util.Slog;
-
-import java.util.ArrayList;
-import java.util.Objects;
-
-class TunerCallback extends ITunerCallback.Stub {
-    private static final String TAG = "BcRadio2Srv.cb";
-
-    final android.hardware.radio.ITunerCallback mClientCb;
-
-    interface RunnableThrowingRemoteException {
-        void run() throws RemoteException;
-    }
-
-    TunerCallback(@NonNull android.hardware.radio.ITunerCallback clientCallback) {
-        mClientCb = Objects.requireNonNull(clientCallback);
-    }
-
-    static void dispatch(RunnableThrowingRemoteException func) {
-        try {
-            func.run();
-        } catch (RemoteException ex) {
-            Slog.e(TAG, "callback call failed", ex);
-        }
-    }
-
-    @Override
-    public void onTuneFailed(int result, ProgramSelector selector) {
-        dispatch(() -> mClientCb.onTuneFailed(result, Convert.programSelectorFromHal(selector)));
-    }
-
-    @Override
-    public void onCurrentProgramInfoChanged(ProgramInfo info) {
-        dispatch(() -> mClientCb.onCurrentProgramInfoChanged(Convert.programInfoFromHal(info)));
-    }
-
-    @Override
-    public void onProgramListUpdated(ProgramListChunk chunk) {
-        dispatch(() -> mClientCb.onProgramListUpdated(Convert.programListChunkFromHal(chunk)));
-    }
-
-    @Override
-    public void onAntennaStateChange(boolean connected) {
-        dispatch(() -> mClientCb.onAntennaState(connected));
-    }
-
-    @Override
-    public void onParametersUpdated(ArrayList<VendorKeyValue> parameters) {
-        dispatch(() -> mClientCb.onParametersUpdated(Convert.vendorInfoFromHal(parameters)));
-    }
-}
diff --git a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
index 05ca144..008fea5 100644
--- a/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
+++ b/services/core/java/com/android/server/broadcastradio/hal2/TunerSession.java
@@ -43,7 +43,7 @@
 
     private final RadioModule mModule;
     private final ITunerSession mHwSession;
-    private final TunerCallback mCallback;
+    final android.hardware.radio.ITunerCallback mCallback;
     private boolean mIsClosed = false;
     private boolean mIsMuted = false;
 
@@ -51,7 +51,7 @@
     private RadioManager.BandConfig mDummyConfig = null;
 
     TunerSession(@NonNull RadioModule module, @NonNull ITunerSession hwSession,
-            @NonNull TunerCallback callback) {
+            @NonNull android.hardware.radio.ITunerCallback callback) {
         mModule = Objects.requireNonNull(module);
         mHwSession = Objects.requireNonNull(hwSession);
         mCallback = Objects.requireNonNull(callback);
@@ -73,9 +73,14 @@
         synchronized (mLock) {
             if (mIsClosed) return;
             if (error != null) {
-                TunerCallback.dispatch(() -> mCallback.mClientCb.onError(error));
+                try {
+                    mCallback.onError(error);
+                } catch (RemoteException ex) {
+                    Slog.w(TAG, "mCallback.onError() failed: ", ex);
+                }
             }
             mIsClosed = true;
+            mModule.onTunerSessionClosed(this);
         }
     }
 
@@ -96,7 +101,7 @@
             checkNotClosedLocked();
             mDummyConfig = Objects.requireNonNull(config);
             Slog.i(TAG, "Ignoring setConfiguration - not applicable for broadcastradio HAL 2.x");
-            TunerCallback.dispatch(() -> mCallback.mClientCb.onConfigurationChanged(config));
+            mModule.fanoutAidlCallback(cb -> cb.onConfigurationChanged(config));
         }
     }
 
@@ -174,7 +179,7 @@
     @Override
     public boolean startBackgroundScan() {
         Slog.i(TAG, "Explicit background scan trigger is not supported with HAL 2.x");
-        TunerCallback.dispatch(() -> mCallback.mClientCb.onBackgroundScanComplete());
+        mModule.fanoutAidlCallback(cb -> cb.onBackgroundScanComplete());
         return true;
     }
 
diff --git a/services/core/java/com/android/server/connectivity/DataConnectionStats.java b/services/core/java/com/android/server/connectivity/DataConnectionStats.java
index 227ab23..4990ea1 100644
--- a/services/core/java/com/android/server/connectivity/DataConnectionStats.java
+++ b/services/core/java/com/android/server/connectivity/DataConnectionStats.java
@@ -91,7 +91,8 @@
         if (DEBUG) Log.d(TAG, String.format("Noting data connection for network type %s: %svisible",
                 networkType, visible ? "" : "not "));
         try {
-            mBatteryStats.notePhoneDataConnectionState(networkType, visible);
+            mBatteryStats.notePhoneDataConnectionState(networkType, visible,
+                    mServiceState.getState());
         } catch (RemoteException e) {
             Log.w(TAG, "Error noting data connection state", e);
         }
diff --git a/services/core/java/com/android/server/connectivity/PermissionMonitor.java b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
index da1360d..b6946023 100644
--- a/services/core/java/com/android/server/connectivity/PermissionMonitor.java
+++ b/services/core/java/com/android/server/connectivity/PermissionMonitor.java
@@ -469,7 +469,10 @@
      */
     @VisibleForTesting
     void sendPackagePermissionsToNetd(SparseIntArray netdPermissionsAppIds) {
-
+        if (mNetd == null) {
+            Log.e(TAG, "Failed to get the netd service");
+            return;
+        }
         ArrayList<Integer> allPermissionAppIds = new ArrayList<>();
         ArrayList<Integer> internetPermissionAppIds = new ArrayList<>();
         ArrayList<Integer> updateStatsPermissionAppIds = new ArrayList<>();
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index e2ea42e..5fb67dd 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -572,9 +572,6 @@
     public void onSwitchUser(@UserIdInt int newUserId) {
         handleSettingsChange(true /* userSwitch */);
         mBrightnessTracker.onSwitchUser(newUserId);
-        if (mDisplayWhiteBalanceSettings != null) {
-            mDisplayWhiteBalanceSettings.onSwitchUser();
-        }
     }
 
     public ParceledListSlice<AmbientBrightnessDayStats> getAmbientBrightnessStats(
diff --git a/services/core/java/com/android/server/display/color/ColorDisplayService.java b/services/core/java/com/android/server/display/color/ColorDisplayService.java
index 4f81c03..9590f81 100644
--- a/services/core/java/com/android/server/display/color/ColorDisplayService.java
+++ b/services/core/java/com/android/server/display/color/ColorDisplayService.java
@@ -105,10 +105,12 @@
      */
     private static final long TRANSITION_DURATION = 3000L;
 
-    private static final int MSG_APPLY_NIGHT_DISPLAY_IMMEDIATE = 0;
-    private static final int MSG_APPLY_NIGHT_DISPLAY_ANIMATED = 1;
-    private static final int MSG_APPLY_GLOBAL_SATURATION = 2;
-    private static final int MSG_APPLY_DISPLAY_WHITE_BALANCE = 3;
+    private static final int MSG_USER_CHANGED = 0;
+    private static final int MSG_SET_UP = 1;
+    private static final int MSG_APPLY_NIGHT_DISPLAY_IMMEDIATE = 2;
+    private static final int MSG_APPLY_NIGHT_DISPLAY_ANIMATED = 3;
+    private static final int MSG_APPLY_GLOBAL_SATURATION = 4;
+    private static final int MSG_APPLY_DISPLAY_WHITE_BALANCE = 5;
 
     /**
      * Return value if a setting has not been set.
@@ -186,7 +188,7 @@
 
             // Register listeners now that boot is complete.
             if (mCurrentUser != UserHandle.USER_NULL && mUserSetupObserver == null) {
-                setUp();
+                mHandler.sendEmptyMessage(MSG_SET_UP);
             }
         }
     }
@@ -196,7 +198,9 @@
         super.onStartUser(userHandle);
 
         if (mCurrentUser == UserHandle.USER_NULL) {
-            onUserChanged(userHandle);
+            final Message message = mHandler.obtainMessage(MSG_USER_CHANGED);
+            message.arg1 = userHandle;
+            mHandler.sendMessage(message);
         }
     }
 
@@ -204,7 +208,9 @@
     public void onSwitchUser(int userHandle) {
         super.onSwitchUser(userHandle);
 
-        onUserChanged(userHandle);
+        final Message message = mHandler.obtainMessage(MSG_USER_CHANGED);
+        message.arg1 = userHandle;
+        mHandler.sendMessage(message);
     }
 
     @Override
@@ -212,7 +218,9 @@
         super.onStopUser(userHandle);
 
         if (mCurrentUser == userHandle) {
-            onUserChanged(UserHandle.USER_NULL);
+            final Message message = mHandler.obtainMessage(MSG_USER_CHANGED);
+            message.arg1 = UserHandle.USER_NULL;
+            mHandler.sendMessage(message);
         }
     }
 
@@ -262,7 +270,7 @@
 
         // Listen for external changes to any of the settings.
         if (mContentObserver == null) {
-            mContentObserver = new ContentObserver(new Handler(DisplayThread.get().getLooper())) {
+            mContentObserver = new ContentObserver(mHandler) {
                 @Override
                 public void onChange(boolean selfChange, Uri uri) {
                     super.onChange(selfChange, uri);
@@ -467,6 +475,9 @@
      * Apply the accessibility daltonizer transform based on the settings value.
      */
     private void onAccessibilityDaltonizerChanged() {
+        if (mCurrentUser == UserHandle.USER_NULL) {
+            return;
+        }
         final boolean enabled = Secure.getIntForUser(getContext().getContentResolver(),
                 Secure.ACCESSIBILITY_DISPLAY_DALTONIZER_ENABLED, 0, mCurrentUser) != 0;
         final int daltonizerMode = enabled ? Secure.getIntForUser(getContext().getContentResolver(),
@@ -490,6 +501,9 @@
      * Apply the accessibility inversion transform based on the settings value.
      */
     private void onAccessibilityInversionChanged() {
+        if (mCurrentUser == UserHandle.USER_NULL) {
+            return;
+        }
         final boolean enabled = Secure.getIntForUser(getContext().getContentResolver(),
                 Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, mCurrentUser) != 0;
         final DisplayTransformManager dtm = getLocalService(DisplayTransformManager.class);
@@ -596,7 +610,19 @@
         }
     }
 
+    private boolean setDisplayWhiteBalanceSettingEnabled(boolean enabled) {
+        if (mCurrentUser == UserHandle.USER_NULL) {
+            return false;
+        }
+        return Secure.putIntForUser(getContext().getContentResolver(),
+                Secure.DISPLAY_WHITE_BALANCE_ENABLED,
+                enabled ? 1 : 0, mCurrentUser);
+    }
+
     private boolean isDisplayWhiteBalanceSettingEnabled() {
+        if (mCurrentUser == UserHandle.USER_NULL) {
+            return false;
+        }
         return Secure.getIntForUser(getContext().getContentResolver(),
                 Secure.DISPLAY_WHITE_BALANCE_ENABLED, 0, mCurrentUser) == 1;
     }
@@ -648,6 +674,9 @@
     }
 
     private int getNightDisplayAutoModeRawInternal() {
+        if (mCurrentUser == UserHandle.USER_NULL) {
+            return NOT_SET;
+        }
         return Secure
                 .getIntForUser(getContext().getContentResolver(), Secure.NIGHT_DISPLAY_AUTO_MODE,
                         NOT_SET, mCurrentUser);
@@ -1214,6 +1243,13 @@
         }
 
         /**
+         * Returns whether Display white balance is currently enabled.
+         */
+        public boolean isDisplayWhiteBalanceEnabled() {
+            return isDisplayWhiteBalanceSettingEnabled();
+        }
+
+        /**
          * Adds a {@link WeakReference<ColorTransformController>} for a newly started activity, and
          * invokes {@link ColorTransformController#applyAppSaturation(float[], float[])} if needed.
          */
@@ -1233,7 +1269,7 @@
          * Notify that the display white balance status has changed, either due to preemption by
          * another transform or the feature being turned off.
          */
-        void onDisplayWhiteBalanceStatusChanged(boolean enabled);
+        void onDisplayWhiteBalanceStatusChanged(boolean activated);
     }
 
     private final class TintHandler extends Handler {
@@ -1245,6 +1281,12 @@
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
+                case MSG_USER_CHANGED:
+                    onUserChanged(msg.arg1);
+                    break;
+                case MSG_SET_UP:
+                    setUp();
+                    break;
                 case MSG_APPLY_GLOBAL_SATURATION:
                     mGlobalSaturationTintController.setMatrix(msg.arg1);
                     applyTint(mGlobalSaturationTintController, false);
@@ -1500,6 +1542,29 @@
         }
 
         @Override
+        public boolean setDisplayWhiteBalanceEnabled(boolean enabled) {
+            getContext().enforceCallingOrSelfPermission(
+                    Manifest.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS,
+                    "Permission required to set night display activated");
+            final long token = Binder.clearCallingIdentity();
+            try {
+                return setDisplayWhiteBalanceSettingEnabled(enabled);
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
+        public boolean isDisplayWhiteBalanceEnabled() {
+            final long token = Binder.clearCallingIdentity();
+            try {
+                return isDisplayWhiteBalanceSettingEnabled();
+            } finally {
+                Binder.restoreCallingIdentity(token);
+            }
+        }
+
+        @Override
         public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
             if (!DumpUtils.checkDumpPermission(getContext(), TAG, pw)) {
                 return;
diff --git a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceSettings.java b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceSettings.java
index 1b7251c..6e78894 100644
--- a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceSettings.java
+++ b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceSettings.java
@@ -18,13 +18,9 @@
 
 import android.annotation.NonNull;
 import android.content.Context;
-import android.database.ContentObserver;
-import android.net.Uri;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
-import android.os.UserHandle;
-import android.provider.Settings.Secure;
 import android.util.Slog;
 
 import com.android.internal.util.Preconditions;
@@ -46,22 +42,19 @@
     protected static final String TAG = "DisplayWhiteBalanceSettings";
     protected boolean mLoggingEnabled;
 
-    private static final String SETTING_URI = Secure.DISPLAY_WHITE_BALANCE_ENABLED;
-    private static final int SETTING_DEFAULT = 0;
-    private static final int SETTING_ENABLED = 1;
-
     private static final int MSG_SET_ACTIVE = 1;
 
     private final Context mContext;
     private final Handler mHandler;
-    private final SettingsObserver mSettingsObserver;
+
+    private final ColorDisplayServiceInternal mCdsi;
 
     // To decouple the DisplayPowerController from the DisplayWhiteBalanceSettings, the DPC
     // implements Callbacks and passes itself to the DWBS so it can call back into it without
     // knowing about it.
     private Callbacks mCallbacks;
 
-    private int mSetting;
+    private boolean mEnabled;
     private boolean mActive;
 
     /**
@@ -79,18 +72,12 @@
         mLoggingEnabled = false;
         mContext = context;
         mHandler = new DisplayWhiteBalanceSettingsHandler(handler.getLooper());
-        mSettingsObserver = new SettingsObserver(mHandler);
-        mSetting = getSetting();
-        mActive = false;
         mCallbacks = null;
 
-        mContext.getContentResolver().registerContentObserver(
-                Secure.getUriFor(SETTING_URI), false /* notifyForDescendants */, mSettingsObserver,
-                UserHandle.USER_ALL);
-
-        ColorDisplayServiceInternal cds =
-                LocalServices.getService(ColorDisplayServiceInternal.class);
-        cds.setDisplayWhiteBalanceListener(this);
+        mCdsi = LocalServices.getService(ColorDisplayServiceInternal.class);
+        setEnabled(mCdsi.isDisplayWhiteBalanceEnabled());
+        final boolean isActive = mCdsi.setDisplayWhiteBalanceListener(this);
+        setActive(isActive);
     }
 
     /**
@@ -99,7 +86,7 @@
      * @param callbacks
      *      The object to call back to.
      *
-     * @return Whether the method suceeded or not.
+     * @return Whether the method succeeded or not.
      */
     public boolean setCallbacks(Callbacks callbacks) {
         if (mCallbacks == callbacks) {
@@ -131,14 +118,7 @@
      * @return Whether display white-balance is enabled.
      */
     public boolean isEnabled() {
-        return (mSetting == SETTING_ENABLED) && mActive;
-    }
-
-    /**
-     * Re-evaluate state after switching to a new user.
-     */
-    public void onSwitchUser() {
-        handleSettingChange();
+        return mEnabled && mActive;
     }
 
     /**
@@ -152,15 +132,14 @@
         writer.println("  mLoggingEnabled=" + mLoggingEnabled);
         writer.println("  mContext=" + mContext);
         writer.println("  mHandler=" + mHandler);
-        writer.println("  mSettingsObserver=" + mSettingsObserver);
-        writer.println("  mSetting=" + mSetting);
+        writer.println("  mEnabled=" + mEnabled);
         writer.println("  mActive=" + mActive);
         writer.println("  mCallbacks=" + mCallbacks);
     }
 
     @Override
-    public void onDisplayWhiteBalanceStatusChanged(boolean active) {
-        Message msg = mHandler.obtainMessage(MSG_SET_ACTIVE, active ? 1 : 0, 0);
+    public void onDisplayWhiteBalanceStatusChanged(boolean activated) {
+        Message msg = mHandler.obtainMessage(MSG_SET_ACTIVE, activated ? 1 : 0, 0);
         msg.sendToTarget();
     }
 
@@ -169,20 +148,14 @@
         Preconditions.checkNotNull(handler, "handler must not be null");
     }
 
-    private int getSetting() {
-        return Secure.getIntForUser(mContext.getContentResolver(), SETTING_URI, SETTING_DEFAULT,
-                UserHandle.USER_CURRENT);
-    }
-
-    private void handleSettingChange() {
-        final int setting = getSetting();
-        if (mSetting == setting) {
+    private void setEnabled(boolean enabled) {
+        if (mEnabled == enabled) {
             return;
         }
         if (mLoggingEnabled) {
-            Slog.d(TAG, "Setting: " + setting);
+            Slog.d(TAG, "Setting: " + enabled);
         }
-        mSetting = setting;
+        mEnabled = enabled;
         if (mCallbacks != null) {
             mCallbacks.updateWhiteBalance();
         }
@@ -201,17 +174,6 @@
         }
     }
 
-    private final class SettingsObserver extends ContentObserver {
-        SettingsObserver(Handler handler) {
-            super(handler);
-        }
-
-        @Override
-        public void onChange(boolean selfChange, Uri uri) {
-            handleSettingChange();
-        }
-    }
-
     private final class DisplayWhiteBalanceSettingsHandler extends Handler {
         DisplayWhiteBalanceSettingsHandler(Looper looper) {
             super(looper, null, true /* async */);
@@ -222,6 +184,7 @@
             switch (msg.what) {
                 case MSG_SET_ACTIVE:
                     setActive(msg.arg1 != 0);
+                    setEnabled(mCdsi.isDisplayWhiteBalanceEnabled());
                     break;
             }
         }
diff --git a/core/java/com/android/internal/net/NetworkStatsFactory.java b/services/core/java/com/android/server/net/NetworkStatsFactory.java
similarity index 99%
rename from core/java/com/android/internal/net/NetworkStatsFactory.java
rename to services/core/java/com/android/server/net/NetworkStatsFactory.java
index f848346..af299cf 100644
--- a/core/java/com/android/internal/net/NetworkStatsFactory.java
+++ b/services/core/java/com/android/server/net/NetworkStatsFactory.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.net;
+package com.android.server.net;
 
 import static android.net.NetworkStats.SET_ALL;
 import static android.net.NetworkStats.TAG_ALL;
diff --git a/services/core/java/com/android/server/net/NetworkStatsService.java b/services/core/java/com/android/server/net/NetworkStatsService.java
index 205ddb0..1559911 100644
--- a/services/core/java/com/android/server/net/NetworkStatsService.java
+++ b/services/core/java/com/android/server/net/NetworkStatsService.java
@@ -130,7 +130,6 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.net.NetworkStatsFactory;
 import com.android.internal.net.VpnInfo;
 import com.android.internal.util.ArrayUtils;
 import com.android.internal.util.DumpUtils;
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index a3e90dc..f34b2cb 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -98,7 +98,7 @@
     private static final int DEFAULT_VISIBILITY = NotificationManager.VISIBILITY_NO_OVERRIDE;
     private static final int DEFAULT_IMPORTANCE = NotificationManager.IMPORTANCE_UNSPECIFIED;
     @VisibleForTesting
-    static final boolean DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS = false;
+    static final boolean DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS = true;
     private static final boolean DEFAULT_SHOW_BADGE = true;
     private static final boolean DEFAULT_ALLOW_BUBBLE = true;
     private static final boolean DEFAULT_OEM_LOCKED_IMPORTANCE  = false;
@@ -132,7 +132,7 @@
     private SparseBooleanArray mBadgingEnabled;
     private SparseBooleanArray mBubblesEnabled;
     private boolean mAreChannelsBypassingDnd;
-    private boolean mHideSilentStatusBarIcons;
+    private boolean mHideSilentStatusBarIcons = DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS;
 
     public PreferencesHelper(Context context, PackageManager pm, RankingHandler rankingHandler,
             ZenModeHelper zenHelper) {
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index d2a160b..3306ccd 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -498,6 +498,7 @@
             info.isStagedSessionReady = mStagedSessionReady;
             info.isStagedSessionFailed = mStagedSessionFailed;
             info.setStagedSessionErrorCode(mStagedSessionErrorCode, mStagedSessionErrorMessage);
+            info.updatedMillis = updatedMillis;
         }
         return info;
     }
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 689f4f2..78aa5a0 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -476,6 +476,7 @@
     static final int SCAN_AS_VENDOR = 1 << 20;
     static final int SCAN_AS_PRODUCT = 1 << 21;
     static final int SCAN_AS_PRODUCT_SERVICES = 1 << 22;
+    static final int SCAN_AS_ODM = 1 << 23;
 
     @IntDef(flag = true, prefix = { "SCAN_" }, value = {
             SCAN_NO_DEX,
@@ -594,6 +595,8 @@
 
     private static final String PRODUCT_SERVICES_OVERLAY_DIR = "/product_services/overlay";
 
+    private static final String ODM_OVERLAY_DIR = "/odm/overlay";
+
     /** Canonical intent used to identify what counts as a "web browser" app */
     private static final Intent sBrowserIntent;
     static {
@@ -2523,6 +2526,13 @@
                     | SCAN_AS_SYSTEM
                     | SCAN_AS_PRODUCT_SERVICES,
                     0);
+            scanDirTracedLI(new File(ODM_OVERLAY_DIR),
+                    mDefParseFlags
+                    | PackageParser.PARSE_IS_SYSTEM_DIR,
+                    scanFlags
+                    | SCAN_AS_SYSTEM
+                    | SCAN_AS_ODM,
+                    0);
 
             mParallelPackageParserCallback.findStaticOverlayPackages();
 
@@ -3226,6 +3236,8 @@
         // once we have a booted system.
         mInstaller.setWarnIfHeld(mPackages);
 
+        PackageParser.readConfigUseRoundIcon(mContext.getResources());
+
         mServiceStartWithDelay = SystemClock.uptimeMillis() + (60 * 1000L);
 
         Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER);
@@ -4688,6 +4700,11 @@
                     if (ps == null || now - ps.lastUpdateTime < maxCachePeriod) {
                         continue;
                     }
+
+                    if (ps.pkg.isSystem()) {
+                        continue;
+                    }
+
                     if (packagesToDelete == null) {
                         packagesToDelete = new ArrayList<>();
                     }
@@ -5137,7 +5154,7 @@
                 continue;
             }
 
-            if (!ps.getUserState().get(userId).isAvailable(flags)) {
+            if (!ps.readUserState(userId).isAvailable(flags)) {
                 continue;
             }
 
@@ -6968,8 +6985,7 @@
         }
         final PackageSetting ps = mSettings.mPackages.get(mInstantAppInstallerActivity.packageName);
         if (ps == null
-                || ps.getUserState().get(userId) == null
-                || !ps.getUserState().get(userId).isEnabled(mInstantAppInstallerActivity, 0)) {
+                || !ps.readUserState(userId).isEnabled(mInstantAppInstallerActivity, 0)) {
             return result;
         }
         final ResolveInfo ephemeralInstaller = new ResolveInfo(mInstantAppInstallerInfo);
@@ -10399,6 +10415,7 @@
      * <li>{@link #SCAN_AS_PRODUCT_SERVICES}</li>
      * <li>{@link #SCAN_AS_INSTANT_APP}</li>
      * <li>{@link #SCAN_AS_VIRTUAL_PRELOAD}</li>
+     * <li>{@link #SCAN_AS_ODM}</li>
      * </ul>
      */
     private @ScanFlags int adjustScanFlags(@ScanFlags int scanFlags,
@@ -10435,6 +10452,10 @@
                     & ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES) != 0) {
                 scanFlags |= SCAN_AS_PRODUCT_SERVICES;
             }
+            if ((systemPkgSetting.pkgPrivateFlags
+                    & ApplicationInfo.PRIVATE_FLAG_ODM) != 0) {
+                scanFlags |= SCAN_AS_ODM;
+            }
         }
         if (pkgSetting != null) {
             final int userId = ((user == null) ? 0 : user.getIdentifier());
@@ -11206,6 +11227,10 @@
             pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES;
         }
 
+        if ((scanFlags & SCAN_AS_ODM) != 0) {
+            pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_ODM;
+        }
+
         // Check if the package is signed with the same key as the platform package.
         if (PLATFORM_PACKAGE_NAME.equals(pkg.packageName) ||
                 (platformPkg != null && compareSignatures(
@@ -12155,6 +12180,8 @@
             codeRoot = Environment.getProductDirectory();
         } else if (FileUtils.contains(Environment.getProductServicesDirectory(), codePath)) {
             codeRoot = Environment.getProductServicesDirectory();
+        } else if (FileUtils.contains(Environment.getOdmDirectory(), codePath)) {
+            codeRoot = Environment.getOdmDirectory();
         } else {
             // Unrecognized code path; take its top real segment as the apk root:
             // e.g. /something/app/blah.apk => /something
@@ -17242,13 +17269,15 @@
                     final boolean oem = isOemApp(oldPackage);
                     final boolean vendor = isVendorApp(oldPackage);
                     final boolean product = isProductApp(oldPackage);
+                    final boolean odm = isOdmApp(oldPackage);
                     final @ParseFlags int systemParseFlags = parseFlags;
                     final @ScanFlags int systemScanFlags = scanFlags
                             | SCAN_AS_SYSTEM
                             | (privileged ? SCAN_AS_PRIVILEGED : 0)
                             | (oem ? SCAN_AS_OEM : 0)
                             | (vendor ? SCAN_AS_VENDOR : 0)
-                            | (product ? SCAN_AS_PRODUCT : 0);
+                            | (product ? SCAN_AS_PRODUCT : 0)
+                            | (odm ? SCAN_AS_ODM : 0);
 
                     if (DEBUG_INSTALL) {
                         Slog.d(TAG, "replaceSystemPackageLI: new=" + pkg
@@ -17579,6 +17608,10 @@
                 & ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES) != 0;
     }
 
+    private static boolean isOdmApp(PackageParser.Package pkg) {
+        return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_ODM) != 0;
+    }
+
     private static boolean hasDomainURLs(PackageParser.Package pkg) {
         return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) != 0;
     }
@@ -18353,6 +18386,15 @@
         return false;
     }
 
+    static boolean locationIsOdm(String path) {
+        try {
+            return path.startsWith(Environment.getOdmDirectory().getCanonicalPath() + "/");
+        } catch (IOException e) {
+            Slog.e(TAG, "Unable to access code path " + path);
+        }
+        return false;
+    }
+
     /*
      * Tries to delete system package.
      */
@@ -18466,6 +18508,9 @@
         if (locationIsProductServices(codePathString)) {
             scanFlags |= SCAN_AS_PRODUCT_SERVICES;
         }
+        if (locationIsOdm(codePathString)) {
+            scanFlags |= SCAN_AS_ODM;
+        }
 
         final File codePath = new File(codePathString);
         final PackageParser.Package pkg =
@@ -20868,6 +20913,7 @@
                 mContext.getContentResolver(),
                 android.provider.Settings.Global.COMPATIBILITY_MODE, 1) == 1;
         PackageParser.setCompatibilityModeEnabled(compatibilityModeEnabled);
+
         if (DEBUG_SETTINGS) {
             Log.d(TAG, "compatibility mode:" + compatibilityModeEnabled);
         }
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 2c2cc7e..ead09b4 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -152,6 +152,10 @@
         return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES) != 0;
     }
 
+    public boolean isOdm() {
+        return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_ODM) != 0;
+    }
+
     public boolean isSystem() {
         return (pkgFlags & ApplicationInfo.FLAG_SYSTEM) != 0;
     }
diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java
index fbf5439..a24818f 100644
--- a/services/core/java/com/android/server/pm/SettingBase.java
+++ b/services/core/java/com/android/server/pm/SettingBase.java
@@ -64,6 +64,7 @@
                 | ApplicationInfo.PRIVATE_FLAG_VENDOR
                 | ApplicationInfo.PRIVATE_FLAG_PRODUCT
                 | ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES
-                | ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER);
+                | ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER
+                | ApplicationInfo.PRIVATE_FLAG_ODM);
     }
 }
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index f0f9f72..4f81fd9 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -777,7 +777,8 @@
                 | ApplicationInfo.PRIVATE_FLAG_OEM
                 | ApplicationInfo.PRIVATE_FLAG_VENDOR
                 | ApplicationInfo.PRIVATE_FLAG_PRODUCT
-                | ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES);
+                | ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES
+                | ApplicationInfo.PRIVATE_FLAG_ODM);
         pkgSetting.pkgFlags |= pkgFlags & ApplicationInfo.FLAG_SYSTEM;
         pkgSetting.pkgPrivateFlags |=
                 pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
@@ -789,6 +790,8 @@
                 pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT;
         pkgSetting.pkgPrivateFlags |=
                 pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES;
+        pkgSetting.pkgPrivateFlags |=
+                pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_ODM;
         pkgSetting.primaryCpuAbiString = primaryCpuAbi;
         pkgSetting.secondaryCpuAbiString = secondaryCpuAbi;
         if (childPkgNames != null) {
@@ -4420,6 +4423,7 @@
             ApplicationInfo.PRIVATE_FLAG_PRODUCT, "PRODUCT",
             ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES, "PRODUCT_SERVICES",
             ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD, "VIRTUAL_PRELOAD",
+            ApplicationInfo.PRIVATE_FLAG_ODM, "ODM",
     };
 
     void dumpVersionLPr(IndentingPrintWriter pw) {
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index b64abdb..10ae782 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -224,6 +224,7 @@
 import android.view.RemoteAnimationAdapter;
 import android.view.RemoteAnimationDefinition;
 import android.view.WindowManager;
+import android.view.inputmethod.InputMethodSystemProperty;
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
@@ -6436,6 +6437,10 @@
          */
         @Override
         public void onImeWindowSetOnDisplay(final int pid, final int displayId) {
+            // Update display configuration for IME process only when Single-client IME window
+            // moving to another display.
+            if (!InputMethodSystemProperty.MULTI_CLIENT_IME_ENABLED) return;
+
             if (pid == MY_PID || pid < 0) {
                 if (DEBUG_CONFIGURATION) {
                     Slog.w(TAG,
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index bbb857f..6ae7720 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -49,7 +49,7 @@
 import static android.view.WindowManager.LayoutParams.LAST_SUB_WINDOW;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_STATUS_BAR_VISIBLE_TRANSPARENT;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_INHERIT_TRANSLUCENT_DECOR;
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_IS_SCREEN_DECOR;
@@ -211,7 +211,6 @@
 
     private final boolean mCarDockEnablesAccelerometer;
     private final boolean mDeskDockEnablesAccelerometer;
-    private final boolean mTranslucentDecorEnabled;
     private final AccessibilityManager mAccessibilityManager;
     private final ImmersiveModeConfirmation mImmersiveModeConfirmation;
     private final ScreenshotHelper mScreenshotHelper;
@@ -434,7 +433,6 @@
         final Resources r = mContext.getResources();
         mCarDockEnablesAccelerometer = r.getBoolean(R.bool.config_carDockEnablesAccelerometer);
         mDeskDockEnablesAccelerometer = r.getBoolean(R.bool.config_deskDockEnablesAccelerometer);
-        mTranslucentDecorEnabled = r.getBoolean(R.bool.config_enableTranslucentDecor);
         mForceShowSystemBarsFromExternal = r.getBoolean(R.bool.config_forceShowSystemBars);
 
         mAccessibilityManager = (AccessibilityManager) mContext.getSystemService(
@@ -1287,14 +1285,12 @@
 
     private static int getImpliedSysUiFlagsForLayout(LayoutParams attrs) {
         int impliedFlags = 0;
-        if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0) {
-            impliedFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
-        }
-        final boolean forceWindowDrawsStatusBarBackground =
-                (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
+        final boolean forceWindowDrawsBarBackgrounds =
+                (attrs.privateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0
+                && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT;
         if ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
-                || forceWindowDrawsStatusBarBackground
-                && attrs.height == MATCH_PARENT && attrs.width == MATCH_PARENT) {
+                || forceWindowDrawsBarBackgrounds) {
+            impliedFlags |= View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION;
             impliedFlags |= View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;
         }
         return impliedFlags;
@@ -1396,9 +1392,6 @@
         navTranslucent &= !immersiveSticky;  // transient trumps translucent
         boolean isKeyguardShowing = isStatusBarKeyguard()
                 && !mService.mPolicy.isKeyguardOccluded();
-        if (!isKeyguardShowing) {
-            navTranslucent &= areTranslucentBarsAllowed();
-        }
         boolean statusBarForcesShowingNavigation = !isKeyguardShowing && mStatusBar != null
                 && (mStatusBar.getAttrs().privateFlags
                 & PRIVATE_FLAG_STATUS_FORCE_SHOW_NAVIGATION) != 0;
@@ -1560,9 +1553,6 @@
         boolean statusBarTransient = (sysui & View.STATUS_BAR_TRANSIENT) != 0;
         boolean statusBarTranslucent = (sysui
                 & (View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT)) != 0;
-        if (!isKeyguardShowing) {
-            statusBarTranslucent &= areTranslucentBarsAllowed();
-        }
 
         // If the status bar is hidden, we don't want to cause windows behind it to scroll.
         if (mStatusBar.isVisibleLw() && !statusBarTransient) {
@@ -1915,13 +1905,14 @@
                         && (fl & FLAG_FULLSCREEN) == 0
                         && (fl & FLAG_TRANSLUCENT_STATUS) == 0
                         && (fl & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
-                        && (pfl & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) == 0) {
+                        && (pfl & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) == 0) {
                     // Ensure policy decor includes status bar
                     dcf.top = displayFrames.mStable.top;
                 }
                 if ((fl & FLAG_TRANSLUCENT_NAVIGATION) == 0
                         && (sysUiFl & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0
-                        && (fl & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0) {
+                        && (fl & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) == 0
+                        && (pfl & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) == 0) {
                     // Ensure policy decor includes navigation bar
                     dcf.bottom = displayFrames.mStable.bottom;
                     dcf.right = displayFrames.mStable.right;
@@ -3148,6 +3139,8 @@
                 drawsStatusBarBackground(vis, mTopFullscreenOpaqueWindowState);
         final boolean dockedDrawsStatusBarBackground =
                 drawsStatusBarBackground(dockedVis, mTopDockedOpaqueWindowState);
+        final boolean fullscreenDrawsNavBarBackground =
+                drawsNavigationBarBackground(vis, mTopFullscreenOpaqueWindowState);
 
         // prevent status bar interaction from clearing certain flags
         int type = win.getAttrs().type;
@@ -3167,12 +3160,12 @@
         if (fullscreenDrawsStatusBarBackground && dockedDrawsStatusBarBackground) {
             vis |= View.STATUS_BAR_TRANSPARENT;
             vis &= ~View.STATUS_BAR_TRANSLUCENT;
-        } else if ((!areTranslucentBarsAllowed() && fullscreenTransWin != mStatusBar)
-                || forceOpaqueStatusBar) {
+        } else if (forceOpaqueStatusBar) {
             vis &= ~(View.STATUS_BAR_TRANSLUCENT | View.STATUS_BAR_TRANSPARENT);
         }
 
-        vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing);
+        vis = configureNavBarOpacity(vis, dockedStackVisible, freeformStackVisible, resizing,
+                fullscreenDrawsNavBarBackground);
 
         // update status bar
         boolean immersiveSticky =
@@ -3256,8 +3249,9 @@
         return vis;
     }
 
-    private boolean drawsStatusBarBackground(int vis, WindowState win) {
-        if (!mStatusBarController.isTransparentAllowed(win)) {
+    private boolean drawsBarBackground(int vis, WindowState win, BarController controller,
+            int translucentFlag) {
+        if (!controller.isTransparentAllowed(win)) {
             return false;
         }
         if (win == null) {
@@ -3267,9 +3261,17 @@
         final boolean drawsSystemBars =
                 (win.getAttrs().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
         final boolean forceDrawsSystemBars =
-                (win.getAttrs().privateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
+                (win.getAttrs().privateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0;
 
-        return forceDrawsSystemBars || drawsSystemBars && (vis & View.STATUS_BAR_TRANSLUCENT) == 0;
+        return forceDrawsSystemBars || drawsSystemBars && (vis & translucentFlag) == 0;
+    }
+
+    private boolean drawsStatusBarBackground(int vis, WindowState win) {
+        return drawsBarBackground(vis, win, mStatusBarController, FLAG_TRANSLUCENT_STATUS);
+    }
+
+    private boolean drawsNavigationBarBackground(int vis, WindowState win) {
+        return drawsBarBackground(vis, win, mNavigationBarController, FLAG_TRANSLUCENT_NAVIGATION);
     }
 
     /**
@@ -3277,10 +3279,13 @@
      *         on the nav bar opacity rules chosen by {@link #mNavBarOpacityMode}.
      */
     private int configureNavBarOpacity(int visibility, boolean dockedStackVisible,
-            boolean freeformStackVisible, boolean isDockedDividerResizing) {
+            boolean freeformStackVisible, boolean isDockedDividerResizing,
+            boolean fullscreenDrawsBackground) {
         if (mNavBarOpacityMode == NAV_BAR_OPAQUE_WHEN_FREEFORM_OR_DOCKED) {
             if (dockedStackVisible || freeformStackVisible || isDockedDividerResizing) {
                 visibility = setNavBarOpaqueFlag(visibility);
+            } else if (fullscreenDrawsBackground) {
+                visibility = setNavBarTransparentFlag(visibility);
             }
         } else if (mNavBarOpacityMode == NAV_BAR_TRANSLUCENT_WHEN_FREEFORM_OPAQUE_OTHERWISE) {
             if (isDockedDividerResizing) {
@@ -3292,9 +3297,6 @@
             }
         }
 
-        if (!areTranslucentBarsAllowed()) {
-            visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT;
-        }
         return visibility;
     }
 
@@ -3307,6 +3309,11 @@
         return visibility | View.NAVIGATION_BAR_TRANSLUCENT;
     }
 
+    private int setNavBarTransparentFlag(int visibility) {
+        visibility &= ~View.NAVIGATION_BAR_TRANSLUCENT;
+        return visibility | View.NAVIGATION_BAR_TRANSPARENT;
+    }
+
     private void clearClearableFlagsLw() {
         int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
         if (newVal != mResettingSystemUiFlags) {
@@ -3338,16 +3345,6 @@
         return (systemUiFlags & disableNavigationBar) == disableNavigationBar;
     }
 
-    /**
-     * @return whether the navigation or status bar can be made translucent
-     *
-     * This should return true unless touch exploration is not enabled or
-     * R.boolean.config_enableTranslucentDecor is false.
-     */
-    private boolean areTranslucentBarsAllowed() {
-        return mTranslucentDecorEnabled;
-    }
-
     boolean shouldRotateSeamlessly(DisplayRotation displayRotation, int oldRotation,
             int newRotation) {
         // For the upside down rotation we don't rotate seamlessly as the navigation
diff --git a/services/core/java/com/android/server/wm/NavigationBarExperiments.java b/services/core/java/com/android/server/wm/NavigationBarExperiments.java
index b74fb45..bb3ff5e 100644
--- a/services/core/java/com/android/server/wm/NavigationBarExperiments.java
+++ b/services/core/java/com/android/server/wm/NavigationBarExperiments.java
@@ -16,7 +16,6 @@
 
 package com.android.server.wm;
 
-import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_BOTTOM;
 import static android.view.WindowManagerPolicyConstants.NAV_BAR_LEFT;
@@ -91,7 +90,7 @@
      * @param w the window that is being offset by experiment
      */
     public void offsetWindowFramesForNavBar(int navPosition, WindowState w) {
-        if (w.getAttrs().type != TYPE_INPUT_METHOD && w.getActivityType() != ACTIVITY_TYPE_HOME) {
+        if (w.getAttrs().type != TYPE_INPUT_METHOD) {
             return;
         }
 
@@ -102,6 +101,7 @@
                 int navHeight = getNavigationBarFrameHeight() - getNavigationBarHeight();
                 if (navHeight > 0) {
                     cf.bottom -= navHeight;
+                    windowFrames.mStableFrame.bottom -= navHeight;
                 }
                 break;
             case NAV_BAR_LEFT:
diff --git a/services/core/java/com/android/server/wm/RecentsAnimation.java b/services/core/java/com/android/server/wm/RecentsAnimation.java
index f1560d9..144efb4 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimation.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimation.java
@@ -17,8 +17,6 @@
 package com.android.server.wm;
 
 import static android.app.ActivityManager.START_TASK_TO_FRONT;
-import static android.app.AppOpsManager.OP_ASSIST_STRUCTURE;
-import static android.app.AppOpsManager.OP_NONE;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
@@ -34,25 +32,16 @@
 import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_RECENTS_ANIMATIONS;
 
 import android.app.ActivityOptions;
-import android.app.AppOpsManager;
 import android.app.IAssistDataReceiver;
 import android.content.ComponentName;
-import android.content.Context;
 import android.content.Intent;
-import android.os.Bundle;
-import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.Trace;
 import android.util.Slog;
 import android.view.IRecentsAnimationRunner;
 
-import com.android.server.LocalServices;
-import com.android.server.am.AssistDataRequester;
-import com.android.server.contentcapture.ContentCaptureManagerInternal;
 import com.android.server.wm.RecentsAnimationController.RecentsAnimationCallbacks;
 
-import java.util.List;
-
 /**
  * Manages the recents animation, including the reordering of the stacks for the transition and
  * cleanup. See {@link com.android.server.wm.RecentsAnimationController}.
@@ -70,7 +59,6 @@
     private final int mCallingPid;
 
     private int mTargetActivityType;
-    private AssistDataRequester mAssistDataRequester;
 
     // The stack to restore the target stack behind when the animation is finished
     private ActivityStack mRestoreTargetBehindStack;
@@ -135,9 +123,6 @@
 
         mWindowManager.deferSurfaceLayout();
         try {
-            // Kick off the assist data request in the background before showing the target activity
-            requestAssistData(recentsComponent, recentsUid, assistDataReceiver);
-
             if (hasExistingActivity) {
                 // Move the recents activity into place for the animation if it is not top most
                 mDefaultDisplay.moveStackBehindBottomMostVisibleStack(targetStack);
@@ -216,78 +201,12 @@
         }
     }
 
-    /**
-     * Requests assist data for the top visible activities.
-     */
-    private void requestAssistData(ComponentName recentsComponent, int recentsUid,
-            @Deprecated IAssistDataReceiver assistDataReceiver) {
-        final AppOpsManager appOpsManager = (AppOpsManager)
-                mService.mContext.getSystemService(Context.APP_OPS_SERVICE);
-        final List<IBinder> topActivities =
-                mService.mRootActivityContainer.getTopVisibleActivities();
-        final AssistDataRequester.AssistDataRequesterCallbacks assistDataCallbacks;
-        if (assistDataReceiver != null) {
-            assistDataCallbacks = new AssistDataReceiverProxy(assistDataReceiver,
-                    recentsComponent.getPackageName()) {
-                @Override
-                public void onAssistDataReceivedLocked(Bundle data, int activityIndex,
-                        int activityCount) {
-                    // Try to notify the intelligence service first
-                    final ContentCaptureManagerInternal imService =
-                            LocalServices.getService(ContentCaptureManagerInternal.class);
-                    final IBinder activityToken = topActivities.get(activityIndex);
-                    final ActivityRecord r = ActivityRecord.forTokenLocked(activityToken);
-                    if (r != null && (imService == null
-                            || !imService.sendActivityAssistData(r.mUserId, activityToken, data))) {
-                        // Otherwise, use the provided assist data receiver
-                        super.onAssistDataReceivedLocked(data, activityIndex, activityCount);
-                    }
-                }
-            };
-        } else {
-            final ContentCaptureManagerInternal imService =
-                    LocalServices.getService(ContentCaptureManagerInternal.class);
-            if (imService == null) {
-                // There is no intelligence service, so there is no point requesting assist data
-                return;
-            }
-
-            assistDataCallbacks = new AssistDataRequester.AssistDataRequesterCallbacks() {
-                @Override
-                public boolean canHandleReceivedAssistDataLocked() {
-                    return true;
-                }
-
-                @Override
-                public void onAssistDataReceivedLocked(Bundle data, int activityIndex,
-                        int activityCount) {
-                    // Try to notify the intelligence service
-                    final IBinder activityToken = topActivities.get(activityIndex);
-                    final ActivityRecord r = ActivityRecord.forTokenLocked(activityToken);
-                    if (r != null) {
-                        imService.sendActivityAssistData(r.mUserId, activityToken, data);
-                    }
-                }
-            };
-        }
-        mAssistDataRequester = new AssistDataRequester(mService.mContext, mWindowManager,
-                appOpsManager, assistDataCallbacks, this, OP_ASSIST_STRUCTURE, OP_NONE);
-        mAssistDataRequester.requestAutofillData(topActivities,
-                recentsUid, recentsComponent.getPackageName());
-    }
-
     private void finishAnimation(@RecentsAnimationController.ReorderMode int reorderMode) {
         synchronized (mService.mGlobalLock) {
             if (DEBUG) Slog.d(TAG, "onAnimationFinished(): controller="
                     + mWindowManager.getRecentsAnimationController()
                     + " reorderMode=" + reorderMode);
 
-            // Cancel the associated assistant data request
-            if (mAssistDataRequester != null) {
-                mAssistDataRequester.cancel();
-                mAssistDataRequester = null;
-            }
-
             // Unregister for stack order changes
             mDefaultDisplay.unregisterStackOrderChangedListener(this);
 
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index dafed9e..39b5662 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -29,8 +29,10 @@
 import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
 import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
 import static android.view.WindowManager.LayoutParams.FLAG_SPLIT_TOUCH;
+import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
+import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
 import static android.view.WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
 
 import static com.android.internal.policy.DecorView.NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES;
@@ -104,7 +106,7 @@
             | FLAG_SCALED
             | FLAG_SECURE;
 
-    private static final int PRIVATE_FLAG_INHERITS = PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
+    private static final int PRIVATE_FLAG_INHERITS = PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
 
     private static final String TAG = TAG_WITH_CLASS_NAME ? "SnapshotStartingWindow" : TAG_WM;
     private static final int MSG_REPORT_DRAW = 0;
@@ -493,10 +495,12 @@
             mWindowPrivateFlags = windowPrivateFlags;
             mSysUiVis = sysUiVis;
             final Context context = ActivityThread.currentActivityThread().getSystemUiContext();
-            mStatusBarColor = DecorView.calculateStatusBarColor(windowFlags,
-                    context.getColor(R.color.system_bar_background_semi_transparent),
-                    statusBarColor);
-            mNavigationBarColor = navigationBarColor;
+            final int semiTransparent = context.getColor(
+                    R.color.system_bar_background_semi_transparent);
+            mStatusBarColor = DecorView.calculateBarColor(windowFlags, FLAG_TRANSLUCENT_STATUS,
+                    semiTransparent, statusBarColor);
+            mNavigationBarColor = DecorView.calculateBarColor(windowFlags,
+                    FLAG_TRANSLUCENT_NAVIGATION, semiTransparent, navigationBarColor);
             mStatusBarPaint.setColor(mStatusBarColor);
             mNavigationBarPaint.setColor(navigationBarColor);
         }
@@ -507,10 +511,10 @@
         }
 
         int getStatusBarColorViewHeight() {
-            final boolean forceStatusBarBackground =
-                    (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND) != 0;
+            final boolean forceBarBackground =
+                    (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0;
             if (STATUS_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
-                    mSysUiVis, mStatusBarColor, mWindowFlags, forceStatusBarBackground)) {
+                    mSysUiVis, mStatusBarColor, mWindowFlags, forceBarBackground)) {
                 return getColorViewTopInset(mStableInsets.top, mContentInsets.top);
             } else {
                 return 0;
@@ -518,8 +522,10 @@
         }
 
         private boolean isNavigationBarColorViewVisible() {
+            final boolean forceBarBackground =
+                    (mWindowPrivateFlags & PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS) != 0;
             return NAVIGATION_BAR_COLOR_VIEW_ATTRIBUTES.isVisible(
-                    mSysUiVis, mNavigationBarColor, mWindowFlags, false /* force */);
+                    mSysUiVis, mNavigationBarColor, mWindowFlags, forceBarBackground);
         }
 
         void drawDecors(Canvas c, @Nullable Rect alreadyDrawnFrame) {
diff --git a/services/core/jni/Android.bp b/services/core/jni/Android.bp
index a7423ea..e1318af 100644
--- a/services/core/jni/Android.bp
+++ b/services/core/jni/Android.bp
@@ -52,6 +52,7 @@
         "com_android_server_GraphicsStatsService.cpp",
         "com_android_server_am_AppCompactor.cpp",
         "onload.cpp",
+        ":lib_networkStatsFactory_native",
     ],
 
     include_dirs: [
@@ -151,3 +152,10 @@
         }
     }
 }
+
+filegroup {
+    name: "lib_networkStatsFactory_native",
+    srcs: [
+        "com_android_server_net_NetworkStatsFactory.cpp",
+    ],
+}
diff --git a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp b/services/core/jni/com_android_server_net_NetworkStatsFactory.cpp
similarity index 87%
rename from core/jni/com_android_internal_net_NetworkStatsFactory.cpp
rename to services/core/jni/com_android_server_net_NetworkStatsFactory.cpp
index 8259ffc..9cd743b 100644
--- a/core/jni/com_android_internal_net_NetworkStatsFactory.cpp
+++ b/services/core/jni/com_android_server_net_NetworkStatsFactory.cpp
@@ -21,9 +21,9 @@
 #include <sys/stat.h>
 #include <sys/types.h>
 
-#include <core_jni_helpers.h>
 #include <jni.h>
 
+#include <nativehelper/JNIHelp.h>
 #include <nativehelper/ScopedUtfChars.h>
 #include <nativehelper/ScopedLocalRef.h>
 #include <nativehelper/ScopedPrimitiveArray.h>
@@ -333,29 +333,27 @@
                 (void*) readNetworkStatsDev },
 };
 
-int register_com_android_internal_net_NetworkStatsFactory(JNIEnv* env) {
-    int err = RegisterMethodsOrDie(env,
-            "com/android/internal/net/NetworkStatsFactory", gMethods,
+int register_android_server_net_NetworkStatsFactory(JNIEnv* env) {
+    int err = jniRegisterNativeMethods(env, "com/android/server/net/NetworkStatsFactory", gMethods,
             NELEM(gMethods));
+    gStringClass = env->FindClass("java/lang/String");
+    gStringClass = static_cast<jclass>(env->NewGlobalRef(gStringClass));
 
-    gStringClass = FindClassOrDie(env, "java/lang/String");
-    gStringClass = MakeGlobalRefOrDie(env, gStringClass);
-
-    jclass clazz = FindClassOrDie(env, "android/net/NetworkStats");
-    gNetworkStatsClassInfo.size = GetFieldIDOrDie(env, clazz, "size", "I");
-    gNetworkStatsClassInfo.capacity = GetFieldIDOrDie(env, clazz, "capacity", "I");
-    gNetworkStatsClassInfo.iface = GetFieldIDOrDie(env, clazz, "iface", "[Ljava/lang/String;");
-    gNetworkStatsClassInfo.uid = GetFieldIDOrDie(env, clazz, "uid", "[I");
-    gNetworkStatsClassInfo.set = GetFieldIDOrDie(env, clazz, "set", "[I");
-    gNetworkStatsClassInfo.tag = GetFieldIDOrDie(env, clazz, "tag", "[I");
-    gNetworkStatsClassInfo.metered = GetFieldIDOrDie(env, clazz, "metered", "[I");
-    gNetworkStatsClassInfo.roaming = GetFieldIDOrDie(env, clazz, "roaming", "[I");
-    gNetworkStatsClassInfo.defaultNetwork = GetFieldIDOrDie(env, clazz, "defaultNetwork", "[I");
-    gNetworkStatsClassInfo.rxBytes = GetFieldIDOrDie(env, clazz, "rxBytes", "[J");
-    gNetworkStatsClassInfo.rxPackets = GetFieldIDOrDie(env, clazz, "rxPackets", "[J");
-    gNetworkStatsClassInfo.txBytes = GetFieldIDOrDie(env, clazz, "txBytes", "[J");
-    gNetworkStatsClassInfo.txPackets = GetFieldIDOrDie(env, clazz, "txPackets", "[J");
-    gNetworkStatsClassInfo.operations = GetFieldIDOrDie(env, clazz, "operations", "[J");
+    jclass clazz = env->FindClass("android/net/NetworkStats");
+    gNetworkStatsClassInfo.size = env->GetFieldID(clazz, "size", "I");
+    gNetworkStatsClassInfo.capacity = env->GetFieldID(clazz, "capacity", "I");
+    gNetworkStatsClassInfo.iface = env->GetFieldID(clazz, "iface", "[Ljava/lang/String;");
+    gNetworkStatsClassInfo.uid = env->GetFieldID(clazz, "uid", "[I");
+    gNetworkStatsClassInfo.set = env->GetFieldID(clazz, "set", "[I");
+    gNetworkStatsClassInfo.tag = env->GetFieldID(clazz, "tag", "[I");
+    gNetworkStatsClassInfo.metered = env->GetFieldID(clazz, "metered", "[I");
+    gNetworkStatsClassInfo.roaming = env->GetFieldID(clazz, "roaming", "[I");
+    gNetworkStatsClassInfo.defaultNetwork = env->GetFieldID(clazz, "defaultNetwork", "[I");
+    gNetworkStatsClassInfo.rxBytes = env->GetFieldID(clazz, "rxBytes", "[J");
+    gNetworkStatsClassInfo.rxPackets = env->GetFieldID(clazz, "rxPackets", "[J");
+    gNetworkStatsClassInfo.txBytes = env->GetFieldID(clazz, "txBytes", "[J");
+    gNetworkStatsClassInfo.txPackets = env->GetFieldID(clazz, "txPackets", "[J");
+    gNetworkStatsClassInfo.operations = env->GetFieldID(clazz, "operations", "[J");
 
     return err;
 }
diff --git a/services/core/jni/onload.cpp b/services/core/jni/onload.cpp
index 2cfaebf..cce96ff 100644
--- a/services/core/jni/onload.cpp
+++ b/services/core/jni/onload.cpp
@@ -52,6 +52,7 @@
 int register_android_server_SyntheticPasswordManager(JNIEnv* env);
 int register_android_server_GraphicsStatsService(JNIEnv* env);
 int register_android_hardware_display_DisplayViewport(JNIEnv* env);
+int register_android_server_net_NetworkStatsFactory(JNIEnv* env);
 int register_android_server_net_NetworkStatsService(JNIEnv* env);
 int register_android_server_security_VerityUtils(JNIEnv* env);
 int register_android_server_am_AppCompactor(JNIEnv* env);
@@ -100,6 +101,7 @@
     register_android_server_SyntheticPasswordManager(env);
     register_android_server_GraphicsStatsService(env);
     register_android_hardware_display_DisplayViewport(env);
+    register_android_server_net_NetworkStatsFactory(env);
     register_android_server_net_NetworkStatsService(env);
     register_android_server_security_VerityUtils(env);
     register_android_server_am_AppCompactor(env);
diff --git a/services/net/java/android/net/ipmemorystore/OnBlobRetrievedListener.java b/services/net/java/android/net/ipmemorystore/OnBlobRetrievedListener.java
index 9685ff6..22978a2 100644
--- a/services/net/java/android/net/ipmemorystore/OnBlobRetrievedListener.java
+++ b/services/net/java/android/net/ipmemorystore/OnBlobRetrievedListener.java
@@ -30,12 +30,15 @@
 
     /** Converts this OnBlobRetrievedListener to a parcelable object */
     @NonNull
-    static IOnBlobRetrievedListener toAIDL(final OnBlobRetrievedListener listener) {
+    static IOnBlobRetrievedListener toAIDL(@NonNull final OnBlobRetrievedListener listener) {
         return new IOnBlobRetrievedListener.Stub() {
             @Override
             public void onBlobRetrieved(final StatusParcelable statusParcelable, final String l2Key,
                     final String name, final Blob blob) {
-                listener.onBlobRetrieved(new Status(statusParcelable), l2Key, name, blob);
+                // NonNull, but still don't crash the system server if null
+                if (null != listener) {
+                    listener.onBlobRetrieved(new Status(statusParcelable), l2Key, name, blob);
+                }
             }
         };
     }
diff --git a/services/net/java/android/net/ipmemorystore/OnL2KeyResponseListener.java b/services/net/java/android/net/ipmemorystore/OnL2KeyResponseListener.java
index 80209c5..9e7c1c8 100644
--- a/services/net/java/android/net/ipmemorystore/OnL2KeyResponseListener.java
+++ b/services/net/java/android/net/ipmemorystore/OnL2KeyResponseListener.java
@@ -30,12 +30,15 @@
 
     /** Converts this OnL2KeyResponseListener to a parcelable object */
     @NonNull
-    static IOnL2KeyResponseListener toAIDL(final OnL2KeyResponseListener listener) {
+    static IOnL2KeyResponseListener toAIDL(@NonNull final OnL2KeyResponseListener listener) {
         return new IOnL2KeyResponseListener.Stub() {
             @Override
             public void onL2KeyResponse(final StatusParcelable statusParcelable,
                     final String l2Key) {
-                listener.onL2KeyResponse(new Status(statusParcelable), l2Key);
+                // NonNull, but still don't crash the system server if null
+                if (null != listener) {
+                    listener.onL2KeyResponse(new Status(statusParcelable), l2Key);
+                }
             }
         };
     }
diff --git a/services/net/java/android/net/ipmemorystore/OnNetworkAttributesRetrievedListener.java b/services/net/java/android/net/ipmemorystore/OnNetworkAttributesRetrievedListener.java
index f0f6f40..59da268 100644
--- a/services/net/java/android/net/ipmemorystore/OnNetworkAttributesRetrievedListener.java
+++ b/services/net/java/android/net/ipmemorystore/OnNetworkAttributesRetrievedListener.java
@@ -31,15 +31,18 @@
     /** Converts this OnNetworkAttributesRetrievedListener to a parcelable object */
     @NonNull
     static IOnNetworkAttributesRetrievedListener toAIDL(
-            final OnNetworkAttributesRetrievedListener listener) {
+            @NonNull final OnNetworkAttributesRetrievedListener listener) {
         return new IOnNetworkAttributesRetrievedListener.Stub() {
             @Override
             public void onNetworkAttributesRetrieved(final StatusParcelable statusParcelable,
                     final String l2Key,
                     final NetworkAttributesParcelable networkAttributesParcelable) {
-                listener.onNetworkAttributesRetrieved(
-                        new Status(statusParcelable), l2Key,
-                        new NetworkAttributes(networkAttributesParcelable));
+                // NonNull, but still don't crash the system server if null
+                if (null != listener) {
+                    listener.onNetworkAttributesRetrieved(
+                            new Status(statusParcelable), l2Key,
+                            new NetworkAttributes(networkAttributesParcelable));
+                }
             }
         };
     }
diff --git a/services/net/java/android/net/ipmemorystore/OnSameL3NetworkResponseListener.java b/services/net/java/android/net/ipmemorystore/OnSameL3NetworkResponseListener.java
index ba1e0e6..0154fd2 100644
--- a/services/net/java/android/net/ipmemorystore/OnSameL3NetworkResponseListener.java
+++ b/services/net/java/android/net/ipmemorystore/OnSameL3NetworkResponseListener.java
@@ -30,14 +30,18 @@
 
     /** Converts this OnSameL3NetworkResponseListener to a parcelable object */
     @NonNull
-    static IOnSameL3NetworkResponseListener toAIDL(final OnSameL3NetworkResponseListener listener) {
+    static IOnSameL3NetworkResponseListener toAIDL(
+            @NonNull final OnSameL3NetworkResponseListener listener) {
         return new IOnSameL3NetworkResponseListener.Stub() {
             @Override
             public void onSameL3NetworkResponse(final StatusParcelable statusParcelable,
                     final SameL3NetworkResponseParcelable sameL3NetworkResponseParcelable) {
-                listener.onSameL3NetworkResponse(
-                        new Status(statusParcelable),
-                        new SameL3NetworkResponse(sameL3NetworkResponseParcelable));
+                // NonNull, but still don't crash the system server if null
+                if (null != listener) {
+                    listener.onSameL3NetworkResponse(
+                            new Status(statusParcelable),
+                            new SameL3NetworkResponse(sameL3NetworkResponseParcelable));
+                }
             }
         };
     }
diff --git a/services/net/java/android/net/ipmemorystore/OnStatusListener.java b/services/net/java/android/net/ipmemorystore/OnStatusListener.java
index 0de1666..824b7b0 100644
--- a/services/net/java/android/net/ipmemorystore/OnStatusListener.java
+++ b/services/net/java/android/net/ipmemorystore/OnStatusListener.java
@@ -17,6 +17,7 @@
 package android.net.ipmemorystore;
 
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 
 /**
  * A listener for the IpMemoryStore to return a status to a client.
@@ -30,11 +31,13 @@
 
     /** Converts this OnStatusListener to a parcelable object */
     @NonNull
-    static IOnStatusListener toAIDL(final OnStatusListener listener) {
+    static IOnStatusListener toAIDL(@Nullable final OnStatusListener listener) {
         return new IOnStatusListener.Stub() {
             @Override
             public void onComplete(final StatusParcelable statusParcelable) {
-                listener.onComplete(new Status(statusParcelable));
+                if (null != listener) {
+                    listener.onComplete(new Status(statusParcelable));
+                }
             }
         };
     }
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/AppCompactorTest.java b/services/tests/mockingservicestests/src/com/android/server/am/AppCompactorTest.java
index b0c97d1..475901a 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/AppCompactorTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/AppCompactorTest.java
@@ -25,6 +25,7 @@
 import android.os.HandlerThread;
 import android.platform.test.annotations.Presubmit;
 import android.provider.DeviceConfig;
+import android.text.TextUtils;
 
 import com.android.server.appop.AppOpsService;
 import com.android.server.testables.TestableDeviceConfig;
@@ -38,6 +39,8 @@
 import org.mockito.junit.MockitoJUnitRunner;
 
 import java.io.File;
+import java.util.HashSet;
+import java.util.Set;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
@@ -103,6 +106,22 @@
                 AppCompactor.DEFAULT_COMPACT_THROTTLE_4);
         assertThat(mCompactorUnderTest.mStatsdSampleRate).isEqualTo(
                 AppCompactor.DEFAULT_STATSD_SAMPLE_RATE);
+        assertThat(mCompactorUnderTest.mFullAnonRssThrottleKb).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB);
+        assertThat(mCompactorUnderTest.mCompactThrottleBFGS).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_THROTTLE_5);
+        assertThat(mCompactorUnderTest.mCompactThrottlePersistent).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_THROTTLE_6);
+        assertThat(mCompactorUnderTest.mFullAnonRssThrottleKb).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB);
+        assertThat(mCompactorUnderTest.mFullDeltaRssThrottleKb).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB);
+
+        Set<Integer> expected = new HashSet<>();
+        for (String s : TextUtils.split(AppCompactor.DEFAULT_COMPACT_PROC_STATE_THROTTLE, ",")) {
+            expected.add(Integer.parseInt(s));
+        }
+        assertThat(mCompactorUnderTest.mProcStateThrottle).containsExactlyElementsIn(expected);
     }
 
     @Test
@@ -139,6 +158,14 @@
         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                 AppCompactor.KEY_COMPACT_STATSD_SAMPLE_RATE,
                 Float.toString(AppCompactor.DEFAULT_STATSD_SAMPLE_RATE + 0.1f), false);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                AppCompactor.KEY_COMPACT_FULL_RSS_THROTTLE_KB,
+                Long.toString(AppCompactor.DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB + 1), false);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                AppCompactor.KEY_COMPACT_FULL_DELTA_RSS_THROTTLE_KB,
+                Long.toString(AppCompactor.DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB + 1), false);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                AppCompactor.KEY_COMPACT_PROC_STATE_THROTTLE, "1,2,3", false);
 
         // Then calling init will read and set that flag.
         mCompactorUnderTest.init();
@@ -157,12 +184,19 @@
                 AppCompactor.DEFAULT_COMPACT_THROTTLE_3 + 1);
         assertThat(mCompactorUnderTest.mCompactThrottleFullFull).isEqualTo(
                 AppCompactor.DEFAULT_COMPACT_THROTTLE_4 + 1);
+        assertThat(mCompactorUnderTest.mCompactThrottleBFGS).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_THROTTLE_5 + 1);
+        assertThat(mCompactorUnderTest.mCompactThrottlePersistent).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_THROTTLE_6 + 1);
         assertThat(mCompactorUnderTest.mStatsdSampleRate).isEqualTo(
                 AppCompactor.DEFAULT_STATSD_SAMPLE_RATE + 0.1f);
         assertThat(mCompactorUnderTest.mCompactThrottleBFGS).isEqualTo(
                 AppCompactor.DEFAULT_COMPACT_THROTTLE_5 + 1);
         assertThat(mCompactorUnderTest.mCompactThrottlePersistent).isEqualTo(
                 AppCompactor.DEFAULT_COMPACT_THROTTLE_6 + 1);
+        assertThat(mCompactorUnderTest.mFullAnonRssThrottleKb).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB + 1);
+        assertThat(mCompactorUnderTest.mProcStateThrottle).containsExactly(1, 2, 3);
     }
 
     @Test
@@ -321,6 +355,10 @@
                 AppCompactor.DEFAULT_COMPACT_THROTTLE_3);
         assertThat(mCompactorUnderTest.mCompactThrottleFullFull).isEqualTo(
                 AppCompactor.DEFAULT_COMPACT_THROTTLE_4);
+        assertThat(mCompactorUnderTest.mCompactThrottleBFGS).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_THROTTLE_5);
+        assertThat(mCompactorUnderTest.mCompactThrottlePersistent).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_THROTTLE_6);
 
         // Repeat for each of the throttle keys.
         mCountDown = new CountDownLatch(1);
@@ -335,6 +373,10 @@
                 AppCompactor.DEFAULT_COMPACT_THROTTLE_3);
         assertThat(mCompactorUnderTest.mCompactThrottleFullFull).isEqualTo(
                 AppCompactor.DEFAULT_COMPACT_THROTTLE_4);
+        assertThat(mCompactorUnderTest.mCompactThrottleBFGS).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_THROTTLE_5);
+        assertThat(mCompactorUnderTest.mCompactThrottlePersistent).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_THROTTLE_6);
 
         mCountDown = new CountDownLatch(1);
         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
@@ -348,6 +390,10 @@
                 AppCompactor.DEFAULT_COMPACT_THROTTLE_3);
         assertThat(mCompactorUnderTest.mCompactThrottleFullFull).isEqualTo(
                 AppCompactor.DEFAULT_COMPACT_THROTTLE_4);
+        assertThat(mCompactorUnderTest.mCompactThrottleBFGS).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_THROTTLE_5);
+        assertThat(mCompactorUnderTest.mCompactThrottlePersistent).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_THROTTLE_6);
 
         mCountDown = new CountDownLatch(1);
         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
@@ -361,13 +407,51 @@
                 AppCompactor.DEFAULT_COMPACT_THROTTLE_3);
         assertThat(mCompactorUnderTest.mCompactThrottleFullFull).isEqualTo(
                 AppCompactor.DEFAULT_COMPACT_THROTTLE_4);
+        assertThat(mCompactorUnderTest.mCompactThrottleBFGS).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_THROTTLE_5);
+        assertThat(mCompactorUnderTest.mCompactThrottlePersistent).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_THROTTLE_6);
+
+        mCountDown = new CountDownLatch(1);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                AppCompactor.KEY_COMPACT_THROTTLE_5, "foo", false);
+        assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
+        assertThat(mCompactorUnderTest.mCompactThrottleSomeSome).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_THROTTLE_1);
+        assertThat(mCompactorUnderTest.mCompactThrottleSomeFull).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_THROTTLE_2);
+        assertThat(mCompactorUnderTest.mCompactThrottleFullSome).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_THROTTLE_3);
+        assertThat(mCompactorUnderTest.mCompactThrottleFullFull).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_THROTTLE_4);
+        assertThat(mCompactorUnderTest.mCompactThrottleBFGS).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_THROTTLE_5);
+        assertThat(mCompactorUnderTest.mCompactThrottlePersistent).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_THROTTLE_6);
+
+        mCountDown = new CountDownLatch(1);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                AppCompactor.KEY_COMPACT_THROTTLE_6, "foo", false);
+        assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
+        assertThat(mCompactorUnderTest.mCompactThrottleSomeSome).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_THROTTLE_1);
+        assertThat(mCompactorUnderTest.mCompactThrottleSomeFull).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_THROTTLE_2);
+        assertThat(mCompactorUnderTest.mCompactThrottleFullSome).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_THROTTLE_3);
+        assertThat(mCompactorUnderTest.mCompactThrottleFullFull).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_THROTTLE_4);
+        assertThat(mCompactorUnderTest.mCompactThrottleBFGS).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_THROTTLE_5);
+        assertThat(mCompactorUnderTest.mCompactThrottlePersistent).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_THROTTLE_6);
     }
 
     @Test
     public void statsdSampleRate_listensToDeviceConfigChanges() throws InterruptedException {
         mCompactorUnderTest.init();
 
-        // When we override mStatsdSampleRate with a reasonable values ...
+        // When we override mStatsdSampleRate with a reasonable value ...
         mCountDown = new CountDownLatch(1);
         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                 AppCompactor.KEY_COMPACT_STATSD_SAMPLE_RATE,
@@ -380,11 +464,11 @@
     }
 
     @Test
-    public void statsdSanokeRate_listensToDeviceConfigChangesBadValues()
+    public void statsdSampleRate_listensToDeviceConfigChangesBadValues()
             throws InterruptedException {
         mCompactorUnderTest.init();
 
-        // When we override mStatsdSampleRate with a reasonable values ...
+        // When we override mStatsdSampleRate with an unreasonable value ...
         mCountDown = new CountDownLatch(1);
         DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
                 AppCompactor.KEY_COMPACT_STATSD_SAMPLE_RATE, "foo", false);
@@ -396,7 +480,7 @@
     }
 
     @Test
-    public void statsdSanokeRate_listensToDeviceConfigChangesOutOfRangeValues()
+    public void statsdSampleRate_listensToDeviceConfigChangesOutOfRangeValues()
             throws InterruptedException {
         mCompactorUnderTest.init();
 
@@ -420,6 +504,147 @@
         assertThat(mCompactorUnderTest.mStatsdSampleRate).isEqualTo(1.0f);
     }
 
+    @Test
+    public void fullCompactionRssThrottleKb_listensToDeviceConfigChanges()
+            throws InterruptedException {
+        mCompactorUnderTest.init();
+
+        // When we override mStatsdSampleRate with a reasonable value ...
+        mCountDown = new CountDownLatch(1);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                AppCompactor.KEY_COMPACT_FULL_RSS_THROTTLE_KB,
+                Long.toString(AppCompactor.DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB + 1), false);
+        assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
+
+        // Then that override is reflected in the compactor.
+        assertThat(mCompactorUnderTest.mFullAnonRssThrottleKb).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB + 1);
+    }
+
+    @Test
+    public void fullCompactionRssThrottleKb_listensToDeviceConfigChangesBadValues()
+            throws InterruptedException {
+        mCompactorUnderTest.init();
+
+        // When we override mStatsdSampleRate with an unreasonable value ...
+        mCountDown = new CountDownLatch(1);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                AppCompactor.KEY_COMPACT_FULL_RSS_THROTTLE_KB, "foo", false);
+        assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
+
+        // Then that override is reflected in the compactor.
+        assertThat(mCompactorUnderTest.mFullAnonRssThrottleKb).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB);
+
+        mCountDown = new CountDownLatch(1);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                AppCompactor.KEY_COMPACT_FULL_RSS_THROTTLE_KB, "-100", false);
+        assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
+
+        // Then that override is reflected in the compactor.
+        assertThat(mCompactorUnderTest.mFullAnonRssThrottleKb).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_FULL_RSS_THROTTLE_KB);
+    }
+
+    @Test
+    public void fullCompactionDeltaRssThrottleKb_listensToDeviceConfigChanges()
+            throws InterruptedException {
+        mCompactorUnderTest.init();
+
+        // When we override mStatsdSampleRate with a reasonable value ...
+        mCountDown = new CountDownLatch(1);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                AppCompactor.KEY_COMPACT_FULL_DELTA_RSS_THROTTLE_KB,
+                Long.toString(AppCompactor.DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB + 1), false);
+        assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
+
+        // Then that override is reflected in the compactor.
+        assertThat(mCompactorUnderTest.mFullDeltaRssThrottleKb).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB + 1);
+    }
+
+    @Test
+    public void fullCompactionDeltaRssThrottleKb_listensToDeviceConfigChangesBadValues()
+            throws InterruptedException {
+        mCompactorUnderTest.init();
+
+        // When we override mStatsdSampleRate with an unreasonable value ...
+        mCountDown = new CountDownLatch(1);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                AppCompactor.KEY_COMPACT_FULL_DELTA_RSS_THROTTLE_KB, "foo", false);
+        assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
+
+        // Then that override is reflected in the compactor.
+        assertThat(mCompactorUnderTest.mFullDeltaRssThrottleKb).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB);
+
+        mCountDown = new CountDownLatch(1);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                AppCompactor.KEY_COMPACT_FULL_DELTA_RSS_THROTTLE_KB, "-100", false);
+        assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
+
+        // Then that override is reflected in the compactor.
+        assertThat(mCompactorUnderTest.mFullDeltaRssThrottleKb).isEqualTo(
+                AppCompactor.DEFAULT_COMPACT_FULL_DELTA_RSS_THROTTLE_KB);
+    }
+
+    @Test
+    public void procStateThrottle_listensToDeviceConfigChanges()
+            throws InterruptedException {
+        mCompactorUnderTest.init();
+        mCountDown = new CountDownLatch(1);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                AppCompactor.KEY_COMPACT_PROC_STATE_THROTTLE, "1,2,3", false);
+        assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
+        assertThat(mCompactorUnderTest.mProcStateThrottle).containsExactly(1, 2, 3);
+
+        mCountDown = new CountDownLatch(1);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                AppCompactor.KEY_COMPACT_PROC_STATE_THROTTLE, "", false);
+        assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
+        assertThat(mCompactorUnderTest.mProcStateThrottle).isEmpty();
+    }
+
+    @Test
+    public void procStateThrottle_listensToDeviceConfigChangesBadValues()
+            throws InterruptedException {
+        mCompactorUnderTest.init();
+
+        Set<Integer> expected = new HashSet<>();
+        for (String s : TextUtils.split(AppCompactor.DEFAULT_COMPACT_PROC_STATE_THROTTLE, ",")) {
+            expected.add(Integer.parseInt(s));
+        }
+
+        // Not numbers
+        mCountDown = new CountDownLatch(1);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                AppCompactor.KEY_COMPACT_PROC_STATE_THROTTLE, "foo", false);
+        assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
+        assertThat(mCompactorUnderTest.mProcStateThrottle).containsExactlyElementsIn(expected);
+        mCountDown = new CountDownLatch(1);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                AppCompactor.KEY_COMPACT_PROC_STATE_THROTTLE, "1,foo", false);
+        assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
+        assertThat(mCompactorUnderTest.mProcStateThrottle).containsExactlyElementsIn(expected);
+
+        // Empty splits
+        mCountDown = new CountDownLatch(1);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                AppCompactor.KEY_COMPACT_PROC_STATE_THROTTLE, ",", false);
+        assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
+        assertThat(mCompactorUnderTest.mProcStateThrottle).containsExactlyElementsIn(expected);
+        mCountDown = new CountDownLatch(1);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                AppCompactor.KEY_COMPACT_PROC_STATE_THROTTLE, ",,3", false);
+        assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
+        assertThat(mCompactorUnderTest.mProcStateThrottle).containsExactlyElementsIn(expected);
+        mCountDown = new CountDownLatch(1);
+        DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ACTIVITY_MANAGER,
+                AppCompactor.KEY_COMPACT_PROC_STATE_THROTTLE, "1,,3", false);
+        assertThat(mCountDown.await(5, TimeUnit.SECONDS)).isTrue();
+        assertThat(mCompactorUnderTest.mProcStateThrottle).containsExactlyElementsIn(expected);
+    }
+
     private class TestInjector extends Injector {
         @Override
         public AppOpsService getAppOpsService(File file, Handler handler) {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index 87f10a4..6ed78b3 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -2124,9 +2124,16 @@
 
     @Test
     public void testXml_statusBarIcons_default() throws Exception {
-        ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
+        String preQXml = "<ranking version=\"1\">\n"
+                + "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n"
+                + "<channel id=\"something\" name=\"name\" importance=\"2\" "
+                + "show_badge=\"true\" />\n"
+                + "<channel id=\"miscellaneous\" name=\"Uncategorized\" usage=\"5\" "
+                + "content_type=\"4\" flags=\"0\" show_badge=\"true\" />\n"
+                + "</package>\n"
+                + "</ranking>\n";
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper);
-        loadStreamXml(baos, false, UserHandle.USER_ALL);
+        loadByteArrayXml(preQXml.getBytes(), true, UserHandle.USER_SYSTEM);
 
         assertEquals(PreferencesHelper.DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS,
                 mHelper.shouldHideSilentStatusIcons());
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
index 03969da..e90f094 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyLayoutTests.java
@@ -27,7 +27,7 @@
 import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
 import static android.view.WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING;
 import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
@@ -142,20 +142,20 @@
     }
 
     @Test
-    public void layoutWindowLw_appWontDrawBars_forceStatus() throws Exception {
+    public void layoutWindowLw_appWontDrawBars_forceStatusAndNav() throws Exception {
         synchronized (mWm.mGlobalLock) {
             mWindow.mAttrs.flags &= ~FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
-            mWindow.mAttrs.privateFlags |= PRIVATE_FLAG_FORCE_DRAW_STATUS_BAR_BACKGROUND;
+            mWindow.mAttrs.privateFlags |= PRIVATE_FLAG_FORCE_DRAW_BAR_BACKGROUNDS;
             addWindow(mWindow);
 
             mDisplayPolicy.beginLayoutLw(mFrames, 0 /* UI mode */);
             mDisplayPolicy.layoutWindowLw(mWindow, null, mFrames);
 
-            assertInsetByTopBottom(mWindow.getParentFrame(), 0, NAV_BAR_HEIGHT);
+            assertInsetByTopBottom(mWindow.getParentFrame(), 0, 0);
             assertInsetByTopBottom(mWindow.getStableFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
             assertInsetByTopBottom(mWindow.getContentFrameLw(), STATUS_BAR_HEIGHT, NAV_BAR_HEIGHT);
-            assertInsetByTopBottom(mWindow.getDecorFrame(), 0, NAV_BAR_HEIGHT);
-            assertInsetByTopBottom(mWindow.getDisplayFrameLw(), 0, NAV_BAR_HEIGHT);
+            assertInsetByTopBottom(mWindow.getDecorFrame(), 0, 0);
+            assertInsetByTopBottom(mWindow.getDisplayFrameLw(), 0, 0);
         }
     }
 
diff --git a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java
index 465c2b1..2cb369d 100644
--- a/telephony/java/android/telephony/DataSpecificRegistrationInfo.java
+++ b/telephony/java/android/telephony/DataSpecificRegistrationInfo.java
@@ -78,7 +78,7 @@
      *
      * @hide
      */
-    public final boolean isUsingCarrierAggregation;
+    public boolean mIsUsingCarrierAggregation;
 
     /**
      * @hide
@@ -92,7 +92,7 @@
         this.isNrAvailable = isNrAvailable;
         this.isEnDcAvailable = isEnDcAvailable;
         this.mLteVopsSupportInfo = lteVops;
-        this.isUsingCarrierAggregation = isUsingCarrierAggregation;
+        this.mIsUsingCarrierAggregation = isUsingCarrierAggregation;
     }
 
     private DataSpecificRegistrationInfo(Parcel source) {
@@ -101,7 +101,7 @@
         isNrAvailable = source.readBoolean();
         isEnDcAvailable = source.readBoolean();
         mLteVopsSupportInfo = LteVopsSupportInfo.CREATOR.createFromParcel(source);
-        isUsingCarrierAggregation = source.readBoolean();
+        mIsUsingCarrierAggregation = source.readBoolean();
     }
 
     @Override
@@ -111,7 +111,7 @@
         dest.writeBoolean(isNrAvailable);
         dest.writeBoolean(isEnDcAvailable);
         mLteVopsSupportInfo.writeToParcel(dest, flags);
-        dest.writeBoolean(isUsingCarrierAggregation);
+        dest.writeBoolean(mIsUsingCarrierAggregation);
     }
 
     @Override
@@ -128,7 +128,7 @@
                 .append(" isNrAvailable = " + isNrAvailable)
                 .append(" isEnDcAvailable = " + isEnDcAvailable)
                 .append(" " + mLteVopsSupportInfo.toString())
-                .append(" isUsingCarrierAggregation = " + isUsingCarrierAggregation)
+                .append(" mIsUsingCarrierAggregation = " + mIsUsingCarrierAggregation)
                 .append(" }")
                 .toString();
     }
@@ -136,7 +136,7 @@
     @Override
     public int hashCode() {
         return Objects.hash(maxDataCalls, isDcNrRestricted, isNrAvailable, isEnDcAvailable,
-                mLteVopsSupportInfo, isUsingCarrierAggregation);
+                mLteVopsSupportInfo, mIsUsingCarrierAggregation);
     }
 
     @Override
@@ -151,7 +151,7 @@
                 && this.isNrAvailable == other.isNrAvailable
                 && this.isEnDcAvailable == other.isEnDcAvailable
                 && this.mLteVopsSupportInfo.equals(other.mLteVopsSupportInfo)
-                && this.isUsingCarrierAggregation == other.isUsingCarrierAggregation;
+                && this.mIsUsingCarrierAggregation == other.mIsUsingCarrierAggregation;
     }
 
     public static final @NonNull Parcelable.Creator<DataSpecificRegistrationInfo> CREATOR =
@@ -174,4 +174,22 @@
     public LteVopsSupportInfo getLteVopsSupportInfo() {
         return mLteVopsSupportInfo;
     }
+
+    /**
+     * Set the flag indicating if using carrier aggregation.
+     *
+     * @param isUsingCarrierAggregation {@code true} if using carrier aggregation.
+     * @hide
+     */
+    public void setIsUsingCarrierAggregation(boolean isUsingCarrierAggregation) {
+        mIsUsingCarrierAggregation = isUsingCarrierAggregation;
+    }
+
+    /**
+     * @return {@code true} if using carrier aggregation.
+     * @hide
+     */
+    public boolean isUsingCarrierAggregation() {
+        return mIsUsingCarrierAggregation;
+    }
 }
diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java
index 2bb02e7..7b9f6d5 100644
--- a/telephony/java/android/telephony/NetworkRegistrationInfo.java
+++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java
@@ -368,6 +368,13 @@
      * @hide
      */
     public void setAccessNetworkTechnology(@NetworkType int tech) {
+        if (tech == TelephonyManager.NETWORK_TYPE_LTE_CA) {
+            // For old device backward compatibility support
+            tech = TelephonyManager.NETWORK_TYPE_LTE;
+            if (mDataSpecificInfo != null) {
+                mDataSpecificInfo.setIsUsingCarrierAggregation(true);
+            }
+        }
         mAccessNetworkTechnology = tech;
     }
 
diff --git a/telephony/java/android/telephony/PhoneNumberUtils.java b/telephony/java/android/telephony/PhoneNumberUtils.java
index 549c044..b75e515 100644
--- a/telephony/java/android/telephony/PhoneNumberUtils.java
+++ b/telephony/java/android/telephony/PhoneNumberUtils.java
@@ -2016,7 +2016,16 @@
     private static boolean isEmergencyNumberInternal(int subId, String number,
                                                      String defaultCountryIso,
                                                      boolean useExactMatch) {
-        return TelephonyManager.getDefault().isEmergencyNumber(number);
+        try {
+            if (useExactMatch) {
+                return TelephonyManager.getDefault().isEmergencyNumber(number);
+            } else {
+                return TelephonyManager.getDefault().isPotentialEmergencyNumber(number);
+            }
+        } catch (RuntimeException ex) {
+            Rlog.e(LOG_TAG, "isEmergencyNumberInternal: RuntimeException: " + ex);
+        }
+        return false;
     }
 
     /**
diff --git a/telephony/java/android/telephony/ServiceState.java b/telephony/java/android/telephony/ServiceState.java
index a794ba1..d2c0705 100644
--- a/telephony/java/android/telephony/ServiceState.java
+++ b/telephony/java/android/telephony/ServiceState.java
@@ -312,18 +312,6 @@
     private boolean mIsManualNetworkSelection;
 
     private boolean mIsEmergencyOnly;
-    /**
-     * TODO: remove mRilVoiceRadioTechnology after completely migrate to
-     * {@link TelephonyManager.NetworkType}
-     */
-    @RilRadioTechnology
-    private int mRilVoiceRadioTechnology;
-    /**
-     * TODO: remove mRilDataRadioTechnology after completely migrate to
-     * {@link TelephonyManager.NetworkType}
-     */
-    @RilRadioTechnology
-    private int mRilDataRadioTechnology;
 
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private boolean mCssIndicator;
@@ -340,9 +328,6 @@
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
     private int mCdmaEriIconMode;
 
-    @UnsupportedAppUsage
-    private boolean mIsUsingCarrierAggregation;
-
     @FrequencyRange
     private int mNrFrequencyRange;
     private int mChannelNumber;
@@ -420,8 +405,6 @@
         mDataOperatorAlphaShort = s.mDataOperatorAlphaShort;
         mDataOperatorNumeric = s.mDataOperatorNumeric;
         mIsManualNetworkSelection = s.mIsManualNetworkSelection;
-        mRilVoiceRadioTechnology = s.mRilVoiceRadioTechnology;
-        mRilDataRadioTechnology = s.mRilDataRadioTechnology;
         mCssIndicator = s.mCssIndicator;
         mNetworkId = s.mNetworkId;
         mSystemId = s.mSystemId;
@@ -430,7 +413,6 @@
         mCdmaEriIconIndex = s.mCdmaEriIconIndex;
         mCdmaEriIconMode = s.mCdmaEriIconMode;
         mIsEmergencyOnly = s.mIsEmergencyOnly;
-        mIsUsingCarrierAggregation = s.mIsUsingCarrierAggregation;
         mChannelNumber = s.mChannelNumber;
         mCellBandwidths = s.mCellBandwidths == null ? null :
                 Arrays.copyOf(s.mCellBandwidths, s.mCellBandwidths.length);
@@ -457,8 +439,6 @@
         mDataOperatorAlphaShort = in.readString();
         mDataOperatorNumeric = in.readString();
         mIsManualNetworkSelection = in.readInt() != 0;
-        mRilVoiceRadioTechnology = in.readInt();
-        mRilDataRadioTechnology = in.readInt();
         mCssIndicator = (in.readInt() != 0);
         mNetworkId = in.readInt();
         mSystemId = in.readInt();
@@ -467,7 +447,6 @@
         mCdmaEriIconIndex = in.readInt();
         mCdmaEriIconMode = in.readInt();
         mIsEmergencyOnly = in.readInt() != 0;
-        mIsUsingCarrierAggregation = in.readInt() != 0;
         mLteEarfcnRsrpBoost = in.readInt();
         mNetworkRegistrationInfos = new ArrayList<>();
         in.readList(mNetworkRegistrationInfos, NetworkRegistrationInfo.class.getClassLoader());
@@ -486,8 +465,6 @@
         out.writeString(mDataOperatorAlphaShort);
         out.writeString(mDataOperatorNumeric);
         out.writeInt(mIsManualNetworkSelection ? 1 : 0);
-        out.writeInt(mRilVoiceRadioTechnology);
-        out.writeInt(mRilDataRadioTechnology);
         out.writeInt(mCssIndicator ? 1 : 0);
         out.writeInt(mNetworkId);
         out.writeInt(mSystemId);
@@ -496,7 +473,6 @@
         out.writeInt(mCdmaEriIconIndex);
         out.writeInt(mCdmaEriIconMode);
         out.writeInt(mIsEmergencyOnly ? 1 : 0);
-        out.writeInt(mIsUsingCarrierAggregation ? 1 : 0);
         out.writeInt(mLteEarfcnRsrpBoost);
         out.writeList(mNetworkRegistrationInfos);
         out.writeInt(mChannelNumber);
@@ -568,7 +544,7 @@
     @DuplexMode
     public int getDuplexMode() {
         // only support LTE duplex mode
-        if (!isLte(mRilDataRadioTechnology)) {
+        if (!isLte(getRilDataRadioTechnology())) {
             return DUPLEX_MODE_UNKNOWN;
         }
 
@@ -850,8 +826,6 @@
                 mDataOperatorAlphaShort,
                 mDataOperatorNumeric,
                 mIsManualNetworkSelection,
-                mRilVoiceRadioTechnology,
-                mRilDataRadioTechnology,
                 mCssIndicator,
                 mNetworkId,
                 mSystemId,
@@ -860,7 +834,6 @@
                 mCdmaEriIconIndex,
                 mCdmaEriIconMode,
                 mIsEmergencyOnly,
-                mIsUsingCarrierAggregation,
                 mLteEarfcnRsrpBoost,
                 mNetworkRegistrationInfos,
                 mNrFrequencyRange);
@@ -871,7 +844,7 @@
         if (!(o instanceof ServiceState)) return false;
         ServiceState s = (ServiceState) o;
 
-        return (mVoiceRegState == s.mVoiceRegState
+        return mVoiceRegState == s.mVoiceRegState
                 && mDataRegState == s.mDataRegState
                 && mIsManualNetworkSelection == s.mIsManualNetworkSelection
                 && mChannelNumber == s.mChannelNumber
@@ -882,8 +855,6 @@
                 && equalsHandlesNulls(mDataOperatorAlphaLong, s.mDataOperatorAlphaLong)
                 && equalsHandlesNulls(mDataOperatorAlphaShort, s.mDataOperatorAlphaShort)
                 && equalsHandlesNulls(mDataOperatorNumeric, s.mDataOperatorNumeric)
-                && equalsHandlesNulls(mRilVoiceRadioTechnology, s.mRilVoiceRadioTechnology)
-                && equalsHandlesNulls(mRilDataRadioTechnology, s.mRilDataRadioTechnology)
                 && equalsHandlesNulls(mCssIndicator, s.mCssIndicator)
                 && equalsHandlesNulls(mNetworkId, s.mNetworkId)
                 && equalsHandlesNulls(mSystemId, s.mSystemId)
@@ -891,7 +862,6 @@
                 && equalsHandlesNulls(mCdmaDefaultRoamingIndicator,
                         s.mCdmaDefaultRoamingIndicator)
                 && mIsEmergencyOnly == s.mIsEmergencyOnly
-                && mIsUsingCarrierAggregation == s.mIsUsingCarrierAggregation)
                 && (mNetworkRegistrationInfos == null
                 ? s.mNetworkRegistrationInfos == null : s.mNetworkRegistrationInfos != null
                 && mNetworkRegistrationInfos.containsAll(s.mNetworkRegistrationInfos))
@@ -1035,27 +1005,27 @@
             .append(", mDataOperatorAlphaShort=").append(mDataOperatorAlphaShort)
             .append(", isManualNetworkSelection=").append(mIsManualNetworkSelection)
             .append(mIsManualNetworkSelection ? "(manual)" : "(automatic)")
-            .append(", mRilVoiceRadioTechnology=").append(mRilVoiceRadioTechnology)
-            .append("(" + rilRadioTechnologyToString(mRilVoiceRadioTechnology) + ")")
-            .append(", mRilDataRadioTechnology=").append(mRilDataRadioTechnology)
-            .append("(" + rilRadioTechnologyToString(mRilDataRadioTechnology) + ")")
+            .append(", getRilVoiceRadioTechnology=").append(getRilVoiceRadioTechnology())
+            .append("(" + rilRadioTechnologyToString(getRilVoiceRadioTechnology()) + ")")
+            .append(", getRilDataRadioTechnology=").append(getRilDataRadioTechnology())
+            .append("(" + rilRadioTechnologyToString(getRilDataRadioTechnology()) + ")")
             .append(", mCssIndicator=").append(mCssIndicator ? "supported" : "unsupported")
             .append(", mNetworkId=").append(mNetworkId)
             .append(", mSystemId=").append(mSystemId)
             .append(", mCdmaRoamingIndicator=").append(mCdmaRoamingIndicator)
             .append(", mCdmaDefaultRoamingIndicator=").append(mCdmaDefaultRoamingIndicator)
             .append(", mIsEmergencyOnly=").append(mIsEmergencyOnly)
-            .append(", mIsUsingCarrierAggregation=").append(mIsUsingCarrierAggregation)
+            .append(", isUsingCarrierAggregation=").append(isUsingCarrierAggregation())
             .append(", mLteEarfcnRsrpBoost=").append(mLteEarfcnRsrpBoost)
             .append(", mNetworkRegistrationInfos=").append(mNetworkRegistrationInfos)
             .append(", mNrFrequencyRange=").append(mNrFrequencyRange)
             .append("}").toString();
     }
 
-    private void setNullState(int state) {
-        if (DBG) Rlog.d(LOG_TAG, "[ServiceState] setNullState=" + state);
-        mVoiceRegState = state;
-        mDataRegState = state;
+    private void init() {
+        if (DBG) Rlog.d(LOG_TAG, "init");
+        mVoiceRegState = STATE_OUT_OF_SERVICE;
+        mDataRegState = STATE_OUT_OF_SERVICE;
         mChannelNumber = -1;
         mCellBandwidths = new int[0];
         mVoiceOperatorAlphaLong = null;
@@ -1065,8 +1035,6 @@
         mDataOperatorAlphaShort = null;
         mDataOperatorNumeric = null;
         mIsManualNetworkSelection = false;
-        mRilVoiceRadioTechnology = 0;
-        mRilDataRadioTechnology = 0;
         mCssIndicator = false;
         mNetworkId = -1;
         mSystemId = -1;
@@ -1075,18 +1043,28 @@
         mCdmaEriIconIndex = -1;
         mCdmaEriIconMode = -1;
         mIsEmergencyOnly = false;
-        mIsUsingCarrierAggregation = false;
         mLteEarfcnRsrpBoost = 0;
-        mNetworkRegistrationInfos = new ArrayList<>();
         mNrFrequencyRange = FREQUENCY_RANGE_UNKNOWN;
+        addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
+                .setDomain(NetworkRegistrationInfo.DOMAIN_CS)
+                .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+                .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN)
+                .build());
+        addNetworkRegistrationInfo(new NetworkRegistrationInfo.Builder()
+                .setDomain(NetworkRegistrationInfo.DOMAIN_PS)
+                .setTransportType(AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
+                .setRegistrationState(NetworkRegistrationInfo.REGISTRATION_STATE_UNKNOWN)
+                .build());
     }
 
     public void setStateOutOfService() {
-        setNullState(STATE_OUT_OF_SERVICE);
+        init();
     }
 
     public void setStateOff() {
-        setNullState(STATE_POWER_OFF);
+        init();
+        mVoiceRegState = STATE_POWER_OFF;
+        mDataRegState = STATE_POWER_OFF;
     }
 
     public void setState(int state) {
@@ -1304,8 +1282,8 @@
         m.putString("data-operator-alpha-short", mDataOperatorAlphaShort);
         m.putString("data-operator-numeric", mDataOperatorNumeric);
         m.putBoolean("manual", mIsManualNetworkSelection);
-        m.putInt("radioTechnology", mRilVoiceRadioTechnology);
-        m.putInt("dataRadioTechnology", mRilDataRadioTechnology);
+        m.putInt("radioTechnology", getRilVoiceRadioTechnology());
+        m.putInt("dataRadioTechnology", getRadioTechnology());
         m.putBoolean("cssIndicator", mCssIndicator);
         m.putInt("networkId", mNetworkId);
         m.putInt("systemId", mSystemId);
@@ -1313,7 +1291,7 @@
         m.putInt("cdmaDefaultRoamingIndicator", mCdmaDefaultRoamingIndicator);
         m.putBoolean("emergencyOnly", mIsEmergencyOnly);
         m.putBoolean("isDataRoamingFromRegistration", getDataRoamingFromRegistration());
-        m.putBoolean("isUsingCarrierAggregation", mIsUsingCarrierAggregation);
+        m.putBoolean("isUsingCarrierAggregation", isUsingCarrierAggregation());
         m.putInt("LteEarfcnRsrpBoost", mLteEarfcnRsrpBoost);
         m.putInt("ChannelNumber", mChannelNumber);
         m.putIntArray("CellBandwidths", mCellBandwidths);
@@ -1323,13 +1301,9 @@
     /** @hide */
     @TestApi
     public void setRilVoiceRadioTechnology(@RilRadioTechnology int rt) {
-        if (rt == RIL_RADIO_TECHNOLOGY_LTE_CA) {
-            rt = RIL_RADIO_TECHNOLOGY_LTE;
-        }
-
-        this.mRilVoiceRadioTechnology = rt;
-
-        // sync to network registration state
+        Rlog.e(LOG_TAG, "ServiceState.setRilVoiceRadioTechnology() called. It's encouraged to "
+                + "use addNetworkRegistrationInfo() instead *******");
+        // Sync to network registration state
         NetworkRegistrationInfo regState = getNetworkRegistrationInfo(
                 NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
         if (regState == null) {
@@ -1339,24 +1313,18 @@
                     .build();
             addNetworkRegistrationInfo(regState);
         }
-        regState.setAccessNetworkTechnology(
-                rilRadioTechnologyToNetworkType(mRilVoiceRadioTechnology));
+        regState.setAccessNetworkTechnology(rilRadioTechnologyToNetworkType(rt));
     }
 
+
     /** @hide */
     @TestApi
     public void setRilDataRadioTechnology(@RilRadioTechnology int rt) {
-        if (rt == RIL_RADIO_TECHNOLOGY_LTE_CA) {
-            rt = RIL_RADIO_TECHNOLOGY_LTE;
-            this.mIsUsingCarrierAggregation = true;
-        } else {
-            this.mIsUsingCarrierAggregation = false;
-        }
-        this.mRilDataRadioTechnology = rt;
-        if (VDBG) Rlog.d(LOG_TAG, "[ServiceState] setRilDataRadioTechnology=" +
-                mRilDataRadioTechnology);
-
-        // sync to network registration state
+        Rlog.e(LOG_TAG, "ServiceState.setRilDataRadioTechnology() called. It's encouraged to "
+                + "use addNetworkRegistrationInfo() instead *******");
+        // Sync to network registration state. Always write down the WWAN transport. For AP-assisted
+        // mode device, use addNetworkRegistrationInfo() to set the correct transport if RAT
+        // is IWLAN.
         NetworkRegistrationInfo regState = getNetworkRegistrationInfo(
                 NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
 
@@ -1367,18 +1335,32 @@
                     .build();
             addNetworkRegistrationInfo(regState);
         }
-        regState.setAccessNetworkTechnology(
-                rilRadioTechnologyToNetworkType(mRilDataRadioTechnology));
+        regState.setAccessNetworkTechnology(rilRadioTechnologyToNetworkType(rt));
     }
 
     /** @hide */
     public boolean isUsingCarrierAggregation() {
-        return mIsUsingCarrierAggregation;
+        NetworkRegistrationInfo nri = getNetworkRegistrationInfo(
+                NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+        if (nri != null) {
+            DataSpecificRegistrationInfo dsri = nri.getDataSpecificInfo();
+            if (dsri != null) {
+                return dsri.isUsingCarrierAggregation();
+            }
+        }
+        return false;
     }
 
     /** @hide */
     public void setIsUsingCarrierAggregation(boolean ca) {
-        mIsUsingCarrierAggregation = ca;
+        NetworkRegistrationInfo nri = getNetworkRegistrationInfo(
+                NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+        if (nri != null) {
+            DataSpecificRegistrationInfo dsri = nri.getDataSpecificInfo();
+            if (dsri != null) {
+                dsri.setIsUsingCarrierAggregation(ca);
+            }
+        }
     }
 
     /**
@@ -1435,12 +1417,29 @@
     /** @hide */
     @UnsupportedAppUsage
     public int getRilVoiceRadioTechnology() {
-        return this.mRilVoiceRadioTechnology;
+        NetworkRegistrationInfo wwanRegInfo = getNetworkRegistrationInfo(
+                NetworkRegistrationInfo.DOMAIN_CS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+        if (wwanRegInfo != null) {
+            return networkTypeToRilRadioTechnology(wwanRegInfo.getAccessNetworkTechnology());
+        }
+        return RIL_RADIO_TECHNOLOGY_UNKNOWN;
     }
     /** @hide */
     @UnsupportedAppUsage
     public int getRilDataRadioTechnology() {
-        return this.mRilDataRadioTechnology;
+        NetworkRegistrationInfo wwanRegInfo = getNetworkRegistrationInfo(
+                NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+        NetworkRegistrationInfo wlanRegInfo = getNetworkRegistrationInfo(
+                NetworkRegistrationInfo.DOMAIN_PS, AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
+        if (wlanRegInfo != null
+                && wlanRegInfo.getAccessNetworkTechnology() == TelephonyManager.NETWORK_TYPE_IWLAN
+                && wlanRegInfo.getRegistrationState()
+                == NetworkRegistrationInfo.REGISTRATION_STATE_HOME) {
+            return RIL_RADIO_TECHNOLOGY_IWLAN;
+        } else if (wwanRegInfo != null) {
+            return networkTypeToRilRadioTechnology(wwanRegInfo.getAccessNetworkTechnology());
+        }
+        return RIL_RADIO_TECHNOLOGY_UNKNOWN;
     }
     /**
      * @hide
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index f393cba..fb82ca6 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -5267,6 +5267,18 @@
      * Use this method when no subscriptions are available on the SIM and the operation must be
      * performed using the physical slot index.
      *
+     * This operation wraps two APDU instructions:
+     * <ul>
+     *     <li>MANAGE CHANNEL to open a logical channel</li>
+     *     <li>SELECT the given {@code AID} using the given {@code p2}</li>
+     * </ul>
+     *
+     * Per Open Mobile API Specification v3.2 section 6.2.7.h, only p2 values of 0x00, 0x04, 0x08,
+     * and 0x0C are guaranteed to be supported.
+     *
+     * If the SELECT command's status word is not '9000', '62xx', or '63xx', the status word will be
+     * considered an error and the channel shall not be opened.
+     *
      * Input parameters equivalent to TS 27.007 AT+CCHO command.
      *
      * <p>Requires Permission:
@@ -5298,6 +5310,18 @@
     /**
      * Opens a logical channel to the ICC card.
      *
+     * This operation wraps two APDU instructions:
+     * <ul>
+     *     <li>MANAGE CHANNEL to open a logical channel</li>
+     *     <li>SELECT the given {@code AID} using the given {@code p2}</li>
+     * </ul>
+     *
+     * Per Open Mobile API Specification v3.2 section 6.2.7.h, only p2 values of 0x00, 0x04, 0x08,
+     * and 0x0C are guaranteed to be supported.
+     *
+     * If the SELECT command's status word is not '9000', '62xx', or '63xx', the status word will be
+     * considered an error and the channel shall not be opened.
+     *
      * Input parameters equivalent to TS 27.007 AT+CCHO command.
      *
      * <p>Requires Permission:
@@ -5315,6 +5339,18 @@
     /**
      * Opens a logical channel to the ICC card.
      *
+     * This operation wraps two APDU instructions:
+     * <ul>
+     *     <li>MANAGE CHANNEL to open a logical channel</li>
+     *     <li>SELECT the given {@code AID} using the given {@code p2}</li>
+     * </ul>
+     *
+     * Per Open Mobile API Specification v3.2 section 6.2.7.h, only p2 values of 0x00, 0x04, 0x08,
+     * and 0x0C are guaranteed to be supported.
+     *
+     * If the SELECT command's status word is not '9000', '62xx', or '63xx', the status word will be
+     * considered an error and the channel shall not be opened.
+     *
      * Input parameters equivalent to TS 27.007 AT+CCHO command.
      *
      * <p>Requires Permission:
@@ -10861,24 +10897,28 @@
     }
 
     /**
-     * Get whether reboot is required or not after making changes to modem configurations.
+     * Get whether making changes to modem configurations by {@link #switchMultiSimConfig(int)} will
+     * trigger device reboot.
      * The modem configuration change refers to switching from single SIM configuration to DSDS
      * or the other way around.
-     * @Return {@code true} if reboot is required after making changes to modem configurations,
-     * otherwise return {@code false}.
      *
-     * @hide
+     *  <p>Requires Permission:
+     * {@link android.Manifest.permission#READ_PHONE_STATE READ_PHONE_STATE} or that the
+     * calling app has carrier privileges (see {@link #hasCarrierPrivileges}).
+     *
+     * @return {@code true} if reboot will be triggered after making changes to modem
+     * configurations, otherwise return {@code false}.
      */
-    @SystemApi
-    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
-    public boolean isRebootRequiredForModemConfigChange() {
+    @RequiresPermission(Manifest.permission.READ_PHONE_STATE)
+    public boolean doesSwitchMultiSimConfigTriggerReboot() {
         try {
             ITelephony service = getITelephony();
             if (service != null) {
-                return service.isRebootRequiredForModemConfigChange();
+                return service.doesSwitchMultiSimConfigTriggerReboot(getSubId(),
+                        getOpPackageName());
             }
         } catch (RemoteException e) {
-            Log.e(TAG, "isRebootRequiredForModemConfigChange RemoteException", e);
+            Log.e(TAG, "doesSwitchMultiSimConfigTriggerReboot RemoteException", e);
         }
         return false;
     }
diff --git a/telephony/java/android/telephony/euicc/EuiccManager.java b/telephony/java/android/telephony/euicc/EuiccManager.java
index cde10ea..96a2514 100644
--- a/telephony/java/android/telephony/euicc/EuiccManager.java
+++ b/telephony/java/android/telephony/euicc/EuiccManager.java
@@ -485,7 +485,7 @@
     public boolean isEnabled() {
         // In the future, this may reach out to IEuiccController (if non-null) to check any dynamic
         // restrictions.
-        return getIEuiccController() != null;
+        return getIEuiccController() != null && refreshCardIdIfUninitialized();
     }
 
     /**
@@ -499,7 +499,7 @@
      */
     @Nullable
     public String getEid() {
-        if (!refreshCardIdIfUninitialized()) {
+        if (!isEnabled()) {
             return null;
         }
         try {
@@ -522,7 +522,7 @@
     @SystemApi
     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
     public int getOtaStatus() {
-        if (!refreshCardIdIfUninitialized()) {
+        if (!isEnabled()) {
             return EUICC_OTA_STATUS_UNAVAILABLE;
         }
         try {
@@ -557,7 +557,7 @@
     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
     public void downloadSubscription(DownloadableSubscription subscription,
             boolean switchAfterDownload, PendingIntent callbackIntent) {
-        if (!refreshCardIdIfUninitialized()) {
+        if (!isEnabled()) {
             sendUnavailableError(callbackIntent);
             return;
         }
@@ -619,7 +619,7 @@
     @SystemApi
     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
     public void continueOperation(Intent resolutionIntent, Bundle resolutionExtras) {
-        if (!refreshCardIdIfUninitialized()) {
+        if (!isEnabled()) {
             PendingIntent callbackIntent =
                     resolutionIntent.getParcelableExtra(
                             EuiccManager.EXTRA_EMBEDDED_SUBSCRIPTION_RESOLUTION_CALLBACK_INTENT);
@@ -656,7 +656,7 @@
     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
     public void getDownloadableSubscriptionMetadata(
             DownloadableSubscription subscription, PendingIntent callbackIntent) {
-        if (!refreshCardIdIfUninitialized()) {
+        if (!isEnabled()) {
             sendUnavailableError(callbackIntent);
             return;
         }
@@ -686,7 +686,7 @@
     @SystemApi
     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
     public void getDefaultDownloadableSubscriptionList(PendingIntent callbackIntent) {
-        if (!refreshCardIdIfUninitialized()) {
+        if (!isEnabled()) {
             sendUnavailableError(callbackIntent);
             return;
         }
@@ -705,7 +705,7 @@
      */
     @Nullable
     public EuiccInfo getEuiccInfo() {
-        if (!refreshCardIdIfUninitialized()) {
+        if (!isEnabled()) {
             return null;
         }
         try {
@@ -730,7 +730,7 @@
      */
     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
     public void deleteSubscription(int subscriptionId, PendingIntent callbackIntent) {
-        if (!refreshCardIdIfUninitialized()) {
+        if (!isEnabled()) {
             sendUnavailableError(callbackIntent);
             return;
         }
@@ -770,7 +770,7 @@
      */
     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
     public void switchToSubscription(int subscriptionId, PendingIntent callbackIntent) {
-        if (!refreshCardIdIfUninitialized()) {
+        if (!isEnabled()) {
             sendUnavailableError(callbackIntent);
             return;
         }
@@ -796,7 +796,7 @@
     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
     public void updateSubscriptionNickname(
             int subscriptionId, @Nullable String nickname, @NonNull PendingIntent callbackIntent) {
-        if (!refreshCardIdIfUninitialized()) {
+        if (!isEnabled()) {
             sendUnavailableError(callbackIntent);
             return;
         }
@@ -820,7 +820,7 @@
     @SystemApi
     @RequiresPermission(Manifest.permission.WRITE_EMBEDDED_SUBSCRIPTIONS)
     public void eraseSubscriptions(PendingIntent callbackIntent) {
-        if (!refreshCardIdIfUninitialized()) {
+        if (!isEnabled()) {
             sendUnavailableError(callbackIntent);
             return;
         }
@@ -850,7 +850,7 @@
      * @hide
      */
     public void retainSubscriptionsForFactoryReset(PendingIntent callbackIntent) {
-        if (!refreshCardIdIfUninitialized()) {
+        if (!isEnabled()) {
             sendUnavailableError(callbackIntent);
             return;
         }
diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl
index 8332ffe..c8cd249 100644
--- a/telephony/java/com/android/internal/telephony/ITelephony.aidl
+++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl
@@ -1945,10 +1945,10 @@
     void switchMultiSimConfig(int numOfSims);
 
     /**
-     * Get if reboot is required upon altering modems configurations
+     * Get if altering modems configurations will trigger reboot.
      * @hide
      */
-    boolean isRebootRequiredForModemConfigChange();
+    boolean doesSwitchMultiSimConfigTriggerReboot(int subId, String callingPackage);
 
     /**
      * Get the mapping from logical slots to physical slots.
diff --git a/tests/benchmarks/Android.bp b/tests/benchmarks/Android.bp
new file mode 100644
index 0000000..f16ddb9
--- /dev/null
+++ b/tests/benchmarks/Android.bp
@@ -0,0 +1,29 @@
+// Copyright (C) 2015 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+// build framework base core benchmarks
+// ============================================================
+
+java_library {
+    name: "networkStatsFactory-benchmarks",
+    installable: true,
+
+    srcs: ["src/**/*.java"],
+
+    libs: [
+        "caliper-api-target",
+        "services.core",
+    ],
+
+}
diff --git a/core/tests/benchmarks/src/com/android/internal/net/NetworkStatsFactoryBenchmark.java b/tests/benchmarks/src/com/android/server/net/NetworkStatsFactoryBenchmark.java
similarity index 95%
rename from core/tests/benchmarks/src/com/android/internal/net/NetworkStatsFactoryBenchmark.java
rename to tests/benchmarks/src/com/android/server/net/NetworkStatsFactoryBenchmark.java
index c213464..ef014f0 100644
--- a/core/tests/benchmarks/src/com/android/internal/net/NetworkStatsFactoryBenchmark.java
+++ b/tests/benchmarks/src/com/android/server/net/NetworkStatsFactoryBenchmark.java
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-package com.android.internal.net;
+package com.android.server.net;
 
 import android.net.NetworkStats;
 import android.os.SystemClock;
+import com.android.server.net.NetworkStatsFactory;
 import com.google.caliper.AfterExperiment;
 import com.google.caliper.BeforeExperiment;
 import java.io.File;
diff --git a/tests/net/Android.bp b/tests/net/Android.bp
index c62d85e..70b4089 100644
--- a/tests/net/Android.bp
+++ b/tests/net/Android.bp
@@ -1,11 +1,8 @@
 //########################################################################
 // Build FrameworksNetTests package
 //########################################################################
-
-android_test {
-    name: "FrameworksNetTests",
-    // Include all test java files.
-    srcs: ["java/**/*.java"],
+java_defaults {
+    name: "FrameworksNetTests-jni-defaults",
     static_libs: [
         "frameworks-base-testutils",
         "framework-protos",
@@ -20,6 +17,53 @@
         "android.test.base",
         "android.test.mock",
     ],
+    jni_libs: [
+        "ld-android",
+        "libartbase",
+        "libbacktrace",
+        "libbase",
+        "libbinder",
+        "libbinderthreadstate",
+        "libbpf",
+        "libbpf_android",
+        "libc++",
+        "libcgrouprc",
+        "libcrypto",
+        "libcutils",
+        "libdexfile",
+        "libdl_android",
+        "libhidl-gen-utils",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "libjsoncpp",
+        "liblog",
+        "liblzma",
+        "libnativehelper",
+        "libnetdbpf",
+        "libnetdutils",
+        "libpackagelistparser",
+        "libpcre2",
+        "libprocessgroup",
+        "libselinux",
+        "libui",
+        "libutils",
+        "libvintf",
+        "libvndksupport",
+        "libtinyxml2",
+        "libunwindstack",
+        "libutilscallstack",
+        "libziparchive",
+        "libz",
+        "netd_aidl_interface-cpp",
+        "libnetworkstatsfactorytestjni",
+    ],
+}
+
+android_test {
+    name: "FrameworksNetTests",
+    defaults: ["FrameworksNetTests-jni-defaults"],
+    srcs: ["java/**/*.java"],
     platform_apis: true,
     test_suites: ["device-tests"],
     certificate: "platform",
diff --git a/tests/net/java/android/net/netlink/InetDiagSocketTest.java b/tests/net/java/android/net/netlink/InetDiagSocketTest.java
index b6038ab..8b2b4e3 100644
--- a/tests/net/java/android/net/netlink/InetDiagSocketTest.java
+++ b/tests/net/java/android/net/netlink/InetDiagSocketTest.java
@@ -189,7 +189,6 @@
         udp.close();
     }
 
-    @Test
     public void testGetConnectionOwnerUid() throws Exception {
         checkGetConnectionOwnerUid("::", null);
         checkGetConnectionOwnerUid("::", "::");
diff --git a/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java b/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java
similarity index 96%
rename from tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
rename to tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java
index 4ec4fdd..95bc7d9 100644
--- a/tests/net/java/com/android/internal/net/NetworkStatsFactoryTest.java
+++ b/tests/net/java/com/android/server/net/NetworkStatsFactoryTest.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.internal.net;
+package com.android.server.net;
 
 import static android.net.NetworkStats.DEFAULT_NETWORK_NO;
 import static android.net.NetworkStats.METERED_NO;
@@ -70,6 +70,10 @@
             IoUtils.deleteContents(mTestProc);
         }
 
+        // The libandroid_servers which have the native method is not available to
+        // applications. So in order to have a test support native library, the native code
+        // related to networkStatsFactory is compiled to a minimal native library and loaded here.
+        System.loadLibrary("networkstatsfactorytestjni");
         mFactory = new NetworkStatsFactory(mTestProc, false);
     }
 
diff --git a/tests/net/jni/Android.bp b/tests/net/jni/Android.bp
new file mode 100644
index 0000000..9225ffb
--- /dev/null
+++ b/tests/net/jni/Android.bp
@@ -0,0 +1,23 @@
+cc_library_shared {
+    name: "libnetworkstatsfactorytestjni",
+
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wno-unused-parameter",
+        "-Wthread-safety",
+    ],
+
+    srcs: [
+        ":lib_networkStatsFactory_native",
+        "test_onload.cpp",
+    ],
+
+    shared_libs: [
+        "libbpf_android",
+        "liblog",
+        "libnativehelper",
+        "libnetdbpf",
+        "libnetdutils",
+    ],
+}
diff --git a/tests/net/jni/test_onload.cpp b/tests/net/jni/test_onload.cpp
new file mode 100644
index 0000000..5194ddb
--- /dev/null
+++ b/tests/net/jni/test_onload.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/*
+ * this is a mini native libaray for NetworkStatsFactoryTest to run properly. It
+ * load all the native method related to NetworkStatsFactory when test run
+ */
+#include <nativehelper/JNIHelp.h>
+#include "jni.h"
+#include "utils/Log.h"
+#include "utils/misc.h"
+
+namespace android {
+int register_android_server_net_NetworkStatsFactory(JNIEnv* env);
+};
+
+using namespace android;
+
+extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
+{
+    JNIEnv* env = NULL;
+    jint result = -1;
+
+    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
+        ALOGE("GetEnv failed!");
+        return result;
+    }
+    ALOG_ASSERT(env, "Could not retrieve the env!");
+    register_android_server_net_NetworkStatsFactory(env);
+    return JNI_VERSION_1_4;
+}