Merge "Do no use libandroidicu for host targets"
diff --git a/Android.bp b/Android.bp
index 727842e..490de6e 100644
--- a/Android.bp
+++ b/Android.bp
@@ -842,6 +842,7 @@
 java_library {
     name: "framework-annotation-proc",
     defaults: ["framework-defaults"],
+    installable: false,
     // Use UsedByApps annotation processor
     plugins: ["unsupportedappusage-annotation-processor"],
 }
@@ -1880,3 +1881,13 @@
     srcs: [":framework-defaults"],
     output: "framework-aidl-mappings.txt",
 }
+
+genrule {
+    name: "framework-annotation-proc-index",
+    srcs: [":framework-annotation-proc"],
+    cmd: "unzip -qp $(in) unsupportedappusage/unsupportedappusage_index.csv > $(out)",
+    out: ["unsupportedappusage_index.csv"],
+    dist: {
+        targets: ["droidcore"],
+    },
+}
diff --git a/api/test-current.txt b/api/test-current.txt
index bf2730a..14c70e3 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -795,6 +795,7 @@
   }
 
   public final class RollbackManager {
+    method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void blockRollbackManager(long);
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) public void commitRollback(int, @NonNull java.util.List<android.content.pm.VersionedPackage>, @NonNull android.content.IntentSender);
     method @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS) public void expireRollbackForPackage(@NonNull String);
     method @RequiresPermission(anyOf={android.Manifest.permission.MANAGE_ROLLBACKS, android.Manifest.permission.TEST_MANAGE_ROLLBACKS}) @NonNull public java.util.List<android.content.rollback.RollbackInfo> getAvailableRollbacks();
@@ -2301,6 +2302,7 @@
     field public static final String NAMESPACE_PRIVACY = "privacy";
     field public static final String NAMESPACE_ROLLBACK = "rollback";
     field public static final String NAMESPACE_ROLLBACK_BOOT = "rollback_boot";
+    field public static final String NAMESPACE_WINDOW_MANAGER = "android:window_manager";
   }
 
   public static interface DeviceConfig.OnPropertiesChangedListener {
@@ -2317,6 +2319,10 @@
     method @Nullable public String getString(@NonNull String, @Nullable String);
   }
 
+  public static interface DeviceConfig.WindowManager {
+    field public static final String KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP = "system_gesture_exclusion_limit_dp";
+  }
+
   public final class MediaStore {
     method @RequiresPermission(android.Manifest.permission.CLEAR_APP_USER_DATA) public static void deleteContributedMedia(android.content.Context, String, android.os.UserHandle) throws java.io.IOException;
     method @RequiresPermission(android.Manifest.permission.CLEAR_APP_USER_DATA) public static long getContributedMediaSize(android.content.Context, String, android.os.UserHandle) throws java.io.IOException;
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index 10f25ea..c30a6f4 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -581,6 +581,7 @@
 Landroid/service/dreams/IDreamManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/dreams/IDreamManager;
 Landroid/service/dreams/IDreamManager;->getDreamComponents()[Landroid/content/ComponentName;
 Landroid/service/euicc/IEuiccService$Stub;-><init>()V
+Landroid/service/media/IMediaBrowserServiceCallbacks$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/media/IMediaBrowserServiceCallbacks;
 Landroid/service/notification/INotificationListener$Stub;-><init>()V
 Landroid/service/persistentdata/IPersistentDataBlockService$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/persistentdata/IPersistentDataBlockService;
 Landroid/service/vr/IVrManager$Stub;->asInterface(Landroid/os/IBinder;)Landroid/service/vr/IVrManager;
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 7a614ce..525bc44b 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1050,6 +1050,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     @Override
     public boolean setInstantAppCookie(@NonNull byte[] cookie) {
         try {
diff --git a/core/java/android/bluetooth/BluetoothHearingAid.java b/core/java/android/bluetooth/BluetoothHearingAid.java
index 60fb6fb..a812c32 100644
--- a/core/java/android/bluetooth/BluetoothHearingAid.java
+++ b/core/java/android/bluetooth/BluetoothHearingAid.java
@@ -22,6 +22,7 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.os.Binder;
 import android.os.IBinder;
@@ -83,6 +84,7 @@
      *
      * @hide
      */
+    @UnsupportedAppUsage
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_ACTIVE_DEVICE_CHANGED =
             "android.bluetooth.hearingaid.profile.action.ACTIVE_DEVICE_CHANGED";
@@ -303,6 +305,7 @@
      * @return false on immediate error, true otherwise
      * @hide
      */
+    @UnsupportedAppUsage
     public boolean setActiveDevice(@Nullable BluetoothDevice device) {
         if (DBG) log("setActiveDevice(" + device + ")");
         final IBluetoothHearingAid service = getService();
@@ -331,6 +334,7 @@
      * is not active, it will be null on that position. Returns empty list on error.
      * @hide
      */
+    @UnsupportedAppUsage
     @RequiresPermission(Manifest.permission.BLUETOOTH)
     public List<BluetoothDevice> getActiveDevices() {
         if (VDBG) log("getActiveDevices()");
diff --git a/core/java/android/content/om/OverlayInfo.java b/core/java/android/content/om/OverlayInfo.java
index 1838bab..f39fc66 100644
--- a/core/java/android/content/om/OverlayInfo.java
+++ b/core/java/android/content/om/OverlayInfo.java
@@ -20,6 +20,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.SystemApi;
+import android.annotation.UnsupportedAppUsage;
 import android.annotation.UserIdInt;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -169,6 +170,7 @@
      * The state of this OverlayInfo as defined by the STATE_* constants in this class.
      * @hide
      */
+    @UnsupportedAppUsage
     public final @State int state;
 
     /**
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index a2994af..cf858f5 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -8397,6 +8397,7 @@
         PackageInfo pi = generatePackageInfo(p, EmptyArray.INT, flags, 0, 0,
                 Collections.emptySet(), state);
         pi.applicationInfo.sourceDir = apexFile.getPath();
+        pi.applicationInfo.publicSourceDir = apexFile.getPath();
         if (apexInfo.isFactory) {
             pi.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
         } else {
diff --git a/core/java/android/content/rollback/IRollbackManager.aidl b/core/java/android/content/rollback/IRollbackManager.aidl
index 1b84f29..8c2a65f 100644
--- a/core/java/android/content/rollback/IRollbackManager.aidl
+++ b/core/java/android/content/rollback/IRollbackManager.aidl
@@ -24,7 +24,7 @@
 interface IRollbackManager {
 
     ParceledListSlice getAvailableRollbacks();
-    ParceledListSlice getRecentlyExecutedRollbacks();
+    ParceledListSlice getRecentlyCommittedRollbacks();
 
     void commitRollback(int rollbackId, in ParceledListSlice causePackages,
             String callerPackageName, in IntentSender statusReceiver);
@@ -51,4 +51,7 @@
     // Used by the staging manager to notify the RollbackManager of the apk
     // session for a staged session.
     void notifyStagedApkSession(int originalSessionId, int apkSessionId);
+
+    // For test purposes only.
+    void blockRollbackManager(long millis);
 }
diff --git a/core/java/android/content/rollback/RollbackManager.java b/core/java/android/content/rollback/RollbackManager.java
index 9a10a0c..73b8a48 100644
--- a/core/java/android/content/rollback/RollbackManager.java
+++ b/core/java/android/content/rollback/RollbackManager.java
@@ -114,7 +114,7 @@
     })
     public @NonNull List<RollbackInfo> getRecentlyCommittedRollbacks() {
         try {
-            return mBinder.getRecentlyExecutedRollbacks().getList();
+            return mBinder.getRecentlyCommittedRollbacks().getList();
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
@@ -250,4 +250,25 @@
             throw e.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Block the RollbackManager for a specified amount of time.
+     * This API is meant to facilitate testing of race conditions in
+     * RollbackManager. Blocks RollbackManager from processing anything for
+     * the given number of milliseconds.
+     *
+     * @param millis number of milliseconds to block the RollbackManager for
+     * @throws SecurityException if the caller does not have appropriate permissions.
+     *
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.TEST_MANAGE_ROLLBACKS)
+    @TestApi
+    public void blockRollbackManager(long millis) {
+        try {
+            mBinder.blockRollbackManager(millis);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/core/java/android/hardware/camera2/CameraMetadata.java b/core/java/android/hardware/camera2/CameraMetadata.java
index 04e8cf4..5ac13d8 100644
--- a/core/java/android/hardware/camera2/CameraMetadata.java
+++ b/core/java/android/hardware/camera2/CameraMetadata.java
@@ -925,14 +925,14 @@
      * case, when the application configures a RAW stream, the camera device will make sure
      * the active physical camera will remain active to ensure consistent RAW output
      * behavior, and not switch to other physical cameras.</p>
-     * <p>To maintain backward compatibility, the capture request and result metadata tags
-     * required for basic camera functionalities will be solely based on the
-     * logical camera capabiltity. Other request and result metadata tags, on the other
-     * hand, will be based on current active physical camera. For example, the physical
-     * cameras' sensor sensitivity and lens capability could be different from each other.
-     * So when the application manually controls sensor exposure time/gain, or does manual
-     * focus control, it must checks the current active physical camera's exposure, gain,
-     * and focus distance range.</p>
+     * <p>The capture request and result metadata tags required for backward compatible camera
+     * functionalities will be solely based on the logical camera capabiltity. On the other
+     * hand, the use of manual capture controls (sensor or post-processing) with a
+     * logical camera may result in unexpected behavior when the HAL decides to switch
+     * between physical cameras with different characteristics under the hood. For example,
+     * when the application manually sets exposure time and sensitivity while zooming in,
+     * the brightness of the camera images may suddenly change because HAL switches from one
+     * physical camera to the other.</p>
      *
      * @see CameraCharacteristics#LENS_DISTORTION
      * @see CameraCharacteristics#LENS_INFO_FOCUS_DISTANCE_CALIBRATION
diff --git a/core/java/android/hardware/display/AmbientDisplayConfiguration.java b/core/java/android/hardware/display/AmbientDisplayConfiguration.java
index c45b8ed..3e995b6 100644
--- a/core/java/android/hardware/display/AmbientDisplayConfiguration.java
+++ b/core/java/android/hardware/display/AmbientDisplayConfiguration.java
@@ -48,7 +48,8 @@
         return pulseOnNotificationEnabled(user)
                 || pulseOnLongPressEnabled(user)
                 || alwaysOnEnabled(user)
-                || wakeScreenGestureEnabled(user)
+                || wakeLockScreenGestureEnabled(user)
+                || wakeDisplayGestureEnabled(user)
                 || pickupGestureEnabled(user)
                 || tapGestureEnabled(user)
                 || doubleTapGestureEnabled(user);
@@ -105,8 +106,14 @@
     }
 
     /** {@hide} */
-    public boolean wakeScreenGestureEnabled(int user) {
-        return boolSettingDefaultOn(Settings.Secure.DOZE_WAKE_SCREEN_GESTURE, user)
+    public boolean wakeLockScreenGestureEnabled(int user) {
+        return boolSettingDefaultOn(Settings.Secure.DOZE_WAKE_LOCK_SCREEN_GESTURE, user)
+                && wakeScreenGestureAvailable();
+    }
+
+    /** {@hide} */
+    public boolean wakeDisplayGestureEnabled(int user) {
+        return boolSettingDefaultOn(Settings.Secure.DOZE_WAKE_DISPLAY_GESTURE, user)
                 && wakeScreenGestureAvailable();
     }
 
diff --git a/core/java/android/net/NetworkAgent.java b/core/java/android/net/NetworkAgent.java
index 660cd848..43ea589 100644
--- a/core/java/android/net/NetworkAgent.java
+++ b/core/java/android/net/NetworkAgent.java
@@ -437,15 +437,23 @@
     }
 
     /**
-     * Called by the bearer to indicate this network was manually selected by the user.
+     * Called by the bearer to indicate whether the network was manually selected by the user.
      * This should be called before the NetworkInfo is marked CONNECTED so that this
-     * Network can be given special treatment at that time. If {@code acceptUnvalidated} is
-     * {@code true}, then the system will switch to this network. If it is {@code false} and the
-     * network cannot be validated, the system will ask the user whether to switch to this network.
-     * If the user confirms and selects "don't ask again", then the system will call
-     * {@link #saveAcceptUnvalidated} to persist the user's choice. Thus, if the transport ever
-     * calls this method with {@code acceptUnvalidated} set to {@code false}, it must also implement
-     * {@link #saveAcceptUnvalidated} to respect the user's choice.
+     * Network can be given special treatment at that time.
+     *
+     * If {@code explicitlySelected} is {@code true}, and {@code acceptUnvalidated} is {@code true},
+     * then the system will switch to this network. If {@code explicitlySelected} is {@code true}
+     * and {@code acceptUnvalidated} is {@code false}, and the  network cannot be validated, the
+     * system will ask the user whether to switch to this network.  If the user confirms and selects
+     * "don't ask again", then the system will call {@link #saveAcceptUnvalidated} to persist the
+     * user's choice. Thus, if the transport ever calls this method with {@code explicitlySelected}
+     * set to {@code true} and {@code acceptUnvalidated} set to {@code false}, it must also
+     * implement {@link #saveAcceptUnvalidated} to respect the user's choice.
+     *
+     * If  {@code explicitlySelected} is {@code false} and {@code acceptUnvalidated} is
+     * {@code true}, the system will interpret this as the user having accepted partial connectivity
+     * on this network. Thus, the system will switch to the network and consider it validated even
+     * if it only provides partial connectivity, but the network is not otherwise treated specially.
      */
     public void explicitlySelected(boolean explicitlySelected, boolean acceptUnvalidated) {
         queueOrSendMessage(EVENT_SET_EXPLICITLY_SELECTED,
diff --git a/core/java/android/os/UserHandle.java b/core/java/android/os/UserHandle.java
index b121234..d70ba99 100644
--- a/core/java/android/os/UserHandle.java
+++ b/core/java/android/os/UserHandle.java
@@ -68,6 +68,7 @@
     public static final @NonNull UserHandle CURRENT_OR_SELF = new UserHandle(USER_CURRENT_OR_SELF);
 
     /** @hide An undefined user id */
+    @UnsupportedAppUsage
     public static final @UserIdInt int USER_NULL = -10000;
 
     /**
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 01b6758..48faf11 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -293,6 +293,15 @@
     public static final String NAMESPACE_SETTINGS_UI = "settings_ui";
 
     /**
+     * Namespace for window manager related features. The names to access the properties in this
+     * namespace should be defined in {@link WindowManager}.
+     *
+     * @hide
+     */
+    @TestApi
+    public static final String NAMESPACE_WINDOW_MANAGER = "android:window_manager";
+
+    /**
      * List of namespaces which can be read without READ_DEVICE_CONFIG permission
      *
      * @hide
@@ -309,6 +318,23 @@
     @TestApi
     public static final String NAMESPACE_PRIVACY = "privacy";
 
+    /**
+     * Interface for accessing keys belonging to {@link #NAMESPACE_WINDOW_MANAGER}.
+     * @hide
+     */
+    @TestApi
+    public interface WindowManager {
+
+        /**
+         * Key for accessing the system gesture exclusion limit (an integer in dp).
+         *
+         * @see android.provider.DeviceConfig#NAMESPACE_WINDOW_MANAGER
+         * @hide
+         */
+        @TestApi
+        String KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP = "system_gesture_exclusion_limit_dp";
+    }
+
     private static final Object sLock = new Object();
     @GuardedBy("sLock")
     private static ArrayMap<OnPropertiesChangedListener, Pair<String, Executor>> sListeners =
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e5b7987..9e1bb94 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -88,6 +88,7 @@
 import android.util.ArraySet;
 import android.util.Log;
 import android.util.MemoryIntArray;
+import android.view.Display;
 import android.view.inputmethod.InputMethodSystemProperty;
 
 import com.android.internal.annotations.GuardedBy;
@@ -4073,7 +4074,7 @@
          * preference, this rotation value will be used. Must be one of the
          * {@link android.view.Surface#ROTATION_0 Surface rotation constants}.
          *
-         * @see android.view.Display#getRotation
+         * @see Display#getRotation
          */
         public static final String USER_ROTATION = "user_rotation";
 
@@ -7733,12 +7734,21 @@
         private static final Validator DOZE_TAP_SCREEN_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
-         * Gesture that wakes up the display, showing the ambient version of the status bar.
+         * Gesture that wakes up the display, showing some version of the lock screen.
          * @hide
          */
-        public static final String DOZE_WAKE_SCREEN_GESTURE = "doze_wake_screen_gesture";
+        public static final String DOZE_WAKE_LOCK_SCREEN_GESTURE = "doze_wake_screen_gesture";
 
-        private static final Validator DOZE_WAKE_SCREEN_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
+        private static final Validator DOZE_WAKE_LOCK_SCREEN_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
+
+        /**
+         * Gesture that wakes up the display, toggling between {@link Display.STATE_OFF} and
+         * {@link Display.STATE_DOZE}.
+         * @hide
+         */
+        public static final String DOZE_WAKE_DISPLAY_GESTURE = "doze_wake_display_gesture";
+
+        private static final Validator DOZE_WAKE_DISPLAY_GESTURE_VALIDATOR = BOOLEAN_VALIDATOR;
 
         /**
          * Gesture that skips media.
@@ -8266,6 +8276,16 @@
                 BOOLEAN_VALIDATOR;
 
         /**
+         * Whether or not media is shown automatically when bypassing as a heads up.
+         * @hide
+         */
+        public static final String SHOW_MEDIA_WHEN_BYPASSING =
+                "show_media_when_bypassing";
+
+        private static final Validator SHOW_MEDIA_WHEN_BYPASSING_VALIDATOR =
+                BOOLEAN_VALIDATOR;
+
+        /**
          * Whether or not face unlock requires attention. This is a cached value, the source of
          * truth is obtained through the HAL.
          * @hide
@@ -8959,10 +8979,12 @@
             DOZE_PICK_UP_GESTURE,
             DOZE_DOUBLE_TAP_GESTURE,
             DOZE_TAP_SCREEN_GESTURE,
-            DOZE_WAKE_SCREEN_GESTURE,
+            DOZE_WAKE_LOCK_SCREEN_GESTURE,
+            DOZE_WAKE_DISPLAY_GESTURE,
             NFC_PAYMENT_DEFAULT_COMPONENT,
             AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
             FACE_UNLOCK_KEYGUARD_ENABLED,
+            SHOW_MEDIA_WHEN_BYPASSING,
             FACE_UNLOCK_DISMISSES_KEYGUARD,
             FACE_UNLOCK_APP_ENABLED,
             FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
@@ -9131,13 +9153,15 @@
             VALIDATORS.put(DOZE_PICK_UP_GESTURE, DOZE_PICK_UP_GESTURE_VALIDATOR);
             VALIDATORS.put(DOZE_DOUBLE_TAP_GESTURE, DOZE_DOUBLE_TAP_GESTURE_VALIDATOR);
             VALIDATORS.put(DOZE_TAP_SCREEN_GESTURE, DOZE_TAP_SCREEN_GESTURE_VALIDATOR);
-            VALIDATORS.put(DOZE_WAKE_SCREEN_GESTURE, DOZE_WAKE_SCREEN_GESTURE_VALIDATOR);
+            VALIDATORS.put(DOZE_WAKE_LOCK_SCREEN_GESTURE, DOZE_WAKE_LOCK_SCREEN_GESTURE_VALIDATOR);
+            VALIDATORS.put(DOZE_WAKE_DISPLAY_GESTURE, DOZE_WAKE_DISPLAY_GESTURE_VALIDATOR);
             VALIDATORS.put(NFC_PAYMENT_DEFAULT_COMPONENT, NFC_PAYMENT_DEFAULT_COMPONENT_VALIDATOR);
             VALIDATORS.put(AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN,
                     AUTOMATIC_STORAGE_MANAGER_DAYS_TO_RETAIN_VALIDATOR);
             VALIDATORS.put(FACE_UNLOCK_KEYGUARD_ENABLED, FACE_UNLOCK_KEYGUARD_ENABLED_VALIDATOR);
             VALIDATORS.put(FACE_UNLOCK_DISMISSES_KEYGUARD,
                     FACE_UNLOCK_DISMISSES_KEYGUARD_VALIDATOR);
+            VALIDATORS.put(SHOW_MEDIA_WHEN_BYPASSING, SHOW_MEDIA_WHEN_BYPASSING_VALIDATOR);
             VALIDATORS.put(FACE_UNLOCK_APP_ENABLED, FACE_UNLOCK_APP_ENABLED_VALIDATOR);
             VALIDATORS.put(FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION,
                     FACE_UNLOCK_ALWAYS_REQUIRE_CONFIRMATION_VALIDATOR);
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index cb64ab1..17f07b5 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -21,6 +21,7 @@
 import android.annotation.UnsupportedAppUsage;
 import android.content.res.CompatibilityInfo.Translator;
 import android.graphics.Canvas;
+import android.graphics.ColorSpace;
 import android.graphics.GraphicBuffer;
 import android.graphics.Matrix;
 import android.graphics.RecordingCanvas;
@@ -80,7 +81,8 @@
     private static native long nativeGetNextFrameNumber(long nativeObject);
     private static native int nativeSetScalingMode(long nativeObject, int scalingMode);
     private static native int nativeForceScopedDisconnect(long nativeObject);
-    private static native int nativeAttachAndQueueBuffer(long nativeObject, GraphicBuffer buffer);
+    private static native int nativeAttachAndQueueBufferWithColorSpace(long nativeObject,
+            GraphicBuffer buffer, int colorSpaceId);
 
     private static native int nativeSetSharedBufferModeEnabled(long nativeObject, boolean enabled);
     private static native int nativeSetAutoRefreshEnabled(long nativeObject, boolean enabled);
@@ -699,18 +701,35 @@
     }
 
     /**
+     * Transfer ownership of buffer with a color space and present it on the Surface.
+     * The supported color spaces are SRGB and Display P3, other color spaces will be
+     * treated as SRGB.
+     * @hide
+     */
+    public void attachAndQueueBufferWithColorSpace(GraphicBuffer buffer, ColorSpace colorSpace) {
+        synchronized (mLock) {
+            checkNotReleasedLocked();
+            if (colorSpace == null) {
+                colorSpace = ColorSpace.get(ColorSpace.Named.SRGB);
+            }
+            int err = nativeAttachAndQueueBufferWithColorSpace(mNativeObject, buffer,
+                    colorSpace.getId());
+            if (err != 0) {
+                throw new RuntimeException(
+                        "Failed to attach and queue buffer to Surface (bad object?), "
+                        + "native error: " + err);
+            }
+        }
+    }
+
+    /**
+     * Deprecated, use attachAndQueueBufferWithColorSpace instead.
      * Transfer ownership of buffer and present it on the Surface.
+     * The color space of the buffer is treated as SRGB.
      * @hide
      */
     public void attachAndQueueBuffer(GraphicBuffer buffer) {
-        synchronized (mLock) {
-            checkNotReleasedLocked();
-            int err = nativeAttachAndQueueBuffer(mNativeObject, buffer);
-            if (err != 0) {
-                throw new RuntimeException(
-                        "Failed to attach and queue buffer to Surface (bad object?)");
-            }
-        }
+        attachAndQueueBufferWithColorSpace(buffer, ColorSpace.get(ColorSpace.Named.SRGB));
     }
 
     /**
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index d1ab7c99..522ad64 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -1846,7 +1846,8 @@
         final ScreenshotGraphicBuffer buffer = screenshotToBuffer(display, sourceCrop, width,
                 height, useIdentityTransform, rotation);
         try {
-            consumer.attachAndQueueBuffer(buffer.getGraphicBuffer());
+            consumer.attachAndQueueBufferWithColorSpace(buffer.getGraphicBuffer(),
+                    buffer.getColorSpace());
         } catch (RuntimeException e) {
             Log.w(TAG, "Failed to take screenshot - " + e.getMessage());
         }
diff --git a/core/java/android/view/accessibility/AccessibilityManager.java b/core/java/android/view/accessibility/AccessibilityManager.java
index 882e6fd..2e9d881 100644
--- a/core/java/android/view/accessibility/AccessibilityManager.java
+++ b/core/java/android/view/accessibility/AccessibilityManager.java
@@ -184,7 +184,7 @@
 
     boolean mIsTouchExplorationEnabled;
 
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 123768939)
+    @UnsupportedAppUsage(trackingBug = 123768939L)
     boolean mIsHighTextContrastEnabled;
 
     AccessibilityPolicy mAccessibilityPolicy;
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 564d972..86cec5e 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -206,13 +206,13 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+    @UnsupportedAppUsage
     public ApplicationInfo mApplication;
 
     /**
      * The resource ID of the layout file. (Added to the parcel)
      */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+    @UnsupportedAppUsage
     private final int mLayoutId;
 
     /**
@@ -224,13 +224,13 @@
      * An array of actions to perform on the view tree once it has been
      * inflated
      */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+    @UnsupportedAppUsage
     private ArrayList<Action> mActions;
 
     /**
      * Maps bitmaps to unique indicies to avoid Bitmap duplication.
      */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+    @UnsupportedAppUsage
     private BitmapCache mBitmapCache;
 
     /**
@@ -252,7 +252,7 @@
      * RemoteViews.
      */
     private RemoteViews mLandscape = null;
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+    @UnsupportedAppUsage
     private RemoteViews mPortrait = null;
 
     @ApplyFlags
@@ -430,7 +430,7 @@
             // Do nothing
         }
 
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+        @UnsupportedAppUsage
         public int mergeBehavior() {
             return MERGE_REPLACE;
         }
@@ -466,7 +466,7 @@
             // Nothing to visit by default
         }
 
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+        @UnsupportedAppUsage
         int viewId;
     }
 
@@ -499,7 +499,7 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+    @UnsupportedAppUsage
     public void mergeRemoteViews(RemoteViews newRv) {
         if (newRv == null) return;
         // We first copy the new RemoteViews, as the process of merging modifies the way the actions
@@ -690,7 +690,7 @@
             return SET_PENDING_INTENT_TEMPLATE_TAG;
         }
 
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+        @UnsupportedAppUsage
         PendingIntent pendingIntentTemplate;
     }
 
@@ -1138,7 +1138,7 @@
 
     private static class BitmapCache {
 
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+        @UnsupportedAppUsage
         ArrayList<Bitmap> mBitmaps;
         int mBitmapMemory = -1;
 
@@ -1190,9 +1190,9 @@
 
     private class BitmapReflectionAction extends Action {
         int bitmapId;
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+        @UnsupportedAppUsage
         Bitmap bitmap;
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+        @UnsupportedAppUsage
         String methodName;
 
         BitmapReflectionAction(int viewId, String methodName, Bitmap bitmap) {
@@ -1258,10 +1258,10 @@
         static final int COLOR_STATE_LIST = 15;
         static final int ICON = 16;
 
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+        @UnsupportedAppUsage
         String methodName;
         int type;
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+        @UnsupportedAppUsage
         Object value;
 
         ReflectionAction(int viewId, String methodName, int type, Object value) {
@@ -1554,7 +1554,7 @@
      * ViewGroup methods that are related to adding Views.
      */
     private class ViewGroupActionAdd extends Action {
-        @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+        @UnsupportedAppUsage
         private RemoteViews mNestedViews;
         private int mIndex;
 
@@ -2469,7 +2469,7 @@
      * Returns an estimate of the bitmap heap memory usage for this RemoteViews.
      */
     /** @hide */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+    @UnsupportedAppUsage
     public int estimateMemoryUsage() {
         return mBitmapCache.getBitmapMemory();
     }
@@ -2517,7 +2517,7 @@
      *
      * @hide
      */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+    @UnsupportedAppUsage
     public void addView(int viewId, RemoteViews nestedView, int index) {
         addAction(new ViewGroupActionAdd(viewId, nestedView, index));
     }
@@ -2994,7 +2994,8 @@
      * @hide
      * @deprecated this appears to have no users outside of UnsupportedAppUsage?
      */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+    @UnsupportedAppUsage
+    @Deprecated
     public void setRemoteAdapter(int viewId, ArrayList<RemoteViews> list, int viewTypeCount) {
         addAction(new SetRemoteViewsAdapterList(viewId, list, viewTypeCount));
     }
diff --git a/core/java/com/android/internal/app/ResolverActivity.java b/core/java/com/android/internal/app/ResolverActivity.java
index 7cc8128..f905ea2 100644
--- a/core/java/com/android/internal/app/ResolverActivity.java
+++ b/core/java/com/android/internal/app/ResolverActivity.java
@@ -29,7 +29,6 @@
 import android.app.VoiceInteractor.PickOptionRequest;
 import android.app.VoiceInteractor.PickOptionRequest.Option;
 import android.app.VoiceInteractor.Prompt;
-import android.app.role.RoleManager;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -111,7 +110,6 @@
     protected AbsListView mAdapterView;
     private Button mAlwaysButton;
     private Button mOnceButton;
-    private Button mSettingsButton;
     protected View mProfileView;
     private int mIconDpi;
     private int mLastSelected = AbsListView.INVALID_POSITION;
@@ -146,6 +144,10 @@
     /** See {@link #setRetainInOnStop}. */
     private boolean mRetainInOnStop;
 
+    private static final String EXTRA_SHOW_FRAGMENT_ARGS = ":settings:show_fragment_args";
+    private static final String EXTRA_FRAGMENT_ARG_KEY = ":settings:fragment_args_key";
+    private static final String OPEN_LINKS_COMPONENT_KEY = "app_link_state";
+
     private final PackageMonitor mPackageMonitor = createPackageMonitor();
 
     /**
@@ -196,9 +198,13 @@
 
         // titles for layout that deals with http(s) intents
         public static final int BROWSABLE_TITLE_RES =
-                com.android.internal.R.string.whichGiveAccessToApplication;
-        public static final int BROWSABLE_NAMED_TITLE_RES =
-                com.android.internal.R.string.whichGiveAccessToApplicationNamed;
+                com.android.internal.R.string.whichOpenLinksWith;
+        public static final int BROWSABLE_HOST_TITLE_RES =
+                com.android.internal.R.string.whichOpenHostLinksWith;
+        public static final int BROWSABLE_HOST_APP_TITLE_RES =
+                com.android.internal.R.string.whichOpenHostLinksWithApp;
+        public static final int BROWSABLE_APP_TITLE_RES =
+                com.android.internal.R.string.whichOpenLinksWithApp;
 
         public final String action;
         public final int titleRes;
@@ -322,9 +328,7 @@
                 ? false
                 : isHttpSchemeAndViewAction(getTargetIntent());
 
-        // We don't want to support Always Use if browsable layout is being used,
-        // as to mitigate Intent Capturing vulnerability
-        mSupportsAlwaysUseOption = supportsAlwaysUseOption && !mUseLayoutForBrowsables;
+        mSupportsAlwaysUseOption = supportsAlwaysUseOption;
 
         if (configureContentView(mIntents, initialIntents, rList)) {
             return;
@@ -554,10 +558,21 @@
         } else if (isHttpSchemeAndViewAction(intent)) {
             // If the Intent's scheme is http(s) then we need to warn the user that
             // they're giving access for the activity to open URLs from this specific host
-            return named
-                    ? getString(ActionTitle.BROWSABLE_NAMED_TITLE_RES, intent.getData().getHost(),
-                    mAdapter.getFilteredItem().getDisplayLabel())
-                    : getString(ActionTitle.BROWSABLE_TITLE_RES, intent.getData().getHost());
+            String dialogTitle = null;
+            if (named && !mUseLayoutForBrowsables) {
+                dialogTitle = getString(ActionTitle.BROWSABLE_APP_TITLE_RES,
+                        mAdapter.getFilteredItem().getDisplayLabel());
+            } else if (named && mUseLayoutForBrowsables) {
+                dialogTitle = getString(ActionTitle.BROWSABLE_HOST_APP_TITLE_RES,
+                        intent.getData().getHost(),
+                        mAdapter.getFilteredItem().getDisplayLabel());
+            } else if (mAdapter.areAllTargetsBrowsers()) {
+                dialogTitle =  getString(ActionTitle.BROWSABLE_TITLE_RES);
+            } else {
+                dialogTitle = getString(ActionTitle.BROWSABLE_HOST_TITLE_RES,
+                        intent.getData().getHost());
+            }
+            return dialogTitle;
         } else {
             return named
                     ? getString(title.namedTitleRes, mAdapter.getFilteredItem().getDisplayLabel())
@@ -856,6 +871,13 @@
             } else {
                 enabled = true;
             }
+            if (mUseLayoutForBrowsables && !ri.handleAllWebDataURI) {
+                mAlwaysButton.setText(getResources()
+                        .getString(R.string.activity_resolver_set_always));
+            } else {
+                mAlwaysButton.setText(getResources()
+                        .getString(R.string.activity_resolver_use_always));
+            }
         }
         mAlwaysButton.setEnabled(enabled);
     }
@@ -866,26 +888,29 @@
                 ? mAdapter.getFilteredPosition()
                 : mAdapterView.getCheckedItemPosition();
         boolean hasIndexBeenFiltered = !mAdapter.hasFilteredItem();
-        if (id == R.id.button_app_settings) {
-            showSettingsForSelected(which, hasIndexBeenFiltered);
+        ResolveInfo ri = mAdapter.resolveInfoForPosition(which, hasIndexBeenFiltered);
+        if (!ri.handleAllWebDataURI && id == R.id.button_always) {
+            showSettingsForSelected(ri);
         } else {
             startSelected(which, id == R.id.button_always, hasIndexBeenFiltered);
         }
     }
 
-    private void showSettingsForSelected(int which, boolean hasIndexBeenFiltered) {
-        ResolveInfo ri = mAdapter.resolveInfoForPosition(which, hasIndexBeenFiltered);
+    private void showSettingsForSelected(ResolveInfo ri) {
         Intent intent = new Intent();
-        // For browsers, we open the Default Browser page
+
+        final String packageName = ri.activityInfo.packageName;
+        Bundle showFragmentArgs = new Bundle();
+        showFragmentArgs.putString(EXTRA_FRAGMENT_ARG_KEY, OPEN_LINKS_COMPONENT_KEY);
+        showFragmentArgs.putString("package", packageName);
+
         // For regular apps, we open the Open by Default page
-        if (ri.handleAllWebDataURI) {
-            intent.setAction(Intent.ACTION_MANAGE_DEFAULT_APP)
-                    .putExtra(Intent.EXTRA_ROLE_NAME, RoleManager.ROLE_BROWSER);
-        } else {
-            intent.setAction(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS)
-                    .setData(Uri.fromParts("package", ri.activityInfo.packageName, null))
-                    .addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT);
-        }
+        intent.setAction(Settings.ACTION_APP_OPEN_BY_DEFAULT_SETTINGS)
+                .setData(Uri.fromParts("package", packageName, null))
+                .addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
+                .putExtra(EXTRA_FRAGMENT_ARG_KEY, OPEN_LINKS_COMPONENT_KEY)
+                .putExtra(EXTRA_SHOW_FRAGMENT_ARGS, showFragmentArgs);
+
         startActivity(intent);
     }
 
@@ -1332,41 +1357,15 @@
                         R.dimen.resolver_button_bar_spacing) + inset);
 
             mOnceButton = (Button) buttonLayout.findViewById(R.id.button_once);
-            mSettingsButton = (Button) buttonLayout.findViewById(R.id.button_app_settings);
             mAlwaysButton = (Button) buttonLayout.findViewById(R.id.button_always);
 
-            if (mUseLayoutForBrowsables) {
-                resetSettingsOrOnceButtonBar();
-            } else {
-                resetAlwaysOrOnceButtonBar();
-            }
+            resetAlwaysOrOnceButtonBar();
         } else {
             Log.e(TAG, "Layout unexpectedly does not have a button bar");
         }
     }
 
-    private void resetSettingsOrOnceButtonBar() {
-        //unsetting always button
-        mAlwaysButton.setVisibility(View.GONE);
-
-        // When the items load in, if an item was already selected,
-        // enable the buttons
-        if (mAdapterView != null
-                && mAdapterView.getCheckedItemPosition() != ListView.INVALID_POSITION) {
-            mSettingsButton.setEnabled(true);
-            mOnceButton.setEnabled(true);
-        }
-    }
-
     private void resetAlwaysOrOnceButtonBar() {
-        // This check needs to be made because layout with default
-        // doesn't have a settings button
-        if (mSettingsButton != null) {
-            //unsetting always button
-            mSettingsButton.setVisibility(View.GONE);
-            mSettingsButton = null;
-        }
-
         if (useLayoutWithDefault()
                 && mAdapter.getFilteredPosition() != ListView.INVALID_POSITION) {
             setAlwaysButtonEnabled(true, mAdapter.getFilteredPosition(), false);
@@ -1626,6 +1625,7 @@
         private DisplayResolveInfo mOtherProfile;
         private ResolverListController mResolverListController;
         private int mPlaceholderCount;
+        private boolean mAllTargetsAreBrowsers = false;
 
         protected final LayoutInflater mInflater;
 
@@ -1701,6 +1701,14 @@
         }
 
         /**
+          * @return true if all items in the display list are defined as browsers by
+          *         ResolveInfo.handleAllWebDataURI
+          */
+        public boolean areAllTargetsBrowsers() {
+            return mAllTargetsAreBrowsers;
+        }
+
+        /**
          * Rebuild the list of resolvers. In some cases some parts will need some asynchronous work
          * to complete.
          *
@@ -1712,6 +1720,7 @@
             mOtherProfile = null;
             mLastChosen = null;
             mLastChosenPosition = -1;
+            mAllTargetsAreBrowsers = false;
             mDisplayList.clear();
             if (mBaseResolveList != null) {
                 currentResolveList = mUnfilteredResolveList = new ArrayList<>();
@@ -1812,6 +1821,8 @@
         private void processSortedList(List<ResolvedComponentInfo> sortedComponents) {
             int N;
             if (sortedComponents != null && (N = sortedComponents.size()) != 0) {
+                mAllTargetsAreBrowsers = mUseLayoutForBrowsables;
+
                 // First put the initial items at the top.
                 if (mInitialIntents != null) {
                     for (int i = 0; i < mInitialIntents.length; i++) {
@@ -1841,6 +1852,8 @@
                             ri.noResourceId = true;
                             ri.icon = 0;
                         }
+                        mAllTargetsAreBrowsers &= ri.handleAllWebDataURI;
+
                         addResolveInfo(new DisplayResolveInfo(ii, ri,
                                 ri.loadLabel(getPackageManager()), null, ii));
                     }
@@ -1850,6 +1863,8 @@
                 for (ResolvedComponentInfo rci : sortedComponents) {
                     final ResolveInfo ri = rci.getResolveInfoAt(0);
                     if (ri != null) {
+                        mAllTargetsAreBrowsers &= ri.handleAllWebDataURI;
+
                         ResolveInfoPresentationGetter pg = makePresentationGetter(ri);
                         addResolveInfoWithAlternates(rci, pg.getSubLabel(), pg.getLabel());
                     }
@@ -2152,14 +2167,8 @@
             final boolean hasValidSelection = checkedPos != ListView.INVALID_POSITION;
             if (!useLayoutWithDefault()
                     && (!hasValidSelection || mLastSelected != checkedPos)
-                    && (mAlwaysButton != null || mSettingsButton != null)) {
-                if (mSettingsButton != null) {
-                    // this implies that the layout for browsables is being used
-                    mSettingsButton.setEnabled(true);
-                } else {
-                    // this implies that mAlwaysButton != null
-                    setAlwaysButtonEnabled(hasValidSelection, checkedPos, true);
-                }
+                    && mAlwaysButton != null) {
+                setAlwaysButtonEnabled(hasValidSelection, checkedPos, true);
                 mOnceButton.setEnabled(hasValidSelection);
                 if (hasValidSelection) {
                     mAdapterView.smoothScrollToPosition(checkedPos);
diff --git a/core/java/com/android/internal/view/menu/MenuPopupHelper.java b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
index 64291de..d00108e 100644
--- a/core/java/com/android/internal/view/menu/MenuPopupHelper.java
+++ b/core/java/com/android/internal/view/menu/MenuPopupHelper.java
@@ -16,8 +16,6 @@
 
 package com.android.internal.view.menu;
 
-import com.android.internal.view.menu.MenuPresenter.Callback;
-
 import android.annotation.AttrRes;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -26,14 +24,14 @@
 import android.content.Context;
 import android.graphics.Point;
 import android.graphics.Rect;
-import android.os.Build;
-import android.util.DisplayMetrics;
 import android.view.Display;
 import android.view.Gravity;
 import android.view.View;
 import android.view.WindowManager;
 import android.widget.PopupWindow.OnDismissListener;
 
+import com.android.internal.view.menu.MenuPresenter.Callback;
+
 /**
  * Presents a menu as a small, simple popup anchored to another view.
  */
@@ -114,7 +112,7 @@
      * @param forceShowIcon {@code true} to force icons to be shown, or
      *                  {@code false} for icons to be optionally shown
      */
-    @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P)
+    @UnsupportedAppUsage
     public void setForceShowIcon(boolean forceShowIcon) {
         mForceShowIcon = forceShowIcon;
         if (mPopup != null) {
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 5611cc4..dad4a28 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -899,20 +899,16 @@
         addOption("-Ximage-compiler-option");
         addOption("--compiler-filter=speed-profile");
     } else {
-        // Make sure there is a preloaded-classes file.
-        if (!hasFile("/system/etc/preloaded-classes")) {
-            ALOGE("Missing preloaded-classes file, /system/etc/preloaded-classes not found: %s\n",
-                  strerror(errno));
-            return -1;
-        }
-        addOption("-Ximage-compiler-option");
-        addOption("--image-classes=/system/etc/preloaded-classes");
+        ALOGE("Missing boot-image.prof file, /system/etc/boot-image.prof not found: %s\n",
+              strerror(errno));
+        return -1;
+    }
 
-        // If there is a dirty-image-objects file, push it.
-        if (hasFile("/system/etc/dirty-image-objects")) {
-            addOption("-Ximage-compiler-option");
-            addOption("--dirty-image-objects=/system/etc/dirty-image-objects");
-        }
+
+    // If there is a dirty-image-objects file, push it.
+    if (hasFile("/system/etc/dirty-image-objects")) {
+        addOption("-Ximage-compiler-option");
+        addOption("--dirty-image-objects=/system/etc/dirty-image-objects");
     }
 
     property_get("dalvik.vm.image-dex2oat-flags", dex2oatImageFlagsBuf, "");
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 7c42994..0d95f99 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -74,6 +74,24 @@
     jfieldID bottom;
 } gRectClassInfo;
 
+class JNamedColorSpace {
+public:
+    // ColorSpace.Named.SRGB.ordinal() = 0;
+    static constexpr jint SRGB = 0;
+
+    // ColorSpace.Named.DISPLAY_P3.ordinal() = 7;
+    static constexpr jint DISPLAY_P3 = 7;
+};
+
+constexpr ui::Dataspace fromNamedColorSpaceValueToDataspace(const jint colorSpace) {
+    switch (colorSpace) {
+        case JNamedColorSpace::DISPLAY_P3:
+            return ui::Dataspace::DISPLAY_P3;
+        default:
+            return ui::Dataspace::V0_SRGB;
+    }
+}
+
 // ----------------------------------------------------------------------------
 
 // this is just a pointer we use to pass to inc/decStrong
@@ -411,11 +429,12 @@
     return surface->disconnect(-1, IGraphicBufferProducer::DisconnectMode::AllLocal);
 }
 
-static jint nativeAttachAndQueueBuffer(JNIEnv *env, jclass clazz, jlong nativeObject,
-        jobject graphicBuffer) {
+static jint nativeAttachAndQueueBufferWithColorSpace(JNIEnv *env, jclass clazz, jlong nativeObject,
+        jobject graphicBuffer, jint colorSpaceId) {
     Surface* surface = reinterpret_cast<Surface*>(nativeObject);
     sp<GraphicBuffer> bp = graphicBufferForJavaObject(env, graphicBuffer);
-    int err = Surface::attachAndQueueBuffer(surface, bp);
+    int err = Surface::attachAndQueueBufferWithDataspace(surface, bp,
+            fromNamedColorSpaceValueToDataspace(colorSpaceId));
     return err;
 }
 
@@ -517,7 +536,8 @@
     {"nativeGetNextFrameNumber", "(J)J", (void*)nativeGetNextFrameNumber },
     {"nativeSetScalingMode", "(JI)I", (void*)nativeSetScalingMode },
     {"nativeForceScopedDisconnect", "(J)I", (void*)nativeForceScopedDisconnect},
-    {"nativeAttachAndQueueBuffer", "(JLandroid/graphics/GraphicBuffer;)I", (void*)nativeAttachAndQueueBuffer},
+    {"nativeAttachAndQueueBufferWithColorSpace", "(JLandroid/graphics/GraphicBuffer;I)I",
+            (void*)nativeAttachAndQueueBufferWithColorSpace},
     {"nativeSetSharedBufferModeEnabled", "(JZ)I", (void*)nativeSetSharedBufferModeEnabled},
     {"nativeSetAutoRefreshEnabled", "(JZ)I", (void*)nativeSetAutoRefreshEnabled},
 
diff --git a/core/proto/android/os/system_properties.proto b/core/proto/android/os/system_properties.proto
index d06e1a6..7e26952 100644
--- a/core/proto/android/os/system_properties.proto
+++ b/core/proto/android/os/system_properties.proto
@@ -497,8 +497,7 @@
         }
         optional Telephony telephony = 38;
 
-        optional string url_legal = 39;
-        optional string url_legal_android_privacy = 40;
+        reserved 39, 40; // Removed url_legal* props
 
         message Vendor {
             optional string build_date = 1;
diff --git a/core/res/res/layout/resolver_list.xml b/core/res/res/layout/resolver_list.xml
index aeaccfd..1dd4207 100644
--- a/core/res/res/layout/resolver_list.xml
+++ b/core/res/res/layout/resolver_list.xml
@@ -129,18 +129,6 @@
             android:enabled="false"
             android:text="@string/activity_resolver_use_always"
             android:onClick="onButtonClick" />
-
-        <Button
-            android:id="@+id/button_app_settings"
-            android:layout_width="wrap_content"
-            android:layout_gravity="end"
-            android:maxLines="2"
-            android:minHeight="@dimen/alert_dialog_button_bar_height"
-            style="?attr/buttonBarPositiveButtonStyle"
-            android:layout_height="wrap_content"
-            android:enabled="false"
-            android:text="@string/activity_resolver_app_settings"
-            android:onClick="onButtonClick" />
     </LinearLayout>
 
 </com.android.internal.widget.ResolverDrawerLayout>
diff --git a/core/res/res/values-mcc313-mnc100/config.xml b/core/res/res/values-mcc313-mnc100/config.xml
new file mode 100644
index 0000000..ccd03f1
--- /dev/null
+++ b/core/res/res/values-mcc313-mnc100/config.xml
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+** Copyright 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.
+*/
+-->
+
+<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
+    <string-array translatable="false" name="config_twoDigitNumberPattern">
+        <item>"0"</item>
+        <item>"00"</item>
+        <item>"*0"</item>
+        <item>"*1"</item>
+        <item>"*2"</item>
+        <item>"*3"</item>
+        <item>"*4"</item>
+        <item>"*5"</item>
+        <item>"*6"</item>
+        <item>"*7"</item>
+        <item>"*8"</item>
+        <item>"*9"</item>
+        <item>"#0"</item>
+        <item>"#1"</item>
+        <item>"#2"</item>
+        <item>"#3"</item>
+        <item>"#4"</item>
+        <item>"#5"</item>
+        <item>"#6"</item>
+        <item>"#7"</item>
+        <item>"#8"</item>
+        <item>"#9"</item>
+    </string-array>
+</resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 597f504..6fd855c 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3077,12 +3077,20 @@
     <string name="whichViewApplicationNamed">Open with %1$s</string>
     <!-- Label for a link to a intent resolver dialog to view something -->
     <string name="whichViewApplicationLabel">Open</string>
-    <!-- Title of intent resolver dialog when selecting a viewer application that opens URI
+    <!-- Title of intent resolver dialog when selecting a browser/application that opens specific URIs
          [CHAR LIMIT=128]. -->
-    <string name="whichGiveAccessToApplication">Give access to open <xliff:g id="host" example="mail.google.com">%1$s</xliff:g> links with</string>
+    <string name="whichOpenHostLinksWith">Open <xliff:g id="host" example="mail.google.com">%1$s</xliff:g> links with</string>
+    <!-- Title of intent resolver dialog when selecting a browser that opens URI
+         [CHAR LIMIT=128]. -->
+    <string name="whichOpenLinksWith">Open links with</string>
+    <!-- Title of intent resolver dialog when defaulting to a specific browser that opens URI
+         [CHAR LIMIT=128]. -->
+    <string name="whichOpenLinksWithApp">Open links with <xliff:g id="application" example="Chrome">%1$s</xliff:g></string>
+    <!-- Title of intent resolver dialog when defaulting to a specific browser that opens URI
+         [CHAR LIMIT=128]. -->
+    <string name="whichOpenHostLinksWithApp">Open <xliff:g id="host" example="mail.google.com">%1$s</xliff:g> links with <xliff:g id="application" example="Chrome">%2$s</xliff:g></string>
     <!-- Title of intent resolver dialog when selecting a viewer application that opens URI
          and a previously used application is known [CHAR LIMIT=128]. -->
-    <string name="whichGiveAccessToApplicationNamed">Give access to open <xliff:g id="host" example="mail.google.com">%1$s</xliff:g> links with <xliff:g id="application" example="Gmail">%2$s</xliff:g></string>
     <!-- Label for a link to an intent resolver dialog to open URI [CHAR LIMIT=18] -->
     <string name="whichGiveAccessToApplicationLabel">Give access</string>
     <!-- Title of intent resolver dialog when selecting an editor application to run. -->
@@ -4215,6 +4223,10 @@
     <string name="activity_resolver_use_always">Always</string>
 
     <!-- Title for a button to choose the currently selected activity
+         as the default in the activity resolver. [CHAR LIMIT=50] -->
+    <string name="activity_resolver_set_always">Set to always open</string>
+
+    <!-- Title for a button to choose the currently selected activity
          from the activity resolver to use just this once. [CHAR LIMIT=25] -->
     <string name="activity_resolver_use_once">Just once</string>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 05c0114..5ca77f9 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2242,7 +2242,6 @@
   <java-symbol type="id" name="resolver_list" />
   <java-symbol type="id" name="button_once" />
   <java-symbol type="id" name="button_always" />
-  <java-symbol type="id" name="button_app_settings" />
   <java-symbol type="integer" name="config_globalActionsKeyTimeout" />
   <java-symbol type="integer" name="config_screenshotChordKeyTimeout" />
   <java-symbol type="integer" name="config_maxResolverActivityColumns" />
@@ -2624,14 +2623,17 @@
   <java-symbol type="bool" name="config_use_voip_mode_for_ims" />
   <java-symbol type="attr" name="touchscreenBlocksFocus" />
   <java-symbol type="layout" name="resolver_list_with_default" />
-  <java-symbol type="string" name="activity_resolver_app_settings" />
+  <java-symbol type="string" name="activity_resolver_set_always" />
+  <java-symbol type="string" name="activity_resolver_use_always" />
   <java-symbol type="string" name="whichApplicationNamed" />
   <java-symbol type="string" name="whichApplicationLabel" />
   <java-symbol type="string" name="whichViewApplication" />
   <java-symbol type="string" name="whichViewApplicationNamed" />
   <java-symbol type="string" name="whichViewApplicationLabel" />
-  <java-symbol type="string" name="whichGiveAccessToApplication" />
-  <java-symbol type="string" name="whichGiveAccessToApplicationNamed" />
+  <java-symbol type="string" name="whichOpenHostLinksWith" />
+  <java-symbol type="string" name="whichOpenHostLinksWithApp" />
+  <java-symbol type="string" name="whichOpenLinksWith" />
+  <java-symbol type="string" name="whichOpenLinksWithApp" />
   <java-symbol type="string" name="whichGiveAccessToApplicationLabel" />
   <java-symbol type="string" name="whichEditApplication" />
   <java-symbol type="string" name="whichEditApplicationNamed" />
diff --git a/core/tests/utiltests/Android.bp b/core/tests/utiltests/Android.bp
new file mode 100644
index 0000000..f13885e
--- /dev/null
+++ b/core/tests/utiltests/Android.bp
@@ -0,0 +1,38 @@
+//########################################################################
+// Build FrameworksUtilTests package
+//########################################################################
+
+android_test {
+    name: "FrameworksUtilTests",
+
+    // We only want this apk build for tests.
+
+    // Include all test java files.
+    srcs: ["src/**/*.java"] + ["src/android/util/IRemoteMemoryIntArray.aidl"],
+
+    jni_libs: [
+        "libmemoryintarraytest",
+        "libcutils",
+        "libc++",
+    ],
+
+    static_libs: [
+        "androidx.test.rules",
+        "frameworks-base-testutils",
+        "mockito-target-minus-junit4",
+        "androidx.test.ext.junit",
+    ],
+
+    libs: [
+        "android.test.runner",
+        "android.test.base",
+        "android.test.mock",
+    ],
+
+    platform_apis: true,
+
+    certificate: "platform",
+
+    test_suites: ["device-tests"],
+
+}
diff --git a/core/tests/utiltests/Android.mk b/core/tests/utiltests/Android.mk
deleted file mode 100644
index 9ef73e9..0000000
--- a/core/tests/utiltests/Android.mk
+++ /dev/null
@@ -1,33 +0,0 @@
-#########################################################################
-# Build FrameworksUtilTests package
-#########################################################################
-
-LOCAL_PATH:= $(call my-dir)
-include $(CLEAR_VARS)
-
-# We only want this apk build for tests.
-LOCAL_MODULE_TAGS := tests
-
-# Include all test java files.
-LOCAL_SRC_FILES := $(call all-java-files-under, src)
-LOCAL_SRC_FILES += src/android/util/IRemoteMemoryIntArray.aidl
-
-LOCAL_JNI_SHARED_LIBRARIES := libmemoryintarraytest libcutils libc++
-
-LOCAL_STATIC_JAVA_LIBRARIES := \
-    androidx.test.rules \
-    frameworks-base-testutils \
-    mockito-target-minus-junit4 \
-    androidx.test.ext.junit
-
-LOCAL_JAVA_LIBRARIES := android.test.runner android.test.base android.test.mock
-
-LOCAL_PACKAGE_NAME := FrameworksUtilTests
-LOCAL_PRIVATE_PLATFORM_APIS := true
-
-LOCAL_CERTIFICATE := platform
-
-LOCAL_COMPATIBILITY_SUITE := device-tests
-
-include $(BUILD_PACKAGE)
-
diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp
index 4f64da7..bbffb35 100644
--- a/libs/hwui/renderthread/VulkanSurface.cpp
+++ b/libs/hwui/renderthread/VulkanSurface.cpp
@@ -27,15 +27,6 @@
 namespace uirenderer {
 namespace renderthread {
 
-static bool IsTransformSupported(int transform) {
-    // For now, only support pure rotations, not flip or flip-and-rotate, until we have
-    // more time to test them and build sample code. As far as I know we never actually
-    // use anything besides pure rotations anyway.
-    return transform == 0 || transform == NATIVE_WINDOW_TRANSFORM_ROT_90 ||
-           transform == NATIVE_WINDOW_TRANSFORM_ROT_180 ||
-           transform == NATIVE_WINDOW_TRANSFORM_ROT_270;
-}
-
 static int InvertTransform(int transform) {
     switch (transform) {
         case NATIVE_WINDOW_TRANSFORM_ROT_90:
@@ -68,28 +59,6 @@
     return SkMatrix::I();
 }
 
-void VulkanSurface::ComputeWindowSizeAndTransform(WindowInfo* windowInfo, const SkISize& minSize,
-                                                  const SkISize& maxSize) {
-    SkISize& windowSize = windowInfo->size;
-
-    // clamp width & height to handle currentExtent of -1 and  protect us from broken hints
-    if (windowSize.width() < minSize.width() || windowSize.width() > maxSize.width() ||
-        windowSize.height() < minSize.height() || windowSize.height() > maxSize.height()) {
-        int width = std::min(maxSize.width(), std::max(minSize.width(), windowSize.width()));
-        int height = std::min(maxSize.height(), std::max(minSize.height(), windowSize.height()));
-        ALOGE("Invalid Window Dimensions [%d, %d]; clamping to [%d, %d]", windowSize.width(),
-              windowSize.height(), width, height);
-        windowSize.set(width, height);
-    }
-
-    windowInfo->actualSize = windowSize;
-    if (windowInfo->transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
-        windowInfo->actualSize.set(windowSize.height(), windowSize.width());
-    }
-
-    windowInfo->preTransform = GetPreTransformMatrix(windowInfo->size, windowInfo->transform);
-}
-
 static bool ConnectAndSetWindowDefaults(ANativeWindow* window) {
     ATRACE_CALL();
 
@@ -125,6 +94,24 @@
         return false;
     }
 
+    // Let consumer drive the size of the buffers.
+    err = native_window_set_buffers_dimensions(window, 0, 0);
+    if (err != 0) {
+        ALOGE("native_window_set_buffers_dimensions(0,0) failed: %s (%d)", strerror(-err), err);
+        return false;
+    }
+
+    // Enable auto prerotation, so when buffer size is driven by the consumer
+    // and the transform hint specifies a 90 or 270 degree rotation, the width
+    // and height used for buffer pre-allocation and dequeueBuffer will be
+    // additionally swapped.
+    err = native_window_set_auto_prerotation(window, true);
+    if (err != 0) {
+        ALOGE("VulkanSurface::UpdateWindow() native_window_set_auto_prerotation failed: %s (%d)",
+              strerror(-err), err);
+        return false;
+    }
+
     return true;
 }
 
@@ -132,10 +119,6 @@
                                      SkColorType colorType, sk_sp<SkColorSpace> colorSpace,
                                      GrContext* grContext, const VulkanManager& vkManager,
                                      uint32_t extraBuffers) {
-    // TODO(http://b/134182502)
-    const SkISize minSize = SkISize::Make(1, 1);
-    const SkISize maxSize = SkISize::Make(4096, 4096);
-
     // Connect and set native window to default configurations.
     if (!ConnectAndSetWindowDefaults(window)) {
         return nullptr;
@@ -144,7 +127,7 @@
     // Initialize WindowInfo struct.
     WindowInfo windowInfo;
     if (!InitializeWindowInfoStruct(window, colorMode, colorType, colorSpace, vkManager,
-                                    extraBuffers, minSize, maxSize, &windowInfo)) {
+                                    extraBuffers, &windowInfo)) {
         return nullptr;
     }
 
@@ -153,15 +136,14 @@
         return nullptr;
     }
 
-    return new VulkanSurface(window, windowInfo, minSize, maxSize, grContext);
+    return new VulkanSurface(window, windowInfo, grContext);
 }
 
 bool VulkanSurface::InitializeWindowInfoStruct(ANativeWindow* window, ColorMode colorMode,
                                                SkColorType colorType,
                                                sk_sp<SkColorSpace> colorSpace,
                                                const VulkanManager& vkManager,
-                                               uint32_t extraBuffers, const SkISize& minSize,
-                                               const SkISize& maxSize, WindowInfo* outWindowInfo) {
+                                               uint32_t extraBuffers, WindowInfo* outWindowInfo) {
     ATRACE_CALL();
 
     int width, height;
@@ -185,7 +167,13 @@
     }
     outWindowInfo->transform = query_value;
 
-    ComputeWindowSizeAndTransform(outWindowInfo, minSize, maxSize);
+    outWindowInfo->actualSize = outWindowInfo->size;
+    if (outWindowInfo->transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+        outWindowInfo->actualSize.set(outWindowInfo->size.height(), outWindowInfo->size.width());
+    }
+
+    outWindowInfo->preTransform =
+            GetPreTransformMatrix(outWindowInfo->size, outWindowInfo->transform);
 
     err = window->query(window, NATIVE_WINDOW_MIN_UNDEQUEUED_BUFFERS, &query_value);
     if (err != 0 || query_value < 0) {
@@ -290,15 +278,6 @@
         return false;
     }
 
-    const SkISize& size = windowInfo.actualSize;
-    err = native_window_set_buffers_dimensions(window, size.width(), size.height());
-    if (err != 0) {
-        ALOGE("VulkanSurface::UpdateWindow() native_window_set_buffers_dimensions(%d,%d) "
-              "failed: %s (%d)",
-              size.width(), size.height(), strerror(-err), err);
-        return false;
-    }
-
     // native_window_set_buffers_transform() expects the transform the app is requesting that
     // the compositor perform during composition. With native windows, pre-transform works by
     // rendering with the same transform the compositor is applying (as in Vulkan), but
@@ -331,12 +310,8 @@
 }
 
 VulkanSurface::VulkanSurface(ANativeWindow* window, const WindowInfo& windowInfo,
-                             SkISize minWindowSize, SkISize maxWindowSize, GrContext* grContext)
-        : mNativeWindow(window)
-        , mWindowInfo(windowInfo)
-        , mGrContext(grContext)
-        , mMinWindowSize(minWindowSize)
-        , mMaxWindowSize(maxWindowSize) {}
+                             GrContext* grContext)
+        : mNativeWindow(window), mWindowInfo(windowInfo), mGrContext(grContext) {}
 
 VulkanSurface::~VulkanSurface() {
     releaseBuffers();
@@ -379,58 +354,51 @@
     // value at the end of the function if everything dequeued correctly.
     mCurrentBufferInfo = nullptr;
 
-    // check if the native window has been resized or rotated and update accordingly
-    SkISize newSize = SkISize::MakeEmpty();
+    // Query the transform hint synced from the initial Surface connect or last queueBuffer. The
+    // auto prerotation on the buffer is based on the same transform hint in use by the producer.
     int transformHint = 0;
-    mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_WIDTH, &newSize.fWidth);
-    mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_HEIGHT, &newSize.fHeight);
-    mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_TRANSFORM_HINT, &transformHint);
-    if (newSize != mWindowInfo.actualSize || transformHint != mWindowInfo.transform) {
-        WindowInfo newWindowInfo = mWindowInfo;
-        newWindowInfo.size = newSize;
-        newWindowInfo.transform = IsTransformSupported(transformHint) ? transformHint : 0;
-        ComputeWindowSizeAndTransform(&newWindowInfo, mMinWindowSize, mMaxWindowSize);
+    int err =
+            mNativeWindow->query(mNativeWindow.get(), NATIVE_WINDOW_TRANSFORM_HINT, &transformHint);
 
-        int err = 0;
-        if (newWindowInfo.actualSize != mWindowInfo.actualSize) {
-            // reset the native buffers and update the window
-            err = native_window_set_buffers_dimensions(mNativeWindow.get(),
-                                                       newWindowInfo.actualSize.width(),
-                                                       newWindowInfo.actualSize.height());
-            if (err != 0) {
-                ALOGE("native_window_set_buffers_dimensions(%d,%d) failed: %s (%d)",
-                      newWindowInfo.actualSize.width(), newWindowInfo.actualSize.height(),
-                      strerror(-err), err);
-                return nullptr;
-            }
-            // reset the NativeBufferInfo (including SkSurface) associated with the old buffers. The
-            // new NativeBufferInfo storage will be populated lazily as we dequeue each new buffer.
-            releaseBuffers();
-            // TODO should we ask the nativewindow to allocate buffers?
-        }
-
-        if (newWindowInfo.transform != mWindowInfo.transform) {
-            err = native_window_set_buffers_transform(mNativeWindow.get(),
-                                                      InvertTransform(newWindowInfo.transform));
-            if (err != 0) {
-                ALOGE("native_window_set_buffers_transform(%d) failed: %s (%d)",
-                      newWindowInfo.transform, strerror(-err), err);
-                newWindowInfo.transform = mWindowInfo.transform;
-                ComputeWindowSizeAndTransform(&newWindowInfo, mMinWindowSize, mMaxWindowSize);
-            }
-        }
-
-        mWindowInfo = newWindowInfo;
-    }
-
+    // Since auto pre-rotation is enabled, dequeueBuffer to get the consumer driven buffer size
+    // from ANativeWindowBuffer.
     ANativeWindowBuffer* buffer;
     int fence_fd;
-    int err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buffer, &fence_fd);
+    err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buffer, &fence_fd);
     if (err != 0) {
         ALOGE("dequeueBuffer failed: %s (%d)", strerror(-err), err);
         return nullptr;
     }
 
+    SkISize actualSize = SkISize::Make(buffer->width, buffer->height);
+    if (actualSize != mWindowInfo.actualSize || transformHint != mWindowInfo.transform) {
+        if (actualSize != mWindowInfo.actualSize) {
+            // reset the NativeBufferInfo (including SkSurface) associated with the old buffers. The
+            // new NativeBufferInfo storage will be populated lazily as we dequeue each new buffer.
+            mWindowInfo.actualSize = actualSize;
+            releaseBuffers();
+        }
+
+        if (transformHint != mWindowInfo.transform) {
+            err = native_window_set_buffers_transform(mNativeWindow.get(),
+                                                      InvertTransform(transformHint));
+            if (err != 0) {
+                ALOGE("native_window_set_buffers_transform(%d) failed: %s (%d)", transformHint,
+                      strerror(-err), err);
+                mNativeWindow->cancelBuffer(mNativeWindow.get(), buffer, fence_fd);
+                return nullptr;
+            }
+            mWindowInfo.transform = transformHint;
+        }
+
+        mWindowInfo.size = actualSize;
+        if (mWindowInfo.transform & NATIVE_WINDOW_TRANSFORM_ROT_90) {
+            mWindowInfo.size.set(actualSize.height(), actualSize.width());
+        }
+
+        mWindowInfo.preTransform = GetPreTransformMatrix(mWindowInfo.size, mWindowInfo.transform);
+    }
+
     uint32_t idx;
     for (idx = 0; idx < mWindowInfo.bufferCount; idx++) {
         if (mNativeBuffers[idx].buffer.get() == buffer) {
diff --git a/libs/hwui/renderthread/VulkanSurface.h b/libs/hwui/renderthread/VulkanSurface.h
index 54007e7..5fa860a 100644
--- a/libs/hwui/renderthread/VulkanSurface.h
+++ b/libs/hwui/renderthread/VulkanSurface.h
@@ -101,16 +101,12 @@
         SkMatrix preTransform;
     };
 
-    VulkanSurface(ANativeWindow* window, const WindowInfo& windowInfo, SkISize minWindowSize,
-                  SkISize maxWindowSize, GrContext* grContext);
+    VulkanSurface(ANativeWindow* window, const WindowInfo& windowInfo, GrContext* grContext);
     static bool InitializeWindowInfoStruct(ANativeWindow* window, ColorMode colorMode,
                                            SkColorType colorType, sk_sp<SkColorSpace> colorSpace,
                                            const VulkanManager& vkManager, uint32_t extraBuffers,
-                                           const SkISize& minSize, const SkISize& maxSize,
                                            WindowInfo* outWindowInfo);
     static bool UpdateWindow(ANativeWindow* window, const WindowInfo& windowInfo);
-    static void ComputeWindowSizeAndTransform(WindowInfo* windowInfo, const SkISize& minSize,
-                                              const SkISize& maxSize);
     void releaseBuffers();
 
     // TODO: Just use a vector?
@@ -122,11 +118,8 @@
 
     uint32_t mPresentCount = 0;
     NativeBufferInfo* mCurrentBufferInfo = nullptr;
-
-    const SkISize mMinWindowSize;
-    const SkISize mMaxWindowSize;
 };
 
 } /* namespace renderthread */
 } /* namespace uirenderer */
-} /* namespace android */
\ No newline at end of file
+} /* namespace android */
diff --git a/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl b/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
index 8238b8c..7e3f2f8 100644
--- a/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
+++ b/media/java/android/service/media/IMediaBrowserServiceCallbacks.aidl
@@ -19,7 +19,9 @@
      *         the playback of the media app.
      * @param extra Extras returned by the media service.
      */
+    @UnsupportedAppUsage
     void onConnect(String root, in MediaSession.Token session, in Bundle extras);
+    @UnsupportedAppUsage
     void onConnectFailed();
     void onLoadChildren(String mediaId, in ParceledListSlice list);
     void onLoadChildrenWithOptions(String mediaId, in ParceledListSlice list,
diff --git a/packages/SystemUI/res/anim/lock_in.xml b/packages/SystemUI/res/anim/lock_in.xml
deleted file mode 100644
index c7014e8..0000000
--- a/packages/SystemUI/res/anim/lock_in.xml
+++ /dev/null
@@ -1,227 +0,0 @@
-<!-- Copyright (C) 2019 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
-                 xmlns:aapt="http://schemas.android.com/aapt">
-    <aapt:attr name="android:drawable">
-        <vector android:height="42dp" android:width="32dp" android:viewportHeight="42"
-                android:viewportWidth="32">
-            <group android:name="_R_G">
-                <group android:name="_R_G_L_2_G" android:translateX="1.6669999999999998"
-                       android:translateY="11.992999999999999" android:pivotX="14.333"
-                       android:pivotY="13" android:scaleX="0" android:scaleY="0">
-                    <path android:name="_R_G_L_2_G_D_0_P_0" android:strokeColor="#ffffff"
-                          android:strokeLineCap="round" android:strokeLineJoin="round"
-                          android:strokeWidth="2" android:strokeAlpha="1"
-                          android:pathData=" M22.33 21 C22.33,21 6.33,21 6.33,21 C5.6,21 5,20.4 5,19.67 C5,19.67 5,6.33 5,6.33 C5,5.6 5.6,5 6.33,5 C6.33,5 22.33,5 22.33,5 C23.07,5 23.67,5.6 23.67,6.33 C23.67,6.33 23.67,19.67 23.67,19.67 C23.67,20.4 23.07,21 22.33,21c "/>
-                </group>
-                <group android:name="_R_G_L_1_G_N_4_T_0" android:translateX="1.6669999999999998"
-                       android:translateY="11.992999999999999" android:pivotX="14.333"
-                       android:pivotY="13" android:scaleX="0" android:scaleY="0">
-                    <group android:name="_R_G_L_1_G" android:translateX="11.583"
-                           android:translateY="10.257">
-                        <path android:name="_R_G_L_1_G_D_0_P_0" android:fillColor="#ffffff"
-                              android:fillAlpha="1" android:fillType="nonZero"
-                              android:pathData=" M2.75 0.25 C4.13,0.25 5.25,1.37 5.25,2.75 C5.25,4.13 4.13,5.25 2.75,5.25 C1.37,5.25 0.25,4.13 0.25,2.75 C0.25,1.37 1.37,0.25 2.75,0.25c "/>
-                    </group>
-                </group>
-                <group android:name="_R_G_L_0_G_N_4_T_0" android:translateX="1.6669999999999998"
-                       android:translateY="11.992999999999999" android:pivotX="14.333"
-                       android:pivotY="13" android:scaleX="0" android:scaleY="0">
-                    <group android:name="_R_G_L_0_G_T_1" android:translateX="14.333"
-                           android:translateY="3.172">
-                        <group android:name="_R_G_L_0_G" android:translateX="-9.667"
-                               android:translateY="-9.667">
-                            <path android:name="_R_G_L_0_G_D_0_P_0" android:strokeColor="#ffffff"
-                                  android:strokeLineCap="round" android:strokeLineJoin="round"
-                                  android:strokeWidth="2" android:strokeAlpha="1"
-                                  android:trimPathStart="0.14" android:trimPathEnd="0.89"
-                                  android:trimPathOffset="0"
-                                  android:pathData=" M14.33 14.33 C14.33,14.33 14.33,9.67 14.33,9.67 C14.33,7.09 12.24,5 9.67,5 C7.09,5 5,7.09 5,9.67 C5,9.67 5,14.33 5,14.33 "/>
-                        </group>
-                    </group>
-                </group>
-            </group>
-            <group android:name="time_group"/>
-        </vector>
-    </aapt:attr>
-    <target android:name="_R_G_L_2_G">
-        <aapt:attr name="android:animation">
-            <set android:ordering="together">
-                <objectAnimator android:propertyName="scaleX" android:duration="233"
-                                android:startOffset="0" android:valueFrom="0" android:valueTo="1.02"
-                                android:valueType="floatType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.438,1 1.0,1.0"/>
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator android:propertyName="scaleY" android:duration="233"
-                                android:startOffset="0" android:valueFrom="0" android:valueTo="1.02"
-                                android:valueType="floatType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.438,1 1.0,1.0"/>
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator android:propertyName="scaleX" android:duration="117"
-                                android:startOffset="233" android:valueFrom="1.02"
-                                android:valueTo="1" android:valueType="floatType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.565,1 1.0,1.0"/>
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator android:propertyName="scaleY" android:duration="117"
-                                android:startOffset="233" android:valueFrom="1.02"
-                                android:valueTo="1" android:valueType="floatType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.565,1 1.0,1.0"/>
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_1_G_N_4_T_0">
-        <aapt:attr name="android:animation">
-            <set android:ordering="together">
-                <objectAnimator android:propertyName="scaleX" android:duration="233"
-                                android:startOffset="0" android:valueFrom="0" android:valueTo="1.02"
-                                android:valueType="floatType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.438,1 1.0,1.0"/>
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator android:propertyName="scaleY" android:duration="233"
-                                android:startOffset="0" android:valueFrom="0" android:valueTo="1.02"
-                                android:valueType="floatType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.438,1 1.0,1.0"/>
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator android:propertyName="scaleX" android:duration="117"
-                                android:startOffset="233" android:valueFrom="1.02"
-                                android:valueTo="1" android:valueType="floatType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.565,1 1.0,1.0"/>
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator android:propertyName="scaleY" android:duration="117"
-                                android:startOffset="233" android:valueFrom="1.02"
-                                android:valueTo="1" android:valueType="floatType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.565,1 1.0,1.0"/>
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_0_G_D_0_P_0">
-        <aapt:attr name="android:animation">
-            <set android:ordering="together">
-                <objectAnimator android:propertyName="trimPathStart" android:duration="50"
-                                android:startOffset="0" android:valueFrom="0.14"
-                                android:valueTo="0.14" android:valueType="floatType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator
-                            android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator android:propertyName="trimPathStart" android:duration="67"
-                                android:startOffset="50" android:valueFrom="0.14"
-                                android:valueTo="0" android:valueType="floatType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator
-                            android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_0_G_D_0_P_0">
-        <aapt:attr name="android:animation">
-            <set android:ordering="together">
-                <objectAnimator android:propertyName="trimPathEnd" android:duration="50"
-                                android:startOffset="0" android:valueFrom="0.89"
-                                android:valueTo="0.89" android:valueType="floatType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator
-                            android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator android:propertyName="trimPathEnd" android:duration="67"
-                                android:startOffset="50" android:valueFrom="0.89"
-                                android:valueTo="1" android:valueType="floatType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator
-                            android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0"/>
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_0_G_T_1">
-        <aapt:attr name="android:animation">
-            <set android:ordering="together">
-                <objectAnimator android:propertyName="translateY" android:duration="150"
-                                android:startOffset="0" android:valueFrom="3.172"
-                                android:valueTo="0.34" android:valueType="floatType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.23,-0.46 0.2,1 1.0,1.0"/>
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_0_G_N_4_T_0">
-        <aapt:attr name="android:animation">
-            <set android:ordering="together">
-                <objectAnimator android:propertyName="scaleX" android:duration="233"
-                                android:startOffset="0" android:valueFrom="0" android:valueTo="1.02"
-                                android:valueType="floatType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.438,1 1.0,1.0"/>
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator android:propertyName="scaleY" android:duration="233"
-                                android:startOffset="0" android:valueFrom="0" android:valueTo="1.02"
-                                android:valueType="floatType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.001,0 0.438,1 1.0,1.0"/>
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator android:propertyName="scaleX" android:duration="117"
-                                android:startOffset="233" android:valueFrom="1.02"
-                                android:valueTo="1" android:valueType="floatType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.565,1 1.0,1.0"/>
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator android:propertyName="scaleY" android:duration="117"
-                                android:startOffset="233" android:valueFrom="1.02"
-                                android:valueTo="1" android:valueType="floatType">
-                    <aapt:attr name="android:interpolator">
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.565,1 1.0,1.0"/>
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="time_group">
-        <aapt:attr name="android:animation">
-            <set android:ordering="together">
-                <objectAnimator android:propertyName="translateX" android:duration="717"
-                                android:startOffset="0" android:valueFrom="0" android:valueTo="1"
-                                android:valueType="floatType"/>
-            </set>
-        </aapt:attr>
-    </target>
-</animated-vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/lock_in_circular.xml b/packages/SystemUI/res/anim/lock_in_circular.xml
deleted file mode 100644
index d1e98db..0000000
--- a/packages/SystemUI/res/anim/lock_in_circular.xml
+++ /dev/null
@@ -1,327 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<animated-vector xmlns:aapt="http://schemas.android.com/aapt"
-    xmlns:android="http://schemas.android.com/apk/res/android" >
-
-    <aapt:attr name="android:drawable" >
-        <vector
-            android:height="32dp"
-            android:viewportHeight="32"
-            android:viewportWidth="32"
-            android:width="32dp" >
-            <group android:name="_R_G" >
-                <group
-                    android:name="_R_G_L_2_G"
-                    android:pivotX="9.583"
-                    android:pivotY="8.916"
-                    android:scaleX="0"
-                    android:scaleY="0"
-                    android:translateX="6.416"
-                    android:translateY="10.416999999999998" >
-                    <path
-                        android:name="_R_G_L_2_G_D_0_P_0"
-                        android:fillAlpha="1"
-                        android:fillColor="#ffffff"
-                        android:fillType="nonZero"
-                        android:pathData=" M17.42 1.75 C17.42,1.75 17.42,14.58 17.42,14.58 C17.42,15.41 16.74,16.08 15.92,16.08 C15.92,16.08 3.25,16.08 3.25,16.08 C2.42,16.08 1.75,15.41 1.75,14.58 C1.75,14.58 1.75,1.75 1.75,1.75 C1.75,1.75 17.42,1.75 17.42,1.75c  M18.92 0.25 C18.92,0.25 0.25,0.25 0.25,0.25 C0.25,0.25 0.25,14.58 0.25,14.58 C0.25,16.24 1.59,17.58 3.25,17.58 C3.25,17.58 15.92,17.58 15.92,17.58 C17.57,17.58 18.92,16.24 18.92,14.58 C18.92,14.58 18.92,0.25 18.92,0.25c " />
-                </group>
-                <group
-                    android:name="_R_G_L_1_G_N_3_T_0"
-                    android:pivotX="9.583"
-                    android:pivotY="8.916"
-                    android:scaleX="0"
-                    android:scaleY="0"
-                    android:translateX="6.416"
-                    android:translateY="10.416999999999998" >
-                    <group
-                        android:name="_R_G_L_1_G"
-                        android:translateX="7.334"
-                        android:translateY="5.333" >
-                        <path
-                            android:name="_R_G_L_1_G_D_0_P_0"
-                            android:fillAlpha="1"
-                            android:fillColor="#ffffff"
-                            android:fillType="nonZero"
-                            android:pathData=" M4.25 2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25 C3.35,0.25 4.25,1.15 4.25,2.25c " />
-                        <path
-                            android:name="_R_G_L_1_G_D_1_P_0"
-                            android:pathData=" M2.25 2.25 C2.25,2.25 2.25,5.92 2.25,5.92 "
-                            android:strokeAlpha="1"
-                            android:strokeColor="#ffffff"
-                            android:strokeLineCap="round"
-                            android:strokeLineJoin="round"
-                            android:strokeWidth="1.5" />
-                    </group>
-                </group>
-                <group
-                    android:name="_R_G_L_0_G_N_3_T_0"
-                    android:pivotX="9.583"
-                    android:pivotY="8.916"
-                    android:scaleX="0"
-                    android:scaleY="0"
-                    android:translateX="6.416"
-                    android:translateY="10.416999999999998" >
-                    <group
-                        android:name="_R_G_L_0_G_T_1"
-                        android:translateX="9.583"
-                        android:translateY="-0.861" >
-                        <group
-                            android:name="_R_G_L_0_G"
-                            android:translateX="-8.083"
-                            android:translateY="-8.173" >
-                            <path
-                                android:name="_R_G_L_0_G_D_0_P_0"
-                                android:pathData=" M12.42 12.6 C12.42,12.6 12.42,8.17 12.42,8.17 C12.42,5.83 10.48,3.75 8.08,3.75 C5.69,3.75 3.75,5.83 3.75,8.17 C3.75,8.17 3.75,12.6 3.75,12.6 "
-                                android:strokeAlpha="1"
-                                android:strokeColor="#ffffff"
-                                android:strokeLineCap="round"
-                                android:strokeLineJoin="round"
-                                android:strokeWidth="1.5"
-                                android:trimPathEnd="0.9"
-                                android:trimPathOffset="0"
-                                android:trimPathStart="0.15" />
-                        </group>
-                    </group>
-                </group>
-            </group>
-            <group android:name="time_group" />
-        </vector>
-    </aapt:attr>
-
-    <target android:name="_R_G_L_2_G" >
-        <aapt:attr name="android:animation" >
-            <set android:ordering="together" >
-                <objectAnimator
-                    android:duration="233"
-                    android:propertyName="scaleX"
-                    android:startOffset="0"
-                    android:valueFrom="0"
-                    android:valueTo="1.025"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="233"
-                    android:propertyName="scaleY"
-                    android:startOffset="0"
-                    android:valueFrom="0"
-                    android:valueTo="1.025"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="117"
-                    android:propertyName="scaleX"
-                    android:startOffset="233"
-                    android:valueFrom="1.025"
-                    android:valueTo="1"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="117"
-                    android:propertyName="scaleY"
-                    android:startOffset="233"
-                    android:valueFrom="1.025"
-                    android:valueTo="1"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_1_G_N_3_T_0" >
-        <aapt:attr name="android:animation" >
-            <set android:ordering="together" >
-                <objectAnimator
-                    android:duration="233"
-                    android:propertyName="scaleX"
-                    android:startOffset="0"
-                    android:valueFrom="0"
-                    android:valueTo="1.025"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="233"
-                    android:propertyName="scaleY"
-                    android:startOffset="0"
-                    android:valueFrom="0"
-                    android:valueTo="1.025"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="117"
-                    android:propertyName="scaleX"
-                    android:startOffset="233"
-                    android:valueFrom="1.025"
-                    android:valueTo="1"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="117"
-                    android:propertyName="scaleY"
-                    android:startOffset="233"
-                    android:valueFrom="1.025"
-                    android:valueTo="1"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_0_G_D_0_P_0" >
-        <aapt:attr name="android:animation" >
-            <set android:ordering="together" >
-                <objectAnimator
-                    android:duration="50"
-                    android:propertyName="trimPathStart"
-                    android:startOffset="0"
-                    android:valueFrom="0.15"
-                    android:valueTo="0.15"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="67"
-                    android:propertyName="trimPathStart"
-                    android:startOffset="50"
-                    android:valueFrom="0.15"
-                    android:valueTo="0"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_0_G_D_0_P_0" >
-        <aapt:attr name="android:animation" >
-            <set android:ordering="together" >
-                <objectAnimator
-                    android:duration="50"
-                    android:propertyName="trimPathEnd"
-                    android:startOffset="0"
-                    android:valueFrom="0.9"
-                    android:valueTo="0.9"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="67"
-                    android:propertyName="trimPathEnd"
-                    android:startOffset="50"
-                    android:valueFrom="0.9"
-                    android:valueTo="1"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_0_G_T_1" >
-        <aapt:attr name="android:animation" >
-            <set android:ordering="together" >
-                <objectAnimator
-                    android:duration="150"
-                    android:pathData="M 9.583,-0.861C 9.583,-1.32784640645981 9.583,-3.19515359354019 9.583,-3.662"
-                    android:propertyName="translateXY"
-                    android:propertyXName="translateX"
-                    android:propertyYName="translateY"
-                    android:startOffset="0" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_0_G_N_3_T_0" >
-        <aapt:attr name="android:animation" >
-            <set android:ordering="together" >
-                <objectAnimator
-                    android:duration="233"
-                    android:propertyName="scaleX"
-                    android:startOffset="0"
-                    android:valueFrom="0"
-                    android:valueTo="1.025"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="233"
-                    android:propertyName="scaleY"
-                    android:startOffset="0"
-                    android:valueFrom="0"
-                    android:valueTo="1.025"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="117"
-                    android:propertyName="scaleX"
-                    android:startOffset="233"
-                    android:valueFrom="1.025"
-                    android:valueTo="1"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="117"
-                    android:propertyName="scaleY"
-                    android:startOffset="233"
-                    android:valueFrom="1.025"
-                    android:valueTo="1"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="time_group" >
-        <aapt:attr name="android:animation" >
-            <set android:ordering="together" >
-                <objectAnimator
-                    android:duration="717"
-                    android:propertyName="translateX"
-                    android:startOffset="0"
-                    android:valueFrom="0"
-                    android:valueTo="1"
-                    android:valueType="floatType" />
-            </set>
-        </aapt:attr>
-    </target>
-
-</animated-vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/lock_in_filled.xml b/packages/SystemUI/res/anim/lock_in_filled.xml
deleted file mode 100644
index 4cde38d..0000000
--- a/packages/SystemUI/res/anim/lock_in_filled.xml
+++ /dev/null
@@ -1,190 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<animated-vector xmlns:aapt="http://schemas.android.com/aapt"
-    xmlns:android="http://schemas.android.com/apk/res/android" >
-
-    <aapt:attr name="android:drawable" >
-        <vector
-            android:height="32dp"
-            android:viewportHeight="32"
-            android:viewportWidth="32"
-            android:width="32dp" >
-            <group android:name="_R_G" >
-                <group
-                    android:name="_R_G_L_1_G"
-                    android:pivotX="10.917"
-                    android:pivotY="9.583"
-                    android:scaleX="0"
-                    android:scaleY="0"
-                    android:translateX="5.083"
-                    android:translateY="10.417" >
-                    <path
-                        android:name="_R_G_L_1_G_D_0_P_0"
-                        android:fillAlpha="1"
-                        android:fillColor="#ffffff"
-                        android:fillType="nonZero"
-                        android:pathData=" M18.92 0.25 C18.92,0.25 2.92,0.25 2.92,0.25 C1.45,0.25 0.25,1.45 0.25,2.92 C0.25,2.92 0.25,16.25 0.25,16.25 C0.25,17.72 1.45,18.92 2.92,18.92 C2.92,18.92 18.92,18.92 18.92,18.92 C20.38,18.92 21.58,17.72 21.58,16.25 C21.58,16.25 21.58,2.92 21.58,2.92 C21.58,1.45 20.38,0.25 18.92,0.25c  M10.92 12.25 C9.45,12.25 8.25,11.05 8.25,9.58 C8.25,8.12 9.45,6.92 10.92,6.92 C12.38,6.92 13.58,8.12 13.58,9.58 C13.58,11.05 12.38,12.25 10.92,12.25c " />
-                </group>
-                <group
-                    android:name="_R_G_L_0_G_N_2_T_0"
-                    android:pivotX="10.917"
-                    android:pivotY="9.583"
-                    android:scaleX="0"
-                    android:scaleY="0"
-                    android:translateX="5.083"
-                    android:translateY="10.417" >
-                    <group
-                        android:name="_R_G_L_0_G_T_1"
-                        android:translateX="10.917"
-                        android:translateY="0.579" >
-                        <group
-                            android:name="_R_G_L_0_G"
-                            android:translateX="-9"
-                            android:translateY="-9" >
-                            <path
-                                android:name="_R_G_L_0_G_D_0_P_0"
-                                android:pathData=" M13 13 C13,13 13,9 13,9 C13,6.79 11.21,5 9,5 C6.79,5 5,6.79 5,9 C5,9 5,13 5,13 "
-                                android:strokeAlpha="1"
-                                android:strokeColor="#ffffff"
-                                android:strokeLineCap="round"
-                                android:strokeLineJoin="round"
-                                android:strokeWidth="2" />
-                        </group>
-                    </group>
-                </group>
-            </group>
-            <group android:name="time_group" />
-        </vector>
-    </aapt:attr>
-
-    <target android:name="_R_G_L_1_G" >
-        <aapt:attr name="android:animation" >
-            <set android:ordering="together" >
-                <objectAnimator
-                    android:duration="233"
-                    android:propertyName="scaleX"
-                    android:startOffset="0"
-                    android:valueFrom="0"
-                    android:valueTo="1.025"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="233"
-                    android:propertyName="scaleY"
-                    android:startOffset="0"
-                    android:valueFrom="0"
-                    android:valueTo="1.025"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="117"
-                    android:propertyName="scaleX"
-                    android:startOffset="233"
-                    android:valueFrom="1.025"
-                    android:valueTo="1"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="117"
-                    android:propertyName="scaleY"
-                    android:startOffset="233"
-                    android:valueFrom="1.025"
-                    android:valueTo="1"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_0_G_T_1" >
-        <aapt:attr name="android:animation" >
-            <set android:ordering="together" >
-                <objectAnimator
-                    android:duration="150"
-                    android:pathData="M 10.917,0.579C 10.917,-0.14248990631104008 10.917,-3.02851009368896 10.917,-3.75"
-                    android:propertyName="translateXY"
-                    android:propertyXName="translateX"
-                    android:propertyYName="translateY"
-                    android:startOffset="0" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_0_G_N_2_T_0" >
-        <aapt:attr name="android:animation" >
-            <set android:ordering="together" >
-                <objectAnimator
-                    android:duration="233"
-                    android:propertyName="scaleX"
-                    android:startOffset="0"
-                    android:valueFrom="0"
-                    android:valueTo="1.025"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="233"
-                    android:propertyName="scaleY"
-                    android:startOffset="0"
-                    android:valueFrom="0"
-                    android:valueTo="1.025"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="117"
-                    android:propertyName="scaleX"
-                    android:startOffset="233"
-                    android:valueFrom="1.025"
-                    android:valueTo="1"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="117"
-                    android:propertyName="scaleY"
-                    android:startOffset="233"
-                    android:valueFrom="1.025"
-                    android:valueTo="1"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="time_group" >
-        <aapt:attr name="android:animation" >
-            <set android:ordering="together" >
-                <objectAnimator
-                    android:duration="717"
-                    android:propertyName="translateX"
-                    android:startOffset="0"
-                    android:valueFrom="0"
-                    android:valueTo="1"
-                    android:valueType="floatType" />
-            </set>
-        </aapt:attr>
-    </target>
-
-</animated-vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/anim/lock_in_rounded.xml b/packages/SystemUI/res/anim/lock_in_rounded.xml
deleted file mode 100644
index 7c8cf9d..0000000
--- a/packages/SystemUI/res/anim/lock_in_rounded.xml
+++ /dev/null
@@ -1,336 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<animated-vector xmlns:aapt="http://schemas.android.com/aapt"
-    xmlns:android="http://schemas.android.com/apk/res/android" >
-
-    <aapt:attr name="android:drawable" >
-        <vector
-            android:height="38dp"
-            android:viewportHeight="38"
-            android:viewportWidth="32"
-            android:width="32dp" >
-            <group android:name="_R_G" >
-                <group
-                    android:name="_R_G_L_2_G"
-                    android:pivotX="14.667"
-                    android:pivotY="12.667"
-                    android:scaleX="0"
-                    android:scaleY="0"
-                    android:translateX="1.3330000000000002"
-                    android:translateY="10.333" >
-                    <path
-                        android:name="_R_G_L_2_G_D_0_P_0"
-                        android:pathData=" M22.09 5 C22.09,5 6,5 6,5 C5.45,5 5,5.45 5,6 C5,6 5,19.33 5,19.33 C5,19.89 5.45,20.33 6,20.33 C6,20.33 23.33,20.33 23.33,20.33 C23.89,20.33 24.33,19.89 24.33,19.33 C24.33,19.33 24.33,6 24.33,6 C24.33,5.45 23.89,5 23.33,5 C23.33,5 22.09,5 22.09,5c "
-                        android:strokeAlpha="1"
-                        android:strokeColor="#ffffff"
-                        android:strokeLineCap="round"
-                        android:strokeLineJoin="round"
-                        android:strokeWidth="1.5" />
-                </group>
-                <group
-                    android:name="_R_G_L_1_G_N_3_T_0"
-                    android:pivotX="14.667"
-                    android:pivotY="12.667"
-                    android:scaleX="0"
-                    android:scaleY="0"
-                    android:translateX="1.3330000000000002"
-                    android:translateY="10.333" >
-                    <group
-                        android:name="_R_G_L_1_G"
-                        android:translateX="12.416"
-                        android:translateY="10.417" >
-                        <path
-                            android:name="_R_G_L_1_G_D_0_P_0"
-                            android:fillAlpha="1"
-                            android:fillColor="#ffffff"
-                            android:fillType="nonZero"
-                            android:pathData=" M2.25 0.25 C3.35,0.25 4.25,1.15 4.25,2.25 C4.25,3.35 3.35,4.25 2.25,4.25 C1.15,4.25 0.25,3.35 0.25,2.25 C0.25,1.15 1.15,0.25 2.25,0.25c " />
-                    </group>
-                </group>
-                <group android:name="_R_G_L_0_G_N_3_T_0_M" >
-                    <group
-                        android:name="_R_G_L_0_G_N_3_T_0"
-                        android:pivotX="14.667"
-                        android:pivotY="12.667"
-                        android:scaleX="0"
-                        android:scaleY="0"
-                        android:translateX="1.3330000000000002"
-                        android:translateY="10.333" >
-                        <group
-                            android:name="_R_G_L_0_G_T_1"
-                            android:translateX="14.666"
-                            android:translateY="3.769" >
-                            <group
-                                android:name="_R_G_L_0_G"
-                                android:translateX="-9.333"
-                                android:translateY="-9.713" >
-                                <path
-                                    android:name="_R_G_L_0_G_D_0_P_0"
-                                    android:pathData=" M13.67 13.8 C13.67,13.8 13.67,8.94 13.67,8.94 C13.63,6.75 11.69,5 9.33,5.04 C6.98,5 5.04,6.75 5,8.94 C5,8.94 5,13.8 5,13.8 "
-                                    android:strokeAlpha="1"
-                                    android:strokeColor="#ffffff"
-                                    android:strokeLineCap="round"
-                                    android:strokeLineJoin="round"
-                                    android:strokeWidth="1.5"
-                                    android:trimPathEnd="0.9"
-                                    android:trimPathOffset="0"
-                                    android:trimPathStart="0.14" />
-                            </group>
-                        </group>
-                    </group>
-                </group>
-            </group>
-            <group android:name="time_group" />
-        </vector>
-    </aapt:attr>
-
-    <target android:name="_R_G_L_2_G" >
-        <aapt:attr name="android:animation" >
-            <set android:ordering="together" >
-                <objectAnimator
-                    android:duration="233"
-                    android:propertyName="scaleX"
-                    android:startOffset="0"
-                    android:valueFrom="0"
-                    android:valueTo="1.025"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="233"
-                    android:propertyName="scaleY"
-                    android:startOffset="0"
-                    android:valueFrom="0"
-                    android:valueTo="1.025"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="117"
-                    android:propertyName="scaleX"
-                    android:startOffset="233"
-                    android:valueFrom="1.025"
-                    android:valueTo="1"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="117"
-                    android:propertyName="scaleY"
-                    android:startOffset="233"
-                    android:valueFrom="1.025"
-                    android:valueTo="1"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_1_G_N_3_T_0" >
-        <aapt:attr name="android:animation" >
-            <set android:ordering="together" >
-                <objectAnimator
-                    android:duration="233"
-                    android:propertyName="scaleX"
-                    android:startOffset="0"
-                    android:valueFrom="0"
-                    android:valueTo="1.025"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="233"
-                    android:propertyName="scaleY"
-                    android:startOffset="0"
-                    android:valueFrom="0"
-                    android:valueTo="1.025"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="117"
-                    android:propertyName="scaleX"
-                    android:startOffset="233"
-                    android:valueFrom="1.025"
-                    android:valueTo="1"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="117"
-                    android:propertyName="scaleY"
-                    android:startOffset="233"
-                    android:valueFrom="1.025"
-                    android:valueTo="1"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_0_G_D_0_P_0" >
-        <aapt:attr name="android:animation" >
-            <set android:ordering="together" >
-                <objectAnimator
-                    android:duration="50"
-                    android:propertyName="trimPathStart"
-                    android:startOffset="0"
-                    android:valueFrom="0.14"
-                    android:valueTo="0.14"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="67"
-                    android:propertyName="trimPathStart"
-                    android:startOffset="50"
-                    android:valueFrom="0.14"
-                    android:valueTo="0"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_0_G_D_0_P_0" >
-        <aapt:attr name="android:animation" >
-            <set android:ordering="together" >
-                <objectAnimator
-                    android:duration="50"
-                    android:propertyName="trimPathEnd"
-                    android:startOffset="0"
-                    android:valueFrom="0.9"
-                    android:valueTo="0.9"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="67"
-                    android:propertyName="trimPathEnd"
-                    android:startOffset="50"
-                    android:valueFrom="0.9"
-                    android:valueTo="1"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.167,0.167 0.833,0.833 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_0_G_T_1" >
-        <aapt:attr name="android:animation" >
-            <set android:ordering="together" >
-                <objectAnimator
-                    android:duration="150"
-                    android:pathData="M 14.666,3.769C 14.666,3.18868762874603 14.666,0.8673123712539699 14.666,0.287"
-                    android:propertyName="translateXY"
-                    android:propertyXName="translateX"
-                    android:propertyYName="translateY"
-                    android:startOffset="0" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_0_G_N_3_T_0" >
-        <aapt:attr name="android:animation" >
-            <set android:ordering="together" >
-                <objectAnimator
-                    android:duration="233"
-                    android:propertyName="scaleX"
-                    android:startOffset="0"
-                    android:valueFrom="0"
-                    android:valueTo="1.025"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="233"
-                    android:propertyName="scaleY"
-                    android:startOffset="0"
-                    android:valueFrom="0"
-                    android:valueTo="1.025"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.043,0.277 0.44,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="117"
-                    android:propertyName="scaleX"
-                    android:startOffset="233"
-                    android:valueFrom="1.025"
-                    android:valueTo="1"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-                <objectAnimator
-                    android:duration="117"
-                    android:propertyName="scaleY"
-                    android:startOffset="233"
-                    android:valueFrom="1.025"
-                    android:valueTo="1"
-                    android:valueType="floatType" >
-                    <aapt:attr name="android:interpolator" >
-                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.667,1 1.0,1.0" />
-                    </aapt:attr>
-                </objectAnimator>
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="_R_G_L_0_G_N_3_T_0_M" >
-        <aapt:attr name="android:animation" >
-            <set android:ordering="together" >
-                <objectAnimator
-                    android:duration="0"
-                    android:propertyName="scaleX"
-                    android:startOffset="50"
-                    android:valueFrom="0"
-                    android:valueTo="1"
-                    android:valueType="floatType" />
-            </set>
-        </aapt:attr>
-    </target>
-    <target android:name="time_group" >
-        <aapt:attr name="android:animation" >
-            <set android:ordering="together" >
-                <objectAnimator
-                    android:duration="717"
-                    android:propertyName="translateX"
-                    android:startOffset="0"
-                    android:valueFrom="0"
-                    android:valueTo="1"
-                    android:valueType="floatType" />
-            </set>
-        </aapt:attr>
-    </target>
-
-</animated-vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/pip_menu_activity.xml b/packages/SystemUI/res/layout/pip_menu_activity.xml
index 0481310..ee0bd14 100644
--- a/packages/SystemUI/res/layout/pip_menu_activity.xml
+++ b/packages/SystemUI/res/layout/pip_menu_activity.xml
@@ -19,46 +19,47 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent">
 
-  <!-- Menu layout -->
-  <FrameLayout
-      android:id="@+id/menu_container"
-      android:layout_width="match_parent"
-      android:layout_height="match_parent"
-      android:forceHasOverlappingRendering="false">
+    <!-- Menu layout -->
+    <FrameLayout
+        android:id="@+id/menu_container"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:forceHasOverlappingRendering="false"
+        android:accessibilityTraversalAfter="@id/dismiss">
 
-      <!-- The margins for this container is calculated in the code depending on whether the
-           actions_container is visible. -->
-      <FrameLayout
-          android:id="@+id/expand_container"
-          android:layout_width="match_parent"
-          android:layout_height="match_parent">
-          <ImageButton
-              android:id="@+id/expand_button"
-              android:layout_width="60dp"
-              android:layout_height="60dp"
-              android:layout_gravity="center"
-              android:contentDescription="@string/pip_phone_expand"
-              android:padding="10dp"
-              android:src="@drawable/pip_expand"
-              android:background="?android:selectableItemBackgroundBorderless" />
-      </FrameLayout>
+        <!-- The margins for this container is calculated in the code depending on whether the
+             actions_container is visible. -->
+        <FrameLayout
+            android:id="@+id/expand_container"
+            android:layout_width="match_parent"
+            android:layout_height="match_parent">
+            <ImageButton
+                android:id="@+id/expand_button"
+                android:layout_width="60dp"
+                android:layout_height="60dp"
+                android:layout_gravity="center"
+                android:contentDescription="@string/pip_phone_expand"
+                android:padding="10dp"
+                android:src="@drawable/pip_expand"
+                android:background="?android:selectableItemBackgroundBorderless" />
+        </FrameLayout>
 
-      <FrameLayout
-          android:id="@+id/actions_container"
-          android:layout_width="match_parent"
-          android:layout_height="@dimen/pip_action_size"
-          android:layout_gravity="bottom"
-          android:visibility="invisible">
-          <LinearLayout
-              android:id="@+id/actions_group"
-              android:layout_width="wrap_content"
-              android:layout_height="match_parent"
-              android:layout_gravity="center_horizontal"
-              android:orientation="horizontal"
-              android:divider="@android:color/transparent"
-              android:showDividers="middle" />
-      </FrameLayout>
-  </FrameLayout>
+        <FrameLayout
+            android:id="@+id/actions_container"
+            android:layout_width="match_parent"
+            android:layout_height="@dimen/pip_action_size"
+            android:layout_gravity="bottom"
+            android:visibility="invisible">
+            <LinearLayout
+                android:id="@+id/actions_group"
+                android:layout_width="wrap_content"
+                android:layout_height="match_parent"
+                android:layout_gravity="center_horizontal"
+                android:orientation="horizontal"
+                android:divider="@android:color/transparent"
+                android:showDividers="middle" />
+        </FrameLayout>
+    </FrameLayout>
 
     <ImageButton
         android:id="@+id/settings"
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index bb7614a..a549870 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -141,6 +141,9 @@
     <!-- The number of milliseconds before the heads up notification auto-dismisses. -->
     <integer name="heads_up_notification_decay">5000</integer>
 
+    <!-- The number of milliseconds before the heads up notification sent automatically by the system auto-dismisses. -->
+    <integer name="auto_heads_up_notification_decay">3000</integer>
+
     <!-- The number of milliseconds after a heads up notification is pushed back
      before the app can interrupt again. -->
     <integer name="heads_up_default_snooze_length_ms">60000</integer>
@@ -197,25 +200,9 @@
     <!-- Doze: duration to avoid false pickup gestures triggered by notification vibrations -->
     <integer name="doze_pickup_vibration_threshold">2000</integer>
 
-    <!-- Doze: can we assume the pickup sensor includes a proximity check?
-         This is ignored if doze_pickup_subtype_performs_proximity_check is not empty.
-         @deprecated: use doze_pickup_subtype_performs_proximity_check instead.-->
+    <!-- Doze: can we assume the pickup sensor includes a proximity check? -->
     <bool name="doze_pickup_performs_proximity_check">false</bool>
 
-    <!-- Doze: a list of pickup sensor subtypes that perform a proximity check before they trigger.
-               If not empty, either * or !* must appear to specify the default.
-               If empty, falls back to doze_pickup_performs_proximity_check.
-
-               Examples: 1,2,3,!* -> subtypes 1,2 and 3 perform the check, all others don't.
-                         !1,!2,*  -> subtypes 1 and 2 don't perform the check, all others do.
-                         !8,*     -> subtype 8 does not perform the check, all others do
-                         1,1,*    -> illegal, every item may only appear once
-                         1,!1,*   -> illegal, no contradictions allowed
-                         1,2      -> illegal, need either * or !*
-                         1,,4a3   -> illegal, no empty or non-numeric terms allowed
-    -->
-    <string name="doze_pickup_subtype_performs_proximity_check"></string>
-
     <!-- Type of a sensor that provides a low-power estimate of the desired display
          brightness, suitable to listen to while the device is asleep (e.g. during
          always-on display) -->
diff --git a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
index 2090748..11d093f 100644
--- a/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
+++ b/packages/SystemUI/src/com/android/keyguard/CarrierTextController.java
@@ -303,6 +303,11 @@
             }
         } else {
             subs = mKeyguardUpdateMonitor.getSubscriptionInfo(false);
+            if (subs == null) {
+                subs = new ArrayList<>();
+            } else {
+                filterMobileSubscriptionInSameGroup(subs);
+            }
         }
         return subs;
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index f465003..45f69d6 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -28,6 +28,7 @@
 import static android.os.BatteryManager.EXTRA_MAX_CHARGING_VOLTAGE;
 import static android.os.BatteryManager.EXTRA_PLUGGED;
 import static android.os.BatteryManager.EXTRA_STATUS;
+import static android.telephony.PhoneStateListener.LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE;
 
 import android.annotation.AnyThread;
 import android.annotation.MainThread;
@@ -70,6 +71,7 @@
 import android.provider.Settings;
 import android.service.dreams.DreamService;
 import android.service.dreams.IDreamManager;
+import android.telephony.PhoneStateListener;
 import android.telephony.ServiceState;
 import android.telephony.SubscriptionInfo;
 import android.telephony.SubscriptionManager;
@@ -382,6 +384,13 @@
         }
     };
 
+    private PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
+        @Override
+        public void onActiveDataSubscriptionIdChanged(int subId) {
+            mHandler.sendEmptyMessage(MSG_SIM_SUBSCRIPTION_INFO_CHANGED);
+        }
+    };
+
     private OnSubscriptionsChangedListener mSubscriptionListener =
             new OnSubscriptionsChangedListener() {
         @Override
@@ -431,7 +440,7 @@
     private void handleSimSubscriptionInfoChanged() {
         if (DEBUG_SIM_STATES) {
             Log.v(TAG, "onSubscriptionInfoChanged()");
-            List<SubscriptionInfo> sil = mSubscriptionManager.getActiveSubscriptionInfoList();
+            List<SubscriptionInfo> sil = mSubscriptionManager.getActiveSubscriptionInfoList(false);
             if (sil != null) {
                 for (SubscriptionInfo subInfo : sil) {
                     Log.v(TAG, "SubInfo:" + subInfo);
@@ -483,7 +492,7 @@
     public List<SubscriptionInfo> getSubscriptionInfo(boolean forceReload) {
         List<SubscriptionInfo> sil = mSubscriptionInfo;
         if (sil == null || forceReload) {
-            sil = mSubscriptionManager.getActiveSubscriptionInfoList();
+            sil = mSubscriptionManager.getActiveSubscriptionInfoList(false);
         }
         if (sil == null) {
             // getActiveSubscriptionInfoList was null callers expect an empty list.
@@ -1080,6 +1089,8 @@
                 }
                 mHandler.sendMessage(
                         mHandler.obtainMessage(MSG_SERVICE_STATE_CHANGE, subId, 0, serviceState));
+            } else if (TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED.equals(action)) {
+                mHandler.sendEmptyMessage(MSG_SIM_SUBSCRIPTION_INFO_CHANGED);
             } else if (DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED.equals(
                     action)) {
                 mHandler.sendEmptyMessage(MSG_DEVICE_POLICY_MANAGER_STATE_CHANGED);
@@ -1490,6 +1501,7 @@
         filter.addAction(Intent.ACTION_AIRPLANE_MODE_CHANGED);
         filter.addAction(TelephonyIntents.ACTION_SIM_STATE_CHANGED);
         filter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);
+        filter.addAction(TelephonyIntents.ACTION_DEFAULT_DATA_SUBSCRIPTION_CHANGED);
         filter.addAction(TelephonyManager.ACTION_PHONE_STATE_CHANGED);
         filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
         filter.addAction(DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED);
@@ -1563,6 +1575,12 @@
         mDevicePolicyManager = context.getSystemService(DevicePolicyManager.class);
         mLogoutEnabled = mDevicePolicyManager.isLogoutEnabled();
         updateAirplaneModeState();
+
+        TelephonyManager telephony =
+                (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+        if (telephony != null) {
+            telephony.listen(mPhoneStateListener, LISTEN_ACTIVE_DATA_SUBSCRIPTION_ID_CHANGE);
+        }
     }
 
     private void updateAirplaneModeState() {
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
index 67ff0e7..4d42e0c 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIFactory.java
@@ -23,6 +23,7 @@
 import android.annotation.NonNull;
 import android.app.AlarmManager;
 import android.content.Context;
+import android.content.pm.PackageManager;
 import android.os.Handler;
 import android.os.Looper;
 import android.util.Log;
@@ -56,6 +57,7 @@
 import com.android.systemui.statusbar.phone.KeyguardBouncer;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.KeyguardEnvironmentImpl;
+import com.android.systemui.statusbar.phone.KeyguardLiftController;
 import com.android.systemui.statusbar.phone.LockIcon;
 import com.android.systemui.statusbar.phone.LockscreenWallpaper;
 import com.android.systemui.statusbar.phone.NotificationIconAreaController;
@@ -66,6 +68,7 @@
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.phone.UnlockMethodCache;
 import com.android.systemui.statusbar.policy.DeviceProvisionedController;
+import com.android.systemui.util.AsyncSensorManager;
 import com.android.systemui.util.InjectionInflationController;
 import com.android.systemui.util.leak.GarbageMonitor;
 import com.android.systemui.volume.VolumeDialogComponent;
@@ -224,6 +227,18 @@
 
     @Singleton
     @Provides
+    @Nullable
+    public KeyguardLiftController provideKeyguardLiftController(Context context,
+            StatusBarStateController statusBarStateController,
+            AsyncSensorManager asyncSensorManager) {
+        if (!context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_FACE)) {
+            return null;
+        }
+        return new KeyguardLiftController(context, statusBarStateController, asyncSensorManager);
+    }
+
+    @Singleton
+    @Provides
     public NotificationListener provideNotificationListener(Context context) {
         return new NotificationListener(context);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index cdcf660..cf04b7f 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -76,6 +76,8 @@
     private final ProxSensor mProxSensor;
     private long mDebounceFrom;
     private boolean mSettingRegistered;
+    private boolean mListening;
+    private boolean mPaused;
 
     public DozeSensors(Context context, AlarmManager alarmManager, SensorManager sensorManager,
             DozeParameters dozeParameters, AmbientDisplayConfiguration config, WakeLock wakeLock,
@@ -100,9 +102,12 @@
                 mPickupSensor = new TriggerSensor(
                         mSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE),
                         Settings.Secure.DOZE_PICK_UP_GESTURE,
+                        true /* settingDef */,
                         config.dozePickupSensorAvailable(),
                         DozeLog.REASON_SENSOR_PICKUP, false /* touchCoords */,
-                        false /* touchscreen */),
+                        false /* touchscreen */,
+                        false /* ignoresSetting */,
+                        mDozeParameters.getPickupPerformsProxCheck()),
                 new TriggerSensor(
                         findSensorWithType(config.doubleTapSensorType()),
                         Settings.Secure.DOZE_DOUBLE_TAP_GESTURE,
@@ -127,15 +132,15 @@
                         true /* touchscreen */),
                 new PluginSensor(
                         new SensorManagerPlugin.Sensor(TYPE_WAKE_DISPLAY),
-                        Settings.Secure.DOZE_WAKE_SCREEN_GESTURE,
+                        Settings.Secure.DOZE_WAKE_DISPLAY_GESTURE,
                         mConfig.wakeScreenGestureAvailable() && alwaysOn,
                         DozeLog.REASON_SENSOR_WAKE_UP,
                         false /* reports touch coordinates */,
                         false /* touchscreen */),
                 new PluginSensor(
                         new SensorManagerPlugin.Sensor(TYPE_WAKE_LOCK_SCREEN),
-                        Settings.Secure.DOZE_WAKE_SCREEN_GESTURE,
-                        mConfig.wakeScreenGestureAvailable() && alwaysOn,
+                        Settings.Secure.DOZE_WAKE_LOCK_SCREEN_GESTURE,
+                        mConfig.wakeScreenGestureAvailable(),
                         DozeLog.PULSE_REASON_SENSOR_WAKE_LOCK_SCREEN,
                         false /* reports touch coordinates */,
                         false /* touchscreen */, mConfig.getWakeLockScreenDebounce()),
@@ -170,11 +175,49 @@
         return null;
     }
 
+    /**
+     * If sensors should be registered and sending signals.
+     */
     public void setListening(boolean listen) {
-        for (TriggerSensor s : mSensors) {
-            s.setListening(listen);
+        if (mListening == listen) {
+            return;
         }
-        registerSettingsObserverIfNeeded(listen);
+        mListening = listen;
+        updateListening();
+    }
+
+    /**
+     * Unregister sensors, when listening, unless they are prox gated.
+     * @see #setListening(boolean)
+     */
+    public void setPaused(boolean paused) {
+        if (mPaused == paused) {
+            return;
+        }
+        mPaused = paused;
+        updateListening();
+    }
+
+    private void updateListening() {
+        boolean anyListening = false;
+        for (TriggerSensor s : mSensors) {
+            // We don't want to be listening while we're PAUSED (prox sensor is covered)
+            // except when the sensor is already gated by prox.
+            boolean listen = mListening && (!mPaused || s.performsProxCheck());
+            s.setListening(listen);
+            if (listen) {
+                anyListening = true;
+            }
+        }
+
+        if (!anyListening) {
+            mResolver.unregisterContentObserver(mSettingsObserver);
+        } else if (!mSettingRegistered) {
+            for (TriggerSensor s : mSensors) {
+                s.registerSettingsObserver(mSettingsObserver);
+            }
+        }
+        mSettingRegistered = anyListening;
     }
 
     /** Set the listening state of only the sensors that require the touchscreen. */
@@ -236,17 +279,6 @@
         return mProxSensor.mCurrentlyFar;
     }
 
-    private void registerSettingsObserverIfNeeded(boolean register) {
-        if (!register) {
-            mResolver.unregisterContentObserver(mSettingsObserver);
-        } else if (!mSettingRegistered) {
-            for (TriggerSensor s : mSensors) {
-                s.registerSettingsObserver(mSettingsObserver);
-            }
-        }
-        mSettingRegistered = register;
-    }
-
     private class ProxSensor implements SensorEventListener {
 
         boolean mRequested;
@@ -334,10 +366,11 @@
         final Sensor mSensor;
         final boolean mConfigured;
         final int mPulseReason;
-        final String mSetting;
-        final boolean mReportsTouchCoordinates;
-        final boolean mSettingDefault;
-        final boolean mRequiresTouchscreen;
+        private final String mSetting;
+        private final boolean mReportsTouchCoordinates;
+        private final boolean mSettingDefault;
+        private final boolean mRequiresTouchscreen;
+        private final boolean mSensorPerformsProxCheck;
 
         protected boolean mRequested;
         protected boolean mRegistered;
@@ -354,12 +387,14 @@
                 boolean configured, int pulseReason, boolean reportsTouchCoordinates,
                 boolean requiresTouchscreen) {
             this(sensor, setting, settingDef, configured, pulseReason, reportsTouchCoordinates,
-                    requiresTouchscreen, false /* ignoresSetting */);
+                    requiresTouchscreen, false /* ignoresSetting */,
+                    false /* sensorPerformsProxCheck */);
         }
 
         private TriggerSensor(Sensor sensor, String setting, boolean settingDef,
                 boolean configured, int pulseReason, boolean reportsTouchCoordinates,
-                boolean requiresTouchscreen, boolean ignoresSetting) {
+                boolean requiresTouchscreen, boolean ignoresSetting,
+                boolean sensorPerformsProxCheck) {
             mSensor = sensor;
             mSetting = setting;
             mSettingDefault = settingDef;
@@ -368,6 +403,7 @@
             mReportsTouchCoordinates = reportsTouchCoordinates;
             mRequiresTouchscreen = requiresTouchscreen;
             mIgnoresSetting = ignoresSetting;
+            mSensorPerformsProxCheck = sensorPerformsProxCheck;
         }
 
         public void setListening(boolean listen) {
@@ -427,14 +463,11 @@
             DozeLog.traceSensor(mContext, mPulseReason);
             mHandler.post(mWakeLock.wrap(() -> {
                 if (DEBUG) Log.d(TAG, "onTrigger: " + triggerEventToString(event));
-                boolean sensorPerformsProxCheck = false;
                 if (mSensor != null && mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) {
                     int subType = (int) event.values[0];
                     MetricsLogger.action(
                             mContext, MetricsProto.MetricsEvent.ACTION_AMBIENT_GESTURE,
                             subType);
-                    sensorPerformsProxCheck =
-                            mDozeParameters.getPickupSubtypePerformsProxCheck(subType);
                 }
 
                 mRegistered = false;
@@ -444,7 +477,7 @@
                     screenX = event.values[0];
                     screenY = event.values[1];
                 }
-                mCallback.onSensorPulse(mPulseReason, sensorPerformsProxCheck, screenX, screenY,
+                mCallback.onSensorPulse(mPulseReason, mSensorPerformsProxCheck, screenX, screenY,
                         event.values);
                 if (!mRegistered) {
                     updateListener();  // reregister, this sensor only fires once
@@ -452,6 +485,15 @@
             }));
         }
 
+        /**
+         * If the sensor itself performs proximity checks, to avoid pocket dialing.
+         * Gated sensors don't need to be stopped when the {@link DozeMachine} is
+         * {@link DozeMachine.State#DOZE_AOD_PAUSED}.
+         */
+        public boolean performsProxCheck() {
+            return mSensorPerformsProxCheck;
+        }
+
         public void registerSettingsObserver(ContentObserver settingsObserver) {
             if (mConfigured && !TextUtils.isEmpty(mSetting)) {
                 mResolver.registerContentObserver(
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
index a381e7b..97b08d5 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeTriggers.java
@@ -107,9 +107,17 @@
     }
 
     private void onNotification() {
-        if (DozeMachine.DEBUG) Log.d(TAG, "requestNotificationPulse");
+        if (DozeMachine.DEBUG) {
+            Log.d(TAG, "requestNotificationPulse");
+        }
+        if (!sWakeDisplaySensorState) {
+            Log.d(TAG, "Wake display false. Pulse denied.");
+            return;
+        }
         mNotificationPulseTime = SystemClock.elapsedRealtime();
-        if (!mConfig.pulseOnNotificationEnabled(UserHandle.USER_CURRENT)) return;
+        if (!mConfig.pulseOnNotificationEnabled(UserHandle.USER_CURRENT)) {
+            return;
+        }
         requestPulse(DozeLog.PULSE_REASON_NOTIFICATION, false /* performedProxCheck */);
         DozeLog.traceNotificationPulse(mContext);
     }
@@ -216,15 +224,21 @@
         if (state == DozeMachine.State.DOZE_PULSING
                 || state == DozeMachine.State.DOZE_PULSING_BRIGHT) {
             boolean ignoreTouch = near;
-            if (DEBUG) Log.i(TAG, "Prox changed, ignore touch = " + ignoreTouch);
+            if (DEBUG) {
+                Log.i(TAG, "Prox changed, ignore touch = " + ignoreTouch);
+            }
             mDozeHost.onIgnoreTouchWhilePulsing(ignoreTouch);
         }
 
         if (far && (paused || pausing)) {
-            if (DEBUG) Log.i(TAG, "Prox FAR, unpausing AOD");
+            if (DEBUG) {
+                Log.i(TAG, "Prox FAR, unpausing AOD");
+            }
             mMachine.requestState(DozeMachine.State.DOZE_AOD);
         } else if (near && aod) {
-            if (DEBUG) Log.i(TAG, "Prox NEAR, pausing AOD");
+            if (DEBUG) {
+                Log.i(TAG, "Prox NEAR, pausing AOD");
+            }
             mMachine.requestState(DozeMachine.State.DOZE_AOD_PAUSING);
         }
     }
@@ -282,6 +296,7 @@
             case DOZE_AOD:
                 mDozeSensors.setProxListening(newState != DozeMachine.State.DOZE);
                 mDozeSensors.setListening(true);
+                mDozeSensors.setPaused(false);
                 if (newState == DozeMachine.State.DOZE_AOD && !sWakeDisplaySensorState) {
                     onWakeScreen(false, newState);
                 }
@@ -289,12 +304,13 @@
             case DOZE_AOD_PAUSED:
             case DOZE_AOD_PAUSING:
                 mDozeSensors.setProxListening(true);
-                mDozeSensors.setListening(false);
+                mDozeSensors.setPaused(true);
                 break;
             case DOZE_PULSING:
             case DOZE_PULSING_BRIGHT:
                 mDozeSensors.setTouchscreenSensorsListening(false);
                 mDozeSensors.setProxListening(true);
+                mDozeSensors.setPaused(false);
                 break;
             case DOZE_PULSE_DONE:
                 mDozeSensors.requestTemporaryDisable();
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
index 0635231..5136682 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java
@@ -52,6 +52,7 @@
 import com.android.systemui.R;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.policy.NextAlarmController;
 import com.android.systemui.statusbar.policy.NextAlarmControllerImpl;
@@ -103,8 +104,8 @@
     private final Date mCurrentTime = new Date();
     private final Handler mHandler;
     private final AlarmManager.OnAlarmListener mUpdateNextAlarm = this::updateNextAlarm;
-    private final HashSet<Integer> mMediaInvisibleStates;
     private final Object mMediaToken = new Object();
+    private DozeParameters mDozeParameters;
     @VisibleForTesting
     protected SettableWakeLock mMediaWakeLock;
     @VisibleForTesting
@@ -184,11 +185,6 @@
         mAlarmUri = Uri.parse(KEYGUARD_NEXT_ALARM_URI);
         mDndUri = Uri.parse(KEYGUARD_DND_URI);
         mMediaUri = Uri.parse(KEYGUARD_MEDIA_URI);
-
-        mMediaInvisibleStates = new HashSet<>();
-        mMediaInvisibleStates.add(PlaybackState.STATE_NONE);
-        mMediaInvisibleStates.add(PlaybackState.STATE_STOPPED);
-        mMediaInvisibleStates.add(PlaybackState.STATE_PAUSED);
     }
 
     /**
@@ -201,12 +197,14 @@
     public void initDependencies(
             NotificationMediaManager mediaManager,
             StatusBarStateController statusBarStateController,
-            KeyguardBypassController keyguardBypassController) {
+            KeyguardBypassController keyguardBypassController,
+            DozeParameters dozeParameters) {
         mMediaManager = mediaManager;
         mMediaManager.addCallback(this);
         mStatusBarStateController = statusBarStateController;
         mStatusBarStateController.addCallback(this);
         mKeyguardBypassController = keyguardBypassController;
+        mDozeParameters = dozeParameters;
     }
 
     @AnyThread
@@ -231,9 +229,9 @@
     }
 
     protected boolean needsMediaLocked() {
-        boolean isBypass = mKeyguardBypassController != null
-                && mKeyguardBypassController.getBypassEnabled();
-        return !TextUtils.isEmpty(mMediaTitle) && mMediaIsVisible && (mDozing || isBypass);
+        boolean keepWhenAwake = mKeyguardBypassController != null
+                && mKeyguardBypassController.getBypassEnabled() && mDozeParameters.getAlwaysOn();
+        return !TextUtils.isEmpty(mMediaTitle) && mMediaIsVisible && (mDozing || keepWhenAwake);
     }
 
     protected void addMediaLocked(ListBuilder listBuilder) {
@@ -458,7 +456,7 @@
     @Override
     public void onMetadataOrStateChanged(MediaMetadata metadata, @PlaybackState.State int state) {
         synchronized (this) {
-            boolean nextVisible = !mMediaInvisibleStates.contains(state);
+            boolean nextVisible = NotificationMediaManager.isPlayingState(state);
             mHandler.removeCallbacksAndMessages(mMediaToken);
             if (mMediaIsVisible && !nextVisible) {
                 // We need to delay this event for a few millis when stopping to avoid jank in the
@@ -477,7 +475,7 @@
     }
 
     private void updateMediaStateLocked(MediaMetadata metadata, @PlaybackState.State int state) {
-        boolean nextVisible = !mMediaInvisibleStates.contains(state);
+        boolean nextVisible = NotificationMediaManager.isPlayingState(state);
         CharSequence title = null;
         if (metadata != null) {
             title = metadata.getText(MediaMetadata.METADATA_KEY_TITLE);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
index b9fb1a1..21f5812 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipMenuActivity.java
@@ -239,9 +239,8 @@
         });
         mDismissButton = findViewById(R.id.dismiss);
         mDismissButton.setAlpha(0);
-        mDismissButton.setOnClickListener((v) -> {
-            dismissPip();
-        });
+        mDismissButton.setOnClickListener(v -> dismissPip());
+        findViewById(R.id.expand_button).setOnClickListener(v -> expandPip());
         mActionsGroup = findViewById(R.id.actions_group);
         mBetweenActionPaddingLand = getResources().getDimensionPixelSize(
                 R.dimen.pip_between_action_padding_land);
diff --git a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
index 99f9e99..ed6f599 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/OverviewProxyService.java
@@ -119,7 +119,7 @@
     private boolean mIsEnabled;
     private int mCurrentBoundedUserId = -1;
     private float mNavBarButtonAlpha;
-    private MotionEvent mStatusBarGestureDownEvent;
+    private boolean mInputFocusTransferStarted;
     private float mWindowCornerRadius;
     private boolean mSupportsRoundedCornersOnWindows;
     private int mNavBarMode = NAV_BAR_MODE_3BUTTON;
@@ -164,6 +164,7 @@
             }
         }
 
+        // TODO: change the method signature to use (boolean inputFocusTransferStarted)
         @Override
         public void onStatusBarMotionEvent(MotionEvent event) {
             if (!verifyCaller("onStatusBarMotionEvent")) {
@@ -175,16 +176,16 @@
                 mHandler.post(()->{
                     StatusBar bar = SysUiServiceProvider.getComponent(mContext, StatusBar.class);
                     if (bar != null) {
-                        bar.dispatchNotificationsPanelTouchEvent(event);
 
                         int action = event.getActionMasked();
                         if (action == ACTION_DOWN) {
-                            mStatusBarGestureDownEvent = MotionEvent.obtain(event);
+                            mInputFocusTransferStarted = true;
+
                         }
                         if (action == ACTION_UP || action == ACTION_CANCEL) {
-                            mStatusBarGestureDownEvent.recycle();
-                            mStatusBarGestureDownEvent = null;
+                            mInputFocusTransferStarted = false;
                         }
+                        bar.onInputFocusTransfer(mInputFocusTransferStarted);
                         event.recycle();
                     }
                 });
@@ -590,14 +591,12 @@
     }
 
     public void cleanupAfterDeath() {
-        if (mStatusBarGestureDownEvent != null) {
+        if (mInputFocusTransferStarted) {
             mHandler.post(()-> {
                 StatusBar bar = SysUiServiceProvider.getComponent(mContext, StatusBar.class);
                 if (bar != null) {
-                    mStatusBarGestureDownEvent.setAction(MotionEvent.ACTION_CANCEL);
-                    bar.dispatchNotificationsPanelTouchEvent(mStatusBarGestureDownEvent);
-                    mStatusBarGestureDownEvent.recycle();
-                    mStatusBarGestureDownEvent = null;
+                    mInputFocusTransferStarted = false;
+                    bar.onInputFocusTransfer(false);
                 }
             });
         }
@@ -782,6 +781,7 @@
         pw.println(QuickStepContract.isBackGestureDisabled(mSysUiStateFlags));
         pw.print("    assistantGestureDisabled=");
         pw.println(QuickStepContract.isAssistantGestureDisabled(mSysUiStateFlags));
+        pw.print(" mInputFocusTransferStarted="); pw.println(mInputFocusTransferStarted);
     }
 
     public interface OverviewProxyListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
index a59d590..f001561 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMediaManager.java
@@ -69,6 +69,7 @@
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
@@ -91,6 +92,14 @@
     private final SysuiColorExtractor mColorExtractor = Dependency.get(SysuiColorExtractor.class);
     private final KeyguardMonitor mKeyguardMonitor = Dependency.get(KeyguardMonitor.class);
     private final KeyguardBypassController mKeyguardBypassController;
+    private static final HashSet<Integer> PAUSED_MEDIA_STATES = new HashSet<>();
+    static {
+        PAUSED_MEDIA_STATES.add(PlaybackState.STATE_NONE);
+        PAUSED_MEDIA_STATES.add(PlaybackState.STATE_STOPPED);
+        PAUSED_MEDIA_STATES.add(PlaybackState.STATE_PAUSED);
+        PAUSED_MEDIA_STATES.add(PlaybackState.STATE_ERROR);
+    }
+
 
     // Late binding
     private NotificationEntryManager mEntryManager;
@@ -207,6 +216,10 @@
                 mPropertiesChangedListener);
     }
 
+    public static boolean isPlayingState(int state) {
+        return !PAUSED_MEDIA_STATES.contains(state);
+    }
+
     public void setUpWithPresenter(NotificationPresenter presenter) {
         mPresenter = presenter;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 0a8b7f8..4ccd0cd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -18,6 +18,7 @@
 
 import static com.android.systemui.Interpolators.FAST_OUT_SLOW_IN_REVERSE;
 import static com.android.systemui.statusbar.phone.NotificationIconContainer.IconState.NO_VALUE;
+import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
 
 import android.content.Context;
 import android.content.res.Configuration;
@@ -48,8 +49,12 @@
 import com.android.systemui.statusbar.notification.stack.ExpandableViewState;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.notification.stack.ViewState;
+import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.NotificationIconContainer;
 
+import javax.inject.Inject;
+import javax.inject.Named;
+
 /**
  * A notification shelf view that is placed inside the notification scroller. It manages the
  * overflow icons that don't fit into the regular list anymore.
@@ -63,6 +68,7 @@
             = SystemProperties.getBoolean("debug.icon_scroll_animations", true);
     private static final int TAG_CONTINUOUS_CLIPPING = R.id.continuous_clipping_tag;
     private static final String TAG = "NotificationShelf";
+    private final KeyguardBypassController mBypassController;
 
     private NotificationIconContainer mShelfIcons;
     private int[] mTmp = new int[2];
@@ -93,8 +99,12 @@
     private int mCutoutHeight;
     private int mGapHeight;
 
-    public NotificationShelf(Context context, AttributeSet attrs) {
+    @Inject
+    public NotificationShelf(@Named(VIEW_CONTEXT) Context context,
+            AttributeSet attrs,
+            KeyguardBypassController keyguardBypassController) {
         super(context, attrs);
+        mBypassController = keyguardBypassController;
     }
 
     @Override
@@ -309,7 +319,10 @@
                     colorTwoBefore = previousColor;
                     transitionAmount = inShelfAmount;
                 }
-                if (isLastChild) {
+                // We don't want to modify the color if the notification is hun'd
+                boolean canModifyColor = mAmbientState.isShadeExpanded()
+                        && !(mAmbientState.isOnKeyguard() && mBypassController.getBypassEnabled());
+                if (isLastChild && canModifyColor) {
                     if (colorOfViewBeforeLast == NO_COLOR) {
                         colorOfViewBeforeLast = ownColorUntinted;
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/BypassHeadsUpNotifier.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/BypassHeadsUpNotifier.kt
new file mode 100644
index 0000000..ea474ce
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/BypassHeadsUpNotifier.kt
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification
+
+import android.content.Context
+import android.media.MediaMetadata
+import android.provider.Settings
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.statusbar.NotificationMediaManager
+import com.android.systemui.statusbar.StatusBarState
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.phone.HeadsUpManagerPhone
+import com.android.systemui.statusbar.phone.KeyguardBypassController
+import com.android.systemui.tuner.TunerService
+import javax.inject.Inject
+import javax.inject.Singleton
+
+/**
+ * A class that automatically creates heads up for important notification when bypassing the
+ * lockscreen
+ */
+@Singleton
+class BypassHeadsUpNotifier @Inject constructor(
+        private val context: Context,
+        private val bypassController: KeyguardBypassController,
+        private val statusBarStateController: StatusBarStateController,
+        private val headsUpManager: HeadsUpManagerPhone,
+        private val mediaManager: NotificationMediaManager,
+        tunerService: TunerService) : StatusBarStateController.StateListener,
+        NotificationMediaManager.MediaListener {
+
+    private lateinit var entryManager: NotificationEntryManager
+    private var currentMediaEntry: NotificationEntry? = null
+    private var enabled = true
+
+    var fullyAwake = false
+        set(value) {
+            field = value
+            if (value) {
+                updateAutoHeadsUp(currentMediaEntry)
+            }
+        }
+
+    init {
+        statusBarStateController.addCallback(this)
+        tunerService.addTunable(
+                TunerService.Tunable { _, _ ->
+                    enabled = Settings.Secure.getIntForUser(
+                            context.contentResolver,
+                            Settings.Secure.SHOW_MEDIA_WHEN_BYPASSING,
+                            1 /* default */,
+                            KeyguardUpdateMonitor.getCurrentUser()) != 0
+                }, Settings.Secure.SHOW_MEDIA_WHEN_BYPASSING)
+    }
+
+    fun setUp(entryManager: NotificationEntryManager) {
+        this.entryManager = entryManager
+        mediaManager.addCallback(this)
+    }
+
+    override fun onMetadataOrStateChanged(metadata: MediaMetadata?, state: Int) {
+        val previous = currentMediaEntry
+        var newEntry = entryManager.notificationData.get(mediaManager.mediaNotificationKey)
+        if (!NotificationMediaManager.isPlayingState(state)) {
+            newEntry = null
+        }
+        if (newEntry?.isSensitive == true) {
+            newEntry = null
+        }
+        currentMediaEntry = newEntry
+        updateAutoHeadsUp(previous)
+        updateAutoHeadsUp(currentMediaEntry)
+    }
+
+    private fun updateAutoHeadsUp(entry: NotificationEntry?) {
+        entry?.let {
+            val autoHeadsUp = it == currentMediaEntry && canAutoHeadsUp()
+            it.isAutoHeadsUp = autoHeadsUp
+            if (autoHeadsUp) {
+                headsUpManager.showNotification(it)
+            }
+        }
+    }
+
+    override fun onStatePostChange() {
+        updateAutoHeadsUp(currentMediaEntry)
+    }
+
+    private fun canAutoHeadsUp() : Boolean {
+        if (!enabled) {
+            return false
+        }
+        if (!bypassController.bypassEnabled) {
+            return false
+        }
+        if (statusBarStateController.state != StatusBarState.KEYGUARD) {
+            return false
+        }
+        if (!fullyAwake) {
+            return false
+        }
+        return true
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
index 8a23f71..d71d407 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationAlertingManager.java
@@ -24,7 +24,6 @@
 import android.util.Log;
 
 import com.android.internal.statusbar.NotificationVisibility;
-import com.android.systemui.statusbar.AlertingNotificationManager;
 import com.android.systemui.statusbar.NotificationListener;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -119,12 +118,11 @@
         shouldAlert = mNotificationInterruptionStateProvider.shouldHeadsUp(entry);
         final boolean wasAlerting = mHeadsUpManager.isAlerting(entry.key);
         if (wasAlerting) {
-            if (!shouldAlert) {
-                // We don't want this to be interrupting anymore, let's remove it
-                mHeadsUpManager.removeNotification(entry.key,
-                        false /* ignoreEarliestRemovalTime */);
-            } else {
+            if (shouldAlert) {
                 mHeadsUpManager.updateNotification(entry.key, alertAgain);
+            } else if (!mHeadsUpManager.isEntryAutoHeadsUpped(entry.key)) {
+                // We don't want this to be interrupting anymore, let's remove it
+                mHeadsUpManager.removeNotification(entry.key, false /* removeImmediately */);
             }
         } else if (shouldAlert && alertAgain) {
             // This notification was updated to be alerting, show it!
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
index 1aa6bc9..dfc6450 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryListener.java
@@ -24,6 +24,8 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.NotificationContentInflater.InflationFlag;
 
+import androidx.annotation.NonNull;
+
 /**
  * Listener interface for changes sent by NotificationEntryManager.
  */
@@ -45,7 +47,7 @@
     /**
      * Called when a new entry is created.
      */
-    default void onNotificationAdded(NotificationEntry entry) {
+    default void onNotificationAdded(@NonNull NotificationEntry entry) {
     }
 
     /**
@@ -61,7 +63,7 @@
     /**
      * Called when a notification was updated, after any filtering of notifications have occurred.
      */
-    default void onPostEntryUpdated(NotificationEntry entry) {
+    default void onPostEntryUpdated(@NonNull NotificationEntry entry) {
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 9db715d..b19d2ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -175,6 +175,7 @@
     private boolean mHighPriority;
     private boolean mSensitive = true;
     private Runnable mOnSensitiveChangedListener;
+    private boolean mAutoHeadsUp;
 
     public NotificationEntry(StatusBarNotification n) {
         this(n, null);
@@ -670,11 +671,25 @@
         if (row != null) row.setHeadsUp(shouldHeadsUp);
     }
 
-
     public void setHeadsUpAnimatingAway(boolean animatingAway) {
         if (row != null) row.setHeadsUpAnimatingAway(animatingAway);
     }
 
+    /**
+     * Set that this notification was automatically heads upped. This happens for example when
+     * the user bypasses the lockscreen and media is playing.
+     */
+    public void setAutoHeadsUp(boolean autoHeadsUp) {
+        mAutoHeadsUp = autoHeadsUp;
+    }
+
+    /**
+     * @return if this notification was automatically heads upped. This happens for example when
+     *      * the user bypasses the lockscreen and media is playing.
+     */
+    public boolean isAutoHeadsUp() {
+        return mAutoHeadsUp;
+    }
 
     public boolean mustStayOnScreen() {
         return row != null && row.mustStayOnScreen();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index ae534d2..a8327f6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -2698,6 +2698,8 @@
                 l.setAlpha(1.0f);
                 l.setLayerType(LAYER_TYPE_NONE, null);
             }
+        } else {
+            setHeadsUpAnimatingAway(false);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index e2cb8d4..58e6399 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -837,7 +837,13 @@
                 break;
             }
         }
-        if (!mAmbientState.isDozing() || anySectionHasVisibleChild) {
+        boolean shouldDrawBackground;
+        if (mKeyguardBypassController.getBypassEnabled() && onKeyguard()) {
+            shouldDrawBackground = isPulseExpanding();
+        } else {
+            shouldDrawBackground = !mAmbientState.isDozing() || anySectionHasVisibleChild;
+        }
+        if (shouldDrawBackground) {
             drawBackgroundRects(canvas, left, right, top, backgroundTopAnimationOffset);
         }
 
@@ -3396,10 +3402,20 @@
         for (Pair<ExpandableNotificationRow, Boolean> eventPair : mHeadsUpChangeAnimations) {
             ExpandableNotificationRow row = eventPair.first;
             boolean isHeadsUp = eventPair.second;
+            if (isHeadsUp != row.isHeadsUp()) {
+                // For cases where we have a heads up showing and appearing again we shouldn't
+                // do the animations at all.
+                continue;
+            }
             int type = AnimationEvent.ANIMATION_TYPE_HEADS_UP_OTHER;
             boolean onBottom = false;
             boolean pinnedAndClosed = row.isPinned() && !mIsExpanded;
-            if (!mIsExpanded && !isHeadsUp) {
+            boolean performDisappearAnimation = !mIsExpanded
+                    // Only animate if we still have pinned heads up, otherwise we just have the
+                    // regular collapse animation of the lock screen
+                    || (mKeyguardBypassController.getBypassEnabled() && onKeyguard()
+                            && mHeadsUpManager.hasPinnedHeadsUp());
+            if (performDisappearAnimation && !isHeadsUp) {
                 type = row.wasJustClicked()
                         ? AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR_CLICK
                         : AnimationEvent.ANIMATION_TYPE_HEADS_UP_DISAPPEAR;
@@ -6246,6 +6262,15 @@
             mAmbientState.onDragFinished(animView);
             updateContinuousShadowDrawing();
             updateContinuousBackgroundDrawing();
+            if (animView instanceof ExpandableNotificationRow) {
+                ExpandableNotificationRow row = (ExpandableNotificationRow) animView;
+                if (row.isPinned() && !canChildBeDismissed(row)
+                        && row.getStatusBarNotification().getNotification().fullScreenIntent
+                                == null) {
+                    mHeadsUpManager.removeNotification(row.getStatusBarNotification().getKey(),
+                            true /* removeImmediately */);
+                }
+            }
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 09c6968..35ba801 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -546,12 +546,12 @@
                 ExpandableViewState topState =
                         topHeadsUpEntry == null ? null : topHeadsUpEntry.getViewState();
                 if (topState != null && !isTopEntry && (!mIsExpanded
-                        || unmodifiedEndLocation < topState.yTranslation + topState.height)) {
+                        || unmodifiedEndLocation > topState.yTranslation + topState.height)) {
                     // Ensure that a headsUp doesn't vertically extend further than the heads-up at
                     // the top most z-position
                     childState.height = row.getIntrinsicHeight();
-                    childState.yTranslation = topState.yTranslation + topState.height
-                            - childState.height;
+                    childState.yTranslation = Math.min(topState.yTranslation + topState.height
+                            - childState.height, childState.yTranslation);
                 }
 
                 // heads up notification show and this row is the top entry of heads up
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
index 4f169eb..0996ff2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
@@ -28,6 +28,7 @@
 import com.android.systemui.R;
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.StatusBarIconView;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.ExpandableView;
 
@@ -451,7 +452,11 @@
                     if (row.isDismissed()) {
                         needsAnimation = false;
                     }
-                    StatusBarIconView icon = row.getEntry().icon;
+                    NotificationEntry entry = row.getEntry();
+                    StatusBarIconView icon = entry.icon;
+                    if (entry.centeredIcon != null && entry.centeredIcon.getParent() != null) {
+                        icon = entry.centeredIcon;
+                    }
                     if (icon.getParent() != null) {
                         icon.getLocationOnScreen(mTmpLocation);
                         float iconPosition = mTmpLocation[0] - icon.getTranslationX()
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
index 89bd1b6..10b48e7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeParameters.java
@@ -22,9 +22,7 @@
 import android.os.SystemProperties;
 import android.os.UserHandle;
 import android.provider.Settings;
-import android.text.TextUtils;
 import android.util.MathUtils;
-import android.util.SparseBooleanArray;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.systemui.Dependency;
@@ -41,13 +39,11 @@
 public class DozeParameters implements TunerService.Tunable,
         com.android.systemui.plugins.statusbar.DozeParameters {
     private static final int MAX_DURATION = 60 * 1000;
-    public static final String DOZE_SENSORS_WAKE_UP_FULLY = "doze_sensors_wake_up_fully";
     public static final boolean FORCE_NO_BLANKING =
             SystemProperties.getBoolean("debug.force_no_blanking", false);
     public static final boolean FORCE_BLANKING =
             SystemProperties.getBoolean("debug.force_blanking", false);
 
-    private static IntInOutMatcher sPickupSubtypePerformsProxMatcher;
     private static DozeParameters sInstance;
 
     private final Context mContext;
@@ -92,20 +88,6 @@
         pw.print("    getVibrateOnPickup(): "); pw.println(getVibrateOnPickup());
         pw.print("    getProxCheckBeforePulse(): "); pw.println(getProxCheckBeforePulse());
         pw.print("    getPickupVibrationThreshold(): "); pw.println(getPickupVibrationThreshold());
-        pw.print("    getPickupSubtypePerformsProxCheck(): ");pw.println(
-                dumpPickupSubtypePerformsProxCheck());
-    }
-
-    private String dumpPickupSubtypePerformsProxCheck() {
-        // Refresh sPickupSubtypePerformsProxMatcher
-        getPickupSubtypePerformsProxCheck(0);
-
-        if (sPickupSubtypePerformsProxMatcher == null) {
-            return "fallback: " + mContext.getResources().getBoolean(
-                    R.bool.doze_pickup_performs_proximity_check);
-        } else {
-            return "spec: " + sPickupSubtypePerformsProxMatcher.mSpec;
-        }
     }
 
     public boolean getDisplayStateSupported() {
@@ -225,21 +207,8 @@
         return SystemProperties.get(propName, mContext.getString(resId));
     }
 
-    public boolean getPickupSubtypePerformsProxCheck(int subType) {
-        String spec = getString("doze.pickup.proxcheck",
-                R.string.doze_pickup_subtype_performs_proximity_check);
-
-        if (TextUtils.isEmpty(spec)) {
-            // Fall back to non-subtype based property.
-            return mContext.getResources().getBoolean(R.bool.doze_pickup_performs_proximity_check);
-        }
-
-        if (sPickupSubtypePerformsProxMatcher == null
-                || !TextUtils.equals(spec, sPickupSubtypePerformsProxMatcher.mSpec)) {
-            sPickupSubtypePerformsProxMatcher = new IntInOutMatcher(spec);
-        }
-
-        return sPickupSubtypePerformsProxMatcher.isIn(subType);
+    public boolean getPickupPerformsProxCheck() {
+        return mContext.getResources().getBoolean(R.bool.doze_pickup_performs_proximity_check);
     }
 
     public int getPulseVisibleDurationExtended() {
@@ -258,81 +227,4 @@
     public AlwaysOnDisplayPolicy getPolicy() {
         return mAlwaysOnPolicy;
     }
-
-    /**
-     * Parses a spec of the form `1,2,3,!5,*`. The resulting object will match numbers that are
-     * listed, will not match numbers that are listed with a ! prefix, and will match / not match
-     * unlisted numbers depending on whether * or !* is present.
-     *
-     * *  -> match any numbers that are not explicitly listed
-     * !* -> don't match any numbers that are not explicitly listed
-     * 2  -> match 2
-     * !3 -> don't match 3
-     *
-     * It is illegal to specify:
-     * - an empty spec
-     * - a spec containing that are empty, or a lone !
-     * - a spec for anything other than numbers or *
-     * - multiple terms for the same number / multiple *s
-     */
-    public static class IntInOutMatcher {
-        private static final String WILDCARD = "*";
-        private static final char OUT_PREFIX = '!';
-
-        private final SparseBooleanArray mIsIn;
-        private final boolean mDefaultIsIn;
-        final String mSpec;
-
-        public IntInOutMatcher(String spec) {
-            if (TextUtils.isEmpty(spec)) {
-                throw new IllegalArgumentException("Spec must not be empty");
-            }
-
-            boolean defaultIsIn = false;
-            boolean foundWildcard = false;
-
-            mSpec = spec;
-            mIsIn = new SparseBooleanArray();
-
-            for (String itemPrefixed : spec.split(",", -1)) {
-                if (itemPrefixed.length() == 0) {
-                    throw new IllegalArgumentException(
-                            "Illegal spec, must not have zero-length items: `" + spec + "`");
-                }
-                boolean isIn = itemPrefixed.charAt(0) != OUT_PREFIX;
-                String item = isIn ? itemPrefixed : itemPrefixed.substring(1);
-
-                if (itemPrefixed.length() == 0) {
-                    throw new IllegalArgumentException(
-                            "Illegal spec, must not have zero-length items: `" + spec + "`");
-                }
-
-                if (WILDCARD.equals(item)) {
-                    if (foundWildcard) {
-                        throw new IllegalArgumentException("Illegal spec, `" + WILDCARD +
-                                "` must not appear multiple times in `" + spec + "`");
-                    }
-                    defaultIsIn = isIn;
-                    foundWildcard = true;
-                } else {
-                    int key = Integer.parseInt(item);
-                    if (mIsIn.indexOfKey(key) >= 0) {
-                        throw new IllegalArgumentException("Illegal spec, `" + key +
-                                "` must not appear multiple times in `" + spec + "`");
-                    }
-                    mIsIn.put(key, isIn);
-                }
-            }
-
-            if (!foundWildcard) {
-                throw new IllegalArgumentException("Illegal spec, must specify either * or !*");
-            }
-
-            mDefaultIsIn = defaultIsIn;
-        }
-
-        public boolean isIn(int value) {
-            return (mIsIn.get(value, mDefaultIsIn));
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index ade855e..c44f953 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -32,7 +32,6 @@
 import androidx.collection.ArraySet;
 
 import com.android.internal.annotations.VisibleForTesting;
-import com.android.systemui.Dependency;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.ScreenDecorations;
@@ -67,6 +66,7 @@
     final int mExtensionTime;
     private final StatusBarStateController mStatusBarStateController;
     private final KeyguardBypassController mBypassController;
+    private final int mAutoHeadsUpNotificationDecay;
     private View mStatusBarWindowView;
     private NotificationGroupManager mGroupManager;
     private VisualStabilityManager mVisualStabilityManager;
@@ -81,6 +81,7 @@
     private boolean mTrackingHeadsUp;
     private HashSet<String> mSwipedOutKeys = new HashSet<>();
     private HashSet<NotificationEntry> mEntriesToRemoveAfterExpand = new HashSet<>();
+    private HashSet<String> mKeysToRemoveWhenLeavingKeyguard = new HashSet<>();
     private ArraySet<NotificationEntry> mEntriesToRemoveWhenReorderingAllowed
             = new ArraySet<>();
     private boolean mIsExpanded;
@@ -121,6 +122,8 @@
         mAutoDismissNotificationDecayDozing = resources.getInteger(
                 R.integer.heads_up_notification_decay_dozing);
         mExtensionTime = resources.getInteger(R.integer.ambient_notification_extension_time);
+        mAutoHeadsUpNotificationDecay = resources.getInteger(
+                R.integer.auto_heads_up_notification_decay);
         mStatusBarStateController = statusBarStateController;
         mStatusBarStateController.addCallback(this);
         mBypassController = bypassController;
@@ -231,7 +234,16 @@
 
     @Override
     public void onStateChanged(int newState) {
+        boolean wasKeyguard = mStatusBarState == StatusBarState.KEYGUARD;
+        boolean isKeyguard = newState == StatusBarState.KEYGUARD;
         mStatusBarState = newState;
+        if (wasKeyguard && !isKeyguard && mKeysToRemoveWhenLeavingKeyguard.size() != 0) {
+            String[] keys = mKeysToRemoveWhenLeavingKeyguard.toArray(new String[0]);
+            for (String key : keys) {
+                removeAlertEntry(key);
+            }
+            mKeysToRemoveWhenLeavingKeyguard.clear();
+        }
     }
 
     @Override
@@ -245,6 +257,15 @@
         }
     }
 
+    @Override
+    public boolean isEntryAutoHeadsUpped(String key) {
+        HeadsUpEntryPhone headsUpEntryPhone = getHeadsUpEntryPhone(key);
+        if (headsUpEntryPhone == null) {
+            return false;
+        }
+        return headsUpEntryPhone.isAutoHeadsUp();
+    }
+
     /**
      * Set that we are exiting the headsUp pinned mode, but some notifications might still be
      * animating out. This is used to keep the touchable regions in a sane state.
@@ -420,6 +441,7 @@
 
     @Override
     protected void onAlertEntryRemoved(AlertEntry alertEntry) {
+        mKeysToRemoveWhenLeavingKeyguard.remove(alertEntry.mEntry.key);
         super.onAlertEntryRemoved(alertEntry);
         mEntryPool.release((HeadsUpEntryPhone) alertEntry);
     }
@@ -479,6 +501,11 @@
          */
         private boolean extended;
 
+        /**
+         * Was this entry received while on keyguard
+         */
+        private boolean mIsAutoHeadsUp;
+
 
         @Override
         protected boolean isSticky() {
@@ -494,10 +521,12 @@
                     mEntriesToRemoveWhenReorderingAllowed.add(entry);
                     mVisualStabilityManager.addReorderingAllowedCallback(
                             HeadsUpManagerPhone.this);
-                } else if (!mTrackingHeadsUp) {
-                    removeAlertEntry(entry.key);
-                } else {
+                } else if (mTrackingHeadsUp) {
                     mEntriesToRemoveAfterExpand.add(entry);
+                } else if (mIsAutoHeadsUp && mStatusBarState == StatusBarState.KEYGUARD) {
+                    mKeysToRemoveWhenLeavingKeyguard.add(entry.key);
+                } else {
+                    removeAlertEntry(entry.key);
                 }
             };
 
@@ -506,6 +535,7 @@
 
         @Override
         public void updateEntry(boolean updatePostTime) {
+            mIsAutoHeadsUp = mEntry.isAutoHeadsUp();
             super.updateEntry(updatePostTime);
 
             if (mEntriesToRemoveAfterExpand.contains(mEntry)) {
@@ -514,6 +544,7 @@
             if (mEntriesToRemoveWhenReorderingAllowed.contains(mEntry)) {
                 mEntriesToRemoveWhenReorderingAllowed.remove(mEntry);
             }
+            mKeysToRemoveWhenLeavingKeyguard.remove(mEntry.key);
         }
 
         @Override
@@ -548,6 +579,7 @@
             super.reset();
             mMenuShownPinned = false;
             extended = false;
+            mIsAutoHeadsUp = false;
         }
 
         private void extendPulse() {
@@ -558,13 +590,35 @@
         }
 
         @Override
+        public int compareTo(AlertEntry alertEntry) {
+            HeadsUpEntryPhone headsUpEntry = (HeadsUpEntryPhone) alertEntry;
+            boolean autoShown = isAutoHeadsUp();
+            boolean otherAutoShown = headsUpEntry.isAutoHeadsUp();
+            if (autoShown && !otherAutoShown) {
+                return 1;
+            } else if (!autoShown && otherAutoShown) {
+                return -1;
+            }
+            return super.compareTo(alertEntry);
+        }
+
+        @Override
         protected long calculateFinishTime() {
             return mPostTime + getDecayDuration() + (extended ? mExtensionTime : 0);
         }
 
         private int getDecayDuration() {
-            return mStatusBarStateController.isDozing() ? mAutoDismissNotificationDecayDozing
-                    : getRecommendedHeadsUpTimeoutMs();
+            if (mStatusBarStateController.isDozing()) {
+                return mAutoDismissNotificationDecayDozing;
+            } else if (isAutoHeadsUp()) {
+                return getRecommendedHeadsUpTimeoutMs(mAutoHeadsUpNotificationDecay);
+            } else {
+                return getRecommendedHeadsUpTimeoutMs(mAutoDismissNotificationDecay);
+            }
+        }
+
+        private boolean isAutoHeadsUp() {
+            return mIsAutoHeadsUp;
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
new file mode 100644
index 0000000..f4635d1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardLiftController.kt
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone
+
+import android.content.Context
+import android.hardware.Sensor
+import android.hardware.TriggerEvent
+import android.hardware.TriggerEventListener
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.keyguard.KeyguardUpdateMonitorCallback
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.util.Assert
+import com.android.systemui.util.AsyncSensorManager
+
+class KeyguardLiftController constructor(
+    context: Context,
+    private val statusBarStateController: StatusBarStateController,
+    private val asyncSensorManager: AsyncSensorManager
+) : StatusBarStateController.StateListener, KeyguardUpdateMonitorCallback() {
+
+    private val keyguardUpdateMonitor = KeyguardUpdateMonitor.getInstance(context)
+    private val pickupSensor = asyncSensorManager.getDefaultSensor(Sensor.TYPE_PICK_UP_GESTURE)
+    private var isListening = false
+    private var bouncerVisible = false
+
+    init {
+        statusBarStateController.addCallback(this)
+        keyguardUpdateMonitor.registerCallback(this)
+        updateListeningState()
+    }
+
+    private val listener: TriggerEventListener = object : TriggerEventListener() {
+        override fun onTrigger(event: TriggerEvent?) {
+            Assert.isMainThread()
+            // Not listening anymore since trigger events unregister themselves
+            isListening = false
+            updateListeningState()
+            keyguardUpdateMonitor.requestFaceAuth()
+        }
+    }
+
+    override fun onDozingChanged(isDozing: Boolean) {
+        updateListeningState()
+    }
+
+    override fun onKeyguardBouncerChanged(bouncer: Boolean) {
+        bouncerVisible = bouncer
+        updateListeningState()
+    }
+
+    override fun onKeyguardVisibilityChanged(showing: Boolean) {
+        updateListeningState()
+    }
+
+    private fun updateListeningState() {
+        val onKeyguard = keyguardUpdateMonitor.isKeyguardVisible &&
+                !statusBarStateController.isDozing
+
+        val shouldListen = onKeyguard || bouncerVisible
+        if (shouldListen != isListening) {
+            isListening = shouldListen
+
+            if (shouldListen) {
+                asyncSensorManager.requestTriggerSensor(listener, pickupSensor)
+            } else {
+                asyncSensorManager.cancelTriggerSensor(listener, pickupSensor)
+            }
+        }
+    }
+}
\ No newline at end of file
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 ca001c6..ea434fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockIcon.java
@@ -16,7 +16,6 @@
 
 package com.android.systemui.statusbar.phone;
 
-import static com.android.systemui.Dependency.MAIN_HANDLER_NAME;
 import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
 
 import android.annotation.IntDef;
@@ -29,12 +28,12 @@
 import android.graphics.drawable.AnimatedVectorDrawable;
 import android.graphics.drawable.Drawable;
 import android.hardware.biometrics.BiometricSourceType;
-import android.os.Handler;
 import android.os.Trace;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.view.ViewGroup;
+import android.view.ViewTreeObserver;
 import android.view.accessibility.AccessibilityNodeInfo;
 
 import androidx.annotation.Nullable;
@@ -43,6 +42,7 @@
 import com.android.internal.telephony.IccCardConstants;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.systemui.Interpolators;
 import com.android.systemui.R;
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -53,6 +53,7 @@
 import com.android.systemui.statusbar.policy.AccessibilityController;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardMonitor;
+import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
 import com.android.systemui.statusbar.policy.UserInfoController.OnUserInfoChangedListener;
 
 import java.lang.annotation.Retention;
@@ -67,7 +68,8 @@
 public class LockIcon extends KeyguardAffordanceView implements OnUserInfoChangedListener,
         StatusBarStateController.StateListener, ConfigurationController.ConfigurationListener,
         UnlockMethodCache.OnUnlockMethodChangedListener,
-        NotificationWakeUpCoordinator.WakeUpListener {
+        NotificationWakeUpCoordinator.WakeUpListener, ViewTreeObserver.OnPreDrawListener,
+        OnHeadsUpChangedListener {
 
     private static final int STATE_LOCKED = 0;
     private static final int STATE_LOCK_OPEN = 1;
@@ -79,12 +81,13 @@
     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     private final AccessibilityController mAccessibilityController;
     private final DockManager mDockManager;
-    private final Handler mMainHandler;
     private final KeyguardMonitor mKeyguardMonitor;
     private final KeyguardBypassController mBypassController;
     private final NotificationWakeUpCoordinator mWakeUpCoordinator;
+    private final HeadsUpManagerPhone mHeadsUpManager;
 
     private int mLastState = 0;
+    private boolean mForceUpdate;
     private boolean mTransientBiometricsError;
     private boolean mIsFaceUnlockState;
     private boolean mSimLocked;
@@ -92,23 +95,20 @@
     private boolean mPulsing;
     private boolean mDozing;
     private boolean mDocked;
-    private boolean mLastDozing;
-    private boolean mLastPulsing;
     private int mIconColor;
     private float mDozeAmount;
-    private int mIconRes;
-    private boolean mBouncerShowing;
-    private boolean mWasPulsingOnThisFrame;
+    private boolean mBouncerShowingScrimmed;
     private boolean mWakeAndUnlockRunning;
     private boolean mKeyguardShowing;
     private boolean mShowingLaunchAffordance;
+    private boolean mUpdatePending;
 
     private final KeyguardMonitor.Callback mKeyguardMonitorCallback =
             new KeyguardMonitor.Callback() {
                 @Override
                 public void onKeyguardShowingChanged() {
                     mKeyguardShowing = mKeyguardMonitor.isShowing();
-                    update(false /* force */);
+                    update();
                 }
             };
     private final DockManager.DockEventListener mDockEventListener =
@@ -119,7 +119,7 @@
                             || event == DockManager.STATE_DOCKED_HIDE;
                     if (docked != mDocked) {
                         mDocked = docked;
-                        update(true /* force */);
+                        update();
                     }
         }
     };
@@ -129,9 +129,8 @@
                 @Override
                 public void onSimStateChanged(int subId, int slotId,
                         IccCardConstants.State simState) {
-                    boolean oldSimLocked = mSimLocked;
                     mSimLocked = mKeyguardUpdateMonitor.isSimPinSecure();
-                    update(oldSimLocked != mSimLocked);
+                    update();
                 }
 
                 @Override
@@ -149,11 +148,6 @@
                 public void onStrongAuthStateChanged(int userId) {
                     update();
                 }
-
-                @Override
-                public void onBiometricsCleared() {
-                    update();
-                }
     };
 
     @Inject
@@ -165,7 +159,7 @@
             NotificationWakeUpCoordinator wakeUpCoordinator,
             KeyguardMonitor keyguardMonitor,
             @Nullable DockManager dockManager,
-            @Named(MAIN_HANDLER_NAME) Handler mainHandler) {
+            HeadsUpManagerPhone headsUpManager) {
         super(context, attrs);
         mContext = context;
         mUnlockMethodCache = UnlockMethodCache.getInstance(context);
@@ -177,7 +171,7 @@
         mWakeUpCoordinator = wakeUpCoordinator;
         mKeyguardMonitor = keyguardMonitor;
         mDockManager = dockManager;
-        mMainHandler = mainHandler;
+        mHeadsUpManager = headsUpManager;
     }
 
     @Override
@@ -194,6 +188,7 @@
             mDockManager.addListener(mDockEventListener);
         }
         onThemeChanged();
+        update();
     }
 
     @Override
@@ -247,63 +242,92 @@
     }
 
     public void update(boolean force) {
-        int state = getState();
-        mIsFaceUnlockState = state == STATE_SCANNING_FACE;
-        if (state != mLastState || mLastDozing != mDozing || mLastPulsing != mPulsing || force) {
-            @LockAnimIndex final int lockAnimIndex = getAnimationIndexForTransition(mLastState,
-                    state, mLastPulsing, mPulsing, mLastDozing, mDozing);
-            boolean isAnim = lockAnimIndex != -1;
-
-            int iconRes = isAnim ? getThemedAnimationResId(lockAnimIndex) : getIconForState(state);
-            if (iconRes != mIconRes) {
-                mIconRes = iconRes;
-
-                Drawable icon = mContext.getDrawable(iconRes);
-                final AnimatedVectorDrawable animation = icon instanceof AnimatedVectorDrawable
-                        ? (AnimatedVectorDrawable) icon
-                        : null;
-                setImageDrawable(icon, false);
-                if (mIsFaceUnlockState) {
-                    announceForAccessibility(getContext().getString(
-                            R.string.accessibility_scanning_face));
-                }
-
-                if (animation != null && isAnim) {
-                    animation.forceAnimationOnUI();
-                    animation.clearAnimationCallbacks();
-                    animation.registerAnimationCallback(new Animatable2.AnimationCallback() {
-                        @Override
-                        public void onAnimationEnd(Drawable drawable) {
-                            if (getDrawable() == animation && state == getState()
-                                    && doesAnimationLoop(lockAnimIndex)) {
-                                animation.start();
-                            } else {
-                                Trace.endAsyncSection("LockIcon#Animation", state);
-                            }
-                        }
-                    });
-                    Trace.beginAsyncSection("LockIcon#Animation", state);
-                    animation.start();
-                }
-            }
-            updateDarkTint();
-
-            mLastState = state;
-            mLastDozing = mDozing;
-            mLastPulsing = mPulsing;
+        if (force) {
+            mForceUpdate = true;
         }
+        if (!mUpdatePending) {
+            mUpdatePending = true;
+            getViewTreeObserver().addOnPreDrawListener(this);
+        }
+    }
+
+    @Override
+    public boolean onPreDraw() {
+        mUpdatePending = false;
+        getViewTreeObserver().removeOnPreDrawListener(this);
+
+        int state = getState();
+        int lastState = mLastState;
+        mIsFaceUnlockState = state == STATE_SCANNING_FACE;
+        mLastState = state;
+
+        if (lastState != state || mForceUpdate) {
+            mForceUpdate = false;
+            @LockAnimIndex final int lockAnimIndex = getAnimationIndexForTransition(lastState,
+                    state, mPulsing, mDozing);
+            boolean isAnim = lockAnimIndex != -1;
+            int iconRes = isAnim ? getThemedAnimationResId(lockAnimIndex) : getIconForState(state);
+
+            Drawable icon = mContext.getDrawable(iconRes);
+            final AnimatedVectorDrawable animation = icon instanceof AnimatedVectorDrawable
+                    ? (AnimatedVectorDrawable) icon
+                    : null;
+            setImageDrawable(icon, false);
+            if (mIsFaceUnlockState) {
+                announceForAccessibility(getContext().getString(
+                        R.string.accessibility_scanning_face));
+            }
+
+            if (animation != null && isAnim) {
+                animation.forceAnimationOnUI();
+                animation.clearAnimationCallbacks();
+                animation.registerAnimationCallback(new Animatable2.AnimationCallback() {
+                    @Override
+                    public void onAnimationEnd(Drawable drawable) {
+                        if (getDrawable() == animation && state == getState()
+                                && doesAnimationLoop(lockAnimIndex)) {
+                            animation.start();
+                        } else {
+                            Trace.endAsyncSection("LockIcon#Animation", state);
+                        }
+                    }
+                });
+                Trace.beginAsyncSection("LockIcon#Animation", state);
+                animation.start();
+            }
+        }
+        updateDarkTint();
 
         boolean onAodNotPulsingOrDocked = mDozing && (!mPulsing || mDocked);
         boolean invisible = onAodNotPulsingOrDocked || mWakeAndUnlockRunning
                 || mShowingLaunchAffordance;
-        if (mBypassController.getBypassEnabled()
-                && mStatusBarStateController.getState() == StatusBarState.KEYGUARD
-                && !mWakeUpCoordinator.getNotificationsFullyHidden()
-                && !mBouncerShowing) {
-            invisible = true;
+        if (mBypassController.getBypassEnabled() && !mBouncerShowingScrimmed) {
+            if (mHeadsUpManager.isHeadsUpGoingAway()
+                    || mHeadsUpManager.hasPinnedHeadsUp()
+                    || (mStatusBarStateController.getState() == StatusBarState.KEYGUARD
+                    && !mWakeUpCoordinator.getNotificationsFullyHidden())) {
+                invisible = true;
+            }
         }
-        setVisibility(invisible ? INVISIBLE : VISIBLE);
+        boolean wasInvisible = getVisibility() == INVISIBLE;
+        if (invisible != wasInvisible) {
+            setVisibility(invisible ? INVISIBLE : VISIBLE);
+            animate().cancel();
+            if (!invisible) {
+                setScaleX(0);
+                setScaleY(0);
+                animate()
+                        .setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN)
+                        .scaleX(1)
+                        .scaleY(1)
+                        .withLayer()
+                        .setDuration(233)
+                        .start();
+            }
+        }
         updateClickability();
+
+        return true;
     }
 
     private void updateClickability() {
@@ -364,30 +388,22 @@
         return lockAnimIndex == SCANNING;
     }
 
-    private int getAnimationIndexForTransition(int oldState, int newState,
-            boolean wasPulsing, boolean pulsing, boolean wasDozing, boolean dozing) {
+    private static int getAnimationIndexForTransition(int oldState, int newState, boolean pulsing,
+            boolean dozing) {
 
         // Never animate when screen is off
-        if (dozing && !pulsing && !mWasPulsingOnThisFrame) {
+        if (dozing && !pulsing) {
             return -1;
         }
 
-        boolean isError = oldState != STATE_BIOMETRICS_ERROR && newState == STATE_BIOMETRICS_ERROR;
-        boolean justUnlocked = oldState != STATE_LOCK_OPEN && newState == STATE_LOCK_OPEN;
-        boolean justLocked = oldState == STATE_LOCK_OPEN && newState == STATE_LOCKED;
-        boolean nowPulsing = !wasPulsing && pulsing;
-        boolean turningOn = wasDozing && !dozing && !mWasPulsingOnThisFrame;
-
-        if (isError) {
+        if (newState == STATE_BIOMETRICS_ERROR) {
             return ERROR;
-        } else if (justUnlocked) {
+        } else if (oldState != STATE_LOCK_OPEN && newState == STATE_LOCK_OPEN) {
             return UNLOCK;
-        } else if (justLocked) {
+        } else if (oldState == STATE_LOCK_OPEN && newState == STATE_LOCKED) {
             return LOCK;
         } else if (newState == STATE_SCANNING_FACE) {
             return SCANNING;
-        } else if ((nowPulsing || turningOn) && newState != STATE_LOCK_OPEN) {
-            return LOCK_IN;
         }
         return -1;
     }
@@ -399,45 +415,41 @@
         }
     }
 
-    public void setBouncerShowing(boolean bouncerShowing) {
-        mBouncerShowing = bouncerShowing;
+    public void setBouncerShowingScrimmed(boolean bouncerShowing) {
+        mBouncerShowingScrimmed = bouncerShowing;
         if (mBypassController.getBypassEnabled()) {
             update();
         }
     }
 
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef({ERROR, UNLOCK, LOCK, SCANNING, LOCK_IN})
+    @IntDef({ERROR, UNLOCK, LOCK, SCANNING})
     @interface LockAnimIndex {}
-    private static final int ERROR = 0, UNLOCK = 1, LOCK = 2, SCANNING = 3, LOCK_IN = 4;
+    private static final int ERROR = 0, UNLOCK = 1, LOCK = 2, SCANNING = 3;
     private static final int[][] LOCK_ANIM_RES_IDS = new int[][] {
             {
                     R.anim.lock_to_error,
                     R.anim.lock_unlock,
                     R.anim.lock_lock,
-                    R.anim.lock_scanning,
-                    R.anim.lock_in,
+                    R.anim.lock_scanning
             },
             {
                     R.anim.lock_to_error_circular,
                     R.anim.lock_unlock_circular,
                     R.anim.lock_lock_circular,
-                    R.anim.lock_scanning_circular,
-                    R.anim.lock_in_circular,
+                    R.anim.lock_scanning_circular
             },
             {
                     R.anim.lock_to_error_filled,
                     R.anim.lock_unlock_filled,
                     R.anim.lock_lock_filled,
-                    R.anim.lock_scanning_filled,
-                    R.anim.lock_in_filled,
+                    R.anim.lock_scanning_filled
             },
             {
                     R.anim.lock_to_error_rounded,
                     R.anim.lock_unlock_rounded,
                     R.anim.lock_lock_rounded,
-                    R.anim.lock_scanning_rounded,
-                    R.anim.lock_in_rounded,
+                    R.anim.lock_scanning_rounded
             },
     };
 
@@ -462,7 +474,7 @@
             return STATE_LOCK_OPEN;
         } else if (mTransientBiometricsError) {
             return STATE_BIOMETRICS_ERROR;
-        } else if (updateMonitor.isFaceDetectionRunning()) {
+        } else if (updateMonitor.isFaceDetectionRunning() && !mPulsing) {
             return STATE_SCANNING_FACE;
         } else {
             return STATE_LOCKED;
@@ -481,12 +493,6 @@
      */
     public void setPulsing(boolean pulsing) {
         mPulsing = pulsing;
-        if (!mPulsing) {
-            mWasPulsingOnThisFrame = true;
-            mMainHandler.post(() -> {
-                mWasPulsingOnThisFrame = false;
-            });
-        }
         update();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
index cd97722..d2159ca 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationIconAreaController.java
@@ -248,7 +248,7 @@
         if (onlyShowCenteredIcon) {
             return isCenteredNotificationIcon;
         }
-        if (hideCenteredIcon && isCenteredNotificationIcon) {
+        if (hideCenteredIcon && isCenteredNotificationIcon && !entry.isRowHeadsUp()) {
             return false;
         }
         if (mEntryManager.getNotificationData().isAmbient(entry.key) && !showAmbient) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index 32dc96d..53ce167 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -290,6 +290,8 @@
     private boolean mIsFullWidth;
     private boolean mBlockingExpansionForCurrentTouch;
 
+    private boolean mExpectingOpenPanelGesture;
+
     /**
      * Current dark amount that follows regular interpolation curve of animation.
      */
@@ -1246,6 +1248,28 @@
         }
     }
 
+    /**
+     * Input focus transfer is about to happen.
+     */
+    public void startWaitingForOpenPanelGesture() {
+        if (!isFullyCollapsed()) {
+            return;
+        }
+        mExpectingOpenPanelGesture = true;
+        onTrackingStarted();
+    }
+
+    /**
+     * Input focus transfer has already happened as this view decided to intercept
+     * very first down event.
+     */
+    public void stopWaitingForOpenPanelGesture() {
+        if (mExpectingOpenPanelGesture) {
+            mExpectingOpenPanelGesture = false;
+            onTrackingStopped(false);
+        }
+    }
+
     @Override
     protected boolean flingExpands(float vel, float vectorVel, float x, float y) {
         boolean expands = super.flingExpands(vel, vectorVel, x, y);
@@ -1258,8 +1282,12 @@
     }
 
     @Override
-    protected boolean hasConflictingGestures() {
-        return mBarState != StatusBarState.SHADE;
+    protected boolean shouldGestureWaitForTouchSlop() {
+        if (mExpectingOpenPanelGesture) {
+            mExpectingOpenPanelGesture = false;
+            return false;
+        }
+        return isFullyCollapsed() || mBarState != StatusBarState.SHADE;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index a9a3b2d..a5b221b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -301,7 +301,7 @@
         final float y = event.getY(pointerIndex);
 
         if (event.getActionMasked() == MotionEvent.ACTION_DOWN) {
-            mGestureWaitForTouchSlop = isFullyCollapsed() || hasConflictingGestures();
+            mGestureWaitForTouchSlop = shouldGestureWaitForTouchSlop();
             mIgnoreXTouchSlop = isFullyCollapsed() || shouldGestureIgnoreXTouchSlop(x, y);
         }
 
@@ -519,7 +519,7 @@
         return (int) (mUnlockFalsingThreshold * factor);
     }
 
-    protected abstract boolean hasConflictingGestures();
+    protected abstract boolean shouldGestureWaitForTouchSlop();
 
     protected abstract boolean shouldGestureIgnoreXTouchSlop(float x, float y);
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 7db4afc..e756d3a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -80,6 +80,7 @@
 import android.net.Uri;
 import android.os.AsyncTask;
 import android.os.Bundle;
+import android.os.Debug;
 import android.os.Handler;
 import android.os.Looper;
 import android.os.Message;
@@ -193,6 +194,7 @@
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.VibratorHelper;
 import com.android.systemui.statusbar.notification.ActivityLaunchAnimator;
+import com.android.systemui.statusbar.notification.BypassHeadsUpNotifier;
 import com.android.systemui.statusbar.notification.NotificationActivityStarter;
 import com.android.systemui.statusbar.notification.NotificationAlertingManager;
 import com.android.systemui.statusbar.notification.NotificationClicker;
@@ -373,6 +375,11 @@
     KeyguardBypassController mKeyguardBypassController;
     @Inject
     protected HeadsUpManagerPhone mHeadsUpManager;
+    @Inject
+    BypassHeadsUpNotifier mBypassHeadsUpNotifier;
+    @Nullable
+    @Inject
+    protected KeyguardLiftController mKeyguardLiftController;
 
     // expanded notifications
     protected NotificationPanelView mNotificationPanel; // the sliding/resizing panel within the notification window
@@ -630,6 +637,7 @@
         mGutsManager = Dependency.get(NotificationGutsManager.class);
         mMediaManager = Dependency.get(NotificationMediaManager.class);
         mEntryManager = Dependency.get(NotificationEntryManager.class);
+        mBypassHeadsUpNotifier.setUp(mEntryManager);
         mNotificationInterruptionStateProvider =
                 Dependency.get(NotificationInterruptionStateProvider.class);
         mViewHierarchyManager = Dependency.get(NotificationViewHierarchyManager.class);
@@ -646,7 +654,7 @@
         KeyguardSliceProvider sliceProvider = KeyguardSliceProvider.getAttachedInstance();
         if (sliceProvider != null) {
             sliceProvider.initDependencies(mMediaManager, mStatusBarStateController,
-                    mKeyguardBypassController);
+                    mKeyguardBypassController, DozeParameters.getInstance(mContext));
         } else {
             Log.w(TAG, "Cannot init KeyguardSliceProvider dependencies");
         }
@@ -1151,8 +1159,9 @@
 
     private void inflateShelf() {
         mNotificationShelf =
-                (NotificationShelf) LayoutInflater.from(mContext).inflate(
-                        R.layout.status_bar_notification_shelf, mStackScroller, false);
+                (NotificationShelf) mInjectionInflater.injectable(
+                        LayoutInflater.from(mContext)).inflate(
+                                R.layout.status_bar_notification_shelf, mStackScroller, false);
         mNotificationShelf.setOnClickListener(mGoToLockedShadeListener);
     }
 
@@ -1918,19 +1927,18 @@
         mStatusBarKeyguardViewManager.readyForKeyguardDone();
     }
 
-    public void dispatchNotificationsPanelTouchEvent(MotionEvent ev) {
+    /**
+     * Called when another window is about to transfer it's input focus.
+     */
+    public void onInputFocusTransfer(boolean start) {
         if (!mCommandQueue.panelsEnabled()) {
             return;
         }
-        mNotificationPanel.dispatchTouchEvent(ev);
 
-        int action = ev.getAction();
-        if (action == MotionEvent.ACTION_DOWN) {
-            // Start ignoring all touch events coming to status bar window.
-            // TODO: handle case where ACTION_UP is not sent over the binder
-            mStatusBarWindowController.setNotTouchable(true);
-        } else if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
-            mStatusBarWindowController.setNotTouchable(false);
+        if (start) {
+            mNotificationPanel.startWaitingForOpenPanelGesture();
+        } else {
+            mNotificationPanel.stopWaitingForOpenPanelGesture();
         }
     }
 
@@ -3574,7 +3582,7 @@
         mBouncerShowing = bouncerShowing;
         mKeyguardBypassController.setBouncerShowing(bouncerShowing);
         mPulseExpansionHandler.setBouncerShowing(bouncerShowing);
-        mStatusBarWindow.setBouncerShowing(bouncerShowing);
+        mStatusBarWindow.setBouncerShowingScrimmed(isBouncerShowingScrimmed());
         if (mStatusBarView != null) mStatusBarView.setBouncerShowing(bouncerShowing);
         updateHideIconsForBouncer(true /* animate */);
         mCommandQueue.recomputeDisableFlags(mDisplayId, true /* animate */);
@@ -3627,6 +3635,7 @@
             notifyHeadsUpGoingToSleep();
             dismissVolumeDialog();
             mWakeUpCoordinator.setFullyAwake(false);
+            mBypassHeadsUpNotifier.setFullyAwake(false);
             mKeyguardBypassController.onStartedGoingToSleep();
         }
 
@@ -3651,6 +3660,7 @@
         @Override
         public void onFinishedWakingUp() {
             mWakeUpCoordinator.setFullyAwake(true);
+            mBypassHeadsUpNotifier.setFullyAwake(true);
             mWakeUpCoordinator.setWakingUp(false);
             if (mLaunchCameraWhenFinishedWaking) {
                 mNotificationPanel.launchCamera(false /* animate */, mLastCameraLaunchSource);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index a82e14e..667521b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -525,9 +525,9 @@
         mBypassController = bypassController;
     }
 
-    public void setBouncerShowing(boolean bouncerShowing) {
+    public void setBouncerShowingScrimmed(boolean bouncerShowing) {
         if (mLockIcon != null) {
-            mLockIcon.setBouncerShowing(bouncerShowing);
+            mLockIcon.setBouncerShowingScrimmed(bouncerShowing);
         }
     }
 
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 78eb394..f36c56f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockMethodCache.java
@@ -190,6 +190,11 @@
         public void onKeyguardVisibilityChanged(boolean showing) {
             update(false /* updateAlways */);
         }
+
+        @Override
+        public void onBiometricsCleared() {
+            update(false /* alwaysUpdate */);
+        }
     };
 
     public boolean isTrustManaged() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index 40d5e4d..b84dc47 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -356,6 +356,10 @@
     public void onDensityOrFontScaleChanged() {
     }
 
+    public boolean isEntryAutoHeadsUpped(String key) {
+        return false;
+    }
+
     /**
      * This represents a notification and how long it is in a heads up mode. It also manages its
      * lifecycle automatically when created.
@@ -416,16 +420,17 @@
 
         @Override
         protected long calculateFinishTime() {
-            return mPostTime + getRecommendedHeadsUpTimeoutMs();
+            return mPostTime + getRecommendedHeadsUpTimeoutMs(mAutoDismissNotificationDecay);
         }
 
         /**
          * Get user-preferred or default timeout duration. The larger one will be returned.
          * @return milliseconds before auto-dismiss
+         * @param requestedTimeout
          */
-        protected int getRecommendedHeadsUpTimeoutMs() {
+        protected int getRecommendedHeadsUpTimeoutMs(int requestedTimeout) {
             return mAccessibilityMgr.getRecommendedTimeoutMillis(
-                    mAutoDismissNotificationDecay,
+                    requestedTimeout,
                     AccessibilityManager.FLAG_CONTENT_CONTROLS
                             | AccessibilityManager.FLAG_CONTENT_ICONS
                             | AccessibilityManager.FLAG_CONTENT_TEXT);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
index 13f93b9..b21ba09 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/MobileSignalController.java
@@ -376,9 +376,9 @@
     }
 
     private void updateDataSim() {
-        int defaultDataSub = mDefaults.getDefaultDataSubId();
-        if (SubscriptionManager.isValidSubscriptionId(defaultDataSub)) {
-            mCurrentState.dataSim = defaultDataSub == mSubscriptionInfo.getSubscriptionId();
+        int activeDataSubId = mDefaults.getActiveDataSubId();
+        if (SubscriptionManager.isValidSubscriptionId(activeDataSubId)) {
+            mCurrentState.dataSim = activeDataSubId == mSubscriptionInfo.getSubscriptionId();
         } else {
             // There doesn't seem to be a data sim selected, however if
             // there isn't a MobileSignalController with dataSim set, then
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
index b2972fc..d545dc8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/NetworkControllerImpl.java
@@ -361,7 +361,7 @@
     }
 
     private MobileSignalController getDataController() {
-        int dataSubId = mSubDefaults.getDefaultDataSubId();
+        int dataSubId = mSubDefaults.getActiveDataSubId();
         if (!SubscriptionManager.isValidSubscriptionId(dataSubId)) {
             if (DEBUG) Log.e(TAG, "No data sim selected");
             return mDefaultSignalController;
@@ -1098,6 +1098,10 @@
         public int getDefaultDataSubId() {
             return SubscriptionManager.getDefaultDataSubscriptionId();
         }
+
+        public int getActiveDataSubId() {
+            return SubscriptionManager.getActiveDataSubscriptionId();
+        }
     }
 
     @VisibleForTesting
diff --git a/packages/SystemUI/src/com/android/systemui/util/AsyncSensorManager.java b/packages/SystemUI/src/com/android/systemui/util/AsyncSensorManager.java
index 31f4991..b9c5ee5 100644
--- a/packages/SystemUI/src/com/android/systemui/util/AsyncSensorManager.java
+++ b/packages/SystemUI/src/com/android/systemui/util/AsyncSensorManager.java
@@ -156,17 +156,21 @@
      * Requests for all sensors that match the given type from all plugins.
      * @param sensor
      * @param listener
+     * @return true if there were plugins to register the listener to
      */
-    public void registerPluginListener(SensorManagerPlugin.Sensor sensor,
+    public boolean registerPluginListener(SensorManagerPlugin.Sensor sensor,
             SensorManagerPlugin.SensorEventListener listener) {
         if (mPlugins.isEmpty()) {
             Log.w(TAG, "No plugins registered");
+            return false;
         }
         mHandler.post(() -> {
             for (int i = 0; i < mPlugins.size(); i++) {
                 mPlugins.get(i).registerListener(sensor, listener);
             }
         });
+
+        return true;
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
index d521e55..ede3004 100644
--- a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
+++ b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
@@ -32,6 +32,7 @@
 import com.android.systemui.qs.QSPanel;
 import com.android.systemui.qs.QuickQSPanel;
 import com.android.systemui.qs.QuickStatusBarHeader;
+import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.phone.LockIcon;
 import com.android.systemui.statusbar.phone.NotificationPanelView;
@@ -138,6 +139,11 @@
         QSCarrierGroup createQSCarrierGroup();
 
         /**
+         * Creates the Shelf.
+         */
+        NotificationShelf creatNotificationShelf();
+
+        /**
          * Creates the KeyguardClockSwitch.
          */
         KeyguardClockSwitch createKeyguardClockSwitch();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
index 9438cbb..2d6ae26 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeConfigurationUtil.java
@@ -36,7 +36,7 @@
         when(params.getPulseOnSigMotion()).thenReturn(false);
         when(params.getPickupVibrationThreshold()).thenReturn(0);
         when(params.getProxCheckBeforePulse()).thenReturn(true);
-        when(params.getPickupSubtypePerformsProxCheck(anyInt())).thenReturn(true);
+        when(params.getPickupPerformsProxCheck()).thenReturn(true);
         when(params.getPolicy()).thenReturn(mock(AlwaysOnDisplayPolicy.class));
         when(params.doubleTapReportsTouchCoordinates()).thenReturn(false);
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
index 3304291..7df45a3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeSensorsTest.java
@@ -23,6 +23,7 @@
 import static org.mockito.ArgumentMatchers.anyFloat;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
@@ -77,7 +78,9 @@
     @Mock
     private AlwaysOnDisplayPolicy mAlwaysOnDisplayPolicy;
     @Mock
-    private TriggerSensor mMockTriggerSensor;
+    private TriggerSensor mTriggerSensor;
+    @Mock
+    private TriggerSensor mProxGatedTriggerSensor;
     private SensorManagerPlugin.SensorEventListener mWakeLockScreenListener;
     private TestableLooper mTestableLooper;
     private DozeSensors mDozeSensors;
@@ -85,6 +88,7 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        when(mProxGatedTriggerSensor.performsProxCheck()).thenReturn(true);
         mTestableLooper = TestableLooper.get(this);
         when(mAmbientDisplayConfiguration.getWakeLockScreenDebounce()).thenReturn(5000L);
         when(mAmbientDisplayConfiguration.alwaysOnEnabled(anyInt())).thenReturn(true);
@@ -114,21 +118,34 @@
 
     @Test
     public void testSetListening_firstTrue_registerSettingsObserver() {
-        mDozeSensors.mSensors = new TriggerSensor[] {mMockTriggerSensor};
-
         mDozeSensors.setListening(true);
 
-        verify(mMockTriggerSensor).registerSettingsObserver(any(ContentObserver.class));
+        verify(mTriggerSensor).registerSettingsObserver(any(ContentObserver.class));
     }
 
     @Test
     public void testSetListening_twiceTrue_onlyRegisterSettingsObserverOnce() {
-        mDozeSensors.mSensors = new TriggerSensor[] {mMockTriggerSensor};
+        mDozeSensors.setListening(true);
         mDozeSensors.setListening(true);
 
-        mDozeSensors.setListening(true);
+        verify(mTriggerSensor, times(1)).registerSettingsObserver(any(ContentObserver.class));
+    }
 
-        verify(mMockTriggerSensor, times(1)).registerSettingsObserver(any(ContentObserver.class));
+    @Test
+    public void testSetPaused_onlyPausesNonGatedSensors() {
+        mDozeSensors.setListening(true);
+        verify(mTriggerSensor).setListening(eq(true));
+        verify(mProxGatedTriggerSensor).setListening(eq(true));
+
+        clearInvocations(mTriggerSensor, mProxGatedTriggerSensor);
+        mDozeSensors.setPaused(true);
+        verify(mTriggerSensor).setListening(eq(false));
+        verify(mProxGatedTriggerSensor).setListening(eq(true));
+
+        clearInvocations(mTriggerSensor, mProxGatedTriggerSensor);
+        mDozeSensors.setPaused(false);
+        verify(mTriggerSensor).setListening(eq(true));
+        verify(mProxGatedTriggerSensor).setListening(eq(true));
     }
 
     private class TestableDozeSensors extends DozeSensors {
@@ -144,6 +161,7 @@
                     mWakeLockScreenListener = (PluginSensor) sensor;
                 }
             }
+            mSensors = new TriggerSensor[] {mTriggerSensor, mProxGatedTriggerSensor};
         }
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
index bf06794..893f3d1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardSliceProviderTest.java
@@ -48,6 +48,7 @@
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.NotificationMediaManager;
+import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.policy.ZenModeController;
 import com.android.systemui.util.wakelock.SettableWakeLock;
@@ -84,6 +85,8 @@
     private SettableWakeLock mMediaWakeLock;
     @Mock
     private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
+    @Mock
+    private DozeParameters mDozeParameters;
     private TestableKeyguardSliceProvider mProvider;
     private boolean mIsZenMode;
 
@@ -94,7 +97,7 @@
         mProvider = new TestableKeyguardSliceProvider();
         mProvider.attachInfo(getContext(), null);
         mProvider.initDependencies(mNotificationMediaManager, mStatusBarStateController,
-                mKeyguardBypassController);
+                mKeyguardBypassController, mDozeParameters);
         SliceProvider.setSpecs(new HashSet<>(Arrays.asList(SliceSpecs.LIST)));
     }
 
@@ -130,6 +133,7 @@
         MediaMetadata metadata = mock(MediaMetadata.class);
         when(metadata.getText(any())).thenReturn("metadata");
         when(mKeyguardBypassController.getBypassEnabled()).thenReturn(true);
+        when(mDozeParameters.getAlwaysOn()).thenReturn(true);
         mProvider.onMetadataOrStateChanged(metadata, PlaybackState.STATE_PLAYING);
         mProvider.onBindSlice(mProvider.getUri());
         verify(metadata).getText(eq(MediaMetadata.METADATA_KEY_TITLE));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
index f6f4eb48..60050b1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/DozeParametersTest.java
@@ -16,10 +16,6 @@
 
 package com.android.systemui.statusbar.phone;
 
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
-import static junit.framework.Assert.fail;
-
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.reset;
@@ -33,7 +29,6 @@
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.doze.DozeScreenState;
-import com.android.systemui.statusbar.phone.DozeParameters.IntInOutMatcher;
 
 import org.junit.Assert;
 import org.junit.Test;
@@ -44,160 +39,6 @@
 public class DozeParametersTest extends SysuiTestCase {
 
     @Test
-    public void test_inOutMatcher_defaultIn() {
-        IntInOutMatcher intInOutMatcher = new IntInOutMatcher("*");
-
-        assertTrue(intInOutMatcher.isIn(1));
-        assertTrue(intInOutMatcher.isIn(-1));
-        assertTrue(intInOutMatcher.isIn(0));
-    }
-
-    @Test
-    public void test_inOutMatcher_defaultOut() {
-        IntInOutMatcher intInOutMatcher = new IntInOutMatcher("!*");
-
-        assertFalse(intInOutMatcher.isIn(1));
-        assertFalse(intInOutMatcher.isIn(-1));
-        assertFalse(intInOutMatcher.isIn(0));
-    }
-
-    @Test
-    public void test_inOutMatcher_someIn() {
-        IntInOutMatcher intInOutMatcher = new IntInOutMatcher("1,2,3,!*");
-
-        assertTrue(intInOutMatcher.isIn(1));
-        assertTrue(intInOutMatcher.isIn(2));
-        assertTrue(intInOutMatcher.isIn(3));
-
-        assertFalse(intInOutMatcher.isIn(0));
-        assertFalse(intInOutMatcher.isIn(4));
-    }
-
-    @Test
-    public void test_inOutMatcher_someOut() {
-        IntInOutMatcher intInOutMatcher = new IntInOutMatcher("!1,!2,!3,*");
-
-        assertFalse(intInOutMatcher.isIn(1));
-        assertFalse(intInOutMatcher.isIn(2));
-        assertFalse(intInOutMatcher.isIn(3));
-
-        assertTrue(intInOutMatcher.isIn(0));
-        assertTrue(intInOutMatcher.isIn(4));
-    }
-
-    @Test
-    public void test_inOutMatcher_mixed() {
-        IntInOutMatcher intInOutMatcher = new IntInOutMatcher("!1,2,!3,*");
-
-        assertFalse(intInOutMatcher.isIn(1));
-        assertTrue(intInOutMatcher.isIn(2));
-        assertFalse(intInOutMatcher.isIn(3));
-
-        assertTrue(intInOutMatcher.isIn(0));
-        assertTrue(intInOutMatcher.isIn(4));
-    }
-
-    @Test
-    public void test_inOutMatcher_failEmpty() {
-        try {
-            new IntInOutMatcher("");
-            fail("Expected IllegalArgumentException");
-        } catch (IllegalArgumentException e) {
-            // expected
-        }
-    }
-
-    @Test
-    public void test_inOutMatcher_failNull() {
-        try {
-            new IntInOutMatcher(null);
-            fail("Expected IllegalArgumentException");
-        } catch (IllegalArgumentException e) {
-            // expected
-        }
-    }
-
-    @Test
-    public void test_inOutMatcher_failEmptyClause() {
-        try {
-            new IntInOutMatcher("!1,*,");
-            fail("Expected IllegalArgumentException");
-        } catch (IllegalArgumentException e) {
-            // expected
-        }
-    }
-
-    @Test
-    public void test_inOutMatcher_failDuplicate() {
-        try {
-            new IntInOutMatcher("!1,*,!1");
-            fail("Expected IllegalArgumentException");
-        } catch (IllegalArgumentException e) {
-            // expected
-        }
-    }
-
-    @Test
-    public void test_inOutMatcher_failDuplicateDefault() {
-        try {
-            new IntInOutMatcher("!1,*,*");
-            fail("Expected IllegalArgumentException");
-        } catch (IllegalArgumentException e) {
-            // expected
-        }
-    }
-
-    @Test
-    public void test_inOutMatcher_failMalformedNot() {
-        try {
-            new IntInOutMatcher("!,*");
-            fail("Expected IllegalArgumentException");
-        } catch (IllegalArgumentException e) {
-            // expected
-        }
-    }
-
-    @Test
-    public void test_inOutMatcher_failText() {
-        try {
-            new IntInOutMatcher("!abc,*");
-            fail("Expected IllegalArgumentException");
-        } catch (IllegalArgumentException e) {
-            // expected
-        }
-    }
-
-    @Test
-    public void test_inOutMatcher_failContradiction() {
-        try {
-            new IntInOutMatcher("1,!1,*");
-            fail("Expected IllegalArgumentException");
-        } catch (IllegalArgumentException e) {
-            // expected
-        }
-    }
-
-    @Test
-    public void test_inOutMatcher_failContradictionDefault() {
-        try {
-            new IntInOutMatcher("1,*,!*");
-            fail("Expected IllegalArgumentException");
-        } catch (IllegalArgumentException e) {
-            // expected
-        }
-    }
-
-    @Test
-    public void test_inOutMatcher_failMissingDefault() {
-        try {
-            new IntInOutMatcher("1");
-            fail("Expected IllegalArgumentException");
-        } catch (IllegalArgumentException e) {
-            // expected
-        }
-    }
-
-    @Test
     public void test_setControlScreenOffAnimation_setsDozeAfterScreenOff_false() {
         TestableDozeParameters dozeParameters = new TestableDozeParameters(getContext());
         PowerManager mockedPowerManager = dozeParameters.getPowerManager();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
index 3464fe5..9ae9ceb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/NetworkControllerBaseTest.java
@@ -181,6 +181,7 @@
     protected void setDefaultSubId(int subId) {
         when(mMockSubDefaults.getDefaultDataSubId()).thenReturn(subId);
         when(mMockSubDefaults.getDefaultVoiceSubId()).thenReturn(subId);
+        when(mMockSubDefaults.getActiveDataSubId()).thenReturn(subId);
     }
 
     protected void setSubscriptions(int... subIds) {
diff --git a/services/autofill/java/com/android/server/autofill/Session.java b/services/autofill/java/com/android/server/autofill/Session.java
index 3764ca4..988db6a 100644
--- a/services/autofill/java/com/android/server/autofill/Session.java
+++ b/services/autofill/java/com/android/server/autofill/Session.java
@@ -2924,6 +2924,7 @@
             if (sVerbose) {
                 Slog.v(TAG, "Adding autofillable view with id " + id + " and state " + state);
             }
+            viewState.setCurrentValue(findValueLocked(id));
             mViewStates.put(id, viewState);
         }
         if ((state & ViewState.STATE_AUTOFILLED) != 0) {
diff --git a/services/autofill/java/com/android/server/autofill/ViewState.java b/services/autofill/java/com/android/server/autofill/ViewState.java
index e1b089c..84886f8 100644
--- a/services/autofill/java/com/android/server/autofill/ViewState.java
+++ b/services/autofill/java/com/android/server/autofill/ViewState.java
@@ -227,6 +227,7 @@
         if (mVirtualBounds != null) {
             builder.append(", virtualBounds:" ).append(mVirtualBounds);
         }
+        builder.append("]");
         return builder.toString();
     }
 
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index f0321c1..4f7900e 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -2579,8 +2579,8 @@
                     if (nai.everConnected) {
                         loge("ERROR: cannot call explicitlySelected on already-connected network");
                     }
-                    nai.networkMisc.explicitlySelected = (msg.arg1 == 1);
-                    nai.networkMisc.acceptUnvalidated = (msg.arg1 == 1) && (msg.arg2 == 1);
+                    nai.networkMisc.explicitlySelected = toBool(msg.arg1);
+                    nai.networkMisc.acceptUnvalidated = toBool(msg.arg1) && toBool(msg.arg2);
                     // Mark the network as temporarily accepting partial connectivity so that it
                     // will be validated (and possibly become default) even if it only provides
                     // partial internet access. Note that if user connects to partial connectivity
@@ -2588,7 +2588,7 @@
                     // out of wifi coverage) and if the same wifi is available again, the device
                     // will auto connect to this wifi even though the wifi has "no internet".
                     // TODO: Evaluate using a separate setting in IpMemoryStore.
-                    nai.networkMisc.acceptPartialConnectivity = (msg.arg2 == 1);
+                    nai.networkMisc.acceptPartialConnectivity = toBool(msg.arg2);
                     break;
                 }
                 case NetworkAgent.EVENT_SOCKET_KEEPALIVE: {
diff --git a/services/core/java/com/android/server/am/LmkdConnection.java b/services/core/java/com/android/server/am/LmkdConnection.java
new file mode 100644
index 0000000..d1e09db
--- /dev/null
+++ b/services/core/java/com/android/server/am/LmkdConnection.java
@@ -0,0 +1,293 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.am;
+
+import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_ERROR;
+import static android.os.MessageQueue.OnFileDescriptorEventListener.EVENT_INPUT;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_AM;
+import static com.android.server.am.ActivityManagerDebugConfig.TAG_WITH_CLASS_NAME;
+
+import android.net.LocalSocket;
+import android.net.LocalSocketAddress;
+import android.os.MessageQueue;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+
+import libcore.io.IoUtils;
+
+import java.io.FileDescriptor;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+import java.util.concurrent.locks.Condition;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Lmkd connection to communicate with lowmemorykiller daemon.
+ */
+public class LmkdConnection {
+    private static final String TAG = TAG_WITH_CLASS_NAME ? "LmkdConnection" : TAG_AM;
+
+    // lmkd reply max size in bytes
+    private static final int LMKD_REPLY_MAX_SIZE = 8;
+
+    // connection listener interface
+    interface LmkdConnectionListener {
+        public boolean onConnect(OutputStream ostream);
+        public void onDisconnect();
+        /**
+         * Check if received reply was expected (reply to an earlier request)
+         *
+         * @param replyBuf The buffer provided in exchange() to receive the reply.
+         *                 It can be used by exchange() caller to store reply-specific
+         *                 tags for later use in isReplyExpected() to verify if
+         *                 received packet is the expected reply.
+         * @param dataReceived The buffer holding received data
+         * @param receivedLen Size of the data received
+         */
+        public boolean isReplyExpected(ByteBuffer replyBuf, ByteBuffer dataReceived,
+            int receivedLen);
+    }
+
+    private final MessageQueue mMsgQueue;
+
+    // lmkd connection listener
+    private final LmkdConnectionListener mListener;
+
+    // mutex to synchronize access to the socket
+    private final Object mLmkdSocketLock = new Object();
+
+    // socket to communicate with lmkd
+    @GuardedBy("mLmkdSocketLock")
+    private LocalSocket mLmkdSocket = null;
+
+    // socket I/O streams
+    @GuardedBy("mLmkdSocketLock")
+    private OutputStream mLmkdOutputStream = null;
+    @GuardedBy("mLmkdSocketLock")
+    private InputStream mLmkdInputStream = null;
+
+    // buffer to store incoming data
+    private final ByteBuffer mInputBuf =
+            ByteBuffer.allocate(LMKD_REPLY_MAX_SIZE);
+
+    // object to protect mReplyBuf and to wait/notify when reply is received
+    private final Object mReplyBufLock = new Object();
+
+    // reply buffer
+    @GuardedBy("mReplyBufLock")
+    private ByteBuffer mReplyBuf = null;
+
+    ////////////////////  END FIELDS  ////////////////////
+
+    LmkdConnection(MessageQueue msgQueue, LmkdConnectionListener listener) {
+        mMsgQueue = msgQueue;
+        mListener = listener;
+    }
+
+    public boolean connect() {
+        synchronized (mLmkdSocketLock) {
+            if (mLmkdSocket != null) {
+                return true;
+            }
+            // temporary sockets and I/O streams
+            final LocalSocket socket = openSocket();
+
+            if (socket == null) {
+                Slog.w(TAG, "Failed to connect to lowmemorykiller, retry later");
+                return false;
+            }
+
+            final OutputStream ostream;
+            final InputStream istream;
+            try {
+                ostream = socket.getOutputStream();
+                istream = socket.getInputStream();
+            } catch (IOException ex) {
+                IoUtils.closeQuietly(socket);
+                return false;
+            }
+            // execute onConnect callback
+            if (mListener != null && !mListener.onConnect(ostream)) {
+                Slog.w(TAG, "Failed to communicate with lowmemorykiller, retry later");
+                IoUtils.closeQuietly(socket);
+                return false;
+            }
+            // connection established
+            mLmkdSocket = socket;
+            mLmkdOutputStream = ostream;
+            mLmkdInputStream = istream;
+            mMsgQueue.addOnFileDescriptorEventListener(mLmkdSocket.getFileDescriptor(),
+                EVENT_INPUT | EVENT_ERROR,
+                new MessageQueue.OnFileDescriptorEventListener() {
+                    public int onFileDescriptorEvents(FileDescriptor fd, int events) {
+                        return fileDescriptorEventHandler(fd, events);
+                    }
+                }
+            );
+            mLmkdSocketLock.notifyAll();
+        }
+        return true;
+    }
+
+    private int fileDescriptorEventHandler(FileDescriptor fd, int events) {
+        if (mListener == null) {
+            return 0;
+        }
+        if ((events & EVENT_INPUT) != 0) {
+            processIncomingData();
+        }
+        if ((events & EVENT_ERROR) != 0) {
+            synchronized (mLmkdSocketLock) {
+                // stop listening on this socket
+                mMsgQueue.removeOnFileDescriptorEventListener(
+                        mLmkdSocket.getFileDescriptor());
+                IoUtils.closeQuietly(mLmkdSocket);
+                mLmkdSocket = null;
+            }
+            // wake up reply waiters if any
+            synchronized (mReplyBufLock) {
+                if (mReplyBuf != null) {
+                    mReplyBuf = null;
+                    mReplyBufLock.notifyAll();
+                }
+            }
+            // notify listener
+            mListener.onDisconnect();
+            return 0;
+        }
+        return (EVENT_INPUT | EVENT_ERROR);
+    }
+
+    private void processIncomingData() {
+        int len = read(mInputBuf);
+        if (len > 0) {
+            synchronized (mReplyBufLock) {
+                if (mReplyBuf != null) {
+                    if (mListener.isReplyExpected(mReplyBuf, mInputBuf, len)) {
+                        // copy into reply buffer
+                        mReplyBuf.put(mInputBuf.array(), 0, len);
+                        mReplyBuf.rewind();
+                        // wakeup the waiting thread
+                        mReplyBufLock.notifyAll();
+                    } else {
+                        // received asynchronous or unexpected packet
+                        // treat this as an error
+                        mReplyBuf = null;
+                        mReplyBufLock.notifyAll();
+                        Slog.e(TAG, "Received unexpected packet from lmkd");
+                    }
+                } else {
+                    // received asynchronous communication from lmkd
+                    // we don't support this yet
+                    Slog.w(TAG, "Received an asynchronous packet from lmkd");
+                }
+            }
+        }
+    }
+
+    public boolean isConnected() {
+        synchronized (mLmkdSocketLock) {
+            return (mLmkdSocket != null);
+        }
+    }
+
+    public boolean waitForConnection(long timeoutMs) {
+        synchronized (mLmkdSocketLock) {
+            if (mLmkdSocket != null) {
+                return true;
+            }
+            try {
+                mLmkdSocketLock.wait(timeoutMs);
+                return (mLmkdSocket != null);
+            } catch (InterruptedException e) {
+                return false;
+            }
+        }
+    }
+
+    private LocalSocket openSocket() {
+        final LocalSocket socket;
+
+        try {
+            socket = new LocalSocket(LocalSocket.SOCKET_SEQPACKET);
+            socket.connect(
+                new LocalSocketAddress("lmkd",
+                        LocalSocketAddress.Namespace.RESERVED));
+        } catch (IOException ex) {
+            Slog.e(TAG, "Connection failed: " + ex.toString());
+            return null;
+        }
+        return socket;
+    }
+
+    private boolean write(ByteBuffer buf) {
+        synchronized (mLmkdSocketLock) {
+            try {
+                mLmkdOutputStream.write(buf.array(), 0, buf.position());
+            } catch (IOException ex) {
+                return false;
+            }
+            return true;
+        }
+    }
+
+    private int read(ByteBuffer buf) {
+        synchronized (mLmkdSocketLock) {
+            try {
+                return mLmkdInputStream.read(buf.array(), 0, buf.array().length);
+            } catch (IOException ex) {
+            }
+            return -1;
+        }
+    }
+
+    /**
+     * Exchange a request/reply packets with lmkd
+     *
+     * @param req The buffer holding the request data to be sent
+     * @param repl The buffer to receive the reply
+     */
+    public boolean exchange(ByteBuffer req, ByteBuffer repl) {
+        if (repl == null) {
+            return write(req);
+        }
+
+        boolean result = false;
+        // set reply buffer to user-defined one to fill it
+        synchronized (mReplyBufLock) {
+            mReplyBuf = repl;
+
+            if (write(req)) {
+                try {
+                    // wait for the reply
+                    mReplyBufLock.wait();
+                    result = (mReplyBuf != null);
+                } catch (InterruptedException ie) {
+                    result = false;
+                }
+            }
+
+            // reset reply buffer
+            mReplyBuf = null;
+        }
+        return result;
+    }
+}
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 9346ab5..ffbc6b3 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -57,8 +57,6 @@
 import android.content.pm.IPackageManager;
 import android.content.res.Resources;
 import android.graphics.Point;
-import android.net.LocalSocket;
-import android.net.LocalSocketAddress;
 import android.os.AppZygote;
 import android.os.Binder;
 import android.os.Build;
@@ -67,6 +65,7 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
+import android.os.MessageQueue;
 import android.os.Process;
 import android.os.RemoteException;
 import android.os.StrictMode;
@@ -117,11 +116,6 @@
 
 /**
  * Activity manager code dealing with processes.
- *
- * Method naming convention:
- * <ul>
- * <li> Methods suffixed with "LS" should be called within the {@link #sLmkdSocketLock} lock.
- * </ul>
  */
 public final class ProcessList {
     static final String TAG = TAG_WITH_CLASS_NAME ? "ProcessList" : TAG_AM;
@@ -268,6 +262,9 @@
     static final byte LMK_PROCPURGE = 3;
     static final byte LMK_GETKILLCNT = 4;
 
+    // lmkd reconnect delay in msecs
+    private final static long LMDK_RECONNECT_DELAY_MS = 1000;
+
     ActivityManagerService mService = null;
 
     // To kill process groups asynchronously
@@ -302,16 +299,9 @@
 
     private boolean mHaveDisplaySize;
 
-    private static Object sLmkdSocketLock = new Object();
+    private static LmkdConnection sLmkdConnection = null;
 
-    @GuardedBy("sLmkdSocketLock")
-    private static LocalSocket sLmkdSocket;
-
-    @GuardedBy("sLmkdSocketLock")
-    private static OutputStream sLmkdOutputStream;
-
-    @GuardedBy("sLmkdSocketLock")
-    private static InputStream sLmkdInputStream;
+    private boolean mOomLevelsSet = false;
 
     /**
      * Temporary to avoid allocations.  Protected by main lock.
@@ -536,6 +526,7 @@
 
     final class KillHandler extends Handler {
         static final int KILL_PROCESS_GROUP_MSG = 4000;
+        static final int LMDK_RECONNECT_MSG = 4001;
 
         public KillHandler(Looper looper) {
             super(looper, null, true);
@@ -549,6 +540,15 @@
                     Process.killProcessGroup(msg.arg1 /* uid */, msg.arg2 /* pid */);
                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
                     break;
+                case LMDK_RECONNECT_MSG:
+                    if (!sLmkdConnection.connect()) {
+                        Slog.i(TAG, "Failed to connect to lmkd, retry after " +
+                                LMDK_RECONNECT_DELAY_MS + " ms");
+                        // retry after LMDK_RECONNECT_DELAY_MS
+                        sKillHandler.sendMessageDelayed(sKillHandler.obtainMessage(
+                                KillHandler.LMDK_RECONNECT_MSG), LMDK_RECONNECT_DELAY_MS);
+                    }
+                    break;
 
                 default:
                     super.handleMessage(msg);
@@ -574,6 +574,30 @@
                     THREAD_PRIORITY_BACKGROUND, true /* allowIo */);
             sKillThread.start();
             sKillHandler = new KillHandler(sKillThread.getLooper());
+            sLmkdConnection = new LmkdConnection(sKillThread.getLooper().getQueue(),
+                    new LmkdConnection.LmkdConnectionListener() {
+                        @Override
+                        public boolean onConnect(OutputStream ostream) {
+                            Slog.i(TAG, "Connection with lmkd established");
+                            return onLmkdConnect(ostream);
+                        }
+                        @Override
+                        public void onDisconnect() {
+                            Slog.w(TAG, "Lost connection to lmkd");
+                            // start reconnection after delay to let lmkd restart
+                            sKillHandler.sendMessageDelayed(sKillHandler.obtainMessage(
+                                    KillHandler.LMDK_RECONNECT_MSG), LMDK_RECONNECT_DELAY_MS);
+                        }
+                        @Override
+                        public boolean isReplyExpected(ByteBuffer replyBuf,
+                                ByteBuffer dataReceived, int receivedLen) {
+                            // compare the preambule (currently one integer) to check if
+                            // this is the reply packet we are waiting for
+                            return (receivedLen == replyBuf.array().length &&
+                                    dataReceived.getInt(0) == replyBuf.getInt(0));
+                        }
+                    }
+            );
         }
     }
 
@@ -679,6 +703,7 @@
 
             writeLmkd(buf, null);
             SystemProperties.set("sys.sysctl.extra_free_kbytes", Integer.toString(reserve));
+            mOomLevelsSet = true;
         }
         // GB: 2048,3072,4096,6144,7168,8192
         // HC: 8192,10240,12288,14336,16384,20480
@@ -1218,93 +1243,50 @@
         buf.putInt(LMK_GETKILLCNT);
         buf.putInt(min_oom_adj);
         buf.putInt(max_oom_adj);
-        if (writeLmkd(buf, repl)) {
-            int i = repl.getInt();
-            if (i != LMK_GETKILLCNT) {
-                Slog.e("ActivityManager", "Failed to get kill count, code mismatch");
-                return null;
-            }
+        // indicate what we are waiting for
+        repl.putInt(LMK_GETKILLCNT);
+        repl.rewind();
+        if (writeLmkd(buf, repl) && repl.getInt() == LMK_GETKILLCNT) {
             return new Integer(repl.getInt());
         }
         return null;
     }
 
-    @GuardedBy("sLmkdSocketLock")
-    private static boolean openLmkdSocketLS() {
+    public boolean onLmkdConnect(OutputStream ostream) {
         try {
-            sLmkdSocket = new LocalSocket(LocalSocket.SOCKET_SEQPACKET);
-            sLmkdSocket.connect(
-                new LocalSocketAddress("lmkd",
-                        LocalSocketAddress.Namespace.RESERVED));
-            sLmkdOutputStream = sLmkdSocket.getOutputStream();
-            sLmkdInputStream = sLmkdSocket.getInputStream();
-        } catch (IOException ex) {
-            Slog.w(TAG, "lowmemorykiller daemon socket open failed");
-            sLmkdSocket = null;
-            return false;
-        }
-
-        return true;
-    }
-
-    // Never call directly, use writeLmkd() instead
-    @GuardedBy("sLmkdSocketLock")
-    private static boolean writeLmkdCommandLS(ByteBuffer buf) {
-        try {
-            sLmkdOutputStream.write(buf.array(), 0, buf.position());
-        } catch (IOException ex) {
-            Slog.w(TAG, "Error writing to lowmemorykiller socket");
-            IoUtils.closeQuietly(sLmkdSocket);
-            sLmkdSocket = null;
-            return false;
-        }
-        return true;
-    }
-
-    // Never call directly, use writeLmkd() instead
-    @GuardedBy("sLmkdSocketLock")
-    private static boolean readLmkdReplyLS(ByteBuffer buf) {
-        int len;
-        try {
-            len = sLmkdInputStream.read(buf.array(), 0, buf.array().length);
-            if (len == buf.array().length) {
-                return true;
+            // Purge any previously registered pids
+            ByteBuffer buf = ByteBuffer.allocate(4);
+            buf.putInt(LMK_PROCPURGE);
+            ostream.write(buf.array(), 0, buf.position());
+            if (mOomLevelsSet) {
+                // Reset oom_adj levels
+                buf = ByteBuffer.allocate(4 * (2 * mOomAdj.length + 1));
+                buf.putInt(LMK_TARGET);
+                for (int i = 0; i < mOomAdj.length; i++) {
+                    buf.putInt((mOomMinFree[i] * 1024)/PAGE_SIZE);
+                    buf.putInt(mOomAdj[i]);
+                }
+                ostream.write(buf.array(), 0, buf.position());
             }
         } catch (IOException ex) {
-            Slog.w(TAG, "Error reading from lowmemorykiller socket");
+            return false;
         }
-
-        IoUtils.closeQuietly(sLmkdSocket);
-        sLmkdSocket = null;
-        return false;
+        return true;
     }
 
     private static boolean writeLmkd(ByteBuffer buf, ByteBuffer repl) {
-        synchronized (sLmkdSocketLock) {
-            for (int i = 0; i < 3; i++) {
-                if (sLmkdSocket == null) {
-                    if (openLmkdSocketLS() == false) {
-                        try {
-                            Thread.sleep(1000);
-                        } catch (InterruptedException ie) {
-                        }
-                        continue;
-                    }
+        if (!sLmkdConnection.isConnected()) {
+            // try to connect immediately and then keep retrying
+            sKillHandler.sendMessage(
+                sKillHandler.obtainMessage(KillHandler.LMDK_RECONNECT_MSG));
 
-                    // Purge any previously registered pids
-                    ByteBuffer purge_buf = ByteBuffer.allocate(4);
-                    purge_buf.putInt(LMK_PROCPURGE);
-                    if (writeLmkdCommandLS(purge_buf) == false) {
-                        // Write failed, skip the rest and retry
-                        continue;
-                    }
-                }
-                if (writeLmkdCommandLS(buf) && (repl == null || readLmkdReplyLS(repl))) {
-                    return true;
-                }
+            // wait for connection retrying 3 times (up to 3 seconds)
+            if (!sLmkdConnection.waitForConnection(3 * LMDK_RECONNECT_DELAY_MS)) {
+                return false;
             }
         }
-        return false;
+
+        return sLmkdConnection.exchange(buf, repl);
     }
 
     static void killProcessGroup(int uid, int pid) {
diff --git a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
index dd3876d..02ec10e 100644
--- a/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
+++ b/services/core/java/com/android/server/display/whitebalance/DisplayWhiteBalanceController.java
@@ -356,13 +356,15 @@
 
         float ambientBrightness = mBrightnessFilter.getEstimate(time);
 
-        if (mLowLightAmbientBrightnessToBiasSpline != null) {
+        if (ambientColorTemperature != -1.0f &&
+                mLowLightAmbientBrightnessToBiasSpline != null) {
             float bias = mLowLightAmbientBrightnessToBiasSpline.interpolate(ambientBrightness);
             ambientColorTemperature =
                     bias * ambientColorTemperature + (1.0f - bias)
                     * mLowLightAmbientColorTemperature;
         }
-        if (mHighLightAmbientBrightnessToBiasSpline != null) {
+        if (ambientColorTemperature != -1.0f &&
+                mHighLightAmbientBrightnessToBiasSpline != null) {
             float bias = mHighLightAmbientBrightnessToBiasSpline.interpolate(ambientBrightness);
             ambientColorTemperature =
                     (1.0f - bias) * ambientColorTemperature + bias
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
index 82aacfe..9f98d63 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceAudioSystem.java
@@ -919,16 +919,12 @@
             }
         }
         // Init arc whenever System Audio Mode is on
-        // Terminate arc when System Audio Mode is off
         // Since some TVs don't request ARC on with System Audio Mode on request
         if (SystemProperties.getBoolean(Constants.PROPERTY_ARC_SUPPORT, true)
                 && isDirectConnectToTv()) {
             if (newSystemAudioMode && !isArcEnabled()
                     && !hasAction(ArcInitiationActionFromAvr.class)) {
                 addAndStartAction(new ArcInitiationActionFromAvr(this));
-            } else if (!newSystemAudioMode && isArcEnabled()) {
-                removeAction(ArcTerminationActionFromAvr.class);
-                addAndStartAction(new ArcTerminationActionFromAvr(this));
             }
         }
     }
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index 440676a..df4674c 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -1498,6 +1498,11 @@
                         Slog.e(TAG, "Callback cannot be null");
                         return;
                     }
+                    if (isPowerStandby()) {
+                        Slog.e(TAG, "Device is in standby. Not handling deviceSelect");
+                        invokeCallback(callback, HdmiControlManager.RESULT_INCORRECT_MODE);
+                        return;
+                    }
                     HdmiCecLocalDeviceTv tv = tv();
                     if (tv == null) {
                         if (!mAddressAllocated) {
@@ -1540,6 +1545,11 @@
                         Slog.e(TAG, "Callback cannot be null");
                         return;
                     }
+                    if (isPowerStandby()) {
+                        Slog.e(TAG, "Device is in standby. Not handling portSelect");
+                        invokeCallback(callback, HdmiControlManager.RESULT_INCORRECT_MODE);
+                        return;
+                    }
                     HdmiCecLocalDeviceTv tv = tv();
                     if (tv != null) {
                         tv.doManualPortSwitching(portId, callback);
diff --git a/services/core/java/com/android/server/pm/ShareTargetInfo.java b/services/core/java/com/android/server/pm/ShareTargetInfo.java
index 9e8b73e..fdfee77 100644
--- a/services/core/java/com/android/server/pm/ShareTargetInfo.java
+++ b/services/core/java/com/android/server/pm/ShareTargetInfo.java
@@ -15,12 +15,36 @@
  */
 package com.android.server.pm;
 
+import android.annotation.NonNull;
 import android.text.TextUtils;
 
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
+
+import java.io.IOException;
+import java.util.ArrayList;
+
 /**
  * Represents a Share Target definition, read from the application's manifest (shortcuts.xml)
  */
 class ShareTargetInfo {
+
+    private static final String TAG_SHARE_TARGET = "share-target";
+    private static final String ATTR_TARGET_CLASS = "targetClass";
+
+    private static final String TAG_DATA = "data";
+    private static final String ATTR_SCHEME = "scheme";
+    private static final String ATTR_HOST = "host";
+    private static final String ATTR_PORT = "port";
+    private static final String ATTR_PATH = "path";
+    private static final String ATTR_PATH_PATTERN = "pathPattern";
+    private static final String ATTR_PATH_PREFIX = "pathPrefix";
+    private static final String ATTR_MIME_TYPE = "mimeType";
+
+    private static final String TAG_CATEGORY = "category";
+    private static final String ATTR_NAME = "name";
+
     static class TargetData {
         final String mScheme;
         final String mHost;
@@ -98,4 +122,72 @@
 
         return strBuilder.toString();
     }
+
+    void saveToXml(@NonNull XmlSerializer out) throws IOException {
+        out.startTag(null, TAG_SHARE_TARGET);
+
+        ShortcutService.writeAttr(out, ATTR_TARGET_CLASS, mTargetClass);
+
+        for (int i = 0; i < mTargetData.length; i++) {
+            out.startTag(null, TAG_DATA);
+            ShortcutService.writeAttr(out, ATTR_SCHEME, mTargetData[i].mScheme);
+            ShortcutService.writeAttr(out, ATTR_HOST, mTargetData[i].mHost);
+            ShortcutService.writeAttr(out, ATTR_PORT, mTargetData[i].mPort);
+            ShortcutService.writeAttr(out, ATTR_PATH, mTargetData[i].mPath);
+            ShortcutService.writeAttr(out, ATTR_PATH_PATTERN, mTargetData[i].mPathPattern);
+            ShortcutService.writeAttr(out, ATTR_PATH_PREFIX, mTargetData[i].mPathPrefix);
+            ShortcutService.writeAttr(out, ATTR_MIME_TYPE, mTargetData[i].mMimeType);
+            out.endTag(null, TAG_DATA);
+        }
+
+        for (int i = 0; i < mCategories.length; i++) {
+            out.startTag(null, TAG_CATEGORY);
+            ShortcutService.writeAttr(out, ATTR_NAME, mCategories[i]);
+            out.endTag(null, TAG_CATEGORY);
+        }
+
+        out.endTag(null, TAG_SHARE_TARGET);
+    }
+
+    static ShareTargetInfo loadFromXml(XmlPullParser parser)
+            throws IOException, XmlPullParserException {
+        final String targetClass = ShortcutService.parseStringAttribute(parser, ATTR_TARGET_CLASS);
+        final ArrayList<ShareTargetInfo.TargetData> targetData = new ArrayList<>();
+        final ArrayList<String> categories = new ArrayList<>();
+
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+            if (type == XmlPullParser.START_TAG) {
+                switch (parser.getName()) {
+                    case TAG_DATA:
+                        targetData.add(parseTargetData(parser));
+                        break;
+                    case TAG_CATEGORY:
+                        categories.add(ShortcutService.parseStringAttribute(parser, ATTR_NAME));
+                        break;
+                }
+            } else if (type == XmlPullParser.END_TAG && parser.getName().equals(TAG_SHARE_TARGET)) {
+                break;
+            }
+        }
+        if (targetData.isEmpty() || targetClass == null || categories.isEmpty()) {
+            return null;
+        }
+        return new ShareTargetInfo(
+                targetData.toArray(new ShareTargetInfo.TargetData[targetData.size()]),
+                targetClass, categories.toArray(new String[categories.size()]));
+    }
+
+    private static ShareTargetInfo.TargetData parseTargetData(XmlPullParser parser) {
+        final String scheme = ShortcutService.parseStringAttribute(parser, ATTR_SCHEME);
+        final String host = ShortcutService.parseStringAttribute(parser, ATTR_HOST);
+        final String port = ShortcutService.parseStringAttribute(parser, ATTR_PORT);
+        final String path = ShortcutService.parseStringAttribute(parser, ATTR_PATH);
+        final String pathPattern = ShortcutService.parseStringAttribute(parser, ATTR_PATH_PATTERN);
+        final String pathPrefix = ShortcutService.parseStringAttribute(parser, ATTR_PATH_PREFIX);
+        final String mimeType = ShortcutService.parseStringAttribute(parser, ATTR_MIME_TYPE);
+
+        return new ShareTargetInfo.TargetData(scheme, host, port, path, pathPattern, pathPrefix,
+                mimeType);
+    }
 }
diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java
index d6e87aa..06c71ba 100644
--- a/services/core/java/com/android/server/pm/ShortcutPackage.java
+++ b/services/core/java/com/android/server/pm/ShortcutPackage.java
@@ -73,6 +73,7 @@
     private static final String TAG_INTENT = "intent";
     private static final String TAG_EXTRAS = "extras";
     private static final String TAG_SHORTCUT = "shortcut";
+    private static final String TAG_SHARE_TARGET = "share-target";
     private static final String TAG_CATEGORIES = "categories";
     private static final String TAG_PERSON = "person";
 
@@ -1453,8 +1454,9 @@
     public void saveToXml(@NonNull XmlSerializer out, boolean forBackup)
             throws IOException, XmlPullParserException {
         final int size = mShortcuts.size();
+        final int shareTargetSize = mShareTargets.size();
 
-        if (size == 0 && mApiCallCount == 0) {
+        if (size == 0 && shareTargetSize == 0 && mApiCallCount == 0) {
             return; // nothing to write.
         }
 
@@ -1470,6 +1472,12 @@
                     getPackageInfo().isBackupAllowed());
         }
 
+        if (!forBackup) {
+            for (int j = 0; j < shareTargetSize; j++) {
+                mShareTargets.get(j).saveToXml(out);
+            }
+        }
+
         out.endTag(null, TAG_ROOT);
     }
 
@@ -1627,6 +1635,9 @@
                         // Don't use addShortcut(), we don't need to save the icon.
                         ret.mShortcuts.put(si.getId(), si);
                         continue;
+                    case TAG_SHARE_TARGET:
+                        ret.mShareTargets.add(ShareTargetInfo.loadFromXml(parser));
+                        continue;
                 }
             }
             ShortcutService.warnForInvalidTag(depth, tag);
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index 505e89d..de3e89f 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -45,10 +45,9 @@
 import android.os.HandlerThread;
 import android.os.ParcelFileDescriptor;
 import android.os.Process;
-import android.os.UserHandle;   // duped to avoid merge conflict
-import android.os.UserManager;  // out of order to avoid merge conflict
 import android.os.SystemClock;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.provider.DeviceConfig;
 import android.util.ArraySet;
 import android.util.IntArray;
@@ -326,7 +325,7 @@
     }
 
     @Override
-    public ParceledListSlice<RollbackInfo> getRecentlyExecutedRollbacks() {
+    public ParceledListSlice<RollbackInfo> getRecentlyCommittedRollbacks() {
         enforceManageRollbacks("getRecentlyCommittedRollbacks");
 
         synchronized (mLock) {
@@ -345,7 +344,7 @@
     @Override
     public void commitRollback(int rollbackId, ParceledListSlice causePackages,
             String callerPackageName, IntentSender statusReceiver) {
-        enforceManageRollbacks("executeRollback");
+        enforceManageRollbacks("commitRollback");
 
         final int callingUid = Binder.getCallingUid();
         AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
@@ -575,6 +574,20 @@
         }
     }
 
+    @Override
+    public void blockRollbackManager(long millis) {
+        mContext.enforceCallingOrSelfPermission(
+                Manifest.permission.TEST_MANAGE_ROLLBACKS,
+                "blockRollbackManager");
+        getHandler().post(() -> {
+            try {
+                Thread.sleep(millis);
+            } catch (InterruptedException e) {
+                // ignored.
+            }
+        });
+    }
+
     void onUnlockUser(int userId) {
         getHandler().post(() -> {
             final List<RollbackData> rollbacks;
@@ -677,8 +690,7 @@
 
     /**
      * Load rollback data from storage if it has not already been loaded.
-     * After calling this funciton, mAvailableRollbacks and
-     * mRecentlyExecutedRollbacks will be non-null.
+     * After calling this function, mRollbacks will be non-null.
      */
     private void ensureRollbackDataLoaded() {
         synchronized (mLock) {
diff --git a/services/core/java/com/android/server/uri/UriGrantsManagerService.java b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
index 8b332d2..55f062b 100644
--- a/services/core/java/com/android/server/uri/UriGrantsManagerService.java
+++ b/services/core/java/com/android/server/uri/UriGrantsManagerService.java
@@ -1032,11 +1032,13 @@
         // must always grant permissions on behalf of someone explicit.
         final int callingAppId = UserHandle.getAppId(callingUid);
         if ((callingAppId == SYSTEM_UID) || (callingAppId == ROOT_UID)) {
-            if ("com.android.settings.files".equals(grantUri.uri.getAuthority())) {
+            if ("com.android.settings.files".equals(grantUri.uri.getAuthority())
+                    || "com.android.settings.module_licenses".equals(grantUri.uri.getAuthority())) {
                 // Exempted authority for
                 // 1. cropping user photos and sharing a generated license html
                 //    file in Settings app
                 // 2. sharing a generated license html file in TvSettings app
+                // 3. Sharing module license files from Settings app
             } else {
                 Slog.w(TAG, "For security reasons, the system cannot issue a Uri permission"
                         + " grant to " + grantUri + "; use startActivityAsCaller() instead");
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 156fb98..157e15a 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -1302,6 +1302,11 @@
             return;
         }
 
+        getDisplay().positionChildAtBottom(this, reason);
+        if (task != null) {
+            insertTaskAtBottom(task);
+        }
+
         /**
          * The intent behind moving a primary split screen stack to the back is usually to hide
          * behind the home stack. Exit split screen in this case.
@@ -1309,11 +1314,6 @@
         if (getWindowingMode() == WINDOWING_MODE_SPLIT_SCREEN_PRIMARY) {
             setWindowingMode(WINDOWING_MODE_UNDEFINED);
         }
-
-        getDisplay().positionChildAtBottom(this, reason);
-        if (task != null) {
-            insertTaskAtBottom(task);
-        }
     }
 
     boolean isFocusable() {
@@ -1388,13 +1388,12 @@
             }
 
             if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Comparing existing cls="
-                    + taskIntent.getComponent().flattenToShortString()
+                    + (task.realActivity != null ? task.realActivity.flattenToShortString() : "")
                     + "/aff=" + r.getTaskRecord().rootAffinity + " to new cls="
                     + intent.getComponent().flattenToShortString() + "/aff=" + info.taskAffinity);
             // TODO Refactor to remove duplications. Check if logic can be simplified.
-            if (taskIntent != null && taskIntent.getComponent() != null &&
-                    taskIntent.getComponent().compareTo(cls) == 0 &&
-                    Objects.equals(documentData, taskDocumentData)) {
+            if (task.realActivity != null && task.realActivity.compareTo(cls) == 0
+                    && Objects.equals(documentData, taskDocumentData)) {
                 if (DEBUG_TASKS) Slog.d(TAG_TASKS, "Found matching class!");
                 //dump();
                 if (DEBUG_TASKS) Slog.d(TAG_TASKS,
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 16dd555..6728bd9 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -3918,10 +3918,10 @@
                     // Caller wants the current split-screen primary stack to be the top stack after
                     // it goes fullscreen, so move it to the front.
                     stack.moveToFront("dismissSplitScreenMode");
-                } else if (mRootActivityContainer.isTopDisplayFocusedStack(stack)) {
+                } else {
                     // In this case the current split-screen primary stack shouldn't be the top
-                    // stack after it goes fullscreen, but it current has focus, so we move the
-                    // focus to the top-most split-screen secondary stack next to it.
+                    // stack after it goes fullscreen, so we move the focus to the top-most
+                    // split-screen secondary stack next to it.
                     final ActivityStack otherStack = stack.getDisplay().getTopStackInWindowingMode(
                             WINDOWING_MODE_SPLIT_SCREEN_SECONDARY);
                     if (otherStack != null) {
@@ -4750,18 +4750,12 @@
 
     private void applyUpdateVrModeLocked(ActivityRecord r) {
         // VR apps are expected to run in a main display. If an app is turning on VR for
-        // itself, but lives in a dynamic stack, then make sure that it is moved to the main
-        // fullscreen stack before enabling VR Mode.
-        // TODO: The goal of this code is to keep the VR app on the main display. When the
-        // stack implementation changes in the future, keep in mind that the use of the fullscreen
-        // stack is a means to move the activity to the main display and a moveActivityToDisplay()
-        // option would be a better choice here.
+        // itself, but isn't on the main display, then move it there before enabling VR Mode.
         if (r.requestedVrComponent != null && r.getDisplayId() != DEFAULT_DISPLAY) {
-            Slog.i(TAG, "Moving " + r.shortComponentName + " from stack " + r.getStackId()
-                    + " to main stack for VR");
-            final ActivityStack stack = mRootActivityContainer.getDefaultDisplay().getOrCreateStack(
-                    WINDOWING_MODE_FULLSCREEN, r.getActivityType(), true /* toTop */);
-            moveTaskToStack(r.getTaskRecord().taskId, stack.mStackId, true /* toTop */);
+            Slog.i(TAG, "Moving " + r.shortComponentName + " from display " + r.getDisplayId()
+                    + " to main display for VR");
+            mRootActivityContainer.moveStackToDisplay(
+                    r.getStackId(), DEFAULT_DISPLAY, true /* toTop */);
         }
         mH.post(() -> {
             if (!mVrController.onVrModeChanged(r)) {
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 4a9a3f7..03cae42 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1322,7 +1322,15 @@
         if (prevDc == null || prevDc == mDisplayContent) {
             return;
         }
-        if (prevDc.mChangingApps.contains(this)) {
+
+        if (prevDc.mOpeningApps.remove(this)) {
+            // Transfer opening transition to new display.
+            mDisplayContent.mOpeningApps.add(this);
+            mDisplayContent.prepareAppTransition(prevDc.mAppTransition.getAppTransition(), true);
+            mDisplayContent.executeAppTransition();
+        }
+
+        if (prevDc.mChangingApps.remove(this)) {
             // This gets called *after* the AppWindowToken has been reparented to the new display.
             // That reparenting resulted in this window changing modes (eg. FREEFORM -> FULLSCREEN),
             // so this token is now "frozen" while waiting for the animation to start on prevDc
@@ -1331,6 +1339,8 @@
             // so we need to cancel the change transition here.
             clearChangeLeash(getPendingTransaction(), true /* cancel */);
         }
+        prevDc.mClosingApps.remove(this);
+
         if (prevDc.mFocusedApp == this) {
             prevDc.setFocusedApp(null);
             final TaskStack stack = dc.getTopStack();
@@ -3216,16 +3226,6 @@
                 true /* topToBottom */);
     }
 
-    void removeFromPendingTransition() {
-        if (isWaitingForTransitionStart() && mDisplayContent != null) {
-            mDisplayContent.mOpeningApps.remove(this);
-            if (mDisplayContent.mChangingApps.remove(this)) {
-                clearChangeLeash(getPendingTransaction(), true /* cancel */);
-            }
-            mDisplayContent.mClosingApps.remove(this);
-        }
-    }
-
     private void updateColorTransform() {
         if (mSurfaceControl != null && mLastAppSaturationInfo != null) {
             getPendingTransaction().setColorTransform(mSurfaceControl,
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 57ed92d..4d548bf 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -30,16 +30,21 @@
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
+import static android.util.DisplayMetrics.DENSITY_DEFAULT;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.FLAG_PRIVATE;
 import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.InsetsState.TYPE_IME;
+import static android.view.InsetsState.TYPE_LEFT_GESTURES;
+import static android.view.InsetsState.TYPE_RIGHT_GESTURES;
 import static android.view.Surface.ROTATION_0;
 import static android.view.Surface.ROTATION_180;
 import static android.view.Surface.ROTATION_270;
 import static android.view.Surface.ROTATION_90;
 import static android.view.View.GONE;
+import static android.view.View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
+import static android.view.View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
 import static android.view.WindowManager.DOCKED_BOTTOM;
 import static android.view.WindowManager.DOCKED_INVALID;
 import static android.view.WindowManager.DOCKED_TOP;
@@ -135,6 +140,7 @@
 import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP;
 import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING;
 import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW;
+import static com.android.server.wm.utils.RegionUtils.forEachRect;
 import static com.android.server.wm.utils.RegionUtils.rectListToRegion;
 
 import android.animation.AnimationHandler;
@@ -323,6 +329,7 @@
     private final RemoteCallbackList<ISystemGestureExclusionListener>
             mSystemGestureExclusionListeners = new RemoteCallbackList<>();
     private final Region mSystemGestureExclusion = new Region();
+    private int mSystemGestureExclusionLimit;
 
     /**
      * For default display it contains real metrics, empty for others.
@@ -893,6 +900,8 @@
         mWallpaperController = new WallpaperController(mWmService, this);
         display.getDisplayInfo(mDisplayInfo);
         display.getMetrics(mDisplayMetrics);
+        mSystemGestureExclusionLimit = mWmService.mSystemGestureExclusionLimitDp
+                * mDisplayMetrics.densityDpi / DENSITY_DEFAULT;
         isDefaultDisplay = mDisplayId == DEFAULT_DISPLAY;
         mDisplayFrames = new DisplayFrames(mDisplayId, mDisplayInfo,
                 calculateDisplayCutoutForRotation(mDisplayInfo.rotation));
@@ -1548,8 +1557,8 @@
             longSize = height;
         }
 
-        final int shortSizeDp = shortSize * DisplayMetrics.DENSITY_DEFAULT / mBaseDisplayDensity;
-        final int longSizeDp = longSize * DisplayMetrics.DENSITY_DEFAULT / mBaseDisplayDensity;
+        final int shortSizeDp = shortSize * DENSITY_DEFAULT / mBaseDisplayDensity;
+        final int longSizeDp = longSize * DENSITY_DEFAULT / mBaseDisplayDensity;
 
         mDisplayPolicy.updateConfigurationAndScreenSizeDependentBehaviors();
         mDisplayRotation.configure(width, height, shortSizeDp, longSizeDp);
@@ -2199,6 +2208,18 @@
         onDisplayChanged(this);
     }
 
+    @Override
+    void onDisplayChanged(DisplayContent dc) {
+        super.onDisplayChanged(dc);
+        updateSystemGestureExclusionLimit();
+    }
+
+    void updateSystemGestureExclusionLimit() {
+        mSystemGestureExclusionLimit = mWmService.mSystemGestureExclusionLimitDp
+                * mDisplayMetrics.densityDpi / DENSITY_DEFAULT;
+        updateSystemGestureExclusion();
+    }
+
     void initializeDisplayBaseInfo() {
         final DisplayManagerInternal displayManagerInternal = mWmService.mDisplayManagerInternal;
         if (displayManagerInternal != null) {
@@ -2376,9 +2397,6 @@
                     + " to its current displayId=" + mDisplayId);
         }
 
-        // Clean up all pending transitions when stack reparent to another display.
-        stack.forAllAppWindows(AppWindowToken::removeFromPendingTransition);
-
         prevDc.mTaskStackContainers.removeChild(stack);
         mTaskStackContainers.addStackToDisplay(stack, onTop);
     }
@@ -5130,24 +5148,35 @@
 
     @VisibleForTesting
     Region calculateSystemGestureExclusion() {
+        final Region unhandled = Region.obtain();
+        unhandled.set(0, 0, mDisplayFrames.mDisplayWidth, mDisplayFrames.mDisplayHeight);
+
+        final Rect leftEdge = mInsetsStateController.getSourceProvider(TYPE_LEFT_GESTURES)
+                .getSource().getFrame();
+        final Rect rightEdge = mInsetsStateController.getSourceProvider(TYPE_RIGHT_GESTURES)
+                .getSource().getFrame();
+
         final Region global = Region.obtain();
         final Region touchableRegion = Region.obtain();
         final Region local = Region.obtain();
+        final int[] remainingLeftRight =
+                {mSystemGestureExclusionLimit, mSystemGestureExclusionLimit};
 
         // Traverse all windows bottom up to assemble the gesture exclusion rects.
         // For each window, we only take the rects that fall within its touchable region.
         forAllWindows(w -> {
             if (w.cantReceiveTouchInput() || !w.isVisible()
-                    || (w.getAttrs().flags & FLAG_NOT_TOUCHABLE) != 0) {
+                    || (w.getAttrs().flags & FLAG_NOT_TOUCHABLE) != 0
+                    || unhandled.isEmpty()) {
                 return;
             }
             final boolean modal =
                     (w.mAttrs.flags & (FLAG_NOT_TOUCH_MODAL | FLAG_NOT_FOCUSABLE)) == 0;
 
-            // Only keep the exclusion zones from the windows behind where the current window
-            // isn't touchable.
+            // Get the touchable region of the window, and intersect with where the screen is still
+            // touchable, i.e. touchable regions on top are not covering it yet.
             w.getTouchableRegion(touchableRegion);
-            global.op(touchableRegion, Op.DIFFERENCE);
+            touchableRegion.op(unhandled, Op.INTERSECT);
 
             rectListToRegion(w.getSystemGestureExclusion(), local);
 
@@ -5159,13 +5188,78 @@
             // A window can only exclude system gestures where it is actually touchable
             local.op(touchableRegion, Op.INTERSECT);
 
-            global.op(local, Op.UNION);
-        }, false /* topToBottom */);
+            // Apply restriction if necessary.
+            if (needsGestureExclusionRestrictions(w, mLastDispatchedSystemUiVisibility)) {
+
+                // Processes the region along the left edge.
+                remainingLeftRight[0] = addToGlobalAndConsumeLimit(local, global, leftEdge,
+                        remainingLeftRight[0]);
+
+                // Processes the region along the right edge.
+                remainingLeftRight[1] = addToGlobalAndConsumeLimit(local, global, rightEdge,
+                        remainingLeftRight[1]);
+
+                // Adds the middle (unrestricted area)
+                final Region middle = Region.obtain(local);
+                middle.op(leftEdge, Op.DIFFERENCE);
+                middle.op(rightEdge, Op.DIFFERENCE);
+                global.op(middle, Op.UNION);
+                middle.recycle();
+            } else {
+                global.op(local, Op.UNION);
+            }
+            unhandled.op(touchableRegion, Op.DIFFERENCE);
+        }, true /* topToBottom */);
         local.recycle();
         touchableRegion.recycle();
+        unhandled.recycle();
         return global;
     }
 
+    /**
+     * @return Whether gesture exclusion area should be restricted from the window depending on the
+     *         current SystemUI visibility flags.
+     */
+    private static boolean needsGestureExclusionRestrictions(WindowState win, int sysUiVisibility) {
+        final int type = win.mAttrs.type;
+        final int stickyHideNavFlags =
+                SYSTEM_UI_FLAG_HIDE_NAVIGATION | SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
+        final boolean stickyHideNav =
+                (sysUiVisibility & stickyHideNavFlags) == stickyHideNavFlags;
+        return !stickyHideNav && type != TYPE_INPUT_METHOD && type != TYPE_STATUS_BAR
+                && win.getActivityType() != ACTIVITY_TYPE_HOME;
+    }
+
+    /**
+     * Adds a local gesture exclusion area to the global area while applying a limit per edge.
+     *
+     * @param local The gesture exclusion area to add.
+     * @param global The destination.
+     * @param edge Only processes the part in that region.
+     * @param limit How much limit in pixels we have.
+     * @return How much of the limit are remaining.
+     */
+    private static int addToGlobalAndConsumeLimit(Region local, Region global, Rect edge,
+            int limit) {
+        final Region r = Region.obtain(local);
+        r.op(edge, Op.INTERSECT);
+
+        final int[] remaining = {limit};
+        forEachRect(r, rect -> {
+            if (remaining[0] <= 0) {
+                return;
+            }
+            final int height = rect.height();
+            if (height > remaining[0]) {
+                rect.bottom = rect.top + remaining[0];
+            }
+            remaining[0] -= height;
+            global.op(rect, Op.UNION);
+        });
+        r.recycle();
+        return remaining[0];
+    }
+
     void registerSystemGestureExclusionListener(ISystemGestureExclusionListener listener) {
         mSystemGestureExclusionListeners.register(listener);
         final boolean changed;
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index fe4c9a4..dc62877 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -279,7 +279,8 @@
                 mService.mDisplayManagerInternal.screenshot(displayId);
             if (gb != null) {
                 try {
-                    surface.attachAndQueueBuffer(gb.getGraphicBuffer());
+                    surface.attachAndQueueBufferWithColorSpace(gb.getGraphicBuffer(),
+                            gb.getColorSpace());
                 } catch (RuntimeException e) {
                     Slog.w(TAG, "Failed to attach screenshot - " + e.getMessage());
                 }
diff --git a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
index 8031cfd..1a57168 100644
--- a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
+++ b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
@@ -68,7 +68,7 @@
         if (buffer != null) {
             final Surface surface = new Surface();
             surface.copyFrom(mSurfaceControl);
-            surface.attachAndQueueBuffer(buffer);
+            surface.attachAndQueueBufferWithColorSpace(buffer, screenshotBuffer.getColorSpace());
             surface.release();
         }
         getPendingTransaction().show(mSurfaceControl);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 2696977..1b3e4c1 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -284,7 +284,6 @@
     }
 
     private void drawSnapshot() {
-        final GraphicBuffer buffer = mSnapshot.getSnapshot();
         mSurface.copyFrom(mSurfaceControl);
 
         if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Drawing snapshot surface sizeMismatch="
@@ -293,9 +292,9 @@
             // The dimensions of the buffer and the window don't match, so attaching the buffer
             // will fail. Better create a child window with the exact dimensions and fill the parent
             // window with the background color!
-            drawSizeMismatchSnapshot(buffer);
+            drawSizeMismatchSnapshot();
         } else {
-            drawSizeMatchSnapshot(buffer);
+            drawSizeMatchSnapshot();
         }
         synchronized (mService.mGlobalLock) {
             mShownTime = SystemClock.uptimeMillis();
@@ -307,15 +306,17 @@
         mSnapshot = null;
     }
 
-    private void drawSizeMatchSnapshot(GraphicBuffer buffer) {
-        mSurface.attachAndQueueBuffer(buffer);
+    private void drawSizeMatchSnapshot() {
+        mSurface.attachAndQueueBufferWithColorSpace(mSnapshot.getSnapshot(),
+                mSnapshot.getColorSpace());
         mSurface.release();
     }
 
-    private void drawSizeMismatchSnapshot(GraphicBuffer buffer) {
+    private void drawSizeMismatchSnapshot() {
         if (!mSurface.isValid()) {
             throw new IllegalStateException("mSurface does not hold a valid surface.");
         }
+        final GraphicBuffer buffer = mSnapshot.getSnapshot();
         final SurfaceSession session = new SurfaceSession();
         // We consider nearly matched dimensions as there can be rounding errors and the user won't
         // notice very minute differences from scaling one dimension more than the other
@@ -355,7 +356,7 @@
         } finally {
             SurfaceControl.closeTransaction();
         }
-        surface.attachAndQueueBuffer(buffer);
+        surface.attachAndQueueBufferWithColorSpace(buffer, mSnapshot.getColorSpace());
         surface.release();
 
         if (aspectRatioMismatch) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 6750ece1..54f712c 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -32,6 +32,7 @@
 import static android.os.Process.SYSTEM_UID;
 import static android.os.Process.myPid;
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
+import static android.provider.DeviceConfig.WindowManager.KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP;
 import static android.provider.Settings.Global.DEVELOPMENT_FORCE_DESKTOP_MODE_ON_EXTERNAL_DISPLAYS;
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
@@ -155,6 +156,7 @@
 import android.os.Bundle;
 import android.os.Debug;
 import android.os.Handler;
+import android.os.HandlerExecutor;
 import android.os.IBinder;
 import android.os.IRemoteCallback;
 import android.os.Looper;
@@ -176,6 +178,7 @@
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.WorkSource;
+import android.provider.DeviceConfig;
 import android.provider.Settings;
 import android.service.vr.IVrManager;
 import android.service.vr.IVrStateCallbacks;
@@ -382,6 +385,8 @@
 
     private static final int ANIMATION_COMPLETED_TIMEOUT_MS = 5000;
 
+    private static final int MIN_GESTURE_EXCLUSION_LIMIT_DP = 200;
+
     final WindowTracing mWindowTracing;
 
     final private KeyguardDisableHandler mKeyguardDisableHandler;
@@ -840,6 +845,8 @@
     final ArrayList<WindowChangeListener> mWindowChangeListeners = new ArrayList<>();
     boolean mWindowsChanged = false;
 
+    int mSystemGestureExclusionLimitDp;
+
     public interface WindowChangeListener {
         public void windowsChanged();
         public void focusChanged();
@@ -1134,6 +1141,21 @@
                 this, mInputManager, mActivityTaskManager, mH.getLooper());
         mDragDropController = new DragDropController(this, mH.getLooper());
 
+        mSystemGestureExclusionLimitDp = Math.max(MIN_GESTURE_EXCLUSION_LIMIT_DP,
+                DeviceConfig.getInt(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+                        KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, 0));
+        DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+                new HandlerExecutor(mH), properties -> {
+                    synchronized (mGlobalLock) {
+                        final int exclusionLimitDp = Math.max(MIN_GESTURE_EXCLUSION_LIMIT_DP,
+                                properties.getInt(KEY_SYSTEM_GESTURE_EXCLUSION_LIMIT_DP, 0));
+                        if (mSystemGestureExclusionLimitDp != exclusionLimitDp) {
+                            mSystemGestureExclusionLimitDp = exclusionLimitDp;
+                            mRoot.forAllDisplays(DisplayContent::updateSystemGestureExclusionLimit);
+                        }
+                    }
+                });
+
         LocalServices.addService(WindowManagerInternal.class, new LocalService());
     }
 
diff --git a/services/core/java/com/android/server/wm/utils/RegionUtils.java b/services/core/java/com/android/server/wm/utils/RegionUtils.java
index 1458440..8cd6f88 100644
--- a/services/core/java/com/android/server/wm/utils/RegionUtils.java
+++ b/services/core/java/com/android/server/wm/utils/RegionUtils.java
@@ -18,8 +18,10 @@
 
 import android.graphics.Rect;
 import android.graphics.Region;
+import android.graphics.RegionIterator;
 
 import java.util.List;
+import java.util.function.Consumer;
 
 /**
  * Utility methods to handle Regions.
@@ -42,4 +44,18 @@
             outRegion.union(rects.get(i));
         }
     }
+
+    /**
+     * Applies actions on each rect contained within a {@code Region}.
+     *
+     * @param region the given region.
+     * @param rectConsumer the action holder.
+     */
+    public static void forEachRect(Region region, Consumer<Rect> rectConsumer) {
+        final RegionIterator it = new RegionIterator(region);
+        final Rect rect = new Rect();
+        while (it.next(rect)) {
+            rectConsumer.accept(rect);
+        }
+    }
 }
diff --git a/services/devicepolicy/TEST_MAPPING b/services/devicepolicy/TEST_MAPPING
index febfa17..a5ee3e2 100644
--- a/services/devicepolicy/TEST_MAPPING
+++ b/services/devicepolicy/TEST_MAPPING
@@ -1,12 +1,20 @@
 {
-  "postsubmit": [
+  "presubmit": [
     {
       "name": "CtsDevicePolicyManagerTestCases",
       "options": [
         {
           "exclude-annotation": "android.platform.test.annotations.FlakyTest"
+        },
+        {
+          "exclude-annotation": "android.platform.test.annotations.LargeTest"
         }
       ]
     }
+  ],
+  "postsubmit": [
+    {
+      "name": "CtsDevicePolicyManagerTestCases"
+    }
   ]
 }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 3ec8b2e..47539d3 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -1893,6 +1893,10 @@
         mSystemServiceManager.startService(IncidentCompanionService.class);
         t.traceEnd();
 
+        if (safeMode) {
+            mActivityManagerService.enterSafeMode();
+        }
+
         // MMS service broker
         t.traceBegin("StartMmsService");
         mmsService = mSystemServiceManager.startService(MmsServiceBroker.class);
diff --git a/services/tests/servicestests/src/com/android/server/display/whitebalance/AmbientLuxTest.java b/services/tests/servicestests/src/com/android/server/display/whitebalance/AmbientLuxTest.java
index 424142c..6b0798b 100644
--- a/services/tests/servicestests/src/com/android/server/display/whitebalance/AmbientLuxTest.java
+++ b/services/tests/servicestests/src/com/android/server/display/whitebalance/AmbientLuxTest.java
@@ -359,6 +359,33 @@
             }
     }
 
+    @Test
+    public void testLowLight_DefaultAmbient() throws Exception {
+        final float lowerBrightness = 10.0f;
+        final float upperBrightness = 50.0f;
+        setBrightnesses(lowerBrightness, upperBrightness);
+        setBiases(0.0f, 1.0f);
+
+        DisplayWhiteBalanceController controller =
+                DisplayWhiteBalanceFactory.create(mHandler, mSensorManagerMock, mResourcesSpy);
+        final float ambientColorTemperature = -1.0f;
+        setEstimatedColorTemperature(controller, ambientColorTemperature);
+        controller.mBrightnessFilter = spy(controller.mBrightnessFilter);
+
+        for (float t = 0.0f; t <= 1.0f; t += 0.1f) {
+            setEstimatedBrightnessAndUpdate(controller,
+                    mix(lowerBrightness, upperBrightness, t));
+            assertEquals(controller.mPendingAmbientColorTemperature, ambientColorTemperature,
+                        0.001);
+        }
+
+        setEstimatedBrightnessAndUpdate(controller, 0.0f);
+        assertEquals(controller.mPendingAmbientColorTemperature, ambientColorTemperature, 0.001);
+
+        setEstimatedBrightnessAndUpdate(controller, upperBrightness + 1.0f);
+        assertEquals(controller.mPendingAmbientColorTemperature, ambientColorTemperature, 0.001);
+    }
+
     void mockThrottler() {
         when(mResourcesSpy.getInteger(
                 R.integer.config_displayWhiteBalanceDecreaseDebounce)).thenReturn(0);
diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
index 7e6b7da..6c917b7 100644
--- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
+++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest1.java
@@ -97,16 +97,25 @@
 import android.test.suitebuilder.annotation.SmallTest;
 import android.util.Log;
 import android.util.SparseArray;
+import android.util.Xml;
 
 import com.android.frameworks.servicestests.R;
+import com.android.internal.util.FastXmlSerializer;
 import com.android.server.pm.ShortcutService.ConfigConstants;
 import com.android.server.pm.ShortcutService.FileOutputStreamWithPath;
 import com.android.server.pm.ShortcutUser.PackageWithUser;
 
 import org.mockito.ArgumentCaptor;
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlSerializer;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.IOException;
+import java.io.InputStreamReader;
+import java.nio.charset.StandardCharsets;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Locale;
@@ -8089,4 +8098,70 @@
             }
         }
     }
+
+    public void testShareTargetInfo_saveToXml() throws IOException, XmlPullParserException {
+        List<ShareTargetInfo> expectedValues = new ArrayList<>();
+        expectedValues.add(new ShareTargetInfo(
+                new ShareTargetInfo.TargetData[]{new ShareTargetInfo.TargetData(
+                        "http", "www.google.com", "1234", "somePath", "somePathPattern",
+                        "somePathPrefix", "text/plain")}, "com.test.directshare.TestActivity1",
+                new String[]{"com.test.category.CATEGORY1", "com.test.category.CATEGORY2"}));
+        expectedValues.add(new ShareTargetInfo(new ShareTargetInfo.TargetData[]{
+                new ShareTargetInfo.TargetData(null, null, null, null, null, null, "video/mp4"),
+                new ShareTargetInfo.TargetData("content", null, null, null, null, null, "video/*")},
+                "com.test.directshare.TestActivity5",
+                new String[]{"com.test.category.CATEGORY5", "com.test.category.CATEGORY6"}));
+
+        // Write ShareTargets to Xml
+        ByteArrayOutputStream outStream = new ByteArrayOutputStream();
+        final XmlSerializer outXml = new FastXmlSerializer();
+        outXml.setOutput(outStream, StandardCharsets.UTF_8.name());
+        outXml.startDocument(null, true);
+        for (int i = 0; i < expectedValues.size(); i++) {
+            expectedValues.get(i).saveToXml(outXml);
+        }
+        outXml.endDocument();
+        outXml.flush();
+
+        // Read ShareTargets from Xml
+        ByteArrayInputStream inStream = new ByteArrayInputStream(outStream.toByteArray());
+        XmlPullParser parser = Xml.newPullParser();
+        parser.setInput(new InputStreamReader(inStream));
+        List<ShareTargetInfo> shareTargets = new ArrayList<>();
+        int type;
+        while ((type = parser.next()) != XmlPullParser.END_DOCUMENT) {
+            if (type == XmlPullParser.START_TAG && parser.getName().equals("share-target")) {
+                shareTargets.add(ShareTargetInfo.loadFromXml(parser));
+            }
+        }
+
+        // Assert two lists are equal
+        assertNotNull(shareTargets);
+        assertEquals(expectedValues.size(), shareTargets.size());
+
+        for (int i = 0; i < expectedValues.size(); i++) {
+            ShareTargetInfo expected = expectedValues.get(i);
+            ShareTargetInfo actual = shareTargets.get(i);
+
+            assertEquals(expected.mTargetData.length, actual.mTargetData.length);
+            for (int j = 0; j < expected.mTargetData.length; j++) {
+                assertEquals(expected.mTargetData[j].mScheme, actual.mTargetData[j].mScheme);
+                assertEquals(expected.mTargetData[j].mHost, actual.mTargetData[j].mHost);
+                assertEquals(expected.mTargetData[j].mPort, actual.mTargetData[j].mPort);
+                assertEquals(expected.mTargetData[j].mPath, actual.mTargetData[j].mPath);
+                assertEquals(expected.mTargetData[j].mPathPrefix,
+                        actual.mTargetData[j].mPathPrefix);
+                assertEquals(expected.mTargetData[j].mPathPattern,
+                        actual.mTargetData[j].mPathPattern);
+                assertEquals(expected.mTargetData[j].mMimeType, actual.mTargetData[j].mMimeType);
+            }
+
+            assertEquals(expected.mTargetClass, actual.mTargetClass);
+
+            assertEquals(expected.mCategories.length, actual.mCategories.length);
+            for (int j = 0; j < expected.mCategories.length; j++) {
+                assertEquals(expected.mCategories[j], actual.mCategories[j]);
+            }
+        }
+    }
 }
diff --git a/services/tests/wmtests/AndroidManifest.xml b/services/tests/wmtests/AndroidManifest.xml
index 4c27a3c..8c454424 100644
--- a/services/tests/wmtests/AndroidManifest.xml
+++ b/services/tests/wmtests/AndroidManifest.xml
@@ -36,6 +36,7 @@
     <uses-permission android:name="android.permission.READ_FRAME_BUFFER" />
     <uses-permission android:name="android.permission.WAKE_LOCK" />
     <uses-permission android:name="android.permission.REORDER_TASKS" />
+    <uses-permission android:name="android.permission.READ_DEVICE_CONFIG" />
 
     <!-- TODO: Remove largeHeap hack when memory leak is fixed (b/123984854) -->
     <application android:debuggable="true"
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
index 757267e5..bde0ef6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -262,6 +262,35 @@
     }
 
     @Test
+    public void testFindTaskAlias() {
+        final String targetActivity = "target.activity";
+        final String aliasActivity = "alias.activity";
+        final ComponentName target = new ComponentName(DEFAULT_COMPONENT_PACKAGE_NAME,
+                targetActivity);
+        final ComponentName alias = new ComponentName(DEFAULT_COMPONENT_PACKAGE_NAME,
+                aliasActivity);
+        final TaskRecord task = new TaskBuilder(mService.mStackSupervisor).setStack(mStack).build();
+        task.origActivity = alias;
+        task.realActivity = target;
+        new ActivityBuilder(mService).setComponent(target).setTask(task).setTargetActivity(
+                targetActivity).build();
+
+        // Using target activity to find task.
+        final ActivityRecord r1 = new ActivityBuilder(mService).setComponent(
+                target).setTargetActivity(targetActivity).build();
+        RootActivityContainer.FindTaskResult result = new RootActivityContainer.FindTaskResult();
+        mStack.findTaskLocked(r1, result);
+        assertThat(result.mRecord).isNotNull();
+
+        // Using alias activity to find task.
+        final ActivityRecord r2 = new ActivityBuilder(mService).setComponent(
+                alias).setTargetActivity(targetActivity).build();
+        result = new RootActivityContainer.FindTaskResult();
+        mStack.findTaskLocked(r2, result);
+        assertThat(result.mRecord).isNotNull();
+    }
+
+    @Test
     public void testMoveStackToBackIncludingParent() {
         final ActivityDisplay display = addNewActivityDisplayAt(ActivityDisplay.POSITION_TOP);
         final ActivityStack stack1 = createStackForShouldBeVisibleTest(display,
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 484fd3b..4a9b174 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2121,24 +2121,27 @@
      * @hide
      */
     @UnsupportedAppUsage
-    public @NonNull int[] getActiveSubscriptionIdList() {
-        int[] subId = null;
+    public static @NonNull int[] getActiveSubscriptionIdList() {
+        return getActiveSubscriptionIdList(true);
+    }
 
+    /**
+     * @return a non-null list of subId's that are active.
+     *
+     * @hide
+     */
+    public static @NonNull int[] getActiveSubscriptionIdList(boolean visibleOnly) {
         try {
             ISub iSub = ISub.Stub.asInterface(ServiceManager.getService("isub"));
             if (iSub != null) {
-                subId = iSub.getActiveSubIdList(/*visibleOnly*/true);
+                int[] subId = iSub.getActiveSubIdList(visibleOnly);
+                if (subId != null) return subId;
             }
         } catch (RemoteException ex) {
             // ignore it
         }
 
-        if (subId == null) {
-            subId = new int[0];
-        }
-
-        return subId;
-
+        return new int[0];
     }
 
     /**
diff --git a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
index 7a0ab9c..5b57c9d 100644
--- a/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
+++ b/telephony/java/com/android/internal/telephony/TelephonyPermissions.java
@@ -605,15 +605,11 @@
      */
     private static boolean checkCarrierPrivilegeForAnySubId(Context context,
             Supplier<ITelephony> telephonySupplier, int uid) {
-        SubscriptionManager sm = (SubscriptionManager) context.getSystemService(
-                Context.TELEPHONY_SUBSCRIPTION_SERVICE);
-        int[] activeSubIds = sm.getActiveSubscriptionIdList();
-        if (activeSubIds != null) {
-            for (int activeSubId : activeSubIds) {
-                if (getCarrierPrivilegeStatus(telephonySupplier, activeSubId, uid)
-                        == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
-                    return true;
-                }
+        int[] activeSubIds = SubscriptionManager.getActiveSubscriptionIdList(/*visibleOnly*/ false);
+        for (int activeSubId : activeSubIds) {
+            if (getCarrierPrivilegeStatus(telephonySupplier, activeSubId, uid)
+                    == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS) {
+                return true;
             }
         }
         return false;
diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
index 8ab71fd..a27df47 100644
--- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
+++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/RollbackTest.java
@@ -1058,6 +1058,10 @@
 
             Uninstall.packages(TestApp.A);
             Install.single(TestApp.A1).commit();
+
+            // Block the RollbackManager to make extra sure it will not be
+            // able to enable the rollback in time.
+            rm.blockRollbackManager(TimeUnit.SECONDS.toMillis(1));
             Install.single(TestApp.A2).setEnableRollback().commit();
 
             assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2);
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 2ce6b13..1b2a1288 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -71,6 +71,7 @@
 
 import static com.android.testutils.ConcurrentUtilsKt.await;
 import static com.android.testutils.ConcurrentUtilsKt.durationOf;
+import static com.android.testutils.ExceptionUtils.ignoreExceptions;
 import static com.android.testutils.HandlerUtilsKt.waitForIdleSerialExecutor;
 import static com.android.testutils.MiscAssertsKt.assertContainsExactly;
 import static com.android.testutils.MiscAssertsKt.assertEmpty;
@@ -205,8 +206,8 @@
 import com.android.server.connectivity.Vpn;
 import com.android.server.net.NetworkPinner;
 import com.android.server.net.NetworkPolicyManagerInternal;
+import com.android.testutils.ExceptionUtils;
 import com.android.testutils.HandlerUtilsKt;
-import com.android.testutils.ThrowingConsumer;
 
 import org.junit.After;
 import org.junit.Before;
@@ -227,7 +228,6 @@
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.Socket;
-import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -417,7 +417,7 @@
     }
 
     @Test
-    public void testWaitForIdle() {
+    public void testWaitForIdle() throws Exception {
         final int attempts = 50;  // Causes the test to take about 200ms on bullhead-eng.
 
         // Tests that waitForIdle returns immediately if the service is already idle.
@@ -444,7 +444,7 @@
     // This test has an inherent race condition in it, and cannot be enabled for continuous testing
     // or presubmit tests. It is kept for manual runs and documentation purposes.
     @Ignore
-    public void verifyThatNotWaitingForIdleCausesRaceConditions() {
+    public void verifyThatNotWaitingForIdleCausesRaceConditions() throws Exception {
         // Bring up a network that we can use to send messages to ConnectivityService.
         ConditionVariable cv = waitForConnectivityBroadcasts(1);
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
@@ -524,11 +524,11 @@
             mNmValidationRedirectUrl = null;
         }
 
-        MockNetworkAgent(int transport) {
+        MockNetworkAgent(int transport) throws Exception {
             this(transport, new LinkProperties());
         }
 
-        MockNetworkAgent(int transport, LinkProperties linkProperties) {
+        MockNetworkAgent(int transport, LinkProperties linkProperties) throws Exception {
             final int type = transportToLegacyType(transport);
             final String typeName = ConnectivityManager.getNetworkTypeName(type);
             mNetworkInfo = new NetworkInfo(type, 0, typeName, "Mock");
@@ -559,16 +559,12 @@
 
             mNetworkMonitor = mock(INetworkMonitor.class);
             final Answer validateAnswer = inv -> {
-                new Thread(this::onValidationRequested).start();
+                new Thread(ignoreExceptions(this::onValidationRequested)).start();
                 return null;
             };
 
-            try {
-                doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any());
-                doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
-            } catch (RemoteException e) {
-                fail(e.getMessage());
-            }
+            doAnswer(validateAnswer).when(mNetworkMonitor).notifyNetworkConnected(any(), any());
+            doAnswer(validateAnswer).when(mNetworkMonitor).forceReevaluation(anyInt());
 
             final ArgumentCaptor<Network> nmNetworkCaptor = ArgumentCaptor.forClass(Network.class);
             final ArgumentCaptor<INetworkMonitorCallbacks> nmCbCaptor =
@@ -623,35 +619,27 @@
             assertEquals(mNetworkAgent.netId, nmNetworkCaptor.getValue().netId);
             mNmCallbacks = nmCbCaptor.getValue();
 
-            try {
-                mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
-            } catch (RemoteException e) {
-                fail(e.getMessage());
-            }
+            mNmCallbacks.onNetworkMonitorCreated(mNetworkMonitor);
 
             // Waits for the NetworkAgent to be registered, which includes the creation of the
             // NetworkMonitor.
             waitForIdle();
         }
 
-        private void onValidationRequested() {
-            try {
-                if (mNmProvNotificationRequested
-                        && ((mNmValidationResult & NETWORK_VALIDATION_RESULT_VALID) != 0)) {
-                    mNmCallbacks.hideProvisioningNotification();
-                    mNmProvNotificationRequested = false;
-                }
+        private void onValidationRequested() throws Exception {
+            if (mNmProvNotificationRequested
+                    && ((mNmValidationResult & NETWORK_VALIDATION_RESULT_VALID) != 0)) {
+                mNmCallbacks.hideProvisioningNotification();
+                mNmProvNotificationRequested = false;
+            }
 
-                mNmCallbacks.notifyNetworkTested(
-                        mNmValidationResult, mNmValidationRedirectUrl);
+            mNmCallbacks.notifyNetworkTested(
+                    mNmValidationResult, mNmValidationRedirectUrl);
 
-                if (mNmValidationRedirectUrl != null) {
-                    mNmCallbacks.showProvisioningNotification(
-                            "test_provisioning_notif_action", "com.android.test.package");
-                    mNmProvNotificationRequested = true;
-                }
-            } catch (RemoteException e) {
-                fail(e.getMessage());
+            if (mNmValidationRedirectUrl != null) {
+                mNmCallbacks.showProvisioningNotification(
+                        "test_provisioning_notif_action", "com.android.test.package");
+                mNmProvNotificationRequested = true;
             }
         }
 
@@ -664,8 +652,8 @@
             return mScore;
         }
 
-        public void explicitlySelected(boolean acceptUnvalidated) {
-            mNetworkAgent.explicitlySelected(acceptUnvalidated);
+        public void explicitlySelected(boolean explicitlySelected, boolean acceptUnvalidated) {
+            mNetworkAgent.explicitlySelected(explicitlySelected, acceptUnvalidated);
         }
 
         public void addCapability(int capability) {
@@ -768,6 +756,11 @@
             connect(false);
         }
 
+        public void connectWithPartialValidConnectivity() {
+            setNetworkPartialValid();
+            connect(false);
+        }
+
         public void suspend() {
             mNetworkInfo.setDetailedState(DetailedState.SUSPENDED, null, null);
             mNetworkAgent.sendNetworkInfo(mNetworkInfo);
@@ -1249,18 +1242,13 @@
             waitForIdle(TIMEOUT_MS);
         }
 
-        public void setUidRulesChanged(int uidRules) {
-            try {
-                mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules);
-            } catch (RemoteException ignored) {
-            }
+        public void setUidRulesChanged(int uidRules) throws RemoteException {
+            mPolicyListener.onUidRulesChanged(Process.myUid(), uidRules);
         }
 
-        public void setRestrictBackgroundChanged(boolean restrictBackground) {
-            try {
-                mPolicyListener.onRestrictBackgroundChanged(restrictBackground);
-            } catch (RemoteException ignored) {
-            }
+        public void setRestrictBackgroundChanged(boolean restrictBackground)
+                throws RemoteException {
+            mPolicyListener.onRestrictBackgroundChanged(restrictBackground);
         }
     }
 
@@ -1815,12 +1803,9 @@
             return mLastAvailableNetwork;
         }
 
-        CallbackInfo nextCallback(int timeoutMs) {
+        CallbackInfo nextCallback(int timeoutMs) throws InterruptedException {
             CallbackInfo cb = null;
-            try {
-                cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
-            } catch (InterruptedException e) {
-            }
+            cb = mCallbacks.poll(timeoutMs, TimeUnit.MILLISECONDS);
             if (cb == null) {
                 // LinkedBlockingQueue.poll() returns null if it timeouts.
                 fail("Did not receive callback after " + timeoutMs + "ms");
@@ -1828,7 +1813,8 @@
             return cb;
         }
 
-        CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs) {
+        CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent, int timeoutMs)
+                throws Exception {
             final Network expectedNetwork = (agent != null) ? agent.getNetwork() : null;
             CallbackInfo expected = new CallbackInfo(state, expectedNetwork, 0);
             CallbackInfo actual = nextCallback(timeoutMs);
@@ -1845,15 +1831,16 @@
             return actual;
         }
 
-        CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent) {
+        CallbackInfo expectCallback(CallbackState state, MockNetworkAgent agent) throws Exception {
             return expectCallback(state, agent, TEST_CALLBACK_TIMEOUT_MS);
         }
 
-        CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn) {
+        CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn) throws Exception {
             return expectCallbackLike(fn, TEST_CALLBACK_TIMEOUT_MS);
         }
 
-        CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn, int timeoutMs) {
+        CallbackInfo expectCallbackLike(Predicate<CallbackInfo> fn, int timeoutMs)
+                throws Exception {
             int timeLeft = timeoutMs;
             while (timeLeft > 0) {
                 long start = SystemClock.elapsedRealtime();
@@ -1879,7 +1866,7 @@
         //        onCapabilitiesChanged callback.
         // @param timeoutMs how long to wait for the callbacks.
         void expectAvailableCallbacks(MockNetworkAgent agent, boolean expectSuspended,
-                boolean expectValidated, boolean expectBlocked, int timeoutMs) {
+                boolean expectValidated, boolean expectBlocked, int timeoutMs) throws Exception {
             expectCallback(CallbackState.AVAILABLE, agent, timeoutMs);
             if (expectSuspended) {
                 expectCallback(CallbackState.SUSPENDED, agent, timeoutMs);
@@ -1894,23 +1881,26 @@
         }
 
         // Expects the available callbacks (validated), plus onSuspended.
-        void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated) {
+        void expectAvailableAndSuspendedCallbacks(MockNetworkAgent agent, boolean expectValidated)
+                throws Exception {
             expectAvailableCallbacks(agent, true, expectValidated, false, TEST_CALLBACK_TIMEOUT_MS);
         }
 
-        void expectAvailableCallbacksValidated(MockNetworkAgent agent) {
+        void expectAvailableCallbacksValidated(MockNetworkAgent agent)
+                throws Exception {
             expectAvailableCallbacks(agent, false, true, false, TEST_CALLBACK_TIMEOUT_MS);
         }
 
-        void expectAvailableCallbacksValidatedAndBlocked(MockNetworkAgent agent) {
+        void expectAvailableCallbacksValidatedAndBlocked(MockNetworkAgent agent) throws Exception {
             expectAvailableCallbacks(agent, false, true, true, TEST_CALLBACK_TIMEOUT_MS);
         }
 
-        void expectAvailableCallbacksUnvalidated(MockNetworkAgent agent) {
+        void expectAvailableCallbacksUnvalidated(MockNetworkAgent agent) throws Exception {
             expectAvailableCallbacks(agent, false, false, false, TEST_CALLBACK_TIMEOUT_MS);
         }
 
-        void expectAvailableCallbacksUnvalidatedAndBlocked(MockNetworkAgent agent) {
+        void expectAvailableCallbacksUnvalidatedAndBlocked(MockNetworkAgent agent)
+                throws Exception {
             expectAvailableCallbacks(agent, false, false, true, TEST_CALLBACK_TIMEOUT_MS);
         }
 
@@ -1918,7 +1908,7 @@
         // VALIDATED capability), plus another onCapabilitiesChanged which is identical to the
         // one we just sent.
         // TODO: this is likely a bug. Fix it and remove this method.
-        void expectAvailableDoubleValidatedCallbacks(MockNetworkAgent agent) {
+        void expectAvailableDoubleValidatedCallbacks(MockNetworkAgent agent) throws Exception {
             expectCallback(CallbackState.AVAILABLE, agent, TEST_CALLBACK_TIMEOUT_MS);
             NetworkCapabilities nc1 = expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
             expectCallback(CallbackState.LINK_PROPERTIES, agent, TEST_CALLBACK_TIMEOUT_MS);
@@ -1932,48 +1922,53 @@
         // Expects the available callbacks where the onCapabilitiesChanged must not have validated,
         // then expects another onCapabilitiesChanged that has the validated bit set. This is used
         // when a network connects and satisfies a callback, and then immediately validates.
-        void expectAvailableThenValidatedCallbacks(MockNetworkAgent agent) {
+        void expectAvailableThenValidatedCallbacks(MockNetworkAgent agent) throws Exception {
             expectAvailableCallbacksUnvalidated(agent);
             expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, agent);
         }
 
-        NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent) {
+        NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent)
+                throws Exception {
             return expectCapabilitiesWith(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
         }
 
         NetworkCapabilities expectCapabilitiesWith(int capability, MockNetworkAgent agent,
-                int timeoutMs) {
+                int timeoutMs) throws Exception {
             CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
             NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
             assertTrue(nc.hasCapability(capability));
             return nc;
         }
 
-        NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent) {
+        NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent)
+                throws Exception {
             return expectCapabilitiesWithout(capability, agent, TEST_CALLBACK_TIMEOUT_MS);
         }
 
         NetworkCapabilities expectCapabilitiesWithout(int capability, MockNetworkAgent agent,
-                int timeoutMs) {
+                int timeoutMs) throws Exception {
             CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent, timeoutMs);
             NetworkCapabilities nc = (NetworkCapabilities) cbi.arg;
             assertFalse(nc.hasCapability(capability));
             return nc;
         }
 
-        void expectCapabilitiesLike(Predicate<NetworkCapabilities> fn, MockNetworkAgent agent) {
+        void expectCapabilitiesLike(Predicate<NetworkCapabilities> fn, MockNetworkAgent agent)
+                throws Exception {
             CallbackInfo cbi = expectCallback(CallbackState.NETWORK_CAPABILITIES, agent);
             assertTrue("Received capabilities don't match expectations : " + cbi.arg,
                     fn.test((NetworkCapabilities) cbi.arg));
         }
 
-        void expectLinkPropertiesLike(Predicate<LinkProperties> fn, MockNetworkAgent agent) {
+        void expectLinkPropertiesLike(Predicate<LinkProperties> fn, MockNetworkAgent agent)
+                throws Exception {
             CallbackInfo cbi = expectCallback(CallbackState.LINK_PROPERTIES, agent);
             assertTrue("Received LinkProperties don't match expectations : " + cbi.arg,
                     fn.test((LinkProperties) cbi.arg));
         }
 
-        void expectBlockedStatusCallback(boolean expectBlocked, MockNetworkAgent agent) {
+        void expectBlockedStatusCallback(boolean expectBlocked, MockNetworkAgent agent)
+                throws Exception {
             CallbackInfo cbi = expectCallback(CallbackState.BLOCKED_STATUS, agent);
             boolean actualBlocked = (boolean) cbi.arg;
             assertEquals(expectBlocked, actualBlocked);
@@ -2085,7 +2080,7 @@
     }
 
     @Test
-    public void testMultipleLingering() {
+    public void testMultipleLingering() throws Exception {
         // This test would be flaky with the default 120ms timer: that is short enough that
         // lingered networks are torn down before assertions can be run. We don't want to mock the
         // lingering timer to keep the WakeupMessage logic realistic: this has already proven useful
@@ -2340,7 +2335,7 @@
     }
 
     @Test
-    public void testNetworkGoesIntoBackgroundAfterLinger() {
+    public void testNetworkGoesIntoBackgroundAfterLinger() throws Exception {
         setAlwaysOnNetworks(true);
         NetworkRequest request = new NetworkRequest.Builder()
                 .clearCapabilities()
@@ -2385,7 +2380,7 @@
     }
 
     @Test
-    public void testExplicitlySelected() {
+    public void testExplicitlySelected() throws Exception {
         NetworkRequest request = new NetworkRequest.Builder()
                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
                 .build();
@@ -2399,7 +2394,7 @@
 
         // Bring up unvalidated wifi with explicitlySelected=true.
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.explicitlySelected(false);
+        mWiFiNetworkAgent.explicitlySelected(true, false);
         mWiFiNetworkAgent.connect(false);
         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
 
@@ -2422,7 +2417,7 @@
         mWiFiNetworkAgent.disconnect();
         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.explicitlySelected(false);
+        mWiFiNetworkAgent.explicitlySelected(true, false);
         mWiFiNetworkAgent.connect(false);
         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
 
@@ -2433,7 +2428,7 @@
 
         // Reconnect, again with explicitlySelected=true, but this time validate.
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.explicitlySelected(false);
+        mWiFiNetworkAgent.explicitlySelected(true, false);
         mWiFiNetworkAgent.connect(true);
         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
@@ -2448,14 +2443,36 @@
         assertEquals(mEthernetNetworkAgent.getNetwork(), mCm.getActiveNetwork());
         callback.assertNoCallback();
 
+        // Disconnect wifi, and then reconnect as if the user had selected "yes, don't ask again"
+        // (i.e., with explicitlySelected=true and acceptUnvalidated=true). Expect to switch to
+        // wifi immediately.
+        mWiFiNetworkAgent.disconnect();
+        callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+        mWiFiNetworkAgent.explicitlySelected(true, true);
+        mWiFiNetworkAgent.connect(false);
+        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        callback.expectCallback(CallbackState.LOSING, mEthernetNetworkAgent);
+        assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+        mEthernetNetworkAgent.disconnect();
+        callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
+
+        // Disconnect and reconnect with explicitlySelected=false and acceptUnvalidated=true.
+        // Check that the network is not scored specially and that the device prefers cell data.
+        mWiFiNetworkAgent.disconnect();
+        callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+        mWiFiNetworkAgent.explicitlySelected(false, true);
+        mWiFiNetworkAgent.connect(false);
+        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        assertEquals(mCellNetworkAgent.getNetwork(), mCm.getActiveNetwork());
+
         // Clean up.
         mWiFiNetworkAgent.disconnect();
         mCellNetworkAgent.disconnect();
-        mEthernetNetworkAgent.disconnect();
 
         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
         callback.expectCallback(CallbackState.LOST, mCellNetworkAgent);
-        callback.expectCallback(CallbackState.LOST, mEthernetNetworkAgent);
     }
 
     private int[] makeIntArray(final int size, final int value) {
@@ -2666,7 +2683,7 @@
     }
 
     @Test
-    public void testPartialConnectivity() {
+    public void testPartialConnectivity() throws Exception {
         // Register network callback.
         NetworkRequest request = new NetworkRequest.Builder()
                 .clearCapabilities().addCapability(NET_CAPABILITY_INTERNET)
@@ -2699,11 +2716,8 @@
         // If user accepts partial connectivity network,
         // NetworkMonitor#setAcceptPartialConnectivity() should be called too.
         waitForIdle();
-        try {
-            verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
-        } catch (RemoteException e) {
-            fail(e.getMessage());
-        }
+        verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
+
         // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
         // validated.
         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
@@ -2734,62 +2748,72 @@
         // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
         // acceptUnvalidated is also used as setting for accepting partial networks.
-        mWiFiNetworkAgent.explicitlySelected(true /* acceptUnvalidated */);
+        mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
+                true /* acceptUnvalidated */);
         mWiFiNetworkAgent.connect(true);
+
         // If user accepted partial connectivity network before,
         // NetworkMonitor#setAcceptPartialConnectivity() will be called in
         // ConnectivityService#updateNetworkInfo().
         waitForIdle();
-        try {
-            verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
-        } catch (RemoteException e) {
-            fail(e.getMessage());
-        }
+        verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
         nc = callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
         assertFalse(nc.hasCapability(NET_CAPABILITY_PARTIAL_CONNECTIVITY));
+
         // Wifi should be the default network.
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
         mWiFiNetworkAgent.disconnect();
         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
 
-        // If user accepted partial connectivity before, and now the device reconnects to the
-        // partial connectivity network. The network should be valid and contain
-        // NET_CAPABILITY_PARTIAL_CONNECTIVITY.
+        // The user accepted partial connectivity and selected "don't ask again". Now the user
+        // reconnects to the partial connectivity network. Switch to wifi as soon as partial
+        // connectivity is detected.
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
-        mWiFiNetworkAgent.explicitlySelected(true /* acceptUnvalidated */);
-        // Current design cannot send multi-testResult from NetworkMonitor to ConnectivityService.
-        // So, if user accepts partial connectivity, NetworkMonitor will send PARTIAL_CONNECTIVITY
-        // to ConnectivityService first then send VALID. Once NetworkMonitor support
-        // multi-testResult, this test case also need to be changed to meet the new design.
+        mWiFiNetworkAgent.explicitlySelected(true /* explicitlySelected */,
+                true /* acceptUnvalidated */);
         mWiFiNetworkAgent.connectWithPartialConnectivity();
         // If user accepted partial connectivity network before,
         // NetworkMonitor#setAcceptPartialConnectivity() will be called in
         // ConnectivityService#updateNetworkInfo().
         waitForIdle();
-        try {
-            verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
-        } catch (RemoteException e) {
-            fail(e.getMessage());
-        }
+        verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
         callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
         callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
-        // TODO: If the user accepted partial connectivity, we shouldn't switch to wifi until
-        // NetworkMonitor detects partial connectivity
         assertEquals(mWiFiNetworkAgent.getNetwork(), mCm.getActiveNetwork());
         callback.expectCapabilitiesWith(NET_CAPABILITY_PARTIAL_CONNECTIVITY, mWiFiNetworkAgent);
         mWiFiNetworkAgent.setNetworkValid();
+
         // Need a trigger point to let NetworkMonitor tell ConnectivityService that network is
         // validated.
         mCm.reportNetworkConnectivity(mWiFiNetworkAgent.getNetwork(), true);
         callback.expectCapabilitiesWith(NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
         mWiFiNetworkAgent.disconnect();
         callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
+
+        // If the user accepted partial connectivity, and the device auto-reconnects to the partial
+        // connectivity network, it should contain both PARTIAL_CONNECTIVITY and VALIDATED.
+        mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
+        mWiFiNetworkAgent.explicitlySelected(false /* explicitlySelected */,
+                true /* acceptUnvalidated */);
+
+        // NetworkMonitor will immediately (once the HTTPS probe fails...) report the network as
+        // valid, because ConnectivityService calls setAcceptPartialConnectivity before it calls
+        // notifyNetworkConnected.
+        mWiFiNetworkAgent.connectWithPartialValidConnectivity();
+        waitForIdle();
+        verify(mWiFiNetworkAgent.mNetworkMonitor, times(1)).setAcceptPartialConnectivity();
+        callback.expectAvailableCallbacksUnvalidated(mWiFiNetworkAgent);
+        callback.expectCallback(CallbackState.LOSING, mCellNetworkAgent);
+        callback.expectCapabilitiesWith(
+                NET_CAPABILITY_PARTIAL_CONNECTIVITY | NET_CAPABILITY_VALIDATED, mWiFiNetworkAgent);
+        mWiFiNetworkAgent.disconnect();
+        callback.expectCallback(CallbackState.LOST, mWiFiNetworkAgent);
     }
 
     @Test
-    public void testCaptivePortalOnPartialConnectivity() throws RemoteException {
+    public void testCaptivePortalOnPartialConnectivity() throws Exception {
         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
@@ -2838,7 +2862,7 @@
     }
 
     @Test
-    public void testCaptivePortal() {
+    public void testCaptivePortal() throws Exception {
         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
@@ -2890,7 +2914,7 @@
     }
 
     @Test
-    public void testCaptivePortalApp() throws RemoteException {
+    public void testCaptivePortalApp() throws Exception {
         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
@@ -2948,7 +2972,7 @@
     }
 
     @Test
-    public void testAvoidOrIgnoreCaptivePortals() {
+    public void testAvoidOrIgnoreCaptivePortals() throws Exception {
         final TestNetworkCallback captivePortalCallback = new TestNetworkCallback();
         final NetworkRequest captivePortalRequest = new NetworkRequest.Builder()
                 .addCapability(NET_CAPABILITY_CAPTIVE_PORTAL).build();
@@ -2988,7 +3012,7 @@
      * does work.
      */
     @Test
-    public void testNetworkSpecifier() {
+    public void testNetworkSpecifier() throws Exception {
         // A NetworkSpecifier subclass that matches all networks but must not be visible to apps.
         class ConfidentialMatchAllNetworkSpecifier extends NetworkSpecifier implements
                 Parcelable {
@@ -3177,7 +3201,7 @@
     }
 
     @Test
-    public void testNetworkSpecifierUidSpoofSecurityException() {
+    public void testNetworkSpecifierUidSpoofSecurityException() throws Exception {
         class UidAwareNetworkSpecifier extends NetworkSpecifier implements Parcelable {
             @Override
             public boolean satisfiedBy(NetworkSpecifier other) {
@@ -3790,7 +3814,7 @@
      * time-out period expires.
      */
     @Test
-    public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() {
+    public void testSatisfiedNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
                 NetworkCapabilities.TRANSPORT_WIFI).build();
         final TestNetworkCallback networkCallback = new TestNetworkCallback();
@@ -3810,7 +3834,7 @@
      * not trigger onUnavailable() once the time-out period expires.
      */
     @Test
-    public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() {
+    public void testSatisfiedThenLostNetworkRequestDoesNotTriggerOnUnavailable() throws Exception {
         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
                 NetworkCapabilities.TRANSPORT_WIFI).build();
         final TestNetworkCallback networkCallback = new TestNetworkCallback();
@@ -3833,7 +3857,7 @@
      * (somehow) satisfied - the callback isn't called later.
      */
     @Test
-    public void testTimedoutNetworkRequest() {
+    public void testTimedoutNetworkRequest() throws Exception {
         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
                 NetworkCapabilities.TRANSPORT_WIFI).build();
         final TestNetworkCallback networkCallback = new TestNetworkCallback();
@@ -3854,7 +3878,7 @@
      * trigger the callback.
      */
     @Test
-    public void testNoCallbackAfterUnregisteredNetworkRequest() {
+    public void testNoCallbackAfterUnregisteredNetworkRequest() throws Exception {
         NetworkRequest nr = new NetworkRequest.Builder().addTransportType(
                 NetworkCapabilities.TRANSPORT_WIFI).build();
         final TestNetworkCallback networkCallback = new TestNetworkCallback();
@@ -3946,7 +3970,7 @@
 
     private static class TestKeepaliveCallback extends PacketKeepaliveCallback {
 
-        public static enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR };
+        public enum CallbackType { ON_STARTED, ON_STOPPED, ON_ERROR }
 
         private class CallbackValue {
             public CallbackType callbackType;
@@ -3994,25 +4018,19 @@
             mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
         }
 
-        private void expectCallback(CallbackValue callbackValue) {
-            try {
-                assertEquals(
-                        callbackValue,
-                        mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-            } catch (InterruptedException e) {
-                fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
-            }
+        private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
+            assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
         }
 
-        public void expectStarted() {
+        public void expectStarted() throws Exception {
             expectCallback(new CallbackValue(CallbackType.ON_STARTED));
         }
 
-        public void expectStopped() {
+        public void expectStopped() throws Exception {
             expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
         }
 
-        public void expectError(int error) {
+        public void expectError(int error) throws Exception {
             expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
         }
     }
@@ -4073,25 +4091,20 @@
             mCallbacks.add(new CallbackValue(CallbackType.ON_ERROR, error));
         }
 
-        private void expectCallback(CallbackValue callbackValue) {
-            try {
-                assertEquals(
-                        callbackValue,
-                        mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
-            } catch (InterruptedException e) {
-                fail(callbackValue.callbackType + " callback not seen after " + TIMEOUT_MS + " ms");
-            }
+        private void expectCallback(CallbackValue callbackValue) throws InterruptedException {
+            assertEquals(callbackValue, mCallbacks.poll(TIMEOUT_MS, TimeUnit.MILLISECONDS));
+
         }
 
-        public void expectStarted() {
+        public void expectStarted() throws InterruptedException {
             expectCallback(new CallbackValue(CallbackType.ON_STARTED));
         }
 
-        public void expectStopped() {
+        public void expectStopped() throws InterruptedException {
             expectCallback(new CallbackValue(CallbackType.ON_STOPPED));
         }
 
-        public void expectError(int error) {
+        public void expectError(int error) throws InterruptedException {
             expectCallback(new CallbackValue(CallbackType.ON_ERROR, error));
         }
 
@@ -4102,7 +4115,7 @@
         }
     }
 
-    private Network connectKeepaliveNetwork(LinkProperties lp) {
+    private Network connectKeepaliveNetwork(LinkProperties lp) throws Exception {
         // Ensure the network is disconnected before we do anything.
         if (mWiFiNetworkAgent != null) {
             assertNull(mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()));
@@ -4236,7 +4249,8 @@
     }
 
     // Helper method to prepare the executor and run test
-    private void runTestWithSerialExecutors(ThrowingConsumer<Executor> functor) throws Exception {
+    private void runTestWithSerialExecutors(ExceptionUtils.ThrowingConsumer<Executor> functor)
+            throws Exception {
         final ExecutorService executorSingleThread = Executors.newSingleThreadExecutor();
         final Executor executorInline = (Runnable r) -> r.run();
         functor.accept(executorSingleThread);
@@ -4554,7 +4568,7 @@
     private static boolean isUdpPortInUse(int port) {
         try (DatagramSocket ignored = new DatagramSocket(port)) {
             return false;
-        } catch (IOException ignored) {
+        } catch (IOException alreadyInUse) {
             return true;
         }
     }
@@ -4566,23 +4580,19 @@
     }
 
     private static class TestNetworkPinner extends NetworkPinner {
-        public static boolean awaitPin(int timeoutMs) {
+        public static boolean awaitPin(int timeoutMs) throws InterruptedException {
             synchronized(sLock) {
                 if (sNetwork == null) {
-                    try {
-                        sLock.wait(timeoutMs);
-                    } catch (InterruptedException e) {}
+                    sLock.wait(timeoutMs);
                 }
                 return sNetwork != null;
             }
         }
 
-        public static boolean awaitUnpin(int timeoutMs) {
+        public static boolean awaitUnpin(int timeoutMs) throws InterruptedException {
             synchronized(sLock) {
                 if (sNetwork != null) {
-                    try {
-                        sLock.wait(timeoutMs);
-                    } catch (InterruptedException e) {}
+                    sLock.wait(timeoutMs);
                 }
                 return sNetwork == null;
             }
@@ -4605,7 +4615,7 @@
     }
 
     @Test
-    public void testNetworkPinner() {
+    public void testNetworkPinner() throws Exception {
         NetworkRequest wifiRequest = new NetworkRequest.Builder()
                 .addTransportType(TRANSPORT_WIFI)
                 .build();
@@ -4757,7 +4767,7 @@
     }
 
     @Test
-    public void testNetworkInfoOfTypeNone() {
+    public void testNetworkInfoOfTypeNone() throws Exception {
         ConditionVariable broadcastCV = waitForConnectivityBroadcasts(1);
 
         verifyNoNetwork();
@@ -4818,7 +4828,7 @@
     }
 
     @Test
-    public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() {
+    public void testLinkPropertiesEnsuresDirectlyConnectedRoutes() throws Exception {
         final NetworkRequest networkRequest = new NetworkRequest.Builder()
                 .addTransportType(TRANSPORT_WIFI).build();
         final TestNetworkCallback networkCallback = new TestNetworkCallback();
@@ -5226,7 +5236,7 @@
     }
 
     @Test
-    public void testVpnNetworkActive() {
+    public void testVpnNetworkActive() throws Exception {
         final int uid = Process.myUid();
 
         final TestNetworkCallback genericNetworkCallback = new TestNetworkCallback();
@@ -5338,7 +5348,7 @@
     }
 
     @Test
-    public void testVpnWithoutInternet() {
+    public void testVpnWithoutInternet() throws Exception {
         final int uid = Process.myUid();
 
         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
@@ -5368,7 +5378,7 @@
     }
 
     @Test
-    public void testVpnWithInternet() {
+    public void testVpnWithInternet() throws Exception {
         final int uid = Process.myUid();
 
         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
@@ -5451,7 +5461,7 @@
     }
 
     @Test
-    public void testVpnSetUnderlyingNetworks() {
+    public void testVpnSetUnderlyingNetworks() throws Exception {
         final int uid = Process.myUid();
 
         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
@@ -5549,7 +5559,7 @@
     }
 
     @Test
-    public void testNullUnderlyingNetworks() {
+    public void testNullUnderlyingNetworks() throws Exception {
         final int uid = Process.myUid();
 
         final TestNetworkCallback vpnNetworkCallback = new TestNetworkCallback();
@@ -5613,7 +5623,7 @@
     }
 
     @Test
-    public void testIsActiveNetworkMeteredOverWifi() {
+    public void testIsActiveNetworkMeteredOverWifi() throws Exception {
         // Returns true by default when no network is available.
         assertTrue(mCm.isActiveNetworkMetered());
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
@@ -5625,7 +5635,7 @@
     }
 
     @Test
-    public void testIsActiveNetworkMeteredOverCell() {
+    public void testIsActiveNetworkMeteredOverCell() throws Exception {
         // Returns true by default when no network is available.
         assertTrue(mCm.isActiveNetworkMetered());
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
@@ -5637,7 +5647,7 @@
     }
 
     @Test
-    public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() {
+    public void testIsActiveNetworkMeteredOverVpnTrackingPlatformDefault() throws Exception {
         // Returns true by default when no network is available.
         assertTrue(mCm.isActiveNetworkMetered());
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
@@ -5691,7 +5701,7 @@
     }
 
    @Test
-   public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() {
+   public void testIsActiveNetworkMeteredOverVpnSpecifyingUnderlyingNetworks() throws Exception {
         // Returns true by default when no network is available.
         assertTrue(mCm.isActiveNetworkMetered());
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
@@ -5762,7 +5772,7 @@
     }
 
     @Test
-    public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() {
+    public void testIsActiveNetworkMeteredOverAlwaysMeteredVpn() throws Exception {
         // Returns true by default when no network is available.
         assertTrue(mCm.isActiveNetworkMetered());
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
@@ -5809,7 +5819,7 @@
     }
 
     @Test
-    public void testNetworkBlockedStatus() {
+    public void testNetworkBlockedStatus() throws Exception {
         final TestNetworkCallback cellNetworkCallback = new TestNetworkCallback();
         final NetworkRequest cellRequest = new NetworkRequest.Builder()
                 .addTransportType(TRANSPORT_CELLULAR)
@@ -5860,7 +5870,7 @@
     }
 
     @Test
-    public void testNetworkBlockedStatusBeforeAndAfterConnect() {
+    public void testNetworkBlockedStatusBeforeAndAfterConnect() throws Exception {
         final TestNetworkCallback defaultCallback = new TestNetworkCallback();
         mCm.registerDefaultNetworkCallback(defaultCallback);
 
@@ -5929,7 +5939,7 @@
     }
 
     @Test
-    public void testStackedLinkProperties() throws UnknownHostException, RemoteException {
+    public void testStackedLinkProperties() throws Exception {
         final LinkAddress myIpv4 = new LinkAddress("1.2.3.4/24");
         final LinkAddress myIpv6 = new LinkAddress("2001:db8:1::1/64");
         final String kNat64PrefixString = "2001:db8:64:64:64:64::";
@@ -6092,7 +6102,7 @@
     }
 
     @Test
-    public void testDataActivityTracking() throws RemoteException {
+    public void testDataActivityTracking() throws Exception {
         final TestNetworkCallback networkCallback = new TestNetworkCallback();
         final NetworkRequest networkRequest = new NetworkRequest.Builder()
                 .addCapability(NET_CAPABILITY_INTERNET)
@@ -6167,21 +6177,17 @@
         mCm.unregisterNetworkCallback(networkCallback);
     }
 
-    private void verifyTcpBufferSizeChange(String tcpBufferSizes) {
+    private void verifyTcpBufferSizeChange(String tcpBufferSizes) throws Exception {
         String[] values = tcpBufferSizes.split(",");
         String rmemValues = String.join(" ", values[0], values[1], values[2]);
         String wmemValues = String.join(" ", values[3], values[4], values[5]);
         waitForIdle();
-        try {
-            verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
-        } catch (RemoteException e) {
-            fail("mMockNetd should never throw RemoteException");
-        }
+        verify(mMockNetd, atLeastOnce()).setTcpRWmemorySize(rmemValues, wmemValues);
         reset(mMockNetd);
     }
 
     @Test
-    public void testTcpBufferReset() {
+    public void testTcpBufferReset() throws Exception {
         final String testTcpBufferSizes = "1,2,3,4,5,6";
 
         mCellNetworkAgent = new MockNetworkAgent(TRANSPORT_CELLULAR);
@@ -6198,7 +6204,7 @@
     }
 
     @Test
-    public void testGetGlobalProxyForNetwork() {
+    public void testGetGlobalProxyForNetwork() throws Exception {
         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
         final Network wifiNetwork = mWiFiNetworkAgent.getNetwork();
@@ -6207,7 +6213,7 @@
     }
 
     @Test
-    public void testGetProxyForActiveNetwork() {
+    public void testGetProxyForActiveNetwork() throws Exception {
         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
         mWiFiNetworkAgent = new MockNetworkAgent(TRANSPORT_WIFI);
         mWiFiNetworkAgent.connect(true);
@@ -6224,7 +6230,7 @@
     }
 
     @Test
-    public void testGetProxyForVPN() {
+    public void testGetProxyForVPN() throws Exception {
         final ProxyInfo testProxyInfo = ProxyInfo.buildDirectProxy("test", 8888);
 
         // Set up a WiFi network with no proxy
@@ -6410,7 +6416,7 @@
 
 
     private MockNetworkAgent establishVpn(LinkProperties lp, int establishingUid,
-            Set<UidRange> vpnRange) {
+            Set<UidRange> vpnRange) throws Exception {
         final MockNetworkAgent vpnNetworkAgent = new MockNetworkAgent(TRANSPORT_VPN, lp);
         vpnNetworkAgent.getNetworkCapabilities().setEstablishingVpnAppUid(establishingUid);
         mMockVpn.setNetworkAgent(vpnNetworkAgent);
diff --git a/tools/aapt2/Android.bp b/tools/aapt2/Android.bp
index b13731f..1be4ea8 100644
--- a/tools/aapt2/Android.bp
+++ b/tools/aapt2/Android.bp
@@ -56,7 +56,7 @@
         "libziparchive",
         "libpng",
         "libbase",
-        "libprotobuf-cpp-lite",
+        "libprotobuf-cpp-full",
         "libz",
         "libbuildversion",
     ],
diff --git a/tools/aapt2/Configuration.proto b/tools/aapt2/Configuration.proto
index fc636a4..8a4644c 100644
--- a/tools/aapt2/Configuration.proto
+++ b/tools/aapt2/Configuration.proto
@@ -19,7 +19,6 @@
 package aapt.pb;
 
 option java_package = "com.android.aapt";
-option optimize_for = LITE_RUNTIME;
 
 // A description of the requirements a device must have in order for a
 // resource to be matched and selected.
diff --git a/tools/aapt2/Resources.proto b/tools/aapt2/Resources.proto
index 65f4652..7498e13 100644
--- a/tools/aapt2/Resources.proto
+++ b/tools/aapt2/Resources.proto
@@ -21,7 +21,6 @@
 package aapt.pb;
 
 option java_package = "com.android.aapt";
-option optimize_for = LITE_RUNTIME;
 
 // A string pool that wraps the binary form of the C++ class android::ResStringPool.
 message StringPool {
diff --git a/tools/aapt2/ResourcesInternal.proto b/tools/aapt2/ResourcesInternal.proto
index 520b242..b0ed3da3 100644
--- a/tools/aapt2/ResourcesInternal.proto
+++ b/tools/aapt2/ResourcesInternal.proto
@@ -22,7 +22,6 @@
 package aapt.pb.internal;
 
 option java_package = "android.aapt.pb.internal";
-option optimize_for = LITE_RUNTIME;
 
 // The top level message representing an external resource file (layout XML, PNG, etc).
 // This is used to represent a compiled file before it is linked. Only useful to aapt2.
diff --git a/tools/aapt2/io/Util.cpp b/tools/aapt2/io/Util.cpp
index ce6d9352..bb925c9 100644
--- a/tools/aapt2/io/Util.cpp
+++ b/tools/aapt2/io/Util.cpp
@@ -58,7 +58,7 @@
   return CopyFileToArchive(context, file, out_path, compression_flags, writer);
 }
 
-bool CopyProtoToArchive(IAaptContext* context, ::google::protobuf::MessageLite* proto_msg,
+bool CopyProtoToArchive(IAaptContext* context, ::google::protobuf::Message* proto_msg,
                         const std::string& out_path, uint32_t compression_flags,
                         IArchiveWriter* writer) {
   TRACE_CALL();
diff --git a/tools/aapt2/io/Util.h b/tools/aapt2/io/Util.h
index 5f978a8..5cb8206 100644
--- a/tools/aapt2/io/Util.h
+++ b/tools/aapt2/io/Util.h
@@ -19,7 +19,7 @@
 
 #include <string>
 
-#include "google/protobuf/message_lite.h"
+#include "google/protobuf/message.h"
 #include "google/protobuf/io/coded_stream.h"
 
 #include "format/Archive.h"
@@ -39,7 +39,7 @@
 bool CopyFileToArchivePreserveCompression(IAaptContext* context, IFile* file,
                                           const std::string& out_path, IArchiveWriter* writer);
 
-bool CopyProtoToArchive(IAaptContext* context, ::google::protobuf::MessageLite* proto_msg,
+bool CopyProtoToArchive(IAaptContext* context, ::google::protobuf::Message* proto_msg,
                         const std::string& out_path, uint32_t compression_flags,
                         IArchiveWriter* writer);
 
@@ -127,13 +127,13 @@
  public:
   explicit ProtoInputStreamReader(io::InputStream* in) : in_(in) { }
 
-  /** Deserializes a MessageLite proto from the current position in the input stream.*/
-  template <typename T> bool ReadMessage(T *message_lite) {
+  /** Deserializes a Message proto from the current position in the input stream.*/
+  template <typename T> bool ReadMessage(T *message) {
     ZeroCopyInputAdaptor adapter(in_);
     google::protobuf::io::CodedInputStream coded_stream(&adapter);
     coded_stream.SetTotalBytesLimit(std::numeric_limits<int32_t>::max(),
                                     coded_stream.BytesUntilTotalBytesLimit());
-    return message_lite->ParseFromCodedStream(&coded_stream);
+    return message->ParseFromCodedStream(&coded_stream);
   }
 
  private:
diff --git a/tools/dump-coverage/Android.bp b/tools/dump-coverage/Android.bp
new file mode 100644
index 0000000..4519ce3
--- /dev/null
+++ b/tools/dump-coverage/Android.bp
@@ -0,0 +1,29 @@
+//
+// 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.
+//
+
+// Build variants {target,host} x {32,64}
+cc_library {
+    name: "libdumpcoverage",
+    srcs: ["dump_coverage.cc"],
+    header_libs: [
+        "libopenjdkjvmti_headers",
+    ],
+
+    host_supported: true,
+    shared_libs: [
+        "libbase",
+    ],
+}
diff --git a/tools/dump-coverage/README.md b/tools/dump-coverage/README.md
new file mode 100644
index 0000000..2bab4bc
--- /dev/null
+++ b/tools/dump-coverage/README.md
@@ -0,0 +1,50 @@
+# dumpcoverage
+
+libdumpcoverage.so is a JVMTI agent designed to dump coverage information for a process, where the binaries have been instrumented by JaCoCo. JaCoCo automatically starts recording data on process start, and we need a way to trigger the resetting or dumping of this data.
+
+The JVMTI agent is used to make the calls to JaCoCo in its process.
+
+# Usage
+
+Note that these examples assume you have an instrumented build (userdebug_coverage). Here is, for example, how to dump coverage information regarding the default clock app. First some setup is necessary:
+
+```
+adb root # necessary to copy files in/out of the /data/data/{package} folder
+adb shell 'mkdir /data/data/com.android.deskclock/folder-to-use'
+```
+
+Then we can run the command to dump the data:
+
+```
+adb shell 'am attach-agent com.android.deskclock /system/lib/libdumpcoverage.so=dump:/data/data/com.android.deskclock/folder-to-use'
+```
+
+We can also reset the coverage information with
+
+```
+adb shell 'am attach-agent com.android.deskclock /system/lib/libdumpcoverage.so=reset'
+```
+
+then perform more actions, then dump the data again. To get the files, we can get
+
+```
+adb pull /data/data/com.android.deskclock/folder-to-use ~/path-on-your-computer
+```
+
+And you should have timestamped `.exec` files on your machine under the folder `~/path-on-your-computer`
+
+# Details
+
+In dump mode, the agent makes JNI calls equivalent to
+
+```
+Agent.getInstance().getExecutionData(/*reset = */ false);
+```
+
+and then saves the result to a file specified by the passed in directory
+
+In reset mode, it makes a JNI call equivalent to
+
+```
+Agent.getInstance().reset();
+```
diff --git a/tools/dump-coverage/dump_coverage.cc b/tools/dump-coverage/dump_coverage.cc
new file mode 100644
index 0000000..3de1865
--- /dev/null
+++ b/tools/dump-coverage/dump_coverage.cc
@@ -0,0 +1,239 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//      http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include <android-base/logging.h>
+#include <jni.h>
+#include <jvmti.h>
+#include <string.h>
+
+#include <atomic>
+#include <ctime>
+#include <fstream>
+#include <iomanip>
+#include <iostream>
+#include <istream>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <vector>
+
+using std::get;
+using std::tuple;
+using std::chrono::system_clock;
+
+namespace dump_coverage {
+
+#define CHECK_JVMTI(x) CHECK_EQ((x), JVMTI_ERROR_NONE)
+#define CHECK_NOTNULL(x) CHECK((x) != nullptr)
+#define CHECK_NO_EXCEPTION(env) CHECK(!(env)->ExceptionCheck());
+
+static JavaVM* java_vm = nullptr;
+
+// Get the current JNI environment.
+static JNIEnv* GetJNIEnv() {
+  JNIEnv* env = nullptr;
+  CHECK_EQ(java_vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6),
+           JNI_OK);
+  return env;
+}
+
+// Get the JaCoCo Agent class and an instance of the class, given a JNI
+// environment.
+// Will crash if the Agent isn't found or if any Java Exception occurs.
+static tuple<jclass, jobject> GetJavaAgent(JNIEnv* env) {
+  jclass java_agent_class =
+      env->FindClass("org/jacoco/agent/rt/internal/Agent");
+  CHECK_NOTNULL(java_agent_class);
+
+  jmethodID java_agent_get_instance =
+      env->GetStaticMethodID(java_agent_class, "getInstance",
+                             "()Lorg/jacoco/agent/rt/internal/Agent;");
+  CHECK_NOTNULL(java_agent_get_instance);
+
+  jobject java_agent_instance =
+      env->CallStaticObjectMethod(java_agent_class, java_agent_get_instance);
+  CHECK_NO_EXCEPTION(env);
+  CHECK_NOTNULL(java_agent_instance);
+
+  return tuple(java_agent_class, java_agent_instance);
+}
+
+// Runs equivalent of Agent.getInstance().getExecutionData(false) and returns
+// the result.
+// Will crash if the Agent isn't found or if any Java Exception occurs.
+static jbyteArray GetExecutionData(JNIEnv* env) {
+  auto java_agent = GetJavaAgent(env);
+  jmethodID java_agent_get_execution_data =
+      env->GetMethodID(get<0>(java_agent), "getExecutionData", "(Z)[B");
+  CHECK_NO_EXCEPTION(env);
+  CHECK_NOTNULL(java_agent_get_execution_data);
+
+  jbyteArray java_result_array = (jbyteArray)env->CallObjectMethod(
+      get<1>(java_agent), java_agent_get_execution_data, false);
+  CHECK_NO_EXCEPTION(env);
+
+  return java_result_array;
+}
+
+// Gets the filename to write execution data to
+//  dirname: the directory in which to place the file
+//  outputs <dirname>/YYYY-MM-DD-HH-MM-SS.SSS.exec
+static std::string GetFilename(const std::string& dirname) {
+  system_clock::time_point time_point = system_clock::now();
+  auto seconds = std::chrono::time_point_cast<std::chrono::seconds>(time_point);
+  auto fractional_time = time_point - seconds;
+  auto millis = std::chrono::duration_cast<std::chrono::milliseconds>(fractional_time);
+
+  std::time_t time = system_clock::to_time_t(time_point);
+  auto tm = *std::gmtime(&time);
+
+  std::ostringstream oss;
+  oss
+    << dirname
+    << "/"
+    << std::put_time(&tm, "%Y-%m-%d-%H-%M-%S.")
+    << std::setfill('0') << std::setw(3) << millis.count()
+    << ".ec";
+  return oss.str();
+}
+
+// Writes the execution data to a file
+//  data, length: represent the data, as a sequence of bytes
+//  dirname: directory name to contain the file
+//  returns JNI_ERR if there is an error in writing the file, otherwise JNI_OK.
+static jint WriteFile(const char* data, int length, const std::string& dirname) {
+  auto filename = GetFilename(dirname);
+
+  LOG(INFO) << "Writing file of length " << length << " to '" << filename
+            << "'";
+  std::ofstream file(filename, std::ios::binary);
+
+  if (!file.is_open()) {
+    LOG(ERROR) << "Could not open file: '" << filename << "'";
+    return JNI_ERR;
+  }
+  file.write(data, length);
+  file.close();
+
+  if (!file) {
+    LOG(ERROR) << "I/O error in reading file";
+    return JNI_ERR;
+  }
+
+  LOG(INFO) << "Done writing file";
+  return JNI_OK;
+}
+
+// Grabs execution data and writes it to a file
+//  dirname: directory name to contain the file
+//  returns JNI_ERR if there is an error writing the file.
+// Will crash if the Agent isn't found or if any Java Exception occurs.
+static jint Dump(const std::string& dirname) {
+  LOG(INFO) << "Dumping file";
+
+  JNIEnv* env = GetJNIEnv();
+  jbyteArray java_result_array = GetExecutionData(env);
+  CHECK_NOTNULL(java_result_array);
+
+  jbyte* result_ptr = env->GetByteArrayElements(java_result_array, 0);
+  CHECK_NOTNULL(result_ptr);
+
+  int result_len = env->GetArrayLength(java_result_array);
+
+  return WriteFile((const char*) result_ptr, result_len, dirname);
+}
+
+// Resets execution data, performing the equivalent of
+//  Agent.getInstance().reset();
+//  args: should be empty
+//  returns JNI_ERR if the arguments are invalid.
+// Will crash if the Agent isn't found or if any Java Exception occurs.
+static jint Reset(const std::string& args) {
+  if (args != "") {
+    LOG(ERROR) << "reset takes no arguments, but received '" << args << "'";
+    return JNI_ERR;
+  }
+
+  JNIEnv* env = GetJNIEnv();
+  auto java_agent = GetJavaAgent(env);
+
+  jmethodID java_agent_reset =
+      env->GetMethodID(get<0>(java_agent), "reset", "()V");
+  CHECK_NOTNULL(java_agent_reset);
+
+  env->CallVoidMethod(get<1>(java_agent), java_agent_reset);
+  CHECK_NO_EXCEPTION(env);
+  return JNI_OK;
+}
+
+// Given a string of the form "<a>:<b>" returns (<a>, <b>).
+// Given a string <a> that doesn't contain a colon, returns (<a>, "").
+static tuple<std::string, std::string> SplitOnColon(const std::string& options) {
+  size_t loc_delim = options.find(':');
+  std::string command, args;
+
+  if (loc_delim == std::string::npos) {
+    command = options;
+  } else {
+    command = options.substr(0, loc_delim);
+    args = options.substr(loc_delim + 1, options.length());
+  }
+  return tuple(command, args);
+}
+
+// Parses and executes a command specified by options of the form
+// "<command>:<args>" where <command> is either "dump" or "reset".
+static jint ParseOptionsAndExecuteCommand(const std::string& options) {
+  auto split = SplitOnColon(options);
+  auto command = get<0>(split), args = get<1>(split);
+
+  LOG(INFO) << "command: '" << command << "' args: '" << args << "'";
+
+  if (command == "dump") {
+    return Dump(args);
+  }
+
+  if (command == "reset") {
+    return Reset(args);
+  }
+
+  LOG(ERROR) << "Invalid command: expected 'dump' or 'reset' but was '"
+             << command << "'";
+  return JNI_ERR;
+}
+
+static jint AgentStart(JavaVM* vm, char* options) {
+  android::base::InitLogging(/* argv= */ nullptr);
+  java_vm = vm;
+
+  return ParseOptionsAndExecuteCommand(options);
+}
+
+// Late attachment (e.g. 'am attach-agent').
+extern "C" JNIEXPORT jint JNICALL
+Agent_OnAttach(JavaVM* vm, char* options, void* reserved ATTRIBUTE_UNUSED) {
+  return AgentStart(vm, options);
+}
+
+// Early attachment.
+extern "C" JNIEXPORT jint JNICALL
+Agent_OnLoad(JavaVM* jvm ATTRIBUTE_UNUSED, char* options ATTRIBUTE_UNUSED, void* reserved ATTRIBUTE_UNUSED) {
+  LOG(ERROR)
+    << "The dumpcoverage agent will not work on load,"
+    << " as it does not have access to the runtime.";
+  return JNI_ERR;
+}
+
+}  // namespace dump_coverage