Merge "Merge mContentCaptureSession and mCachedContentCaptureSession."
diff --git a/.mailmap b/.mailmap
new file mode 100644
index 0000000..b061ccf
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1 @@
+Ember Rose <emberr@google.com> <ashleyrose@google.com>
diff --git a/api/system-current.txt b/api/system-current.txt
index 4ed9633..1c5f772 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -3029,6 +3029,26 @@
     field public static final int STATUS_OK = 0; // 0x0
   }
 
+  public static final class SoundTrigger.ModuleProperties implements android.os.Parcelable {
+    method public int describeContents();
+    method public void writeToParcel(android.os.Parcel, int);
+    field @NonNull public static final android.os.Parcelable.Creator<android.hardware.soundtrigger.SoundTrigger.ModuleProperties> CREATOR;
+    field @NonNull public final String description;
+    field public final int id;
+    field @NonNull public final String implementor;
+    field public final int maxBufferMs;
+    field public final int maxKeyphrases;
+    field public final int maxSoundModels;
+    field public final int maxUsers;
+    field public final int powerConsumptionMw;
+    field public final int recognitionModes;
+    field public final boolean returnsTriggerInEvent;
+    field public final boolean supportsCaptureTransition;
+    field public final boolean supportsConcurrentCapture;
+    field @NonNull public final java.util.UUID uuid;
+    field public final int version;
+  }
+
   public static class SoundTrigger.RecognitionEvent {
     method @Nullable public android.media.AudioFormat getCaptureFormat();
     method public int getCaptureSession();
@@ -3771,6 +3791,7 @@
     method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public void deleteModel(java.util.UUID);
     method public int getDetectionServiceOperationsTimeout();
     method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public android.media.soundtrigger.SoundTriggerManager.Model getModel(java.util.UUID);
+    method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) @Nullable public android.hardware.soundtrigger.SoundTrigger.ModuleProperties getModuleProperties();
     method @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER) public void updateModel(android.media.soundtrigger.SoundTriggerManager.Model);
   }
 
@@ -8187,7 +8208,9 @@
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getPreferredNetworkTypeBitmask();
     method @RequiresPermission(anyOf={android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE, android.Manifest.permission.READ_PHONE_STATE}) public int getRadioPowerState();
     method public int getSimApplicationState();
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimApplicationState(int);
     method public int getSimCardState();
+    method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getSimCardState(int);
     method @Nullable @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public java.util.Locale getSimLocale();
     method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public long getSupportedRadioAccessFamily();
     method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public java.util.List<android.telephony.TelephonyHistogram> getTelephonyHistograms();
diff --git a/api/test-current.txt b/api/test-current.txt
index 16bdefa..43b9086 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -620,7 +620,6 @@
     method public int describeContents();
     method public static android.content.AutofillOptions forWhitelistingItself();
     method public boolean isAugmentedAutofillEnabled(@NonNull android.content.Context);
-    method public boolean isAutofillDisabledLocked(@NonNull android.content.ComponentName);
     method public void writeToParcel(android.os.Parcel, int);
     field @NonNull public static final android.os.Parcelable.Creator<android.content.AutofillOptions> CREATOR;
     field public long appDisabledExpiration;
diff --git a/config/hiddenapi-greylist.txt b/config/hiddenapi-greylist.txt
index 917ee6d..b4913c8 100644
--- a/config/hiddenapi-greylist.txt
+++ b/config/hiddenapi-greylist.txt
@@ -1150,8 +1150,6 @@
 Lcom/android/internal/statusbar/IStatusBarService$Stub;-><init>()V
 Lcom/android/internal/statusbar/IStatusBarService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/statusbar/IStatusBarService;
 Lcom/android/internal/telecom/ITelecomService$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telecom/ITelecomService;
-Lcom/android/internal/telephony/IIccPhoneBook$Stub$Proxy;->mRemote:Landroid/os/IBinder;
-Lcom/android/internal/telephony/IIccPhoneBook$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IIccPhoneBook;
 Lcom/android/internal/telephony/IMms$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IMms;
 Lcom/android/internal/telephony/IPhoneStateListener$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/IPhoneStateListener;
 Lcom/android/internal/telephony/IPhoneSubInfo$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
@@ -1159,7 +1157,6 @@
 Lcom/android/internal/telephony/IPhoneSubInfo$Stub;->TRANSACTION_getDeviceId:I
 Lcom/android/internal/telephony/ISms$Stub;-><init>()V
 Lcom/android/internal/telephony/ISms$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ISms;
-Lcom/android/internal/telephony/ISub$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Lcom/android/internal/telephony/ISub$Stub;->asInterface(Landroid/os/IBinder;)Lcom/android/internal/telephony/ISub;
 Lcom/android/internal/telephony/ITelephony$Stub$Proxy;-><init>(Landroid/os/IBinder;)V
 Lcom/android/internal/telephony/ITelephony$Stub$Proxy;->mRemote:Landroid/os/IBinder;
@@ -1183,5 +1180,4 @@
 Lcom/android/server/ResettableTimeout$T;-><init>(Lcom/android/server/ResettableTimeout;)V
 Lcom/google/android/gles_jni/EGLImpl;-><init>()V
 Lcom/google/android/gles_jni/GLImpl;-><init>()V
-Lcom/google/android/mms/pdu/PduParser;->$assertionsDisabled:Z
 Lcom/google/android/util/AbstractMessageParser$Token$Type;->values()[Lcom/google/android/util/AbstractMessageParser$Token$Type;
diff --git a/core/java/android/app/IActivityManager.aidl b/core/java/android/app/IActivityManager.aidl
index 48ca716..dbe50c3 100644
--- a/core/java/android/app/IActivityManager.aidl
+++ b/core/java/android/app/IActivityManager.aidl
@@ -287,7 +287,8 @@
     void handleApplicationStrictModeViolation(in IBinder app, int penaltyMask,
             in StrictMode.ViolationInfo crashInfo);
     boolean isTopActivityImmersive();
-    void crashApplication(int uid, int initialPid, in String packageName, int userId, in String message);
+    void crashApplication(int uid, int initialPid, in String packageName, int userId,
+            in String message, boolean force);
     @UnsupportedAppUsage
     String getProviderMimeType(in Uri uri, int userId);
     // Cause the specified process to dump the specified heap.
@@ -350,11 +351,13 @@
     // Request a heap dump for the system server.
     void requestSystemServerHeapDump();
 
-    // Deprecated - This method is only used by a few internal components and it will soon be
-    // replaced by a proper bug report API (which will be restricted to a few, pre-defined apps).
+    // Deprecated - This method is only used by a few internal components and it will soon start
+    // using bug report API (which will be restricted to a few, pre-defined apps).
     // No new code should be calling it.
     @UnsupportedAppUsage
     void requestBugReport(int bugreportType);
+    void requestBugReportWithDescription(in @nullable String shareTitle,
+                in @nullable String shareDescription, int bugreportType);
 
     /**
      *  Takes a telephony bug report and notifies the user with the title and description
@@ -369,7 +372,7 @@
     void requestTelephonyBugReport(in String shareTitle, in String shareDescription);
 
     /**
-     *  Deprecated - This method is only used by Wifi, and it will soon be replaced by a proper
+     *  Deprecated - This method is only used by Wifi, and it will soon start using
      *  bug report API.
      *
      *  Takes a minimal bugreport of Wifi-related state.
@@ -381,6 +384,12 @@
      *          parameters cannot be encoding to an UTF-8 charset.
      */
     void requestWifiBugReport(in String shareTitle, in String shareDescription);
+    void requestInteractiveBugReportWithDescription(in String shareTitle,
+            in String shareDescription);
+
+    void requestInteractiveBugReport();
+    void requestFullBugReport();
+    void requestRemoteBugReport();
 
     @UnsupportedAppUsage
     Intent getIntentForIntentSender(in IIntentSender sender);
diff --git a/core/java/android/app/role/RoleControllerService.java b/core/java/android/app/role/RoleControllerService.java
index 85db6a4..06623f9 100644
--- a/core/java/android/app/role/RoleControllerService.java
+++ b/core/java/android/app/role/RoleControllerService.java
@@ -279,6 +279,10 @@
     /**
      * Check whether an application is visible for a role.
      *
+     * While an application can be qualified for a role, it can still stay hidden from user (thus
+     * not visible). If an application is visible for a role, we may show things related to the role
+     * for it, e.g. showing an entry pointing to the role settings in its application info page.
+     *
      * @param roleName name of the role to check for
      * @param packageName package name of the application to check for
      *
diff --git a/core/java/android/bluetooth/BluetoothAdapter.java b/core/java/android/bluetooth/BluetoothAdapter.java
index 39d63de..e7ba85a 100644
--- a/core/java/android/bluetooth/BluetoothAdapter.java
+++ b/core/java/android/bluetooth/BluetoothAdapter.java
@@ -858,7 +858,10 @@
         if (DBG) {
             Log.d(TAG, "isLeEnabled(): " + BluetoothAdapter.nameForState(state));
         }
-        return (state == BluetoothAdapter.STATE_ON || state == BluetoothAdapter.STATE_BLE_ON);
+        return (state == BluetoothAdapter.STATE_ON
+                || state == BluetoothAdapter.STATE_BLE_ON
+                || state == BluetoothAdapter.STATE_TURNING_ON
+                || state == BluetoothAdapter.STATE_TURNING_OFF);
     }
 
     /**
diff --git a/core/java/android/bluetooth/BluetoothOutputStream.java b/core/java/android/bluetooth/BluetoothOutputStream.java
index a0aa2de..dfec4e1 100644
--- a/core/java/android/bluetooth/BluetoothOutputStream.java
+++ b/core/java/android/bluetooth/BluetoothOutputStream.java
@@ -75,4 +75,16 @@
         }
         mSocket.write(b, offset, count);
     }
+
+    /**
+     * Wait until the data in sending queue is emptied. A polling version
+     * for flush implementation. Use it to ensure the writing data afterwards will
+     * be packed in the new RFCOMM frame.
+     *
+     * @throws IOException if an i/o error occurs.
+     * @since Android 4.2.3
+     */
+    public void flush() throws IOException {
+        mSocket.flush();
+    }
 }
diff --git a/core/java/android/bluetooth/BluetoothSocket.java b/core/java/android/bluetooth/BluetoothSocket.java
index 760166b..a6e3153 100644
--- a/core/java/android/bluetooth/BluetoothSocket.java
+++ b/core/java/android/bluetooth/BluetoothSocket.java
@@ -515,6 +515,20 @@
         return mSocketIS.available();
     }
 
+    /**
+     * Wait until the data in sending queue is emptied. A polling version
+     * for flush implementation. Used to ensure the writing data afterwards will
+     * be packed in new RFCOMM frame.
+     *
+     * @throws IOException if an i/o error occurs.
+     */
+    @UnsupportedAppUsage
+    /*package*/ void flush() throws IOException {
+        if (mSocketOS == null) throw new IOException("flush is called on null OutputStream");
+        if (VDBG) Log.d(TAG, "flush: " + mSocketOS);
+        mSocketOS.flush();
+    }
+
     /*package*/ int read(byte[] b, int offset, int length) throws IOException {
         int ret = 0;
         if (VDBG) Log.d(TAG, "read in:  " + mSocketIS + " len: " + length);
diff --git a/core/java/android/content/AutofillOptions.java b/core/java/android/content/AutofillOptions.java
index 082663e..97b33b7 100644
--- a/core/java/android/content/AutofillOptions.java
+++ b/core/java/android/content/AutofillOptions.java
@@ -97,6 +97,8 @@
 
     /**
      * Returns if autofill is disabled by service to the given activity.
+     *
+     * @hide
      */
     public boolean isAutofillDisabledLocked(@NonNull ComponentName componentName) {
         final long elapsedTime = SystemClock.elapsedRealtime();
diff --git a/core/java/android/content/pm/AndroidTelephonyCommonUpdater.java b/core/java/android/content/pm/AndroidTelephonyCommonUpdater.java
new file mode 100644
index 0000000..1a720d5
--- /dev/null
+++ b/core/java/android/content/pm/AndroidTelephonyCommonUpdater.java
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.content.pm;
+
+import static android.content.pm.SharedLibraryNames.ANDROID_TELEPHONY_COMMON;
+
+
+import com.android.internal.compat.IPlatformCompat;
+import android.compat.annotation.ChangeId;
+import android.compat.annotation.EnabledAfter;
+import android.content.pm.PackageParser.Package;
+
+import android.os.Build.VERSION_CODES;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.ServiceManager;
+import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
+
+/**
+ * Updates a package to ensure that
+ * <ul>
+ * <li> if apps have target SDK < R, then telephony-common library is included by default to
+ * their class path. Even without <uses-library>.</li>
+ * <li> if apps with target SDK level >= R && have special permission (or Phone UID):
+ * apply <uses-library> on telephony-common should work.</li>
+ * <li> Otherwise not allow to use the lib.
+ * See {@link PackageSharedLibraryUpdater#removeLibrary(Package, String)}.</li>
+ * </ul>
+ *
+ * @hide
+ */
+@VisibleForTesting
+public class AndroidTelephonyCommonUpdater extends PackageSharedLibraryUpdater {
+
+    private static final String TAG = AndroidTelephonyCommonUpdater.class.getSimpleName();
+    /**
+     * Restrict telephony-common lib for apps having target SDK >= R
+     */
+    @ChangeId
+    @EnabledAfter(targetSdkVersion = VERSION_CODES.Q)
+    static final long RESTRICT_TELEPHONY_COMMON_CHANGE_ID = 139318877L;
+
+    private static boolean apkTargetsApiLevelLessThanROrCurrent(Package pkg) {
+        boolean shouldRestrict = false;
+        try {
+            IBinder b = ServiceManager.getService("platform_compat");
+            IPlatformCompat platformCompat = IPlatformCompat.Stub.asInterface(b);
+            shouldRestrict = platformCompat.isChangeEnabled(RESTRICT_TELEPHONY_COMMON_CHANGE_ID,
+                pkg.applicationInfo);
+        } catch (RemoteException ex) {
+            Log.e(TAG, ex.getMessage());
+        }
+        // TODO(b/139318877): remove version check for CUR_DEVELOPEMENT after clean up work.
+        return !shouldRestrict
+            || pkg.applicationInfo.targetSdkVersion == VERSION_CODES.CUR_DEVELOPMENT;
+    }
+
+    @Override
+    public void updatePackage(Package pkg) {
+        // for apps with targetSDKVersion < R include the library for backward compatibility.
+        if (apkTargetsApiLevelLessThanROrCurrent(pkg)) {
+            prefixRequiredLibrary(pkg, ANDROID_TELEPHONY_COMMON);
+        } else if (pkg.mSharedUserId == null || !pkg.mSharedUserId.equals("android.uid.phone")) {
+            // if apps target >= R
+            removeLibrary(pkg, ANDROID_TELEPHONY_COMMON);
+        }
+    }
+}
diff --git a/core/java/android/content/pm/PackageBackwardCompatibility.java b/core/java/android/content/pm/PackageBackwardCompatibility.java
index 4331bd4..797ba64b 100644
--- a/core/java/android/content/pm/PackageBackwardCompatibility.java
+++ b/core/java/android/content/pm/PackageBackwardCompatibility.java
@@ -51,6 +51,8 @@
 
         packageUpdaters.add(new AndroidHidlUpdater());
 
+        packageUpdaters.add(new AndroidTelephonyCommonUpdater());
+
         // Add this before adding AndroidTestBaseUpdater so that android.test.base comes before
         // android.test.mock.
         packageUpdaters.add(new AndroidTestRunnerSplitUpdater());
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index ef08bf5..4c970da 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -57,6 +57,7 @@
 import android.content.IntentFilter;
 import android.content.pm.PackageParserCacheHelper.ReadHelper;
 import android.content.pm.PackageParserCacheHelper.WriteHelper;
+import android.content.pm.permission.SplitPermissionInfoParcelable;
 import android.content.pm.split.DefaultSplitAssetLoader;
 import android.content.pm.split.SplitAssetDependencyLoader;
 import android.content.pm.split.SplitAssetLoader;
@@ -79,7 +80,6 @@
 import android.os.Trace;
 import android.os.UserHandle;
 import android.os.storage.StorageManager;
-import android.permission.PermissionManager;
 import android.system.ErrnoException;
 import android.system.OsConstants;
 import android.system.StructStat;
@@ -2528,11 +2528,17 @@
             Slog.i(TAG, newPermsMsg.toString());
         }
 
+        List<SplitPermissionInfoParcelable> splitPermissions;
 
-        final int NS = PermissionManager.SPLIT_PERMISSIONS.size();
-        for (int is=0; is<NS; is++) {
-            final PermissionManager.SplitPermissionInfo spi =
-                    PermissionManager.SPLIT_PERMISSIONS.get(is);
+        try {
+            splitPermissions = ActivityThread.getPermissionManager().getSplitPermissions();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+
+        final int listSize = splitPermissions.size();
+        for (int is = 0; is < listSize; is++) {
+            final SplitPermissionInfoParcelable spi = splitPermissions.get(is);
             if (pkg.applicationInfo.targetSdkVersion >= spi.getTargetSdk()
                     || !pkg.requestedPermissions.contains(spi.getSplitPermission())) {
                 continue;
@@ -8501,5 +8507,4 @@
             this.error = error;
         }
     }
-
 }
diff --git a/core/java/android/content/pm/SharedLibraryNames.java b/core/java/android/content/pm/SharedLibraryNames.java
index a607a9f..4c66fc0 100644
--- a/core/java/android/content/pm/SharedLibraryNames.java
+++ b/core/java/android/content/pm/SharedLibraryNames.java
@@ -33,4 +33,6 @@
     static final String ANDROID_TEST_RUNNER = "android.test.runner";
 
     public static final String ORG_APACHE_HTTP_LEGACY = "org.apache.http.legacy";
+
+    public static final String ANDROID_TELEPHONY_COMMON = "telephony-common";
 }
diff --git a/services/core/java/com/android/server/wm/SurfaceBuilderFactory.java b/core/java/android/content/pm/permission/SplitPermissionInfoParcelable.aidl
similarity index 62%
rename from services/core/java/com/android/server/wm/SurfaceBuilderFactory.java
rename to core/java/android/content/pm/permission/SplitPermissionInfoParcelable.aidl
index 5390e5a..d84454c 100644
--- a/services/core/java/com/android/server/wm/SurfaceBuilderFactory.java
+++ b/core/java/android/content/pm/permission/SplitPermissionInfoParcelable.aidl
@@ -1,11 +1,11 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
+/**
+ * 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
+ *     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,
@@ -14,12 +14,6 @@
  * limitations under the License.
  */
 
-package com.android.server.wm;
+ package android.content.pm.permission;
 
-import android.view.SurfaceSession;
-import android.view.SurfaceControl;
-
-interface SurfaceBuilderFactory {
-    SurfaceControl.Builder make(SurfaceSession s);
-};
-
+ parcelable SplitPermissionInfoParcelable;
\ No newline at end of file
diff --git a/core/java/android/content/pm/permission/SplitPermissionInfoParcelable.java b/core/java/android/content/pm/permission/SplitPermissionInfoParcelable.java
new file mode 100644
index 0000000..421ae49
--- /dev/null
+++ b/core/java/android/content/pm/permission/SplitPermissionInfoParcelable.java
@@ -0,0 +1,202 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm.permission;
+
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.android.internal.util.DataClass;
+import com.android.internal.util.Preconditions;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Parcelable version of {@link android.permission.PermissionManager.SplitPermissionInfo}
+ * @hide
+ */
+@DataClass(genEqualsHashCode = true)
+public class SplitPermissionInfoParcelable implements Parcelable {
+
+    /**
+     * The permission that is split.
+     */
+    @NonNull
+    private final String mSplitPermission;
+
+    /**
+     * The permissions that are added.
+     */
+    @NonNull
+    private final List<String> mNewPermissions;
+
+    /**
+     * The target API level when the permission was split.
+     */
+    @IntRange(from = 0)
+    private final int mTargetSdk;
+
+    private void onConstructed() {
+        Preconditions.checkCollectionElementsNotNull(mNewPermissions, "newPermissions");
+    }
+
+
+
+    // Code below generated by codegen v1.0.0.
+    //
+    // DO NOT MODIFY!
+    //
+    // To regenerate run:
+    // $ codegen $ANDROID_BUILD_TOP/frameworks/base/core/java/android/content/pm/permission/SplitPermissionInfoParcelable.java
+    //
+    // CHECKSTYLE:OFF Generated code
+
+    /**
+     * Creates a new SplitPermissionInfoParcelable.
+     *
+     * @param splitPermission
+     *   The permission that is split.
+     * @param newPermissions
+     *   The permissions that are added.
+     * @param targetSdk
+     *   The target API level when the permission was split.
+     */
+    @DataClass.Generated.Member
+    public SplitPermissionInfoParcelable(
+            @NonNull String splitPermission,
+            @NonNull List<String> newPermissions,
+            @IntRange(from = 0) int targetSdk) {
+        this.mSplitPermission = splitPermission;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mSplitPermission);
+        this.mNewPermissions = newPermissions;
+        com.android.internal.util.AnnotationValidations.validate(
+                NonNull.class, null, mNewPermissions);
+        this.mTargetSdk = targetSdk;
+        com.android.internal.util.AnnotationValidations.validate(
+                IntRange.class, null, mTargetSdk,
+                "from", 0);
+
+        onConstructed();
+    }
+
+    /**
+     * The permission that is split.
+     */
+    @DataClass.Generated.Member
+    public @NonNull String getSplitPermission() {
+        return mSplitPermission;
+    }
+
+    /**
+     * The permissions that are added.
+     */
+    @DataClass.Generated.Member
+    public @NonNull List<String> getNewPermissions() {
+        return mNewPermissions;
+    }
+
+    /**
+     * The target API level when the permission was split.
+     */
+    @DataClass.Generated.Member
+    public @IntRange(from = 0) int getTargetSdk() {
+        return mTargetSdk;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public boolean equals(Object o) {
+        // You can override field equality logic by defining either of the methods like:
+        // boolean fieldNameEquals(SplitPermissionInfoParcelable other) { ... }
+        // boolean fieldNameEquals(FieldType otherValue) { ... }
+
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+        @SuppressWarnings("unchecked")
+        SplitPermissionInfoParcelable that = (SplitPermissionInfoParcelable) o;
+        //noinspection PointlessBooleanExpression
+        return true
+                && Objects.equals(mSplitPermission, that.mSplitPermission)
+                && Objects.equals(mNewPermissions, that.mNewPermissions)
+                && mTargetSdk == that.mTargetSdk;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int hashCode() {
+        // You can override field hashCode logic by defining methods like:
+        // int fieldNameHashCode() { ... }
+
+        int _hash = 1;
+        _hash = 31 * _hash + Objects.hashCode(mSplitPermission);
+        _hash = 31 * _hash + Objects.hashCode(mNewPermissions);
+        _hash = 31 * _hash + mTargetSdk;
+        return _hash;
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public void writeToParcel(Parcel dest, int flags) {
+        // You can override field parcelling by defining methods like:
+        // void parcelFieldName(Parcel dest, int flags) { ... }
+
+        dest.writeString(mSplitPermission);
+        dest.writeStringList(mNewPermissions);
+        dest.writeInt(mTargetSdk);
+    }
+
+    @Override
+    @DataClass.Generated.Member
+    public int describeContents() { return 0; }
+
+    @DataClass.Generated.Member
+    public static final @NonNull Parcelable.Creator<SplitPermissionInfoParcelable> CREATOR
+            = new Parcelable.Creator<SplitPermissionInfoParcelable>() {
+        @Override
+        public SplitPermissionInfoParcelable[] newArray(int size) {
+            return new SplitPermissionInfoParcelable[size];
+        }
+
+        @Override
+        @SuppressWarnings({"unchecked", "RedundantCast"})
+        public SplitPermissionInfoParcelable createFromParcel(Parcel in) {
+            // You can override field unparcelling by defining methods like:
+            // static FieldType unparcelFieldName(Parcel in) { ... }
+
+            String splitPermission = in.readString();
+            List<String> newPermissions = new java.util.ArrayList<>();
+            in.readStringList(newPermissions);
+            int targetSdk = in.readInt();
+            return new SplitPermissionInfoParcelable(
+                    splitPermission,
+                    newPermissions,
+                    targetSdk);
+        }
+    };
+
+    @DataClass.Generated(
+            time = 1567634390477L,
+            codegenVersion = "1.0.0",
+            sourceFile = "frameworks/base/core/java/android/content/pm/permission/SplitPermissionInfoParcelable.java",
+            inputSignatures = "private final @android.annotation.NonNull java.lang.String mSplitPermission\nprivate final @android.annotation.NonNull java.util.List<java.lang.String> mNewPermissions\nprivate final @android.annotation.IntRange(from=0L) int mTargetSdk\nprivate  void onConstructed()\nclass SplitPermissionInfoParcelable extends java.lang.Object implements [android.os.Parcelable]\n@com.android.internal.util.DataClass(genEqualsHashCode=true)")
+    @Deprecated
+    private void __metadata() {}
+
+}
diff --git a/core/java/android/hardware/display/DisplayManager.java b/core/java/android/hardware/display/DisplayManager.java
index 21c49ad..0b25dbd 100644
--- a/core/java/android/hardware/display/DisplayManager.java
+++ b/core/java/android/hardware/display/DisplayManager.java
@@ -829,23 +829,36 @@
     public interface DeviceConfig {
 
         /**
-         * Key for accessing the 60 hz only regions.
+         * Key for refresh rate in the zone defined by thresholds.
+         *
+         * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
+         * @see android.R.integer#config_defaultZoneBehavior
+         */
+        String KEY_REFRESH_RATE_IN_ZONE = "refresh_rate_in_zone";
+
+        /**
+         * Key for accessing the display brightness thresholds for the configured refresh rate zone.
+         * The value will be a pair of comma separated integers representing the minimum and maximum
+         * thresholds of the zone, respectively, in display backlight units (i.e. [0, 255]).
          *
          * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
          * @see android.R.array#config_brightnessThresholdsOfPeakRefreshRate
          * @hide
          */
-        String KEY_PEAK_REFRESH_RATE_BRIGHTNESS_THRESHOLDS =
+        String KEY_PEAK_REFRESH_RATE_DISPLAY_BRIGHTNESS_THRESHOLDS =
                 "peak_refresh_rate_brightness_thresholds";
 
         /**
-         * Key for accessing the 60 hz only regions.
+         * Key for accessing the ambient brightness thresholds for the configured refresh rate zone.
+         * The value will be a pair of comma separated integers representing the minimum and maximum
+         * thresholds of the zone, respectively, in lux.
          *
          * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
-         * @see android.R.array#config_brightnessThresholdsOfPeakRefreshRate
+         * @see android.R.array#config_ambientThresholdsOfPeakRefreshRate
          * @hide
          */
-        String KEY_PEAK_REFRESH_RATE_AMBIENT_THRESHOLDS = "peak_refresh_rate_ambient_thresholds";
+        String KEY_PEAK_REFRESH_RATE_AMBIENT_BRIGHTNESS_THRESHOLDS =
+                "peak_refresh_rate_ambient_thresholds";
 
         /**
          * Key for default peak refresh rate
@@ -855,5 +868,16 @@
          * @hide
          */
         String KEY_PEAK_REFRESH_RATE_DEFAULT = "peak_refresh_rate_default";
+
+        /**
+         * Key for controlling which packages are explicitly blocked from running at refresh rates
+         * higher than 60hz. An app may be added to this list if they exhibit performance issues at
+         * higher refresh rates.
+         *
+         * @see android.provider.DeviceConfig#NAMESPACE_DISPLAY_MANAGER
+         * @see android.R.array#config_highRefreshRateBlacklist
+         * @hide
+         */
+        String KEY_HIGH_REFRESH_RATE_BLACKLIST = "high_refresh_rate_blacklist";
     }
 }
diff --git a/core/java/android/hardware/soundtrigger/SoundTrigger.java b/core/java/android/hardware/soundtrigger/SoundTrigger.java
index f96f47d..b1134e1 100644
--- a/core/java/android/hardware/soundtrigger/SoundTrigger.java
+++ b/core/java/android/hardware/soundtrigger/SoundTrigger.java
@@ -71,28 +71,27 @@
      * ID used to target any API call to this paricular module. Module
      * properties are returned by listModules() method.
      *
-     * @hide
      ****************************************************************************/
-    public static class ModuleProperties implements Parcelable {
+    public static final class ModuleProperties implements Parcelable {
         /** Unique module ID provided by the native service */
-        @UnsupportedAppUsage
         public final int id;
 
         /** human readable voice detection engine implementor */
+        @NonNull
         public final String implementor;
 
         /** human readable voice detection engine description */
+        @NonNull
         public final String description;
 
         /** Unique voice engine Id (changes with each version) */
-        @UnsupportedAppUsage
+        @NonNull
         public final UUID uuid;
 
         /** Voice detection engine version */
         public final int version;
 
         /** Maximum number of active sound models */
-        @UnsupportedAppUsage
         public final int maxSoundModels;
 
         /** Maximum number of key phrases */
@@ -120,7 +119,6 @@
          * recognition callback event */
         public final boolean returnsTriggerInEvent;
 
-        @UnsupportedAppUsage
         ModuleProperties(int id, String implementor, String description,
                 String uuid, int version, int maxSoundModels, int maxKeyphrases,
                 int maxUsers, int recognitionModes, boolean supportsCaptureTransition,
diff --git a/core/java/android/net/LocalSocketImpl.java b/core/java/android/net/LocalSocketImpl.java
index b066a15..fe7632c 100644
--- a/core/java/android/net/LocalSocketImpl.java
+++ b/core/java/android/net/LocalSocketImpl.java
@@ -157,6 +157,40 @@
                 write_native(b, myFd);
             }
         }
+
+        /**
+         * Wait until the data in sending queue is emptied. A polling version
+         * for flush implementation.
+         * @throws IOException
+         *             if an i/o error occurs.
+         */
+        @Override
+        public void flush() throws IOException {
+            FileDescriptor myFd = fd;
+            if (myFd == null) throw new IOException("socket closed");
+
+            // Loop until the output buffer is empty.
+            Int32Ref pending = new Int32Ref(0);
+            while (true) {
+                try {
+                    // See linux/net/unix/af_unix.c
+                    Os.ioctlInt(myFd, OsConstants.TIOCOUTQ, pending);
+                } catch (ErrnoException e) {
+                    throw e.rethrowAsIOException();
+                }
+
+                if (pending.value <= 0) {
+                    // The output buffer is empty.
+                    break;
+                }
+
+                try {
+                    Thread.sleep(10);
+                } catch (InterruptedException ie) {
+                    break;
+                }
+            }
+        }
     }
 
     private native int read_native(FileDescriptor fd) throws IOException;
diff --git a/core/java/android/permission/IPermissionManager.aidl b/core/java/android/permission/IPermissionManager.aidl
index 9fa5f16..60c8811 100644
--- a/core/java/android/permission/IPermissionManager.aidl
+++ b/core/java/android/permission/IPermissionManager.aidl
@@ -19,6 +19,7 @@
 import android.content.pm.ParceledListSlice;
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
+import android.content.pm.permission.SplitPermissionInfoParcelable;
 import android.permission.IOnPermissionsChangeListener;
 
 /**
@@ -97,4 +98,6 @@
             String packageName, int userId);
 
     boolean isPermissionRevokedByPolicy(String permName, String packageName, int userId);
+
+    List<SplitPermissionInfoParcelable> getSplitPermissions();
 }
diff --git a/core/java/android/permission/PermissionManager.java b/core/java/android/permission/PermissionManager.java
index 5e35958..6c4ee01 100644
--- a/core/java/android/permission/PermissionManager.java
+++ b/core/java/android/permission/PermissionManager.java
@@ -24,16 +24,18 @@
 import android.annotation.SystemApi;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
+import android.app.ActivityThread;
 import android.content.Context;
 import android.content.pm.IPackageManager;
+import android.content.pm.permission.SplitPermissionInfoParcelable;
 import android.os.RemoteException;
+import android.util.Slog;
 
 import com.android.internal.annotations.Immutable;
-import com.android.server.SystemConfig;
 
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
-import java.util.Objects;
 
 /**
  * System level service for accessing the permission capabilities of the platform.
@@ -44,6 +46,8 @@
 @SystemApi
 @SystemService(Context.PERMISSION_SERVICE)
 public final class PermissionManager {
+    private static final String TAG = PermissionManager.class.getName();
+
     /** @hide */
     public static final String KILL_APP_REASON_PERMISSIONS_REVOKED =
             "permissions revoked";
@@ -51,19 +55,12 @@
     public static final String KILL_APP_REASON_GIDS_CHANGED =
             "permission grant or revoke changed gids";
 
-
-    /**
-     * {@link android.content.pm.PackageParser} needs access without having a {@link Context}.
-     *
-     * @hide
-     */
-    public static final ArrayList<SplitPermissionInfo> SPLIT_PERMISSIONS =
-            SystemConfig.getInstance().getSplitPermissions();
-
     private final @NonNull Context mContext;
 
     private final IPackageManager mPackageManager;
 
+    private List<SplitPermissionInfo> mSplitPermissionInfos;
+
     /**
      * Creates a new instance.
      *
@@ -131,7 +128,48 @@
      * @return All permissions that are split.
      */
     public @NonNull List<SplitPermissionInfo> getSplitPermissions() {
-        return SPLIT_PERMISSIONS;
+        if (mSplitPermissionInfos != null) {
+            return mSplitPermissionInfos;
+        }
+
+        List<SplitPermissionInfoParcelable> parcelableList;
+        try {
+            parcelableList = ActivityThread.getPermissionManager().getSplitPermissions();
+        } catch (RemoteException e) {
+            Slog.e(TAG, "Error getting split permissions", e);
+            return Collections.emptyList();
+        }
+
+        mSplitPermissionInfos = splitPermissionInfoListToNonParcelableList(parcelableList);
+
+        return mSplitPermissionInfos;
+    }
+
+    private List<SplitPermissionInfo> splitPermissionInfoListToNonParcelableList(
+            List<SplitPermissionInfoParcelable> parcelableList) {
+        final int size = parcelableList.size();
+        List<SplitPermissionInfo> list = new ArrayList<>(size);
+        for (int i = 0; i < size; i++) {
+            list.add(new SplitPermissionInfo(parcelableList.get(i)));
+        }
+        return list;
+    }
+
+    /**
+     * Converts a {@link List} of {@link SplitPermissionInfo} into a List of
+     * {@link SplitPermissionInfoParcelable} and returns it.
+     * @hide
+     */
+    public static List<SplitPermissionInfoParcelable> splitPermissionInfoListToParcelableList(
+            List<SplitPermissionInfo> splitPermissionsList) {
+        final int size = splitPermissionsList.size();
+        List<SplitPermissionInfoParcelable> outList = new ArrayList<>(size);
+        for (int i = 0; i < size; i++) {
+            SplitPermissionInfo info = splitPermissionsList.get(i);
+            outList.add(new SplitPermissionInfoParcelable(
+                    info.getSplitPermission(), info.getNewPermissions(), info.getTargetSdk()));
+        }
+        return outList;
     }
 
     /**
@@ -140,44 +178,40 @@
      */
     @Immutable
     public static final class SplitPermissionInfo {
-        private final @NonNull String mSplitPerm;
-        private final @NonNull List<String> mNewPerms;
-        private final int mTargetSdk;
+        private @NonNull final SplitPermissionInfoParcelable mSplitPermissionInfoParcelable;
 
         @Override
         public boolean equals(@Nullable Object o) {
             if (this == o) return true;
             if (o == null || getClass() != o.getClass()) return false;
             SplitPermissionInfo that = (SplitPermissionInfo) o;
-            return mTargetSdk == that.mTargetSdk
-                    && mSplitPerm.equals(that.mSplitPerm)
-                    && mNewPerms.equals(that.mNewPerms);
+            return mSplitPermissionInfoParcelable.equals(that.mSplitPermissionInfoParcelable);
         }
 
         @Override
         public int hashCode() {
-            return Objects.hash(mSplitPerm, mNewPerms, mTargetSdk);
+            return mSplitPermissionInfoParcelable.hashCode();
         }
 
         /**
          * Get the permission that is split.
          */
         public @NonNull String getSplitPermission() {
-            return mSplitPerm;
+            return mSplitPermissionInfoParcelable.getSplitPermission();
         }
 
         /**
          * Get the permissions that are added.
          */
         public @NonNull List<String> getNewPermissions() {
-            return mNewPerms;
+            return mSplitPermissionInfoParcelable.getNewPermissions();
         }
 
         /**
          * Get the target API level when the permission was split.
          */
         public int getTargetSdk() {
-            return mTargetSdk;
+            return mSplitPermissionInfoParcelable.getTargetSdk();
         }
 
         /**
@@ -191,9 +225,11 @@
          */
         public SplitPermissionInfo(@NonNull String splitPerm, @NonNull List<String> newPerms,
                 int targetSdk) {
-            mSplitPerm = splitPerm;
-            mNewPerms = newPerms;
-            mTargetSdk = targetSdk;
+            this(new SplitPermissionInfoParcelable(splitPerm, newPerms, targetSdk));
+        }
+
+        private SplitPermissionInfo(@NonNull SplitPermissionInfoParcelable parcelable) {
+            mSplitPermissionInfoParcelable = parcelable;
         }
     }
 }
diff --git a/core/java/android/provider/DeviceConfig.java b/core/java/android/provider/DeviceConfig.java
index 4b9daf1..5e201e4 100644
--- a/core/java/android/provider/DeviceConfig.java
+++ b/core/java/android/provider/DeviceConfig.java
@@ -367,15 +367,6 @@
          */
         String KEY_SYSTEM_GESTURE_EXCLUSION_LOG_DEBOUNCE_MILLIS =
                 "system_gesture_exclusion_log_debounce_millis";
-
-        /**
-         * Key for controlling which packages are explicitly blocked from running at refresh rates
-         * higher than 90hz.
-         *
-         * @see android.provider.DeviceConfig#NAMESPACE_WINDOW_MANAGER
-         * @hide
-         */
-        String KEY_HIGH_REFRESH_RATE_BLACKLIST = "high_refresh_rate_blacklist";
     }
 
     private static final Object sLock = new Object();
diff --git a/core/java/android/service/euicc/EuiccService.java b/core/java/android/service/euicc/EuiccService.java
index d2f22bf..ff8b135 100644
--- a/core/java/android/service/euicc/EuiccService.java
+++ b/core/java/android/service/euicc/EuiccService.java
@@ -29,7 +29,6 @@
 import android.telephony.euicc.DownloadableSubscription;
 import android.telephony.euicc.EuiccInfo;
 import android.telephony.euicc.EuiccManager.OtaStatus;
-import android.util.ArraySet;
 import android.util.Log;
 
 import java.lang.annotation.Retention;
@@ -252,18 +251,6 @@
     public static final int RESULT_FIRST_USER = 1;
 
     /**
-     * List of all valid resolution actions for validation purposes.
-     * @hide
-     */
-    public static final ArraySet<String> RESOLUTION_ACTIONS;
-    static {
-        RESOLUTION_ACTIONS = new ArraySet<>();
-        RESOLUTION_ACTIONS.add(EuiccService.ACTION_RESOLVE_DEACTIVATE_SIM);
-        RESOLUTION_ACTIONS.add(EuiccService.ACTION_RESOLVE_NO_PRIVILEGES);
-        RESOLUTION_ACTIONS.add(EuiccService.ACTION_RESOLVE_RESOLVABLE_ERRORS);
-    }
-
-    /**
      * Boolean extra for resolution actions indicating whether the user granted consent.
      * This is used and set by the implementation and used in {@code EuiccOperation}.
      */
diff --git a/core/java/android/view/GestureExclusionTracker.java b/core/java/android/view/GestureExclusionTracker.java
index fcc14c1..fffb323e 100644
--- a/core/java/android/view/GestureExclusionTracker.java
+++ b/core/java/android/view/GestureExclusionTracker.java
@@ -44,7 +44,7 @@
         while (i.hasNext()) {
             final GestureExclusionViewInfo info = i.next();
             final View v = info.getView();
-            if (v == null || !v.isAttachedToWindow() || !v.isShown()) {
+            if (v == null || !v.isAttachedToWindow() || !v.isAggregatedVisible()) {
                 mGestureExclusionViewsChanged = true;
                 i.remove();
                 continue;
@@ -123,7 +123,7 @@
         public int update() {
             final View excludedView = getView();
             if (excludedView == null || !excludedView.isAttachedToWindow()
-                    || !excludedView.isShown()) return GONE;
+                    || !excludedView.isAggregatedVisible()) return GONE;
             final List<Rect> localRects = excludedView.getSystemGestureExclusionRects();
             final List<Rect> newRects = new ArrayList<>(localRects.size());
             for (Rect src : localRects) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 0a24940..7ee3973 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -14327,6 +14327,14 @@
     }
 
     /**
+     * @return true if this view and all ancestors are visible as of the last
+     * {@link #onVisibilityAggregated(boolean)} call.
+     */
+    boolean isAggregatedVisible() {
+        return (mPrivateFlags3 & PFLAG3_AGGREGATED_VISIBLE) != 0;
+    }
+
+    /**
      * Internal dispatching method for {@link #onVisibilityAggregated}. Overridden by
      * ViewGroup. Intended to only be called when {@link #isAttachedToWindow()},
      * {@link #getWindowVisibility()} is {@link #VISIBLE} and this view's parent {@link #isShown()}.
@@ -14354,7 +14362,7 @@
     @CallSuper
     public void onVisibilityAggregated(boolean isVisible) {
         // Update our internal visibility tracking so we can detect changes
-        boolean oldVisible = (mPrivateFlags3 & PFLAG3_AGGREGATED_VISIBLE) != 0;
+        boolean oldVisible = isAggregatedVisible();
         mPrivateFlags3 = isVisible ? (mPrivateFlags3 | PFLAG3_AGGREGATED_VISIBLE)
                 : (mPrivateFlags3 & ~PFLAG3_AGGREGATED_VISIBLE);
         if (isVisible && mAttachInfo != null) {
@@ -14406,7 +14414,9 @@
         }
 
         notifyAppearedOrDisappearedForContentCaptureIfNeeded(isVisible);
-        updateSystemGestureExclusionRects();
+        if (isVisible != oldVisible) {
+            updateSystemGestureExclusionRects();
+        }
     }
 
     /**
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index d302c2b..032af1c 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -707,9 +707,10 @@
                         if (mBindSequence != bindSequence) {
                             return;
                         }
-                        if (matrixValues == null) {
-                            // That this app is unbound from the parent ActivityView. In this case,
-                            // calling updateCursorAnchorInfo() isn't safe.  Only clear the matrix.
+                        if (matrixValues == null || mActivityViewToScreenMatrix == null) {
+                            // Either InputBoundResult#mActivityViewToScreenMatrixValues is null
+                            // OR this app is unbound from the parent ActivityView. In this case,
+                            // calling updateCursorAnchorInfo() isn't safe. Only clear the matrix.
                             mActivityViewToScreenMatrix = null;
                             return;
                         }
diff --git a/core/java/android/view/inspector/OWNERS b/core/java/android/view/inspector/OWNERS
index 0473f54..4554fdc 100644
--- a/core/java/android/view/inspector/OWNERS
+++ b/core/java/android/view/inspector/OWNERS
@@ -1,3 +1,3 @@
 alanv@google.com
-ashleyrose@google.com
-aurimas@google.com
\ No newline at end of file
+aurimas@google.com
+emberr@google.com
diff --git a/core/java/com/android/internal/app/ISoundTriggerService.aidl b/core/java/com/android/internal/app/ISoundTriggerService.aidl
index 764c0cf..ea24d5f 100644
--- a/core/java/com/android/internal/app/ISoundTriggerService.aidl
+++ b/core/java/com/android/internal/app/ISoundTriggerService.aidl
@@ -54,4 +54,6 @@
     boolean isRecognitionActive(in ParcelUuid parcelUuid);
 
     int getModelState(in ParcelUuid soundModelId);
+
+    @nullable SoundTrigger.ModuleProperties getModuleProperties();
 }
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index 364278d..7cd3e95 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -53,6 +53,8 @@
 
 /**
  * Loads global system configuration info.
+ * Note: Initializing this class hits the disk and is slow.  This class should generally only be
+ * accessed by the system_server process.
  */
 public class SystemConfig {
     static final String TAG = "SystemConfig";
@@ -208,6 +210,11 @@
     private final ArraySet<String> mBugreportWhitelistedPackages = new ArraySet<>();
 
     public static SystemConfig getInstance() {
+        if (!isSystemProcess()) {
+            Slog.wtf(TAG, "SystemConfig is being accessed by a process other than "
+                    + "system_server.");
+        }
+
         synchronized (SystemConfig.class) {
             if (sInstance == null) {
                 sInstance = new SystemConfig();
@@ -1161,4 +1168,8 @@
             mSplitPermissions.add(new SplitPermissionInfo(splitPerm, newPermissions, targetSdk));
         }
     }
+
+    private static boolean isSystemProcess() {
+        return Process.myUid() == Process.SYSTEM_UID;
+    }
 }
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 2d7069c..a52a7ed 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -28,7 +28,11 @@
 #include <meminfo/sysmeminfo.h>
 #include <processgroup/processgroup.h>
 #include <processgroup/sched_policy.h>
+#include <android-base/unique_fd.h>
 
+#include <algorithm>
+#include <limits>
+#include <memory>
 #include <string>
 #include <vector>
 
@@ -58,8 +62,18 @@
 
 static const bool kDebugPolicy = false;
 static const bool kDebugProc = false;
-// When reading `proc` files, how many bytes to read at a time
-static const int kReadSize = 4096;
+
+// Stack reservation for reading small proc files.  Most callers of
+// readProcFile() are reading files under this threshold, e.g.,
+// /proc/pid/stat.  /proc/pid/time_in_state ends up being about 520
+// bytes, so use 1024 for the stack to provide a bit of slack.
+static const ssize_t kProcReadStackBufferSize = 1024;
+
+// The other files we read from proc tend to be a bit larger (e.g.,
+// /proc/stat is about 3kB), so once we exhaust the stack buffer,
+// retry with a relatively large heap-allocated buffer.  We double
+// this size and retry until the whole file fits.
+static const ssize_t kProcReadMinHeapBufferSize = 4096;
 
 #if GUARD_THREAD_PRIORITY
 Mutex gKeyCreateMutex;
@@ -1004,9 +1018,9 @@
         jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
         return JNI_FALSE;
     }
-    int fd = open(file8, O_RDONLY | O_CLOEXEC);
 
-    if (fd < 0) {
+    ::android::base::unique_fd fd(open(file8, O_RDONLY | O_CLOEXEC));
+    if (!fd.ok()) {
         if (kDebugProc) {
             ALOGW("Unable to open process file: %s\n", file8);
         }
@@ -1015,35 +1029,52 @@
     }
     env->ReleaseStringUTFChars(file, file8);
 
-    std::vector<char> fileBuffer(kReadSize);
-    int numBytesRead = 0;
-    while (true) {
-        // Resize buffer to make space for contents. This might be more than we need, but once we've
-        // read we resize back down
-        fileBuffer.resize(numBytesRead + kReadSize, 0);
-        // Read in contents
-        int len = TEMP_FAILURE_RETRY(read(fd, fileBuffer.data() + numBytesRead, kReadSize));
-        numBytesRead += len;
-        if (len < 0) {
-            // If `len` is negative, an error occurred on read
+    // Most proc files we read are small, so we only go through the
+    // loop once and use the stack buffer.  We allocate a buffer big
+    // enough for the whole file.
+
+    char readBufferStack[kProcReadStackBufferSize];
+    std::unique_ptr<char[]> readBufferHeap;
+    char* readBuffer = &readBufferStack[0];
+    ssize_t readBufferSize = kProcReadStackBufferSize;
+    ssize_t numberBytesRead;
+    for (;;) {
+        // By using pread, we can avoid an lseek to rewind the FD
+        // before retry, saving a system call.
+        numberBytesRead = pread(fd, readBuffer, readBufferSize, 0);
+        if (numberBytesRead < 0 && errno == EINTR) {
+            continue;
+        }
+        if (numberBytesRead < 0) {
             if (kDebugProc) {
-                ALOGW("Unable to open process file: %s fd=%d\n", file8, fd);
+                ALOGW("Unable to open process file: %s fd=%d\n", file8, fd.get());
             }
-            close(fd);
             return JNI_FALSE;
-        } else if (len == 0) {
-            // If nothing read, we're done
+        }
+        if (numberBytesRead < readBufferSize) {
             break;
         }
+        if (readBufferSize > std::numeric_limits<ssize_t>::max() / 2) {
+            if (kDebugProc) {
+                ALOGW("Proc file too big: %s fd=%d\n", file8, fd.get());
+            }
+            return JNI_FALSE;
+        }
+        readBufferSize = std::max(readBufferSize * 2,
+                                  kProcReadMinHeapBufferSize);
+        readBufferHeap.reset();  // Free address space before getting more.
+        readBufferHeap = std::make_unique<char[]>(readBufferSize);
+        if (!readBufferHeap) {
+            jniThrowException(env, "java/lang/OutOfMemoryError", NULL);
+            return JNI_FALSE;
+        }
+        readBuffer = readBufferHeap.get();
     }
-    // Resize back down to the amount we read
-    fileBuffer.resize(numBytesRead);
-    // Terminate buffer with null byte
-    fileBuffer.push_back('\0');
-    close(fd);
 
-    return android_os_Process_parseProcLineArray(env, clazz, fileBuffer.data(), 0, numBytesRead,
-            format, outStrings, outLongs, outFloats);
+    // parseProcLineArray below modifies the buffer while parsing!
+    return android_os_Process_parseProcLineArray(
+        env, clazz, readBuffer, 0, numberBytesRead,
+        format, outStrings, outLongs, outFloats);
 }
 
 void android_os_Process_setApplicationObject(JNIEnv* env, jobject clazz,
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 2cd39cb..5fd53de 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4202,6 +4202,10 @@
         -->
     </integer-array>
 
+    <!-- Default refresh rate in the zone defined by brightness and ambient thresholds.
+         If non-positive, then the refresh rate is unchanged even if thresholds are configured. -->
+    <integer name="config_defaultRefreshRateInZone">0</integer>
+
     <!-- The type of the light sensor to be used by the display framework for things like
          auto-brightness. If unset, then it just gets the default sensor of type TYPE_LIGHT. -->
     <string name="config_displayLightSensorType" translatable="false" />
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index eaebd91..8aa4a8c 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3801,6 +3801,7 @@
 
   <!-- For high refresh rate displays -->
   <java-symbol type="integer" name="config_defaultPeakRefreshRate" />
+  <java-symbol type="integer" name="config_defaultRefreshRateInZone" />
   <java-symbol type="array" name="config_brightnessThresholdsOfPeakRefreshRate" />
   <java-symbol type="array" name="config_ambientThresholdsOfPeakRefreshRate" />
 
diff --git a/core/tests/coretests/src/android/content/pm/AndroidTelephonyCommonUpdaterTest.java b/core/tests/coretests/src/android/content/pm/AndroidTelephonyCommonUpdaterTest.java
new file mode 100644
index 0000000..8ab9ddb
--- /dev/null
+++ b/core/tests/coretests/src/android/content/pm/AndroidTelephonyCommonUpdaterTest.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.content.pm;
+
+import static android.content.pm.PackageBuilder.builder;
+import static android.content.pm.SharedLibraryNames.ANDROID_HIDL_BASE;
+import static android.content.pm.SharedLibraryNames.ANDROID_HIDL_MANAGER;
+import static android.content.pm.SharedLibraryNames.ANDROID_TELEPHONY_COMMON;
+
+import android.os.Build;
+import androidx.test.filters.SmallTest;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+/**
+ * Test for {@link AndroidHidlUpdater}
+ */
+@SmallTest
+@RunWith(JUnit4.class)
+public class AndroidTelephonyCommonUpdaterTest extends PackageSharedLibraryUpdaterTest {
+
+    private static final String OTHER_LIBRARY = "other.library";
+    private static final String PHONE_UID = "android.uid.phone";
+
+    @Test
+    public void targeted_at_Q() {
+        PackageBuilder before = builder()
+                .targetSdkVersion(Build.VERSION_CODES.Q);
+
+        PackageBuilder after = builder().targetSdkVersion(Build.VERSION_CODES.Q)
+            .requiredLibraries(ANDROID_TELEPHONY_COMMON);
+
+        // Should add telephony-common libraries
+        checkBackwardsCompatibility(before, after);
+    }
+
+    @Test
+    public void targeted_at_Q_phoneUID() {
+        PackageBuilder before = builder().setSharedUid(PHONE_UID)
+                .targetSdkVersion(Build.VERSION_CODES.Q);
+
+        // Should add telephony-common libraries
+        PackageBuilder after = builder().setSharedUid(PHONE_UID)
+                .targetSdkVersion(Build.VERSION_CODES.Q)
+                .requiredLibraries(ANDROID_TELEPHONY_COMMON);
+
+        checkBackwardsCompatibility(before, after);
+    }
+
+    @Test
+    public void targeted_at_Q_not_empty_usesLibraries() {
+        PackageBuilder before = builder()
+                .targetSdkVersion(Build.VERSION_CODES.Q)
+                .requiredLibraries(OTHER_LIBRARY);
+
+        // no change
+        checkBackwardsCompatibility(before, before);
+    }
+
+    @Test
+    public void targeted_at_Q_not_empty_usesLibraries_phoneUID() {
+        PackageBuilder before = builder().setSharedUid(PHONE_UID)
+                .targetSdkVersion(Build.VERSION_CODES.Q)
+                .requiredLibraries(OTHER_LIBRARY);
+
+        // The telephony-common jars should be added at the start of the list because it
+        // is not on the bootclasspath and the package targets pre-R.
+        PackageBuilder after = builder().setSharedUid(PHONE_UID)
+                .targetSdkVersion(Build.VERSION_CODES.Q)
+                .requiredLibraries(ANDROID_TELEPHONY_COMMON, OTHER_LIBRARY);
+
+        checkBackwardsCompatibility(before, after);
+    }
+
+    @Test
+    public void targeted_at_R_in_usesLibraries() {
+        PackageBuilder before = builder()
+                .targetSdkVersion(Build.VERSION_CODES.Q + 1)
+                .requiredLibraries(ANDROID_TELEPHONY_COMMON);
+
+        PackageBuilder after = builder()
+                .targetSdkVersion(Build.VERSION_CODES.Q + 1);
+
+        // Libraries are removed because they are not available for apps target >= R and not run
+        // on phone-uid
+        checkBackwardsCompatibility(before, after);
+    }
+
+    @Test
+    public void targeted_at_Q_in_usesLibraries() {
+        PackageBuilder before = builder().asSystemApp()
+                .targetSdkVersion(Build.VERSION_CODES.Q)
+                .requiredLibraries(ANDROID_TELEPHONY_COMMON);
+
+        // No change is required because the package explicitly requests the telephony libraries
+        // and is targeted at the current version so does not need backwards compatibility.
+        checkBackwardsCompatibility(before, before);
+    }
+
+
+    @Test
+    public void targeted_at_R_in_usesOptionalLibraries() {
+        PackageBuilder before = builder().targetSdkVersion(Build.VERSION_CODES.Q + 1)
+            .optionalLibraries(ANDROID_TELEPHONY_COMMON);
+
+        // Dependency is removed, it is not available.
+        PackageBuilder after = builder().targetSdkVersion(Build.VERSION_CODES.Q + 1);
+
+        // Libraries are removed because they are not available for apps targeting Q+
+        checkBackwardsCompatibility(before, after);
+    }
+
+    @Test
+    public void targeted_at_R() {
+        PackageBuilder before = builder()
+            .targetSdkVersion(Build.VERSION_CODES.Q + 1);
+
+        // no change
+        checkBackwardsCompatibility(before, before);
+    }
+
+    private void checkBackwardsCompatibility(PackageBuilder before, PackageBuilder after) {
+        checkBackwardsCompatibility(before, after, AndroidTelephonyCommonUpdater::new);
+    }
+}
diff --git a/core/tests/coretests/src/android/content/pm/PackageBuilder.java b/core/tests/coretests/src/android/content/pm/PackageBuilder.java
index f7544af..f3a56e2 100644
--- a/core/tests/coretests/src/android/content/pm/PackageBuilder.java
+++ b/core/tests/coretests/src/android/content/pm/PackageBuilder.java
@@ -37,6 +37,8 @@
 
     private ArrayList<String> mOptionalLibraries;
 
+    private String mSharedUid;
+
     public static PackageBuilder builder() {
         return new PackageBuilder();
     }
@@ -47,6 +49,7 @@
         pkg.applicationInfo.flags = mFlags;
         pkg.usesLibraries = mRequiredLibraries;
         pkg.usesOptionalLibraries = mOptionalLibraries;
+        pkg.mSharedUserId = mSharedUid;
         return pkg;
     }
 
@@ -55,6 +58,11 @@
         return this;
     }
 
+    PackageBuilder setSharedUid(String uid) {
+        this.mSharedUid = uid;
+        return this;
+    }
+
     PackageBuilder asSystemApp() {
         this.mFlags |= ApplicationInfo.FLAG_SYSTEM;
         return this;
diff --git a/data/etc/car/Android.bp b/data/etc/car/Android.bp
index 9272ea5..c445651 100644
--- a/data/etc/car/Android.bp
+++ b/data/etc/car/Android.bp
@@ -128,3 +128,10 @@
     filename_from_src: true,
     product_specific: true,
 }
+
+prebuilt_etc {
+    name: "privapp_whitelist_com.android.car.floatingcardslauncher",
+    sub_dir: "permissions",
+    src: "com.android.car.floatingcardslauncher.xml",
+    filename_from_src: true,
+}
diff --git a/data/etc/car/com.android.car.floatingcardslauncher.xml b/data/etc/car/com.android.car.floatingcardslauncher.xml
new file mode 100644
index 0000000..2755fee
--- /dev/null
+++ b/data/etc/car/com.android.car.floatingcardslauncher.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright (C) 2019 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License
+  -->
+<permissions>
+    <privapp-permissions package="com.android.car.floatingcardslauncher">
+        <permission name="android.permission.ACTIVITY_EMBEDDING"/>
+        <permission name="android.permission.INTERACT_ACROSS_USERS"/>
+        <permission name="android.permission.MANAGE_USERS"/>
+        <permission name="android.permission.MEDIA_CONTENT_CONTROL"/>
+        <permission name="android.permission.MODIFY_PHONE_STATE"/>
+    </privapp-permissions>
+</permissions>
diff --git a/data/etc/car/com.android.car.settings.xml b/data/etc/car/com.android.car.settings.xml
index 5f7e1c1..291ce80 100644
--- a/data/etc/car/com.android.car.settings.xml
+++ b/data/etc/car/com.android.car.settings.xml
@@ -50,7 +50,6 @@
         <permission name="android.permission.USE_RESERVED_DISK"/>
         <permission name="android.permission.USER_ACTIVITY"/>
         <permission name="android.permission.WRITE_APN_SETTINGS"/>
-        <permission name="android.permission.WRITE_MEDIA_STORAGE"/>
         <permission name="android.permission.WRITE_SECURE_SETTINGS"/>
         <permission name="android.permission.CONTROL_DISPLAY_COLOR_TRANSFORMS" />
     </privapp-permissions>
diff --git a/data/etc/platform.xml b/data/etc/platform.xml
index 0960f78..d66930a 100644
--- a/data/etc/platform.xml
+++ b/data/etc/platform.xml
@@ -225,6 +225,8 @@
     <library name="android.hidl.manager-V1.0-java"
             file="/system/framework/android.hidl.manager-V1.0-java.jar"
             dependency="android.hidl.base-V1.0-java" />
+    <library name="telephony-common"
+        file="/system/framework/telephony-common.jar" />
 
     <!-- These are the standard packages that are white-listed to always have internet
          access while in power save mode, even if they aren't in the foreground. -->
diff --git a/libs/hwui/SkiaCanvas.cpp b/libs/hwui/SkiaCanvas.cpp
index 54ac0bd..2314072 100644
--- a/libs/hwui/SkiaCanvas.cpp
+++ b/libs/hwui/SkiaCanvas.cpp
@@ -163,7 +163,7 @@
     SkCanvas::SaveLayerFlags layerFlags = 0;
 
     if (!(flags & SaveFlags::ClipToLayer)) {
-        layerFlags |= SkCanvas::kDontClipToLayer_Legacy_SaveLayerFlag;
+        layerFlags |= SkCanvasPriv::kDontClipToLayer_SaveLayerFlag;
     }
 
     return layerFlags;
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index aad15ab..0ad050d 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -15,7 +15,17 @@
  */
 
 #include "CanvasContext.h"
+
 #include <GpuMemoryTracker.h>
+#include <apex/window.h>
+#include <fcntl.h>
+#include <strings.h>
+#include <sys/stat.h>
+
+#include <algorithm>
+#include <cstdint>
+#include <cstdlib>
+#include <functional>
 
 #include "../Properties.h"
 #include "AnimationContext.h"
@@ -32,16 +42,6 @@
 #include "utils/TimeUtils.h"
 #include "utils/TraceUtils.h"
 
-#include <strings.h>
-
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <algorithm>
-
-#include <cstdint>
-#include <cstdlib>
-#include <functional>
-
 #define TRIM_MEMORY_COMPLETE 80
 #define TRIM_MEMORY_UI_HIDDEN 20
 
@@ -484,16 +484,16 @@
         swap.swapCompletedTime = systemTime(SYSTEM_TIME_MONOTONIC);
         swap.vsyncTime = mRenderThread.timeLord().latestVsync();
         if (didDraw) {
-            int durationUs;
             nsecs_t dequeueStart = mNativeSurface->getLastDequeueStartTime();
             if (dequeueStart < mCurrentFrameInfo->get(FrameInfoIndex::SyncStart)) {
                 // Ignoring dequeue duration as it happened prior to frame render start
                 // and thus is not part of the frame.
                 swap.dequeueDuration = 0;
             } else {
-                mNativeSurface->query(NATIVE_WINDOW_LAST_DEQUEUE_DURATION, &durationUs);
-                swap.dequeueDuration = us2ns(durationUs);
+                swap.dequeueDuration =
+                        us2ns(ANativeWindow_getLastDequeueDuration(mNativeSurface.get()));
             }
+            int durationUs;
             mNativeSurface->query(NATIVE_WINDOW_LAST_QUEUE_DURATION, &durationUs);
             swap.queueDuration = us2ns(durationUs);
         } else {
diff --git a/media/java/android/media/soundtrigger/SoundTriggerManager.java b/media/java/android/media/soundtrigger/SoundTriggerManager.java
index ada77c5..dc400ad 100644
--- a/media/java/android/media/soundtrigger/SoundTriggerManager.java
+++ b/media/java/android/media/soundtrigger/SoundTriggerManager.java
@@ -383,4 +383,20 @@
             throw e.rethrowFromSystemServer();
         }
     }
+
+    /**
+     * Get the hardware sound trigger module properties currently loaded.
+     *
+     * @return The properties currently loaded. Returns null if no supported hardware loaded.
+     */
+    @RequiresPermission(android.Manifest.permission.MANAGE_SOUND_TRIGGER)
+    @Nullable
+    public SoundTrigger.ModuleProperties getModuleProperties() {
+
+        try {
+            return mSoundTriggerService.getModuleProperties();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
diff --git a/packages/CarSystemUI/res/layout/super_status_bar.xml b/packages/CarSystemUI/res/layout/super_status_bar.xml
index 728a239..e1bcc2e 100644
--- a/packages/CarSystemUI/res/layout/super_status_bar.xml
+++ b/packages/CarSystemUI/res/layout/super_status_bar.xml
@@ -42,6 +42,14 @@
     </com.android.systemui.statusbar.BackDropView>
 
     <com.android.systemui.statusbar.ScrimView
+        android:id="@+id/scrim_for_bubble"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:importantForAccessibility="no"
+        sysui:ignoreRightInset="true"
+    />
+
+    <com.android.systemui.statusbar.ScrimView
         android:id="@+id/scrim_behind"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
diff --git a/packages/CarSystemUI/res/layout/trust_agent_unlock_dialog.xml b/packages/CarSystemUI/res/layout/trust_agent_unlock_dialog.xml
index 2d9901c..9df78f1 100644
--- a/packages/CarSystemUI/res/layout/trust_agent_unlock_dialog.xml
+++ b/packages/CarSystemUI/res/layout/trust_agent_unlock_dialog.xml
@@ -16,12 +16,13 @@
   -->
 
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:id="@+id/layout"
+    android:id="@+id/unlock_dialog_parent"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:gravity="center">
 
     <LinearLayout
+        android:id="@+id/unlock_dialog"
         android:layout_width="@dimen/unlock_dialog_width"
         android:layout_height="wrap_content"
         android:gravity="center"
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java
index 013c63b..ec72ee7 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/CarTrustAgentUnlockDialogHelper.java
@@ -52,7 +52,7 @@
      * Not using Dialog because context passed from {@link FullscreenUserSwitcher} is not an
      * activity.
      */
-    private final View mUnlockDialog;
+    private final View mUnlockDialogLayout;
     private final TextView mUnlockingText;
     private final Button mButton;
     private final IntentFilter mFilter;
@@ -70,14 +70,25 @@
         mParams.packageName = mContext.getPackageName();
         mParams.setTitle(mContext.getString(R.string.unlock_dialog_title));
 
-        mUnlockDialog = LayoutInflater.from(mContext).inflate(
+        mUnlockDialogLayout = LayoutInflater.from(mContext).inflate(
             R.layout.trust_agent_unlock_dialog, null);
-        mUnlockDialog.setLayoutParams(mParams);
+        mUnlockDialogLayout.setLayoutParams(mParams);
 
-        mUnlockingText = mUnlockDialog.findViewById(R.id.unlocking_text);
-        mButton = mUnlockDialog.findViewById(R.id.enter_pin_button);
+        View dialogParent = mUnlockDialogLayout.findViewById(R.id.unlock_dialog_parent);
+        dialogParent.setOnTouchListener((v, event)-> {
+            hideUnlockDialog(/* dismissUserSwitcher= */ false);
+            return true;
+        });
+        View unlockDialog = mUnlockDialogLayout.findViewById(R.id.unlock_dialog);
+        unlockDialog.setOnTouchListener((v, event) -> {
+            // If the person taps inside the unlock dialog, the touch event will be intercepted here
+            // and the dialog will not exit
+            return true;
+        });
+        mUnlockingText = mUnlockDialogLayout.findViewById(R.id.unlocking_text);
+        mButton = mUnlockDialogLayout.findViewById(R.id.enter_pin_button);
         mButton.setOnClickListener(v -> {
-            hideUnlockDialog(/* notifyOnHideListener= */true);
+            hideUnlockDialog(/* dismissUserSwitcher= */true);
             // TODO(b/138250105) Stop unlock advertising
         });
 
@@ -133,7 +144,7 @@
                 if (!mUserManager.isUserUnlocked(uid)) {
                     logd("Showed unlock dialog for user: " + uid + " after " + delayMillis
                             + " delay.");
-                    mWindowManager.addView(mUnlockDialog, mParams);
+                    mWindowManager.addView(mUnlockDialogLayout, mParams);
                 }
             }, delayMillis);
         }
@@ -142,22 +153,22 @@
 
     private void setUid(int uid) {
         mUid = uid;
-        TextView userName = mUnlockDialog.findViewById(R.id.user_name);
+        TextView userName = mUnlockDialogLayout.findViewById(R.id.user_name);
         userName.setText(mUserManager.getUserInfo(mUid).name);
-        ImageView avatar = mUnlockDialog.findViewById(R.id.avatar);
+        ImageView avatar = mUnlockDialogLayout.findViewById(R.id.avatar);
         avatar.setImageBitmap(mUserManager.getUserIcon(mUid));
         setButtonText();
     }
 
-    private void hideUnlockDialog(boolean notifyOnHideListener) {
+    private void hideUnlockDialog(boolean dismissUserSwitcher) {
         if (!mIsDialogShowing) {
             return;
         }
-        mWindowManager.removeView(mUnlockDialog);
+        mWindowManager.removeView(mUnlockDialogLayout);
         logd("Receiver unregistered");
         mContext.unregisterReceiver(this);
-        if (notifyOnHideListener && mOnHideListener != null) {
-            mOnHideListener.onHide();
+        if (mOnHideListener != null) {
+            mOnHideListener.onHide(dismissUserSwitcher);
         }
         mIsDialogShowing = false;
     }
@@ -240,6 +251,6 @@
      * Listener used to notify when the dialog is hidden
      */
     interface OnHideListener {
-        void onHide();
+        void onHide(boolean dismissUserSwitcher);
     }
 }
diff --git a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
index 7cd6adb..0f7c1ee 100644
--- a/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
+++ b/packages/CarSystemUI/src/com/android/systemui/statusbar/car/FullscreenUserSwitcher.java
@@ -34,6 +34,7 @@
 import androidx.recyclerview.widget.GridLayoutManager;
 
 import com.android.systemui.R;
+import com.android.systemui.statusbar.car.CarTrustAgentUnlockDialogHelper.OnHideListener;
 import com.android.systemui.statusbar.car.UserGridRecyclerView.UserRecord;
 
 /**
@@ -116,7 +117,7 @@
         // Show unlock dialog for initial user
         if (hasTrustedDevice(initialUser)) {
             mUnlockDialogHelper.showUnlockDialogAfterDelay(initialUser,
-                    () -> dismissUserSwitcher());
+                    mOnHideListener);
         }
     }
 
@@ -162,7 +163,7 @@
     private void onUserSelected(UserGridRecyclerView.UserRecord record) {
         mSelectedUser = record;
         if (hasTrustedDevice(record.mInfo.id)) {
-            mUnlockDialogHelper.showUnlockDialog(record.mInfo.id, () -> dismissUserSwitcher());
+            mUnlockDialogHelper.showUnlockDialog(record.mInfo.id, mOnHideListener);
             return;
         }
         if (Log.isLoggable(TAG, Log.DEBUG)) {
@@ -202,4 +203,18 @@
     private boolean hasTrustedDevice(int uid) {
         return !mEnrollmentManager.getEnrolledDeviceInfoForUser(uid).isEmpty();
     }
+
+    private OnHideListener mOnHideListener = new OnHideListener() {
+        @Override
+        public void onHide(boolean dismissUserSwitcher) {
+            if (dismissUserSwitcher) {
+                dismissUserSwitcher();
+            } else {
+                // Re-draw the parent view, otherwise the unlock dialog will not be removed from
+                // the screen immediately.
+                mParent.invalidate();
+            }
+
+        }
+    };
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java
index eeb6cb0..ea8a62f 100644
--- a/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java
+++ b/packages/SettingsLib/src/com/android/settingslib/fuelgauge/PowerWhitelistBackend.java
@@ -49,6 +49,7 @@
     private final ArraySet<String> mWhitelistedApps = new ArraySet<>();
     private final ArraySet<String> mSysWhitelistedApps = new ArraySet<>();
     private final ArraySet<String> mSysWhitelistedAppsExceptIdle = new ArraySet<>();
+    private final ArraySet<String> mDefaultActiveApps = new ArraySet<>();
 
     public PowerWhitelistBackend(Context context) {
         this(context, IDeviceIdleController.Stub.asInterface(
@@ -90,17 +91,7 @@
         // should be automatically whitelisted (otherwise user may be able to set restriction on
         // them, leading to bad device behavior.)
 
-        final boolean hasTelephony = mAppContext.getPackageManager().hasSystemFeature(
-                PackageManager.FEATURE_TELEPHONY);
-        final ComponentName defaultSms = SmsApplication.getDefaultSmsApplication(mAppContext,
-                true /* updateIfNeeded */);
-        if (hasTelephony && defaultSms != null && TextUtils.equals(pkg,
-                defaultSms.getPackageName())) {
-            return true;
-        }
-
-        final String defaultDialer = DefaultDialerManager.getDefaultDialerApplication(mAppContext);
-        if (hasTelephony && TextUtils.equals(pkg, defaultDialer)) {
+        if (mDefaultActiveApps.contains(pkg)) {
             return true;
         }
 
@@ -166,6 +157,7 @@
         mSysWhitelistedApps.clear();
         mSysWhitelistedAppsExceptIdle.clear();
         mWhitelistedApps.clear();
+        mDefaultActiveApps.clear();
         if (mDeviceIdleService == null) {
             return;
         }
@@ -183,6 +175,21 @@
             for (String app : sysWhitelistedAppsExceptIdle) {
                 mSysWhitelistedAppsExceptIdle.add(app);
             }
+            final boolean hasTelephony = mAppContext.getPackageManager().hasSystemFeature(
+                    PackageManager.FEATURE_TELEPHONY);
+            final ComponentName defaultSms = SmsApplication.getDefaultSmsApplication(mAppContext,
+                    true /* updateIfNeeded */);
+            final String defaultDialer = DefaultDialerManager.getDefaultDialerApplication(
+                    mAppContext);
+
+            if (hasTelephony) {
+                if (defaultSms != null) {
+                    mDefaultActiveApps.add(defaultSms.getPackageName());
+                }
+                if (!TextUtils.isEmpty(defaultDialer)) {
+                    mDefaultActiveApps.add(defaultDialer);
+                }
+            }
         } catch (RemoteException e) {
             Log.w(TAG, "Unable to reach IDeviceIdleController", e);
         }
diff --git a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixin.java b/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixin.java
deleted file mode 100644
index fcf2363..0000000
--- a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixin.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * Copyright (C) 2016 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.settingslib.widget;
-
-import android.content.Context;
-
-import androidx.preference.PreferenceFragment;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.SetPreferenceScreen;
-
-/**
- * Framework mixin is deprecated, use the compat version instead.
- *
- * @deprecated
- */
-@Deprecated
-public class FooterPreferenceMixin implements LifecycleObserver, SetPreferenceScreen {
-
-    private final PreferenceFragment mFragment;
-    private FooterPreference mFooterPreference;
-
-    public FooterPreferenceMixin(PreferenceFragment fragment, Lifecycle lifecycle) {
-        mFragment = fragment;
-        lifecycle.addObserver(this);
-    }
-
-    @Override
-    public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
-        if (mFooterPreference != null) {
-            preferenceScreen.addPreference(mFooterPreference);
-        }
-    }
-
-    /**
-     * Creates a new {@link FooterPreference}.
-     */
-    public FooterPreference createFooterPreference() {
-        final PreferenceScreen screen = mFragment.getPreferenceScreen();
-        if (mFooterPreference != null && screen != null) {
-            screen.removePreference(mFooterPreference);
-        }
-        mFooterPreference = new FooterPreference(getPrefContext());
-
-        if (screen != null) {
-            screen.addPreference(mFooterPreference);
-        }
-        return mFooterPreference;
-    }
-
-    /**
-     * Returns an UI context with theme properly set for new Preference objects.
-     */
-    private Context getPrefContext() {
-        return mFragment.getPreferenceManager().getContext();
-    }
-
-    public boolean hasFooter() {
-        return mFooterPreference != null;
-    }
-}
-
diff --git a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixinCompat.java b/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixinCompat.java
deleted file mode 100644
index d45e56d..0000000
--- a/packages/SettingsLib/src/com/android/settingslib/widget/FooterPreferenceMixinCompat.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settingslib.widget;
-
-import android.content.Context;
-
-import androidx.preference.PreferenceFragmentCompat;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settingslib.core.lifecycle.Lifecycle;
-import com.android.settingslib.core.lifecycle.LifecycleObserver;
-import com.android.settingslib.core.lifecycle.events.SetPreferenceScreen;
-
-public class FooterPreferenceMixinCompat implements LifecycleObserver, SetPreferenceScreen {
-
-    private final PreferenceFragmentCompat mFragment;
-    private FooterPreference mFooterPreference;
-
-    public FooterPreferenceMixinCompat(PreferenceFragmentCompat fragment, Lifecycle lifecycle) {
-        mFragment = fragment;
-        lifecycle.addObserver(this);
-    }
-
-    @Override
-    public void setPreferenceScreen(PreferenceScreen preferenceScreen) {
-        if (mFooterPreference != null) {
-            preferenceScreen.addPreference(mFooterPreference);
-        }
-    }
-
-    /**
-     * Creates a new {@link FooterPreference}.
-     */
-    public FooterPreference createFooterPreference() {
-        final PreferenceScreen screen = mFragment.getPreferenceScreen();
-        if (mFooterPreference != null && screen != null) {
-            screen.removePreference(mFooterPreference);
-        }
-        mFooterPreference = new FooterPreference(getPrefContext());
-
-        if (screen != null) {
-            screen.addPreference(mFooterPreference);
-        }
-        return mFooterPreference;
-    }
-
-    /**
-     * Returns an UI context with theme properly set for new Preference objects.
-     */
-    private Context getPrefContext() {
-        return mFragment.getPreferenceManager().getContext();
-    }
-
-    public boolean hasFooter() {
-        return mFooterPreference != null;
-    }
-}
-
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
index 44ee423..3a571f9 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/fuelgauge/PowerWhitelistBackendTest.java
@@ -117,6 +117,8 @@
         final String testSms = "com.android.test.defaultsms";
         ShadowSmsApplication.setDefaultSmsApplication(new ComponentName(testSms, "receiver"));
 
+        mPowerWhitelistBackend.refreshList();
+
         assertThat(mPowerWhitelistBackend.isWhitelisted(testSms)).isTrue();
         assertThat(mPowerWhitelistBackend.isDefaultActiveApp(testSms)).isTrue();
     }
@@ -126,6 +128,8 @@
         final String testDialer = "com.android.test.defaultdialer";
         ShadowDefaultDialerManager.setDefaultDialerApplication(testDialer);
 
+        mPowerWhitelistBackend.refreshList();
+
         assertThat(mPowerWhitelistBackend.isWhitelisted(testDialer)).isTrue();
         assertThat(mPowerWhitelistBackend.isDefaultActiveApp(testDialer)).isTrue();
     }
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinCompatTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinCompatTest.java
deleted file mode 100644
index 601da051..0000000
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinCompatTest.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright (C) 2016 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.settingslib.widget;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import androidx.lifecycle.LifecycleOwner;
-import androidx.preference.PreferenceFragmentCompat;
-import androidx.preference.PreferenceManager;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settingslib.core.lifecycle.Lifecycle;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class FooterPreferenceMixinCompatTest {
-
-    @Mock
-    private PreferenceFragmentCompat mFragment;
-    @Mock
-    private PreferenceScreen mScreen;
-
-    private LifecycleOwner mLifecycleOwner;
-    private Lifecycle mLifecycle;
-    private FooterPreferenceMixinCompat mMixin;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mLifecycleOwner = () -> mLifecycle;
-        mLifecycle = new Lifecycle(mLifecycleOwner);
-        when(mFragment.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
-        when(mFragment.getPreferenceManager().getContext())
-                .thenReturn(RuntimeEnvironment.application);
-        mMixin = new FooterPreferenceMixinCompat(mFragment, mLifecycle);
-    }
-
-    @Test
-    public void createFooter_screenNotAvailable_noCrash() {
-        assertThat(mMixin.createFooterPreference()).isNotNull();
-    }
-
-    @Test
-    public void createFooter_screenAvailable_canAttachToScreen() {
-        when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
-
-        final FooterPreference preference = mMixin.createFooterPreference();
-
-        assertThat(preference).isNotNull();
-        verify(mScreen).addPreference(preference);
-    }
-
-    @Test
-    public void createFooter_screenAvailableDelayed_canAttachToScreen() {
-        final FooterPreference preference = mMixin.createFooterPreference();
-
-        mLifecycle.setPreferenceScreen(mScreen);
-
-        assertThat(preference).isNotNull();
-        verify(mScreen).addPreference(preference);
-    }
-
-    @Test
-    public void createFooterTwice_screenAvailable_replaceOldFooter() {
-        when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
-
-        mMixin.createFooterPreference();
-        mMixin.createFooterPreference();
-
-        verify(mScreen).removePreference(any(FooterPreference.class));
-        verify(mScreen, times(2)).addPreference(any(FooterPreference.class));
-    }
-}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java
deleted file mode 100644
index 7ae5d2d..0000000
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/widget/FooterPreferenceMixinTest.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2016 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.settingslib.widget;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import androidx.lifecycle.LifecycleOwner;
-import androidx.preference.PreferenceFragment;
-import androidx.preference.PreferenceManager;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settingslib.core.lifecycle.Lifecycle;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class FooterPreferenceMixinTest {
-
-    @Mock
-    private PreferenceFragment mFragment;
-    @Mock
-    private PreferenceScreen mScreen;
-
-    private LifecycleOwner mLifecycleOwner;
-    private Lifecycle mLifecycle;
-    private FooterPreferenceMixin mMixin;
-
-    @Before
-    public void setUp() {
-        MockitoAnnotations.initMocks(this);
-        mLifecycleOwner = () -> mLifecycle;
-        mLifecycle = new Lifecycle(mLifecycleOwner);
-        when(mFragment.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
-        when(mFragment.getPreferenceManager().getContext())
-                .thenReturn(RuntimeEnvironment.application);
-        mMixin = new FooterPreferenceMixin(mFragment, mLifecycle);
-    }
-
-    @Test
-    public void createFooter_screenNotAvailable_noCrash() {
-        assertThat(mMixin.createFooterPreference()).isNotNull();
-    }
-
-    @Test
-    public void createFooter_screenAvailable_canAttachToScreen() {
-        when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
-
-        final FooterPreference preference = mMixin.createFooterPreference();
-
-        assertThat(preference).isNotNull();
-        verify(mScreen).addPreference(preference);
-    }
-
-    @Test
-    public void createFooter_screenAvailableDelayed_canAttachToScreen() {
-        final FooterPreference preference = mMixin.createFooterPreference();
-
-        mLifecycle.setPreferenceScreen(mScreen);
-
-        assertThat(preference).isNotNull();
-        verify(mScreen).addPreference(preference);
-    }
-
-    @Test
-    public void createFooterTwice_screenAvailable_replaceOldFooter() {
-        when(mFragment.getPreferenceScreen()).thenReturn(mScreen);
-
-        mMixin.createFooterPreference();
-        mMixin.createFooterPreference();
-
-        verify(mScreen).removePreference(any(FooterPreference.class));
-        verify(mScreen, times(2)).addPreference(any(FooterPreference.class));
-    }
-
-}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
new file mode 100644
index 0000000..30be775
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/pip/PipBoundsHandler.java
@@ -0,0 +1,375 @@
+/*
+ * 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.pip;
+
+import static android.util.TypedValue.COMPLEX_UNIT_DIP;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.os.RemoteException;
+import android.util.DisplayMetrics;
+import android.util.Log;
+import android.util.Size;
+import android.util.TypedValue;
+import android.view.DisplayInfo;
+import android.view.Gravity;
+import android.view.IPinnedStackController;
+import android.view.IWindowManager;
+import android.view.WindowManagerGlobal;
+
+import com.android.internal.policy.PipSnapAlgorithm;
+
+import java.io.PrintWriter;
+
+/**
+ * Handles bounds calculation for PIP on Phone and other form factors, it keeps tracking variant
+ * state changes originated from Window Manager and is the source of truth for PiP window bounds.
+ */
+public class PipBoundsHandler {
+
+    private static final String TAG = PipBoundsHandler.class.getSimpleName();
+    private static final float INVALID_SNAP_FRACTION = -1f;
+
+    // System.identityHashCode guarantees zero for null object.
+    private static final int INVALID_SYSTEM_IDENTITY_TOKEN = 0;
+
+    private final Context mContext;
+    private final IWindowManager mWindowManager;
+    private final PipSnapAlgorithm mSnapAlgorithm;
+    private final DisplayInfo mDisplayInfo = new DisplayInfo();
+    private final Rect mStableInsets = new Rect();
+    private final Rect mTmpInsets = new Rect();
+    private final Point mTmpDisplaySize = new Point();
+
+    private IPinnedStackController mPinnedStackController;
+    private int mLastPipToken;
+    private float mReentrySnapFraction = INVALID_SNAP_FRACTION;
+
+    private float mDefaultAspectRatio;
+    private float mMinAspectRatio;
+    private float mMaxAspectRatio;
+    private float mAspectRatio;
+    private int mDefaultStackGravity;
+    private int mDefaultMinSize;
+    private Point mScreenEdgeInsets;
+    private int mCurrentMinSize;
+
+    private boolean mIsMinimized;
+    private boolean mIsImeShowing;
+    private int mImeHeight;
+    private boolean mIsShelfShowing;
+    private int mShelfHeight;
+
+    public PipBoundsHandler(Context context) {
+        mContext = context;
+        mSnapAlgorithm = new PipSnapAlgorithm(context);
+        mWindowManager = WindowManagerGlobal.getWindowManagerService();
+        mAspectRatio = mDefaultAspectRatio;
+        reloadResources();
+    }
+
+    /**
+     * TODO: move the resources to SysUI package.
+     */
+    private void reloadResources() {
+        final Resources res = mContext.getResources();
+        mDefaultAspectRatio = res.getFloat(
+                com.android.internal.R.dimen.config_pictureInPictureDefaultAspectRatio);
+        mDefaultStackGravity = res.getInteger(
+                com.android.internal.R.integer.config_defaultPictureInPictureGravity);
+        mDefaultMinSize = res.getDimensionPixelSize(
+                com.android.internal.R.dimen.default_minimal_size_pip_resizable_task);
+        mCurrentMinSize = mDefaultMinSize;
+        final String screenEdgeInsetsDpString = res.getString(
+                com.android.internal.R.string.config_defaultPictureInPictureScreenEdgeInsets);
+        final Size screenEdgeInsetsDp = !screenEdgeInsetsDpString.isEmpty()
+                ? Size.parseSize(screenEdgeInsetsDpString)
+                : null;
+        mScreenEdgeInsets = screenEdgeInsetsDp == null ? new Point()
+                : new Point(dpToPx(screenEdgeInsetsDp.getWidth(), res.getDisplayMetrics()),
+                        dpToPx(screenEdgeInsetsDp.getHeight(), res.getDisplayMetrics()));
+        mMinAspectRatio = res.getFloat(
+                com.android.internal.R.dimen.config_pictureInPictureMinAspectRatio);
+        mMaxAspectRatio = res.getFloat(
+                com.android.internal.R.dimen.config_pictureInPictureMaxAspectRatio);
+    }
+
+    public void setPinnedStackController(IPinnedStackController controller) {
+        mPinnedStackController = controller;
+    }
+
+    public void setMinEdgeSize(int minEdgeSize) {
+        mCurrentMinSize = minEdgeSize;
+    }
+
+    /**
+     * Responds to IPinnedStackListener on IME visibility change.
+     */
+    public void onImeVisibilityChanged(boolean imeVisible, int imeHeight) {
+        mIsImeShowing = imeVisible;
+        mImeHeight = imeHeight;
+    }
+
+    /**
+     * Responds to IPinnedStackListener on shelf visibility change.
+     */
+    public void onShelfVisibilityChanged(boolean shelfVisible, int shelfHeight) {
+        mIsShelfShowing = shelfVisible;
+        mShelfHeight = shelfHeight;
+    }
+
+    /**
+     * Responds to IPinnedStackListener on minimized state change.
+     */
+    public void onMinimizedStateChanged(boolean minimized) {
+        mIsMinimized = minimized;
+    }
+
+    /**
+     * Responds to IPinnedStackListener on movement bounds change.
+     * Note that both inset and normal bounds will be calculated here rather than in the caller.
+     */
+    public void onMovementBoundsChanged(Rect insetBounds, Rect normalBounds,
+            Rect animatingBounds, DisplayInfo displayInfo) {
+        getInsetBounds(insetBounds);
+        final Rect defaultBounds = getDefaultBounds(INVALID_SNAP_FRACTION);
+        normalBounds.set(defaultBounds);
+        if (animatingBounds.isEmpty()) {
+            animatingBounds.set(defaultBounds);
+        }
+        if (isValidPictureInPictureAspectRatio(mAspectRatio)) {
+            transformBoundsToAspectRatio(normalBounds, mAspectRatio,
+                    false /* useCurrentMinEdgeSize */);
+        }
+        displayInfo.copyFrom(mDisplayInfo);
+    }
+
+    /**
+     * Responds to IPinnedStackListener on saving reentry snap fraction for a given token.
+     * Token should be generated via {@link System#identityHashCode(Object)}
+     */
+    public void onSaveReentrySnapFraction(int token, Rect stackBounds) {
+        mReentrySnapFraction = getSnapFraction(stackBounds);
+        mLastPipToken = token;
+    }
+
+    /**
+     * Responds to IPinnedStackListener on resetting reentry snap fraction for a given token.
+     * Token should be generated via {@link System#identityHashCode(Object)}
+     */
+    public void onResetReentrySnapFraction(int token) {
+        if (mLastPipToken == token) {
+            onResetReentrySnapFractionUnchecked();
+        }
+    }
+
+    private void onResetReentrySnapFractionUnchecked() {
+        mReentrySnapFraction = INVALID_SNAP_FRACTION;
+        mLastPipToken = INVALID_SYSTEM_IDENTITY_TOKEN;
+    }
+
+    /**
+     * Responds to IPinnedStackListener on {@link DisplayInfo} change.
+     * It will normally follow up with a
+     * {@link #onMovementBoundsChanged(Rect, Rect, Rect, DisplayInfo)} callback.
+     */
+    public void onDisplayInfoChanged(DisplayInfo displayInfo) {
+        mDisplayInfo.copyFrom(displayInfo);
+    }
+
+    /**
+     * Responds to IPinnedStackListener on configuration change.
+     */
+    public void onConfigurationChanged() {
+        reloadResources();
+    }
+
+    /**
+     * Responds to IPinnedStackListener on resetting aspect ratio for the pinned window.
+     * It will normally follow up with a
+     * {@link #onMovementBoundsChanged(Rect, Rect, Rect, DisplayInfo)} callback.
+     */
+    public void onAspectRatioChanged(float aspectRatio) {
+        mAspectRatio = aspectRatio;
+    }
+
+    /**
+     * Responds to IPinnedStackListener on preparing the pinned stack animation.
+     */
+    public void onPrepareAnimation(Rect sourceRectHint, float aspectRatio, Rect stackBounds) {
+        final Rect targetStackBounds;
+        if (stackBounds == null) {
+            targetStackBounds = getDefaultBounds(mReentrySnapFraction);
+        } else {
+            targetStackBounds = new Rect();
+            targetStackBounds.set(stackBounds);
+        }
+        if (isValidPictureInPictureAspectRatio(aspectRatio)) {
+            transformBoundsToAspectRatio(targetStackBounds, aspectRatio,
+                    true /* useCurrentMinEdgeSize */);
+        }
+        if (targetStackBounds.equals(stackBounds)) {
+            return;
+        }
+        mAspectRatio = aspectRatio;
+        onResetReentrySnapFractionUnchecked();
+        // TODO: callback Window Manager on starting animation with calculated bounds
+    }
+
+    /**
+     * @return whether the given {@param aspectRatio} is valid.
+     */
+    private boolean isValidPictureInPictureAspectRatio(float aspectRatio) {
+        return Float.compare(mMinAspectRatio, aspectRatio) <= 0
+                && Float.compare(aspectRatio, mMaxAspectRatio) <= 0;
+    }
+
+    /**
+     * Set the current bounds (or the default bounds if there are no current bounds) with the
+     * specified aspect ratio.
+     */
+    private void transformBoundsToAspectRatio(Rect stackBounds, float aspectRatio,
+            boolean useCurrentMinEdgeSize) {
+        // Save the snap fraction, calculate the aspect ratio based on screen size
+        final float snapFraction = mSnapAlgorithm.getSnapFraction(stackBounds,
+                getMovementBounds(stackBounds));
+
+        final int minEdgeSize = useCurrentMinEdgeSize ? mCurrentMinSize : mDefaultMinSize;
+        final Size size = mSnapAlgorithm.getSizeForAspectRatio(aspectRatio, minEdgeSize,
+                mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
+        final int left = (int) (stackBounds.centerX() - size.getWidth() / 2f);
+        final int top = (int) (stackBounds.centerY() - size.getHeight() / 2f);
+        stackBounds.set(left, top, left + size.getWidth(), top + size.getHeight());
+        mSnapAlgorithm.applySnapFraction(stackBounds, getMovementBounds(stackBounds), snapFraction);
+        if (mIsMinimized) {
+            applyMinimizedOffset(stackBounds, getMovementBounds(stackBounds));
+        }
+    }
+
+    /**
+     * @return the default bounds to show the PIP, if a {@param snapFraction} is provided, then it
+     * will apply the default bounds to the provided snap fraction.
+     */
+    private Rect getDefaultBounds(float snapFraction) {
+        final Rect insetBounds = new Rect();
+        getInsetBounds(insetBounds);
+
+        final Rect defaultBounds = new Rect();
+        final Size size = mSnapAlgorithm.getSizeForAspectRatio(mDefaultAspectRatio,
+                mDefaultMinSize, mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
+        if (snapFraction != INVALID_SNAP_FRACTION) {
+            defaultBounds.set(0, 0, size.getWidth(), size.getHeight());
+            final Rect movementBounds = getMovementBounds(defaultBounds);
+            mSnapAlgorithm.applySnapFraction(defaultBounds, movementBounds, snapFraction);
+        } else {
+            Gravity.apply(mDefaultStackGravity, size.getWidth(), size.getHeight(), insetBounds,
+                    0, Math.max(mIsImeShowing ? mImeHeight : 0,
+                            mIsShelfShowing ? mShelfHeight : 0),
+                    defaultBounds);
+        }
+        return defaultBounds;
+    }
+
+    /**
+     * Populates the bounds on the screen that the PIP can be visible in.
+     */
+    private void getInsetBounds(Rect outRect) {
+        try {
+            mWindowManager.getStableInsets(mContext.getDisplayId(), mTmpInsets);
+            outRect.set(mTmpInsets.left + mScreenEdgeInsets.x,
+                    mTmpInsets.top + mScreenEdgeInsets.y,
+                    mDisplayInfo.logicalWidth - mTmpInsets.right - mScreenEdgeInsets.x,
+                    mDisplayInfo.logicalHeight - mTmpInsets.bottom - mScreenEdgeInsets.y);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to get stable insets from WM", e);
+        }
+    }
+
+    /**
+     * @return the movement bounds for the given {@param stackBounds} and the current state of the
+     *         controller.
+     */
+    private Rect getMovementBounds(Rect stackBounds) {
+        return getMovementBounds(stackBounds, true /* adjustForIme */);
+    }
+
+    /**
+     * @return the movement bounds for the given {@param stackBounds} and the current state of the
+     *         controller.
+     */
+    private Rect getMovementBounds(Rect stackBounds, boolean adjustForIme) {
+        final Rect movementBounds = new Rect();
+        getInsetBounds(movementBounds);
+
+        // Apply the movement bounds adjustments based on the current state.
+        mSnapAlgorithm.getMovementBounds(stackBounds, movementBounds, movementBounds,
+                (adjustForIme && mIsImeShowing) ? mImeHeight : 0);
+        return movementBounds;
+    }
+
+    /**
+     * Applies the minimized offsets to the given stack bounds.
+     */
+    private void applyMinimizedOffset(Rect stackBounds, Rect movementBounds) {
+        mTmpDisplaySize.set(mDisplayInfo.logicalWidth, mDisplayInfo.logicalHeight);
+        try {
+            mWindowManager.getStableInsets(mContext.getDisplayId(), mStableInsets);
+            mSnapAlgorithm.applyMinimizedOffset(stackBounds, movementBounds, mTmpDisplaySize,
+                    mStableInsets);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Failed to get stable insets from WM", e);
+        }
+    }
+
+    /**
+     * @return the default snap fraction to apply instead of the default gravity when calculating
+     *         the default stack bounds when first entering PiP.
+     */
+    private float getSnapFraction(Rect stackBounds) {
+        return mSnapAlgorithm.getSnapFraction(stackBounds, getMovementBounds(stackBounds));
+    }
+
+    /**
+     * @return the pixels for a given dp value.
+     */
+    private int dpToPx(float dpValue, DisplayMetrics dm) {
+        return (int) TypedValue.applyDimension(COMPLEX_UNIT_DIP, dpValue, dm);
+    }
+
+    /**
+     * Dumps internal states.
+     */
+    public void dump(PrintWriter pw, String prefix) {
+        final String innerPrefix = prefix + "  ";
+        pw.println(prefix + TAG);
+        pw.println(innerPrefix + "mReentrySnapFraction=" + mReentrySnapFraction);
+        pw.println(innerPrefix + "mDisplayInfo=" + mDisplayInfo);
+        pw.println(innerPrefix + "mDefaultAspectRatio=" + mDefaultAspectRatio);
+        pw.println(innerPrefix + "mMinAspectRatio=" + mMinAspectRatio);
+        pw.println(innerPrefix + "mMaxAspectRatio=" + mMaxAspectRatio);
+        pw.println(innerPrefix + "mAspectRatio=" + mAspectRatio);
+        pw.println(innerPrefix + "mDefaultStackGravity=" + mDefaultStackGravity);
+        pw.println(innerPrefix + "mIsMinimized=" + mIsMinimized);
+        pw.println(innerPrefix + "mIsImeShowing=" + mIsImeShowing);
+        pw.println(innerPrefix + "mImeHeight=" + mImeHeight);
+        pw.println(innerPrefix + "mIsShelfShowing=" + mIsShelfShowing);
+        pw.println(innerPrefix + "mShelfHeight=" + mShelfHeight);
+        mSnapAlgorithm.dump(pw, innerPrefix);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 83b000d..38153ec 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -38,8 +38,8 @@
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
-import com.android.systemui.Dependency;
 import com.android.systemui.R;
+import com.android.systemui.keyguard.ScreenLifecycle;
 import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.plugins.qs.QSTile;
 import com.android.systemui.qs.QSDetailClipper;
@@ -52,6 +52,8 @@
 import java.util.ArrayList;
 import java.util.List;
 
+import javax.inject.Inject;
+
 /**
  * Allows full-screen customization of QS, through show() and hide().
  *
@@ -66,6 +68,8 @@
 
     private final QSDetailClipper mClipper;
     private final LightBarController mLightBarController;
+    private KeyguardMonitor mKeyguardMonitor;
+    private final ScreenLifecycle mScreenLifecycle;
     private final TileQueryHelper mTileQueryHelper;
     private final View mTransparentView;
 
@@ -82,7 +86,11 @@
     private boolean mOpening;
     private boolean mIsShowingNavBackdrop;
 
-    public QSCustomizer(Context context, AttributeSet attrs) {
+    @Inject
+    public QSCustomizer(Context context, AttributeSet attrs,
+            LightBarController lightBarController,
+            KeyguardMonitor keyguardMonitor,
+            ScreenLifecycle screenLifecycle) {
         super(new ContextThemeWrapper(context, R.style.edit_theme), attrs);
 
         LayoutInflater.from(getContext()).inflate(R.layout.qs_customize_panel_content, this);
@@ -115,7 +123,9 @@
         DefaultItemAnimator animator = new DefaultItemAnimator();
         animator.setMoveDuration(TileAdapter.MOVE_DURATION);
         mRecyclerView.setItemAnimator(animator);
-        mLightBarController = Dependency.get(LightBarController.class);
+        mLightBarController = lightBarController;
+        mKeyguardMonitor = keyguardMonitor;
+        mScreenLifecycle = screenLifecycle;
         updateNavBackDrop(getResources().getConfiguration());
     }
 
@@ -177,7 +187,7 @@
             queryTiles();
             mNotifQsContainer.setCustomizerAnimating(true);
             mNotifQsContainer.setCustomizerShowing(true);
-            Dependency.get(KeyguardMonitor.class).addCallback(mKeyguardCallback);
+            mKeyguardMonitor.addCallback(mKeyguardCallback);
             updateNavColors();
         }
     }
@@ -193,7 +203,7 @@
             queryTiles();
             mNotifQsContainer.setCustomizerAnimating(false);
             mNotifQsContainer.setCustomizerShowing(true);
-            Dependency.get(KeyguardMonitor.class).addCallback(mKeyguardCallback);
+            mKeyguardMonitor.addCallback(mKeyguardCallback);
             updateNavColors();
         }
     }
@@ -203,16 +213,21 @@
     }
 
     public void hide() {
+        final boolean animate = mScreenLifecycle.getScreenState() != ScreenLifecycle.SCREEN_OFF;
         if (isShown) {
             MetricsLogger.hidden(getContext(), MetricsProto.MetricsEvent.QS_EDIT);
             isShown = false;
             mToolbar.dismissPopupMenus();
             setCustomizing(false);
             save();
-            mClipper.animateCircularClip(mX, mY, false, mCollapseAnimationListener);
-            mNotifQsContainer.setCustomizerAnimating(true);
+            if (animate) {
+                mClipper.animateCircularClip(mX, mY, false, mCollapseAnimationListener);
+            } else {
+                setVisibility(View.GONE);
+            }
+            mNotifQsContainer.setCustomizerAnimating(animate);
             mNotifQsContainer.setCustomizerShowing(false);
-            Dependency.get(KeyguardMonitor.class).removeCallback(mKeyguardCallback);
+            mKeyguardMonitor.removeCallback(mKeyguardCallback);
             updateNavColors();
         }
     }
@@ -268,7 +283,7 @@
 
     public void saveInstanceState(Bundle outState) {
         if (isShown) {
-            Dependency.get(KeyguardMonitor.class).removeCallback(mKeyguardCallback);
+            mKeyguardMonitor.removeCallback(mKeyguardCallback);
         }
         outState.putBoolean(EXTRA_QS_CUSTOMIZING, mCustomizing);
     }
@@ -300,7 +315,7 @@
         @Override
         public void onKeyguardShowingChanged() {
             if (!isAttachedToWindow()) return;
-            if (Dependency.get(KeyguardMonitor.class).isShowing() && !mOpening) {
+            if (mKeyguardMonitor.isShowing() && !mOpening) {
                 hide();
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
index d6dad68..187a3bd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/UserDetailView.java
@@ -76,7 +76,7 @@
                 UserSwitcherController.UserRecord item) {
             UserDetailItemView v = UserDetailItemView.convertOrInflate(
                     mContext, convertView, parent);
-            if ((v != convertView && !item.isCurrent) || item.isGuest) {
+            if (!item.isCurrent || item.isGuest) {
                 v.setOnClickListener(this);
             } else {
                 v.setOnClickListener(null);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index 6556ed0..2ae2ac5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -653,7 +653,6 @@
             if (!updateMonitor.isUnlockingWithBiometricAllowed()) {
                 return;
             }
-            animatePadlockError();
             boolean showSwipeToUnlock =
                     msgId == KeyguardUpdateMonitor.BIOMETRIC_HELP_FACE_NOT_RECOGNIZED;
             if (mStatusBarKeyguardViewManager.isBouncerShowing()) {
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 a58ba85..256c8e4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -1798,7 +1798,8 @@
     private void setQsExpansion(float height) {
         height = Math.min(Math.max(height, mQsMinExpansionHeight), mQsMaxExpansionHeight);
         mQsFullyExpanded = height == mQsMaxExpansionHeight && mQsMaxExpansionHeight != 0;
-        if (height > mQsMinExpansionHeight && !mQsExpanded && !mStackScrollerOverscrolling) {
+        if (height > mQsMinExpansionHeight && !mQsExpanded && !mStackScrollerOverscrolling
+                && !mDozing) {
             setQsExpanded(true);
         } else if (height <= mQsMinExpansionHeight && mQsExpanded) {
             setQsExpanded(false);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
index e1ef809..6dc90b9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
@@ -19,7 +19,6 @@
 public interface KeyguardMonitor extends CallbackController<Callback> {
 
     boolean isSecure();
-    boolean canSkipBouncer();
     boolean isShowing();
     boolean isOccluded();
     boolean isKeyguardFadingAway();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
index a950626..e8b0f9b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitorImpl.java
@@ -17,14 +17,12 @@
 package com.android.systemui.statusbar.policy;
 
 import android.annotation.NonNull;
-import android.app.ActivityManager;
 import android.content.Context;
 
 import com.android.internal.util.Preconditions;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
 import com.android.systemui.Dependency;
-import com.android.systemui.settings.CurrentUserTracker;
 
 import java.util.ArrayList;
 
@@ -40,14 +38,11 @@
     private final ArrayList<Callback> mCallbacks = new ArrayList<>();
 
     private final Context mContext;
-    private final CurrentUserTracker mUserTracker;
     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
 
-    private int mCurrentUser;
     private boolean mShowing;
     private boolean mSecure;
     private boolean mOccluded;
-    private boolean mCanSkipBouncer;
 
     private boolean mListening;
     private boolean mKeyguardFadingAway;
@@ -63,13 +58,6 @@
     public KeyguardMonitorImpl(Context context) {
         mContext = context;
         mKeyguardUpdateMonitor = Dependency.get(KeyguardUpdateMonitor.class);
-        mUserTracker = new CurrentUserTracker(mContext) {
-            @Override
-            public void onUserSwitched(int newUserId) {
-                mCurrentUser = newUserId;
-                updateCanSkipBouncerState();
-            }
-        };
     }
 
     @Override
@@ -78,10 +66,7 @@
         mCallbacks.add(callback);
         if (mCallbacks.size() != 0 && !mListening) {
             mListening = true;
-            mCurrentUser = ActivityManager.getCurrentUser();
-            updateCanSkipBouncerState();
             mKeyguardUpdateMonitor.registerCallback(this);
-            mUserTracker.startTracking();
         }
     }
 
@@ -91,7 +76,6 @@
         if (mCallbacks.remove(callback) && mCallbacks.size() == 0 && mListening) {
             mListening = false;
             mKeyguardUpdateMonitor.removeCallback(this);
-            mUserTracker.stopTracking();
         }
     }
 
@@ -110,11 +94,6 @@
         return mOccluded;
     }
 
-    @Override
-    public boolean canSkipBouncer() {
-        return mCanSkipBouncer;
-    }
-
     public void notifyKeyguardState(boolean showing, boolean secure, boolean occluded) {
         if (mShowing == showing && mSecure == secure && mOccluded == occluded) return;
         mShowing = showing;
@@ -125,7 +104,6 @@
 
     @Override
     public void onTrustChanged(int userId) {
-        updateCanSkipBouncerState();
         notifyKeyguardChanged();
     }
 
@@ -133,10 +111,6 @@
         return mKeyguardUpdateMonitor.isDeviceInteractive();
     }
 
-    private void updateCanSkipBouncerState() {
-        mCanSkipBouncer = mKeyguardUpdateMonitor.getUserCanSkipBouncer(mCurrentUser);
-    }
-
     private void notifyKeyguardChanged() {
         // Copy the list to allow removal during callback.
         new ArrayList<>(mCallbacks).forEach(Callback::onKeyguardShowingChanged);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 2e1e520..4fa4b6c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -62,6 +62,7 @@
 import com.android.systemui.plugins.qs.DetailAdapter;
 import com.android.systemui.qs.tiles.UserDetailView;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
+import com.android.systemui.statusbar.phone.UnlockMethodCache;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -597,17 +598,19 @@
 
         final UserSwitcherController mController;
         private final KeyguardMonitor mKeyguardMonitor;
+        private final UnlockMethodCache mUnlockMethodCache;
 
         protected BaseUserAdapter(UserSwitcherController controller) {
             mController = controller;
             mKeyguardMonitor = controller.mKeyguardMonitor;
+            mUnlockMethodCache = UnlockMethodCache.getInstance(controller.mContext);
             controller.addAdapter(new WeakReference<>(this));
         }
 
         public int getUserCount() {
             boolean secureKeyguardShowing = mKeyguardMonitor.isShowing()
                     && mKeyguardMonitor.isSecure()
-                    && !mKeyguardMonitor.canSkipBouncer();
+                    && !mUnlockMethodCache.canSkipBouncer();
             if (!secureKeyguardShowing) {
                 return mController.getUsers().size();
             }
@@ -629,7 +632,7 @@
         public int getCount() {
             boolean secureKeyguardShowing = mKeyguardMonitor.isShowing()
                     && mKeyguardMonitor.isSecure()
-                    && !mKeyguardMonitor.canSkipBouncer();
+                    && !mUnlockMethodCache.canSkipBouncer();
             if (!secureKeyguardShowing) {
                 return mController.getUsers().size();
             }
diff --git a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
index 9b264c4..e44e58a 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.qs.customize.QSCustomizer;
 import com.android.systemui.statusbar.NotificationShelf;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
 import com.android.systemui.statusbar.phone.LockIcon;
@@ -172,6 +173,11 @@
          * Creates the QuickQSPanel.
          */
         QuickQSPanel createQuickQSPanel();
+
+        /**
+         * Creates the QSCustomizer.
+         */
+        QSCustomizer createQSCustomizer();
     }
 
     /**
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
index f2292fd..07fbbcf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSTileHostTest.java
@@ -97,6 +97,8 @@
                 mLooper.getLooper(),
                 mPluginManager, mTunerService, mAutoTiles, mDumpController);
         setUpTileFactory();
+        Settings.Secure.putStringForUser(mContext.getContentResolver(), QSTileHost.TILES_SETTING,
+                "", ActivityManager.getCurrentUser());
     }
 
     private void setUpTileFactory() {
@@ -188,7 +190,8 @@
             // changed
             String newSetting = Settings.Secure.getStringForUser(getContext().getContentResolver(),
                     TILES_SETTING, ActivityManager.getCurrentUser());
-            if (!previousSetting.equals(newSetting)) {
+            // newSetting is not null, as it has just been set.
+            if (!newSetting.equals(previousSetting)) {
                 onTuningChanged(TILES_SETTING, newSetting);
             }
         }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt
new file mode 100644
index 0000000..b51e716
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/UserDetailViewAdapterTest.kt
@@ -0,0 +1,128 @@
+/*
+ * 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.qs.tiles
+
+import android.content.Context
+import android.content.pm.UserInfo
+import android.graphics.Bitmap
+import android.testing.AndroidTestingRunner
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.policy.UserSwitcherController
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyBoolean
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class UserDetailViewAdapterTest : SysuiTestCase() {
+
+    @Mock private lateinit var mUserSwitcherController: UserSwitcherController
+    @Mock private lateinit var mParent: ViewGroup
+    @Mock private lateinit var mUserDetailItemView: UserDetailItemView
+    @Mock private lateinit var mOtherView: View
+    @Mock private lateinit var mInflatedUserDetailItemView: UserDetailItemView
+    @Mock private lateinit var mUserInfo: UserInfo
+    @Mock private lateinit var mPicture: Bitmap
+    @Mock private lateinit var mLayoutInflater: LayoutInflater
+    private lateinit var adapter: UserDetailView.Adapter
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+
+        mContext.addMockSystemService(Context.LAYOUT_INFLATER_SERVICE, mLayoutInflater)
+        `when`(mLayoutInflater.inflate(anyInt(), any(ViewGroup::class.java), anyBoolean()))
+                .thenReturn(mInflatedUserDetailItemView)
+        adapter = UserDetailView.Adapter(mContext, mUserSwitcherController)
+    }
+
+    private fun clickableTest(
+        current: Boolean,
+        guest: Boolean,
+        convertView: View,
+        shouldBeClickable: Boolean
+    ) {
+        val user = createUserRecord(current, guest)
+        val v = adapter.createUserDetailItemView(convertView, mParent, user)
+        if (shouldBeClickable) {
+            verify(v).setOnClickListener(adapter)
+        } else {
+            verify(v).setOnClickListener(null)
+        }
+    }
+
+    @Test
+    fun testGuestIsClickable_differentViews_notCurrent() {
+        clickableTest(false, true, mOtherView, true)
+    }
+
+    @Test
+    fun testGuestIsClickable_differentViews_Current() {
+        clickableTest(true, true, mOtherView, true)
+    }
+
+    @Test
+    fun testGuestIsClickable_sameView_notCurrent() {
+        clickableTest(false, true, mUserDetailItemView, true)
+    }
+
+    @Test
+    fun testGuestIsClickable_sameView_Current() {
+        clickableTest(true, true, mUserDetailItemView, true)
+    }
+
+    @Test
+    fun testNotGuestCurrentUserIsNotClickable_otherView() {
+        clickableTest(true, false, mOtherView, false)
+    }
+
+    @Test
+    fun testNotGuestCurrentUserIsNotClickable_sameView() {
+        clickableTest(true, false, mUserDetailItemView, false)
+    }
+
+    @Test
+    fun testNotGuestNotCurrentUserIsClickable_otherView() {
+        clickableTest(false, false, mOtherView, true)
+    }
+
+    @Test
+    fun testNotGuestNotCurrentUserIsClickable_sameView() {
+        clickableTest(false, false, mUserDetailItemView, true)
+    }
+
+    private fun createUserRecord(current: Boolean, guest: Boolean) =
+            UserSwitcherController.UserRecord(
+                    mUserInfo,
+                    mPicture,
+                    guest,
+                    current,
+                    false /* isAddUser */,
+                    false /* isRestricted */,
+                    true /* isSwitchToEnabled */)
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
index 95c7a4d..2fb0e0e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
@@ -80,9 +80,4 @@
     public long calculateGoingToFullShadeDelay() {
         return 0;
     }
-
-    @Override
-    public boolean canSkipBouncer() {
-        return false;
-    }
 }
diff --git a/packages/WAPPushManager/Android.bp b/packages/WAPPushManager/Android.bp
index 1bec492..c391369 100644
--- a/packages/WAPPushManager/Android.bp
+++ b/packages/WAPPushManager/Android.bp
@@ -9,4 +9,6 @@
     optimize: {
         proguard_flags_files: ["proguard.flags"],
     },
+
+    product_specific: true,
 }
diff --git a/packages/WAPPushManager/CleanSpec.mk b/packages/WAPPushManager/CleanSpec.mk
index b84e1b6..2dcbb10 100644
--- a/packages/WAPPushManager/CleanSpec.mk
+++ b/packages/WAPPushManager/CleanSpec.mk
@@ -47,3 +47,5 @@
 # ************************************************
 # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST
 # ************************************************
+
+$(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/app/WAPPushManager)
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java
index 73ec561..e194f72 100644
--- a/services/core/java/com/android/server/PackageWatchdog.java
+++ b/services/core/java/com/android/server/PackageWatchdog.java
@@ -29,7 +29,6 @@
 import android.os.Environment;
 import android.os.Handler;
 import android.os.Looper;
-import android.os.SystemClock;
 import android.provider.DeviceConfig;
 import android.text.TextUtils;
 import android.util.ArrayMap;
@@ -117,6 +116,10 @@
     private final AtomicFile mPolicyFile;
     private final ExplicitHealthCheckController mHealthCheckController;
     private final ConnectivityModuleConnector mConnectivityModuleConnector;
+    private final Runnable mSyncRequests = this::syncRequests;
+    private final Runnable mSyncStateWithScheduledReason = this::syncStateWithScheduledReason;
+    private final Runnable mSaveToFile = this::saveToFile;
+    private final SystemClock mSystemClock;
     @GuardedBy("mLock")
     private boolean mIsPackagesReady;
     // Flag to control whether explicit health checks are supported or not
@@ -131,9 +134,11 @@
     @GuardedBy("mLock")
     private long mUptimeAtLastStateSync;
 
-    private final Runnable mSyncRequests = this::syncRequests;
-    private final Runnable mSyncStateWithScheduledReason = this::syncStateWithScheduledReason;
-    private final Runnable mSaveToFile = this::saveToFile;
+    @FunctionalInterface
+    @VisibleForTesting
+    interface SystemClock {
+        long uptimeMillis();
+    }
 
     private PackageWatchdog(Context context) {
         // Needs to be constructed inline
@@ -142,7 +147,8 @@
                                 "package-watchdog.xml")),
                 new Handler(Looper.myLooper()), BackgroundThread.getHandler(),
                 new ExplicitHealthCheckController(context),
-                ConnectivityModuleConnector.getInstance());
+                ConnectivityModuleConnector.getInstance(),
+                android.os.SystemClock::uptimeMillis);
     }
 
     /**
@@ -151,13 +157,14 @@
     @VisibleForTesting
     PackageWatchdog(Context context, AtomicFile policyFile, Handler shortTaskHandler,
             Handler longTaskHandler, ExplicitHealthCheckController controller,
-            ConnectivityModuleConnector connectivityModuleConnector) {
+            ConnectivityModuleConnector connectivityModuleConnector, SystemClock clock) {
         mContext = context;
         mPolicyFile = policyFile;
         mShortTaskHandler = shortTaskHandler;
         mLongTaskHandler = longTaskHandler;
         mHealthCheckController = controller;
         mConnectivityModuleConnector = connectivityModuleConnector;
+        mSystemClock = clock;
         loadFromFile();
     }
 
@@ -579,7 +586,7 @@
             mUptimeAtLastStateSync = 0;
         } else {
             Slog.i(TAG, "Scheduling next state sync in " + durationMs + "ms");
-            mUptimeAtLastStateSync = SystemClock.uptimeMillis();
+            mUptimeAtLastStateSync = mSystemClock.uptimeMillis();
             mShortTaskHandler.postDelayed(mSyncStateWithScheduledReason, durationMs);
         }
     }
@@ -612,7 +619,7 @@
     @GuardedBy("mLock")
     private void pruneObserversLocked() {
         long elapsedMs = mUptimeAtLastStateSync == 0
-                ? 0 : SystemClock.uptimeMillis() - mUptimeAtLastStateSync;
+                ? 0 : mSystemClock.uptimeMillis() - mUptimeAtLastStateSync;
         if (elapsedMs <= 0) {
             Slog.i(TAG, "Not pruning observers, elapsed time: " + elapsedMs + "ms");
             return;
@@ -1036,7 +1043,7 @@
          */
         @GuardedBy("mLock")
         public boolean onFailureLocked() {
-            final long now = SystemClock.uptimeMillis();
+            final long now = mSystemClock.uptimeMillis();
             final long duration = now - mUptimeStartMs;
             if (duration > mTriggerFailureDurationMs) {
                 // TODO(b/120598832): Reseting to 1 is not correct
diff --git a/services/core/java/com/android/server/RecoverySystemService.java b/services/core/java/com/android/server/RecoverySystemService.java
index 997178e..1517887 100644
--- a/services/core/java/com/android/server/RecoverySystemService.java
+++ b/services/core/java/com/android/server/RecoverySystemService.java
@@ -25,12 +25,15 @@
 import android.os.RecoverySystem;
 import android.os.RemoteException;
 import android.os.SystemProperties;
+import android.system.ErrnoException;
+import android.system.Os;
 import android.util.Slog;
 
 import libcore.io.IoUtils;
 
 import java.io.DataInputStream;
 import java.io.DataOutputStream;
+import java.io.File;
 import java.io.FileWriter;
 import java.io.IOException;
 
@@ -285,6 +288,7 @@
                     byte[] cmdUtf8 = command.getBytes("UTF-8");
                     dos.writeInt(cmdUtf8.length);
                     dos.write(cmdUtf8, 0, cmdUtf8.length);
+                    dos.flush();
                 }
 
                 // Read the status from the socket.
diff --git a/services/core/java/com/android/server/am/ActiveServices.java b/services/core/java/com/android/server/am/ActiveServices.java
index 8eb5d9b..1675b94 100644
--- a/services/core/java/com/android/server/am/ActiveServices.java
+++ b/services/core/java/com/android/server/am/ActiveServices.java
@@ -829,6 +829,15 @@
         }
     }
 
+    void killMisbehavingService(ServiceRecord r,
+            int appUid, int appPid, String localPackageName) {
+        synchronized (mAm) {
+            stopServiceLocked(r);
+            mAm.crashApplication(appUid, appPid, localPackageName, -1,
+                    "Bad notification for startForeground", true /*force*/);
+        }
+    }
+
     IBinder peekServiceLocked(Intent service, String resolvedType, String callingPackage) {
         ServiceLookupResult r = retrieveServiceLocked(service, null, resolvedType, callingPackage,
                 Binder.getCallingPid(), Binder.getCallingUid(),
@@ -3930,7 +3939,7 @@
     void serviceForegroundCrash(ProcessRecord app, CharSequence serviceRecord) {
         mAm.crashApplication(app.uid, app.pid, app.info.packageName, app.userId,
                 "Context.startForegroundService() did not then call Service.startForeground(): "
-                    + serviceRecord);
+                    + serviceRecord, false /*force*/);
     }
 
     void scheduleServiceTimeoutLocked(ProcessRecord proc) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 3dc33f8..9b1eb3a 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -3568,7 +3568,7 @@
 
     @Override
     public void crashApplication(int uid, int initialPid, String packageName, int userId,
-            String message) {
+            String message, boolean force) {
         if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES)
                 != PackageManager.PERMISSION_GRANTED) {
             String msg = "Permission Denial: crashApplication() from pid="
@@ -3580,7 +3580,8 @@
         }
 
         synchronized(this) {
-            mAppErrors.scheduleAppCrashLocked(uid, initialPid, packageName, userId, message);
+            mAppErrors.scheduleAppCrashLocked(uid, initialPid, packageName, userId,
+                    message, force);
         }
     }
 
@@ -8203,10 +8204,12 @@
     }
 
     /**
-     * @deprecated This method is only used by a few internal components and it will soon be
-     * replaced by a proper bug report API (which will be restricted to a few, pre-defined apps).
+     * @deprecated This method is only used by a few internal components and it will soon start
+     * using bug report API (which will be restricted to a few, pre-defined apps).
      * No new code should be calling it.
      */
+    // TODO(b/137825297): Remove deprecated annotation and rephrase comments for all
+    // requestBugreport functions below.
     @Deprecated
     @Override
     public void requestBugReport(int bugreportType) {
@@ -8214,11 +8217,12 @@
     }
 
     /**
-     * @deprecated This method is only used by a few internal components and it will soon be
-     * replaced by a proper bug report API (which will be restricted to a few, pre-defined apps).
+     * @deprecated This method is only used by a few internal components and it will soon start
+     * using bug report API (which will be restricted to a few, pre-defined apps).
      * No new code should be calling it.
      */
     @Deprecated
+    @Override
     public void requestBugReportWithDescription(@Nullable String shareTitle,
             @Nullable String shareDescription, int bugreportType) {
         String type = null;
@@ -8299,8 +8303,8 @@
     }
 
     /**
-     * @deprecated This method is only used by a few internal components and it will soon be
-     * replaced by a proper bug report API (which will be restricted to a few, pre-defined apps).
+     * @deprecated This method is only used by a few internal components and it will soon start
+     * using bug report API (which will be restricted to a few, pre-defined apps).
      * No new code should be calling it.
      */
     @Deprecated
@@ -8311,8 +8315,8 @@
     }
 
     /**
-     * @deprecated This method is only used by a few internal components and it will soon be
-     * replaced by a proper bug report API (which will be restricted to a few, pre-defined apps).
+     * @deprecated This method is only used by a few internal components and it will soon start
+     * using bug report API (which will be restricted to a few, pre-defined apps).
      * No new code should be calling it.
      */
     @Deprecated
@@ -8322,6 +8326,41 @@
                 ActivityManager.BUGREPORT_OPTION_WIFI);
     }
 
+    /**
+     * Takes an interactive bugreport with a progress notification
+     */
+    @Override
+    public void requestInteractiveBugReport() {
+        requestBugReportWithDescription(null, null, ActivityManager.BUGREPORT_OPTION_INTERACTIVE);
+    }
+
+    /**
+     * Takes an interactive bugreport with a progress notification. Also, shows the given title and
+     * description on the final share notification
+     */
+    @Override
+    public void requestInteractiveBugReportWithDescription(String shareTitle,
+            String shareDescription) {
+        requestBugReportWithDescription(shareTitle, shareDescription,
+                ActivityManager.BUGREPORT_OPTION_INTERACTIVE);
+    }
+
+    /**
+     * Takes a bugreport with minimal user interference
+     */
+    @Override
+    public void requestFullBugReport() {
+        requestBugReportWithDescription(null, null, ActivityManager.BUGREPORT_OPTION_FULL);
+    }
+
+    /**
+     * Takes a bugreport remotely
+     */
+    @Override
+    public void requestRemoteBugReport() {
+        requestBugReportWithDescription(null, null, ActivityManager.BUGREPORT_OPTION_REMOTE);
+    }
+
     public void registerProcessObserver(IProcessObserver observer) {
         enforceCallingPermission(android.Manifest.permission.SET_ACTIVITY_WATCHER,
                 "registerProcessObserver()");
diff --git a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
index a0900b6..8b8c40e 100644
--- a/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
+++ b/services/core/java/com/android/server/am/ActivityManagerShellCommand.java
@@ -1070,7 +1070,7 @@
         } catch (NumberFormatException e) {
             packageName = arg;
         }
-        mInterface.crashApplication(-1, pid, packageName, userId, "shell-induced crash");
+        mInterface.crashApplication(-1, pid, packageName, userId, "shell-induced crash", false);
         return 0;
     }
 
diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java
index 1ff6f4d..6a29c75 100644
--- a/services/core/java/com/android/server/am/AppErrors.java
+++ b/services/core/java/com/android/server/am/AppErrors.java
@@ -314,20 +314,24 @@
     }
 
     void killAppAtUserRequestLocked(ProcessRecord app, Dialog fromDialog) {
-        app.setCrashing(false);
-        app.crashingReport = null;
-        app.setNotResponding(false);
-        app.notRespondingReport = null;
         if (app.anrDialog == fromDialog) {
             app.anrDialog = null;
         }
         if (app.waitDialog == fromDialog) {
             app.waitDialog = null;
         }
+        killAppImmediateLocked(app, "user-terminated", "user request after error");
+    }
+
+    private void killAppImmediateLocked(ProcessRecord app, String reason, String killReason) {
+        app.setCrashing(false);
+        app.crashingReport = null;
+        app.setNotResponding(false);
+        app.notRespondingReport = null;
         if (app.pid > 0 && app.pid != MY_PID) {
-            handleAppCrashLocked(app, "user-terminated" /*reason*/,
+            handleAppCrashLocked(app, reason,
                     null /*shortMsg*/, null /*longMsg*/, null /*stackTrace*/, null /*data*/);
-            app.kill("user request after error", true);
+            app.kill(killReason, true);
         }
     }
 
@@ -341,7 +345,7 @@
      * @param message
      */
     void scheduleAppCrashLocked(int uid, int initialPid, String packageName, int userId,
-            String message) {
+            String message, boolean force) {
         ProcessRecord proc = null;
 
         // Figure out which process to kill.  We don't trust that initialPid
@@ -374,6 +378,14 @@
         }
 
         proc.scheduleCrash(message);
+        if (force) {
+            // If the app is responsive, the scheduled crash will happen as expected
+            // and then the delayed summary kill will be a no-op.
+            final ProcessRecord p = proc;
+            mService.mHandler.postDelayed(
+                    () -> killAppImmediateLocked(p, "forced", "killed for invalid state"),
+                    5000L);
+        }
     }
 
     /**
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index 7a3d3c2..3c2aee4 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1576,7 +1576,7 @@
         }
 
         if (adj == ProcessList.SERVICE_ADJ) {
-            if (doingAll) {
+            if (doingAll && !cycleReEval) {
                 app.serviceb = mNewNumAServiceProcs > (mNumServiceProcs/3);
                 mNewNumServiceProcs++;
                 //Slog.i(TAG, "ADJ " + app + " serviceb=" + app.serviceb);
diff --git a/services/core/java/com/android/server/am/ServiceRecord.java b/services/core/java/com/android/server/am/ServiceRecord.java
index 8c038aa..cc4b160 100644
--- a/services/core/java/com/android/server/am/ServiceRecord.java
+++ b/services/core/java/com/android/server/am/ServiceRecord.java
@@ -803,6 +803,7 @@
             final String localPackageName = packageName;
             final int localForegroundId = foregroundId;
             final Notification _foregroundNoti = foregroundNoti;
+            final ServiceRecord record = this;
             ams.mHandler.post(new Runnable() {
                 public void run() {
                     NotificationManagerInternal nm = LocalServices.getService(
@@ -901,10 +902,8 @@
                         Slog.w(TAG, "Error showing notification for service", e);
                         // If it gave us a garbage notification, it doesn't
                         // get to be foreground.
-                        ams.setServiceForeground(instanceName, ServiceRecord.this,
-                                0, null, 0, 0);
-                        ams.crashApplication(appUid, appPid, localPackageName, -1,
-                                "Bad notification for startForeground: " + e);
+                        ams.mServices.killMisbehavingService(record,
+                                appUid, appPid, localPackageName);
                     }
                 }
             });
diff --git a/services/core/java/com/android/server/connectivity/Vpn.java b/services/core/java/com/android/server/connectivity/Vpn.java
index 7b3eae1..faf01f9 100644
--- a/services/core/java/com/android/server/connectivity/Vpn.java
+++ b/services/core/java/com/android/server/connectivity/Vpn.java
@@ -2082,6 +2082,7 @@
                     }
                     out.write(0xFF);
                     out.write(0xFF);
+                    out.flush();
 
                     // Wait for End-of-File.
                     InputStream in = mSockets[i].getInputStream();
diff --git a/services/core/java/com/android/server/display/DisplayModeDirector.java b/services/core/java/com/android/server/display/DisplayModeDirector.java
index 58aadd1..1fc0db3 100644
--- a/services/core/java/com/android/server/display/DisplayModeDirector.java
+++ b/services/core/java/com/android/server/display/DisplayModeDirector.java
@@ -69,6 +69,7 @@
     private static final int MSG_ALLOWED_MODES_CHANGED = 1;
     private static final int MSG_BRIGHTNESS_THRESHOLDS_CHANGED = 2;
     private static final int MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED = 3;
+    private static final int MSG_REFRESH_RATE_IN_ZONE_CHANGED = 4;
 
     // Special ID used to indicate that given vote is to be applied globally, rather than to a
     // specific display.
@@ -440,23 +441,48 @@
                     mSettingsObserver.onDeviceConfigDefaultPeakRefreshRateChanged(
                             defaultPeakRefreshRate);
                     break;
+
+                case MSG_REFRESH_RATE_IN_ZONE_CHANGED:
+                    int refreshRateInZone = msg.arg1;
+                    mBrightnessObserver.onDeviceConfigRefreshRateInZoneChanged(
+                            refreshRateInZone);
+                    break;
             }
         }
     }
 
     private static final class Vote {
-        // We split the app request into two priorities in case we can satisfy one desire without
-        // the other.
-        public static final int PRIORITY_APP_REQUEST_REFRESH_RATE = 0;
-        public static final int PRIORITY_APP_REQUEST_SIZE = 1;
-        public static final int PRIORITY_USER_SETTING_REFRESH_RATE = 2;
-        public static final int PRIORITY_LOW_BRIGHTNESS = 3;
-        public static final int PRIORITY_LOW_POWER_MODE = 4;
+        // LOW_BRIGHTNESS votes for a single refresh rate like [60,60], [90,90] or null.
+        // If the higher voters result is a range, it will fix the rate to a single choice.
+        // It's used to avoid rate switch in certain conditions.
+        public static final int PRIORITY_LOW_BRIGHTNESS = 0;
+
+        // SETTING_MIN_REFRESH_RATE is used to propose a lower bound of display refresh rate.
+        // It votes [MIN_REFRESH_RATE, Float.POSITIVE_INFINITY]
+        public static final int PRIORITY_USER_SETTING_MIN_REFRESH_RATE = 1;
+
+        // We split the app request into different priorities in case we can satisfy one desire
+        // without the other.
+
+        // Application can specify preferred refresh rate with below attrs.
+        // @see android.view.WindowManager.LayoutParams#preferredRefreshRate
+        // @see android.view.WindowManager.LayoutParams#preferredDisplayModeId
+        // System also forces some apps like blacklisted app to run at a lower refresh rate.
+        // @see android.R.array#config_highRefreshRateBlacklist
+        public static final int PRIORITY_APP_REQUEST_REFRESH_RATE = 2;
+        public static final int PRIORITY_APP_REQUEST_SIZE = 3;
+
+        // SETTING_PEAK_REFRESH_RATE has a high priority and will restrict the bounds of the rest
+        // of low priority voters. It votes [0, max(PEAK, MIN)]
+        public static final int PRIORITY_USER_SETTING_PEAK_REFRESH_RATE = 4;
+
+        // LOW_POWER_MODE force display to [0, 60HZ] if Settings.Global.LOW_POWER_MODE is on.
+        public static final int PRIORITY_LOW_POWER_MODE = 5;
 
         // Whenever a new priority is added, remember to update MIN_PRIORITY and/or MAX_PRIORITY as
         // appropriate, as well as priorityToString.
 
-        public static final int MIN_PRIORITY = PRIORITY_APP_REQUEST_REFRESH_RATE;
+        public static final int MIN_PRIORITY = PRIORITY_LOW_BRIGHTNESS;
         public static final int MAX_PRIORITY = PRIORITY_LOW_POWER_MODE;
 
         /**
@@ -500,12 +526,16 @@
 
         public static String priorityToString(int priority) {
             switch (priority) {
+                case PRIORITY_LOW_BRIGHTNESS:
+                    return "PRIORITY_LOW_BRIGHTNESS";
+                case PRIORITY_USER_SETTING_MIN_REFRESH_RATE:
+                    return "PRIORITY_USER_SETTING_MIN_REFRESH_RATE";
                 case PRIORITY_APP_REQUEST_REFRESH_RATE:
                     return "PRIORITY_APP_REQUEST_REFRESH_RATE";
                 case PRIORITY_APP_REQUEST_SIZE:
                     return "PRIORITY_APP_REQUEST_SIZE";
-                case PRIORITY_USER_SETTING_REFRESH_RATE:
-                    return "PRIORITY_USER_SETTING_REFRESH_RATE";
+                case PRIORITY_USER_SETTING_PEAK_REFRESH_RATE:
+                    return "PRIORITY_USER_SETTING_PEAK_REFRESH_RATE";
                 case PRIORITY_LOW_POWER_MODE:
                     return "PRIORITY_LOW_POWER_MODE";
                 default:
@@ -608,12 +638,11 @@
             float peakRefreshRate = Settings.System.getFloat(mContext.getContentResolver(),
                     Settings.System.PEAK_REFRESH_RATE, mDefaultPeakRefreshRate);
 
-            if (peakRefreshRate < minRefreshRate) {
-                peakRefreshRate = minRefreshRate;
-            }
+            updateVoteLocked(Vote.PRIORITY_USER_SETTING_PEAK_REFRESH_RATE,
+                    Vote.forRefreshRates(0f, Math.max(minRefreshRate, peakRefreshRate)));
+            updateVoteLocked(Vote.PRIORITY_USER_SETTING_MIN_REFRESH_RATE,
+                    Vote.forRefreshRates(minRefreshRate, Float.POSITIVE_INFINITY));
 
-            Vote vote = Vote.forRefreshRates(minRefreshRate, peakRefreshRate);
-            updateVoteLocked(Vote.PRIORITY_USER_SETTING_REFRESH_RATE, vote);
             mBrightnessObserver.onRefreshRateSettingChangedLocked(minRefreshRate, peakRefreshRate);
         }
 
@@ -655,6 +684,7 @@
                 refreshRateVote = null;
                 sizeVote = null;
             }
+
             updateVoteLocked(displayId, Vote.PRIORITY_APP_REQUEST_REFRESH_RATE, refreshRateVote);
             updateVoteLocked(displayId, Vote.PRIORITY_APP_REQUEST_SIZE, sizeVote);
             return;
@@ -799,6 +829,8 @@
         private boolean mRefreshRateChangeable = false;
         private boolean mLowPowerModeEnabled = false;
 
+        private int mRefreshRateInZone;
+
         BrightnessObserver(Context context, Handler handler) {
             super(handler);
             mContext = context;
@@ -815,6 +847,7 @@
 
         public void observe(SensorManager sensorManager) {
             mSensorManager = sensorManager;
+
             // DeviceConfig is accessible after system ready.
             int[] brightnessThresholds = mDeviceConfigDisplaySettings.getBrightnessThresholds();
             int[] ambientThresholds = mDeviceConfigDisplaySettings.getAmbientThresholds();
@@ -824,6 +857,8 @@
                 mDisplayBrightnessThresholds = brightnessThresholds;
                 mAmbientBrightnessThresholds = ambientThresholds;
             }
+
+            mRefreshRateInZone = mDeviceConfigDisplaySettings.getRefreshRateInZone();
             restartObserver();
             mDeviceConfigDisplaySettings.startListening();
         }
@@ -863,8 +898,16 @@
             restartObserver();
         }
 
+        public void onDeviceConfigRefreshRateInZoneChanged(int refreshRate) {
+            if (refreshRate != mRefreshRateInZone) {
+                mRefreshRateInZone = refreshRate;
+                restartObserver();
+            }
+        }
+
         public void dumpLocked(PrintWriter pw) {
             pw.println("  BrightnessObserver");
+            pw.println("    mRefreshRateInZone: " + mRefreshRateInZone);
 
             for (int d: mDisplayBrightnessThresholds) {
                 pw.println("    mDisplayBrightnessThreshold: " + d);
@@ -950,6 +993,10 @@
          * to value changes.
          */
         private boolean checkShouldObserve(int[] a) {
+            if (mRefreshRateInZone <= 0) {
+                return false;
+            }
+
             for (int d: a) {
                 if (d >= 0) {
                     return true;
@@ -959,37 +1006,42 @@
             return false;
         }
 
+        private boolean isInsideZone(int brightness, float lux) {
+            for (int i = 0; i < mDisplayBrightnessThresholds.length; i++) {
+                int disp = mDisplayBrightnessThresholds[i];
+                int ambi = mAmbientBrightnessThresholds[i];
+
+                if (disp >= 0 && ambi >= 0) {
+                    if (brightness <= disp && mAmbientLux <= ambi) {
+                        return true;
+                    }
+                } else if (disp >= 0) {
+                    if (brightness <= disp) {
+                        return true;
+                    }
+                } else if (ambi >= 0) {
+                    if (mAmbientLux <= ambi) {
+                        return true;
+                    }
+                }
+            }
+
+            return false;
+        }
+
         private void onBrightnessChangedLocked() {
             int brightness = Settings.System.getInt(mContext.getContentResolver(),
                     Settings.System.SCREEN_BRIGHTNESS, -1);
 
             Vote vote = null;
-            for (int i = 0; i < mDisplayBrightnessThresholds.length; i++) {
-                int disp = mDisplayBrightnessThresholds[i];
-                int ambi = mAmbientBrightnessThresholds[i];
-
-                if (disp >= 0 && ambi >= 0) {
-                    if (brightness <= disp && mAmbientLux <= ambi) {
-                        vote = Vote.forRefreshRates(0f, 60f);
-                    }
-                } else if (disp >= 0) {
-                    if (brightness <= disp) {
-                        vote = Vote.forRefreshRates(0f, 60f);
-                    }
-                } else if (ambi >= 0) {
-                    if (mAmbientLux <= ambi) {
-                        vote = Vote.forRefreshRates(0f, 60f);
-                    }
-                }
-
-                if (vote != null) {
-                    break;
-                }
+            boolean insideZone = isInsideZone(brightness, mAmbientLux);
+            if (insideZone) {
+                vote = Vote.forRefreshRates(mRefreshRateInZone, mRefreshRateInZone);
             }
 
             if (DEBUG) {
                 Slog.d(TAG, "Display brightness " + brightness + ", ambient lux " +  mAmbientLux +
-                        (vote != null ? " 60hz only" : " no refresh rate limit"));
+                        ", Vote " + vote);
             }
             updateVoteLocked(Vote.PRIORITY_LOW_BRIGHTNESS, vote);
         }
@@ -1104,7 +1156,6 @@
     }
 
     private class DeviceConfigDisplaySettings implements DeviceConfig.OnPropertiesChangedListener {
-
         public DeviceConfigDisplaySettings() {
         }
 
@@ -1118,7 +1169,8 @@
          */
         public int[] getBrightnessThresholds() {
             return getIntArrayProperty(
-                    DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_BRIGHTNESS_THRESHOLDS);
+                    DisplayManager.DeviceConfig.
+                            KEY_PEAK_REFRESH_RATE_DISPLAY_BRIGHTNESS_THRESHOLDS);
         }
 
         /*
@@ -1126,7 +1178,8 @@
          */
         public int[] getAmbientThresholds() {
             return getIntArrayProperty(
-                    DisplayManager.DeviceConfig.KEY_PEAK_REFRESH_RATE_AMBIENT_THRESHOLDS);
+                    DisplayManager.DeviceConfig.
+                            KEY_PEAK_REFRESH_RATE_AMBIENT_BRIGHTNESS_THRESHOLDS);
         }
 
         /*
@@ -1143,17 +1196,32 @@
             return defaultPeakRefreshRate;
         }
 
+        public int getRefreshRateInZone() {
+            int defaultRefreshRateInZone = mContext.getResources().getInteger(
+                    R.integer.config_defaultRefreshRateInZone);
+
+            int refreshRate = DeviceConfig.getInt(
+                    DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
+                    DisplayManager.DeviceConfig.KEY_REFRESH_RATE_IN_ZONE,
+                    defaultRefreshRateInZone);
+
+            return refreshRate;
+        }
+
         @Override
         public void onPropertiesChanged(@NonNull DeviceConfig.Properties properties) {
             int[] brightnessThresholds = getBrightnessThresholds();
             int[] ambientThresholds = getAmbientThresholds();
             Float defaultPeakRefreshRate = getDefaultPeakRefreshRate();
+            int refreshRateInZone = getRefreshRateInZone();
 
             mHandler.obtainMessage(MSG_BRIGHTNESS_THRESHOLDS_CHANGED,
                     new Pair<int[], int[]>(brightnessThresholds, ambientThresholds))
                     .sendToTarget();
             mHandler.obtainMessage(MSG_DEFAULT_PEAK_REFRESH_RATE_CHANGED,
                     defaultPeakRefreshRate).sendToTarget();
+            mHandler.obtainMessage(MSG_REFRESH_RATE_IN_ZONE_CHANGED, refreshRateInZone,
+                    0).sendToTarget();
         }
 
         private int[] getIntArrayProperty(String prop) {
diff --git a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
index dacf372..9a85f952 100644
--- a/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
+++ b/services/core/java/com/android/server/hdmi/HdmiCecLocalDeviceTv.java
@@ -1635,6 +1635,10 @@
         removeAction(SystemAudioAutoInitiationAction.class);
         removeAction(SystemAudioStatusAction.class);
         removeAction(VolumeControlAction.class);
+
+        if (!mService.isControlEnabled()) {
+            setSystemAudioMode(false);
+        }
     }
 
     @ServiceThreadOnly
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index f04d459..db8d098 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -926,7 +926,7 @@
                         () -> mAm.crashApplication(uid, initialPid, pkg, -1,
                             "Bad notification(tag=" + tag + ", id=" + id + ") posted from package "
                                 + pkg + ", crashing app(uid=" + uid + ", pid=" + initialPid + "): "
-                                + message));
+                                + message, true /* force */));
             }
         }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 6e2fd38..ab77cc6 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -13852,7 +13852,7 @@
 
         // If this is an update to a package that might be potentially downgraded, then we
         // need to check with the rollback manager whether there's any userdata that might
-        // need to be restored for the package.
+        // need to be snapshotted or restored for the package.
         //
         // TODO(narayan): Get this working for cases where userId == UserHandle.USER_ALL.
         if (res.returnCode == PackageManager.INSTALL_SUCCEEDED && !doRestore && update) {
@@ -13879,12 +13879,16 @@
                 installedUsers = ps.queryInstalledUsers(allUsers, true);
             }
 
-            if (ps != null) {
+            boolean doSnapshotOrRestore = data != null && data.args != null
+                    && ((data.args.installFlags & PackageManager.INSTALL_ENABLE_ROLLBACK) != 0
+                    || (data.args.installFlags & PackageManager.INSTALL_REQUEST_DOWNGRADE) != 0);
+
+            if (ps != null && doSnapshotOrRestore) {
                 try {
                     rm.snapshotAndRestoreUserData(packageName, installedUsers, appId, ceDataInode,
                             seInfo, token);
                 } catch (RemoteException re) {
-                    // Cannot happen, the RollbackManager is hosted in the same process.
+                    Log.e(TAG, "Error snapshotting/restoring user data: " + re);
                 }
                 doRestore = true;
             }
@@ -18013,19 +18017,20 @@
                         // or packages running under the shared user of the removed
                         // package if revoking the permissions requested only by the removed
                         // package is successful and this causes a change in gids.
+                        boolean shouldKill = false;
                         for (int userId : UserManagerService.getInstance().getUserIds()) {
                             final int userIdToKill = mSettings.updateSharedUserPermsLPw(deletedPs,
                                     userId);
-                            if (userIdToKill == UserHandle.USER_ALL
-                                    || userIdToKill >= UserHandle.USER_SYSTEM) {
-                                // If gids changed for this user, kill all affected packages.
-                                mHandler.post(() -> {
-                                    // This has to happen with no lock held.
-                                    killApplication(deletedPs.name, deletedPs.appId,
-                                            KILL_APP_REASON_GIDS_CHANGED);
-                                });
-                                break;
-                            }
+                            shouldKill |= userIdToKill == UserHandle.USER_ALL
+                                    || userIdToKill >= UserHandle.USER_SYSTEM;
+                        }
+                        // If gids changed, kill all affected packages.
+                        if (shouldKill) {
+                            mHandler.post(() -> {
+                                // This has to happen with no lock held.
+                                killApplication(deletedPs.name, deletedPs.appId,
+                                        KILL_APP_REASON_GIDS_CHANGED);
+                            });
                         }
                     }
                     clearPackagePreferredActivitiesLPw(
diff --git a/services/core/java/com/android/server/pm/StagingManager.java b/services/core/java/com/android/server/pm/StagingManager.java
index dd1eb83..8d1ed43 100644
--- a/services/core/java/com/android/server/pm/StagingManager.java
+++ b/services/core/java/com/android/server/pm/StagingManager.java
@@ -150,6 +150,14 @@
             return;
         }
 
+        // Verify signing details for downgrade
+        // Allow downgrading from B to A iff it is possible to upgrade from A to B
+        if (existingApexPkg.getLongVersionCode() > newApexPkg.getLongVersionCode()
+                && existingSigningDetails.checkCapability(signingDetails,
+                        PackageParser.SigningDetails.CertCapabilities.INSTALLED_DATA)) {
+            return;
+        }
+
         throw new PackageManagerException(SessionInfo.STAGED_SESSION_VERIFICATION_FAILED,
                 "APK-container signature of APEX package " + packageName + " with version "
                         + newApexPkg.versionCodeMajor + " and path " + apexPath + " is not"
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 72c8b22..83aa07d 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -67,6 +67,7 @@
 import android.content.pm.ParceledListSlice;
 import android.content.pm.PermissionGroupInfo;
 import android.content.pm.PermissionInfo;
+import android.content.pm.permission.SplitPermissionInfoParcelable;
 import android.metrics.LogMaker;
 import android.os.Binder;
 import android.os.Build;
@@ -2348,10 +2349,11 @@
                         // or has updated its target SDK and AR is no longer implicit to it.
                         // This is a compatibility workaround for apps when AR permission was
                         // split in Q.
-                        int numSplitPerms = PermissionManager.SPLIT_PERMISSIONS.size();
+                        final List<SplitPermissionInfoParcelable> permissionList =
+                                getSplitPermissions();
+                        int numSplitPerms = permissionList.size();
                         for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {
-                            PermissionManager.SplitPermissionInfo sp =
-                                    PermissionManager.SPLIT_PERMISSIONS.get(splitPermNum);
+                            SplitPermissionInfoParcelable sp = permissionList.get(splitPermNum);
                             String splitPermName = sp.getSplitPermission();
                             if (sp.getNewPermissions().contains(permName)
                                     && origPermissions.hasInstallPermission(splitPermName)) {
@@ -2920,10 +2922,10 @@
         String pkgName = pkg.packageName;
         ArrayMap<String, ArraySet<String>> newToSplitPerms = new ArrayMap<>();
 
-        int numSplitPerms = PermissionManager.SPLIT_PERMISSIONS.size();
+        final List<SplitPermissionInfoParcelable> permissionList = getSplitPermissions();
+        int numSplitPerms = permissionList.size();
         for (int splitPermNum = 0; splitPermNum < numSplitPerms; splitPermNum++) {
-            PermissionManager.SplitPermissionInfo spi =
-                    PermissionManager.SPLIT_PERMISSIONS.get(splitPermNum);
+            SplitPermissionInfoParcelable spi = permissionList.get(splitPermNum);
 
             List<String> newPerms = spi.getNewPermissions();
             int numNewPerms = newPerms.size();
@@ -2991,6 +2993,12 @@
         return updatedUserIds;
     }
 
+    @Override
+    public List<SplitPermissionInfoParcelable> getSplitPermissions() {
+        return PermissionManager.splitPermissionInfoListToParcelableList(
+                SystemConfig.getInstance().getSplitPermissions());
+    }
+
     private boolean isNewPlatformPermissionForPackage(String perm, PackageParser.Package pkg) {
         boolean allowed = false;
         final int NP = PackageParser.NEW_PERMISSIONS.length;
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index ddbd9c9..a671e5f 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -118,6 +118,10 @@
     @GuardedBy("mLock")
     private final List<Rollback> mRollbacks;
 
+    // Apk sessions from a staged session with no matching rollback.
+    @GuardedBy("mLock")
+    private final IntArray mOrphanedApkSessionIds = new IntArray();
+
     private final RollbackStore mRollbackStore;
 
     private final Context mContext;
@@ -655,6 +659,11 @@
                 // hasn't actually been updated.
                 onPackageReplaced(apexPackageName);
             }
+
+            synchronized (mLock) {
+                mOrphanedApkSessionIds.clear();
+            }
+
             mPackageHealthObserver.onBootCompletedAsync();
         });
     }
@@ -865,6 +874,16 @@
             }
         }
 
+        // Check to see if this is the apk session for a staged session for which rollback was
+        // cancelled.
+        synchronized (mLock) {
+            if (mOrphanedApkSessionIds.indexOf(parentSession.getSessionId()) != -1) {
+                Slog.w(TAG, "Not enabling rollback for apk as no matching staged session "
+                        + "rollback exists");
+                return false;
+            }
+        }
+
         NewRollback newRollback;
         synchronized (mLock) {
             // See if we already have a NewRollback that contains this package
@@ -1122,6 +1141,13 @@
                         break;
                     }
                 }
+                if (rollback == null) {
+                    // Did not find rollback matching originalSessionId.
+                    Slog.e(TAG, "notifyStagedApkSession did not find rollback for session "
+                            + originalSessionId
+                            + ". Adding orphaned apk session " + apkSessionId);
+                    mOrphanedApkSessionIds.add(apkSessionId);
+                }
             }
 
             if (rollback != null) {
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 30a3aef..ad340fe 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -255,13 +255,19 @@
         }
     }
 
-    public void onSomeWindowResizedOrMovedLocked(int displayId) {
+    /**
+     * Called when the location or the size of the window is changed. Moving the window to
+     * another display is also taken into consideration.
+     * @param displayIds the display ids of displays when the situation happens.
+     */
+    public void onSomeWindowResizedOrMovedLocked(int... displayIds) {
         // Not relevant for the display magnifier.
-
-        final WindowsForAccessibilityObserver windowsForA11yObserver =
-                mWindowsForAccessibilityObserver.get(displayId);
-        if (windowsForA11yObserver != null) {
-            windowsForA11yObserver.scheduleComputeChangedWindowsLocked();
+        for (int i = 0; i < displayIds.length; i++) {
+            final WindowsForAccessibilityObserver windowsForA11yObserver =
+                    mWindowsForAccessibilityObserver.get(displayIds[i]);
+            if (windowsForA11yObserver != null) {
+                windowsForA11yObserver.scheduleComputeChangedWindowsLocked();
+            }
         }
     }
 
@@ -808,7 +814,7 @@
                 private final Paint mPaint = new Paint();
 
                 private final SurfaceControl mSurfaceControl;
-                private final Surface mSurface = new Surface();
+                private final Surface mSurface = mService.mSurfaceFactory.get();
 
                 private final AnimationController mAnimationController;
 
@@ -961,7 +967,7 @@
                 }
 
                 public void releaseSurface() {
-                    mService.mTransactionFactory.make().remove(mSurfaceControl).apply();
+                    mService.mTransactionFactory.get().remove(mSurfaceControl).apply();
                     mSurface.release();
                 }
 
diff --git a/services/core/java/com/android/server/wm/ActivityDisplay.java b/services/core/java/com/android/server/wm/ActivityDisplay.java
index e76078f..f3e7384 100644
--- a/services/core/java/com/android/server/wm/ActivityDisplay.java
+++ b/services/core/java/com/android/server/wm/ActivityDisplay.java
@@ -574,11 +574,9 @@
      * then we should explicitly pause that stack's top activity.
      * @param userLeaving Passed to pauseActivity() to indicate whether to call onUserLeaving().
      * @param resuming The resuming activity.
-     * @param dontWait The resuming activity isn't going to wait for all activities to be paused
-     *                 before resuming.
      * @return {@code true} if any activity was paused as a result of this call.
      */
-    boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming, boolean dontWait) {
+    boolean pauseBackStacks(boolean userLeaving, ActivityRecord resuming) {
         boolean someActivityPaused = false;
         for (int stackNdx = mStacks.size() - 1; stackNdx >= 0; --stackNdx) {
             final ActivityStack stack = mStacks.get(stackNdx);
@@ -588,8 +586,8 @@
                         || !stack.isFocusable())) {
                 if (DEBUG_STATES) Slog.d(TAG_STATES, "pauseBackStacks: stack=" + stack +
                         " mResumedActivity=" + resumedActivity);
-                someActivityPaused |= stack.startPausingLocked(userLeaving, false, resuming,
-                        dontWait);
+                someActivityPaused |= stack.startPausingLocked(userLeaving, false /* uiSleeping*/,
+                        resuming);
             }
         }
         return someActivityPaused;
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 8e42943..12cb94d 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -118,7 +118,6 @@
 import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
 import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
 import static com.android.server.wm.ActivityStack.STACK_VISIBILITY_VISIBLE;
-import static com.android.server.wm.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
 import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
 import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_APP;
@@ -1664,11 +1663,10 @@
     @interface FinishRequest {}
 
     /**
-     * See {@link #finishIfPossible(int, Intent, String, boolean, boolean)}
+     * See {@link #finishIfPossible(int, Intent, String, boolean)}
      */
     @FinishRequest int finishIfPossible(String reason, boolean oomAdj) {
-        return finishIfPossible(Activity.RESULT_CANCELED, null /* resultData */, reason,
-                oomAdj, !PAUSE_IMMEDIATELY);
+        return finishIfPossible(Activity.RESULT_CANCELED, null /* resultData */, reason, oomAdj);
     }
 
     /**
@@ -1683,7 +1681,7 @@
      * request to finish it was not ignored.
      */
     @FinishRequest int finishIfPossible(int resultCode, Intent resultData, String reason,
-            boolean oomAdj, boolean pauseImmediately) {
+            boolean oomAdj) {
         if (DEBUG_RESULTS || DEBUG_STATES) {
             Slog.v(TAG_STATES, "Finishing activity r=" + this + ", result=" + resultCode
                     + ", data=" + resultData + ", reason=" + reason);
@@ -1768,7 +1766,8 @@
                     if (DEBUG_USER_LEAVING) {
                         Slog.v(TAG_USER_LEAVING, "finish() => pause with userLeaving=false");
                     }
-                    stack.startPausingLocked(false, false, null, pauseImmediately);
+                    stack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */,
+                            null /* resuming */);
                 }
 
                 if (endTask) {
@@ -2104,7 +2103,7 @@
                 // TODO: If the callers to removeTask() changes such that we have multiple places
                 //       where we are destroying the task, move this back into removeTask()
                 mStackSupervisor.removeTaskByIdLocked(task.taskId, false /* killProcess */,
-                        !REMOVE_FROM_RECENTS, PAUSE_IMMEDIATELY, reason);
+                        !REMOVE_FROM_RECENTS, reason);
             }
 
             // We must keep the task around until all activities are destroyed. The following
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index a8eaaa4c..f5f6625 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -63,7 +63,6 @@
 import static com.android.server.wm.ActivityStack.ActivityState.STARTED;
 import static com.android.server.wm.ActivityStack.ActivityState.STOPPED;
 import static com.android.server.wm.ActivityStack.ActivityState.STOPPING;
-import static com.android.server.wm.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
 import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
 import static com.android.server.wm.ActivityStackSupervisor.dumpHistoryList;
 import static com.android.server.wm.ActivityStackSupervisor.printThisActivity;
@@ -1547,7 +1546,7 @@
             if (DEBUG_USER_LEAVING) Slog.v(TAG_USER_LEAVING,
                     "Sleep => pause with userLeaving=false");
 
-            startPausingLocked(false, true, null, false);
+            startPausingLocked(false /* userLeaving */, true /* uiSleeping */, null /* resuming */);
             shouldSleep = false ;
         } else if (mPausingActivity != null) {
             // Still waiting for something to pause; can't sleep yet.
@@ -1617,13 +1616,11 @@
      * @param resuming The activity we are currently trying to resume or null if this is not being
      *                 called as part of resuming the top activity, so we shouldn't try to instigate
      *                 a resume here if not null.
-     * @param pauseImmediately True if the caller does not want to wait for the activity callback to
-     *                         complete pausing.
      * @return Returns true if an activity now is in the PAUSING state, and we are waiting for
      * it to tell us when it is done.
      */
     final boolean startPausingLocked(boolean userLeaving, boolean uiSleeping,
-            ActivityRecord resuming, boolean pauseImmediately) {
+            ActivityRecord resuming) {
         if (mPausingActivity != null) {
             Slog.wtf(TAG, "Going to pause when pause is already pending for " + mPausingActivity
                     + " state=" + mPausingActivity.getState());
@@ -1661,6 +1658,19 @@
 
         mService.updateCpuStats();
 
+        boolean pauseImmediately = false;
+        if (resuming != null && (resuming.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0) {
+            // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous
+            // activity to be paused, while at the same time resuming the new resume activity
+            // only if the previous activity can't go into Pip since we want to give Pip
+            // activities a chance to enter Pip before resuming the next activity.
+            final boolean lastResumedCanPip = prev != null && prev.checkEnterPictureInPictureState(
+                    "shouldResumeWhilePausing", userLeaving);
+            if (!lastResumedCanPip) {
+                pauseImmediately = true;
+            }
+        }
+
         if (prev.attachedToProcess()) {
             if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Enqueueing pending pause: " + prev);
             try {
@@ -1758,7 +1768,8 @@
         mRootActivityContainer.ensureActivitiesVisible(null, 0, !PRESERVE_WINDOWS);
     }
 
-    private void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
+    @VisibleForTesting
+    void completePauseLocked(boolean resumeNext, ActivityRecord resuming) {
         ActivityRecord prev = mPausingActivity;
         if (DEBUG_PAUSE) Slog.v(TAG_PAUSE, "Complete pause: " + prev);
 
@@ -2594,7 +2605,6 @@
 
         mStackSupervisor.setLaunchSource(next.info.applicationInfo.uid);
 
-        boolean lastResumedCanPip = false;
         ActivityRecord lastResumed = null;
         final ActivityStack lastFocusedStack = display.getLastFocusedStack();
         if (lastFocusedStack != null && lastFocusedStack != this) {
@@ -2608,23 +2618,15 @@
                         + " next=" + next + " lastResumed=" + lastResumed);
                 userLeaving = false;
             }
-            lastResumedCanPip = lastResumed != null && lastResumed.checkEnterPictureInPictureState(
-                    "resumeTopActivity", userLeaving /* beforeStopping */);
         }
-        // If the flag RESUME_WHILE_PAUSING is set, then continue to schedule the previous activity
-        // to be paused, while at the same time resuming the new resume activity only if the
-        // previous activity can't go into Pip since we want to give Pip activities a chance to
-        // enter Pip before resuming the next activity.
-        final boolean resumeWhilePausing = (next.info.flags & FLAG_RESUME_WHILE_PAUSING) != 0
-                && !lastResumedCanPip;
 
-        boolean pausing = display.pauseBackStacks(userLeaving, next, false);
+        boolean pausing = display.pauseBackStacks(userLeaving, next);
         if (mResumedActivity != null) {
             if (DEBUG_STATES) Slog.d(TAG_STATES,
                     "resumeTopActivityLocked: Pausing " + mResumedActivity);
-            pausing |= startPausingLocked(userLeaving, false, next, false);
+            pausing |= startPausingLocked(userLeaving, false /* uiSleeping */, next);
         }
-        if (pausing && !resumeWhilePausing) {
+        if (pausing) {
             if (DEBUG_SWITCH || DEBUG_STATES) Slog.v(TAG_STATES,
                     "resumeTopActivityLocked: Skip resume: need to start pausing");
             // At this point we want to put the upcoming activity's process
@@ -3802,8 +3804,7 @@
         final long origId = Binder.clearCallingIdentity();
         for (int i = start; i > finishTo; i--) {
             final ActivityRecord r = activities.get(i);
-            r.finishIfPossible(resultCode, resultData, "navigate-up", true /* oomAdj */,
-                    !PAUSE_IMMEDIATELY);
+            r.finishIfPossible(resultCode, resultData, "navigate-up", true /* oomAdj */);
             // Only return the supplied result for the first activity finished
             resultCode = Activity.RESULT_CANCELED;
             resultData = null;
@@ -3840,8 +3841,7 @@
                 } catch (RemoteException e) {
                     foundParentInTask = false;
                 }
-                parent.finishIfPossible(resultCode, resultData, "navigate-top",
-                        true /* oomAdj */, !PAUSE_IMMEDIATELY);
+                parent.finishIfPossible(resultCode, resultData, "navigate-top", true /* oomAdj */);
             }
         }
         Binder.restoreCallingIdentity(origId);
diff --git a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
index a06b9ce..a480fb8 100644
--- a/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityStackSupervisor.java
@@ -200,10 +200,6 @@
     // Used to indicate that a task is removed it should also be removed from recents.
     static final boolean REMOVE_FROM_RECENTS = true;
 
-    // Used to indicate that pausing an activity should occur immediately without waiting for
-    // the activity callback indicating that it has completed pausing
-    static final boolean PAUSE_IMMEDIATELY = true;
-
     /** True if the docked stack is currently being resized. */
     private boolean mDockedStackResizing;
 
@@ -1778,30 +1774,19 @@
     }
 
     /**
-     * See {@link #removeTaskByIdLocked(int, boolean, boolean, boolean)}
-     */
-    boolean removeTaskByIdLocked(int taskId, boolean killProcess, boolean removeFromRecents,
-            String reason) {
-        return removeTaskByIdLocked(taskId, killProcess, removeFromRecents, !PAUSE_IMMEDIATELY,
-                reason);
-    }
-
-    /**
      * Removes the task with the specified task id.
      *
      * @param taskId Identifier of the task to be removed.
      * @param killProcess Kill any process associated with the task if possible.
      * @param removeFromRecents Whether to also remove the task from recents.
-     * @param pauseImmediately Pauses all task activities immediately without waiting for the
-     *                         pause-complete callback from the activity.
      * @return Returns true if the given task was found and removed.
      */
     boolean removeTaskByIdLocked(int taskId, boolean killProcess, boolean removeFromRecents,
-            boolean pauseImmediately, String reason) {
+            String reason) {
         final TaskRecord tr =
                 mRootActivityContainer.anyTaskForId(taskId, MATCH_TASK_IN_STACKS_OR_RECENT_TASKS);
         if (tr != null) {
-            tr.removeTaskActivitiesLocked(pauseImmediately, reason);
+            tr.removeTaskActivitiesLocked(reason);
             cleanUpRemovedTaskLocked(tr, killProcess, removeFromRecents);
             mService.getLockTaskController().clearLockedTask(tr);
             if (tr.isPersistable) {
@@ -1925,7 +1910,7 @@
             // Task was trimmed from the recent tasks list -- remove the active task record as well
             // since the user won't really be able to go back to it
             removeTaskByIdLocked(task.taskId, killProcess, false /* removeFromRecents */,
-                    !PAUSE_IMMEDIATELY, "recent-task-trimmed");
+                    "recent-task-trimmed");
         }
         task.removedFromRecents();
     }
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 8d40f87..ee56c09 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -87,7 +87,6 @@
 import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_DESTROYING;
 import static com.android.server.wm.ActivityStackSupervisor.DEFER_RESUME;
 import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
-import static com.android.server.wm.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
 import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
 import static com.android.server.wm.ActivityStackSupervisor.REMOVE_FROM_RECENTS;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ALL;
@@ -1616,8 +1615,7 @@
                     // Explicitly dismissing the activity so reset its relaunch flag.
                     r.mRelaunchReason = RELAUNCH_REASON_NONE;
                 } else {
-                    r.finishIfPossible(resultCode, resultData, "app-request",
-                            true /* oomAdj */, !PAUSE_IMMEDIATELY);
+                    r.finishIfPossible(resultCode, resultData, "app-request", true /* oomAdj */);
                     res = r.finishing;
                     if (!res) {
                         Slog.i(TAG, "Failed to finish by app-request");
diff --git a/services/core/java/com/android/server/wm/AppWindowThumbnail.java b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
index 4ceae72..b52ade4 100644
--- a/services/core/java/com/android/server/wm/AppWindowThumbnail.java
+++ b/services/core/java/com/android/server/wm/AppWindowThumbnail.java
@@ -41,6 +41,8 @@
 
 import com.android.server.wm.SurfaceAnimator.Animatable;
 
+import java.util.function.Supplier;
+
 /**
  * Represents a surface that is displayed over an {@link AppWindowToken}
  */
@@ -55,8 +57,9 @@
     private final int mHeight;
     private final boolean mRelative;
 
-    AppWindowThumbnail(Transaction t, AppWindowToken appToken, GraphicBuffer thumbnailHeader) {
-        this(t, appToken, thumbnailHeader, false /* relative */);
+    AppWindowThumbnail(Supplier<Surface> surfaceFactory, Transaction t, AppWindowToken appToken,
+            GraphicBuffer thumbnailHeader) {
+        this(surfaceFactory, t, appToken, thumbnailHeader, false /* relative */);
     }
 
     /**
@@ -66,9 +69,9 @@
      * @param relative Whether this thumbnail will be a child of appToken (and thus positioned
      *                 relative to it) or not.
      */
-    AppWindowThumbnail(Transaction t, AppWindowToken appToken, GraphicBuffer thumbnailHeader,
-            boolean relative) {
-        this(t, appToken, thumbnailHeader, relative, new Surface(), null);
+    AppWindowThumbnail(Supplier<Surface> surfaceFactory, Transaction t, AppWindowToken appToken,
+            GraphicBuffer thumbnailHeader, boolean relative) {
+        this(t, appToken, thumbnailHeader, relative, surfaceFactory.get(), null);
     }
 
     AppWindowThumbnail(Transaction t, AppWindowToken appToken, GraphicBuffer thumbnailHeader,
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index 7e0d9a0..ffd9021 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -1793,8 +1793,8 @@
                     mWmService.mTaskSnapshotController.createTaskSnapshot(
                             task, 1 /* scaleFraction */);
             if (snapshot != null) {
-                mThumbnail = new AppWindowThumbnail(t, this, snapshot.getGraphicBuffer(),
-                        true /* relative */);
+                mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory, t, this,
+                        snapshot.getGraphicBuffer(), true /* relative */);
             }
         }
     }
@@ -2033,7 +2033,8 @@
         final boolean needsLetterbox = surfaceReady && w.isLetterboxedAppWindow() && fillsParent();
         if (needsLetterbox) {
             if (mLetterbox == null) {
-                mLetterbox = new Letterbox(() -> makeChildSurface(null));
+                mLetterbox = new Letterbox(() -> makeChildSurface(null),
+                        mWmService.mTransactionFactory);
                 mLetterbox.attachInput(w);
             }
             getPosition(mTmpPoint);
@@ -2981,7 +2982,8 @@
             return;
         }
         clearThumbnail();
-        mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnailHeader);
+        mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory, getPendingTransaction(),
+                this, thumbnailHeader);
         mThumbnail.startAnimation(getPendingTransaction(), loadThumbnailAnimation(thumbnailHeader));
     }
 
@@ -3009,7 +3011,8 @@
         if (thumbnail == null) {
             return;
         }
-        mThumbnail = new AppWindowThumbnail(getPendingTransaction(), this, thumbnail);
+        mThumbnail = new AppWindowThumbnail(mWmService.mSurfaceFactory,
+                getPendingTransaction(), this, thumbnail);
         final Animation animation =
                 getDisplayContent().mAppTransition.createCrossProfileAppsThumbnailAnimationLocked(
                         win.getFrameLw());
diff --git a/services/core/java/com/android/server/wm/BlackFrame.java b/services/core/java/com/android/server/wm/BlackFrame.java
index 7fc17e1..7557271a 100644
--- a/services/core/java/com/android/server/wm/BlackFrame.java
+++ b/services/core/java/com/android/server/wm/BlackFrame.java
@@ -27,6 +27,7 @@
 import android.view.SurfaceControl;
 
 import java.io.PrintWriter;
+import java.util.function.Supplier;
 
 /**
  * Four black surfaces put together to make a black frame.
@@ -97,7 +98,7 @@
     final BlackSurface[] mBlackSurfaces = new BlackSurface[4];
 
     final boolean mForceDefaultOrientation;
-    private final TransactionFactory mTransactionFactory;
+    private final Supplier<SurfaceControl.Transaction> mTransactionFactory;
 
     public void printTo(String prefix, PrintWriter pw) {
         pw.print(prefix); pw.print("Outer: "); mOuterRect.printShortString(pw);
@@ -112,8 +113,8 @@
         }
     }
 
-    public BlackFrame(TransactionFactory factory, SurfaceControl.Transaction t, Rect outer,
-            Rect inner, int layer, DisplayContent dc, boolean forceDefaultOrientation)
+    public BlackFrame(Supplier<SurfaceControl.Transaction> factory, SurfaceControl.Transaction t,
+            Rect outer, Rect inner, int layer, DisplayContent dc, boolean forceDefaultOrientation)
             throws OutOfResourcesException {
         boolean success = false;
 
@@ -151,7 +152,7 @@
 
     public void kill() {
         if (mBlackSurfaces != null) {
-            SurfaceControl.Transaction t = mTransactionFactory.make();
+            SurfaceControl.Transaction t = mTransactionFactory.get();
             for (int i=0; i<mBlackSurfaces.length; i++) {
                 if (mBlackSurfaces[i] != null) {
                     if (SHOW_TRANSACTIONS || SHOW_SURFACE_ALLOC) Slog.i(TAG_WM,
diff --git a/services/core/java/com/android/server/wm/CircularDisplayMask.java b/services/core/java/com/android/server/wm/CircularDisplayMask.java
index c3d6211..c1ca816 100644
--- a/services/core/java/com/android/server/wm/CircularDisplayMask.java
+++ b/services/core/java/com/android/server/wm/CircularDisplayMask.java
@@ -34,6 +34,8 @@
 import android.view.Surface.OutOfResourcesException;
 import android.view.SurfaceControl;
 
+import java.util.function.Supplier;
+
 class CircularDisplayMask {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "CircularDisplayMask" : TAG_WM;
 
@@ -43,7 +45,7 @@
     private Point mScreenSize;
 
     private final SurfaceControl mSurfaceControl;
-    private final Surface mSurface = new Surface();
+    private final Surface mSurface;
     private int mLastDW;
     private int mLastDH;
     private boolean mDrawNeeded;
@@ -53,10 +55,10 @@
     private boolean mDimensionsUnequal = false;
     private int mMaskThickness;
 
-    public CircularDisplayMask(DisplayContent dc, int zOrder,
+    CircularDisplayMask(Supplier<Surface> surfaceFactory, DisplayContent dc, int zOrder,
             int screenOffset, int maskThickness) {
         final Display display = dc.getDisplay();
-
+        mSurface = surfaceFactory.get();
         mScreenSize = new Point();
         display.getSize(mScreenSize);
         if (mScreenSize.x != mScreenSize.y + screenOffset) {
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 71a0126..1267652 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -1062,6 +1062,12 @@
         }
 
         addWindowToken(token.token, token);
+
+        if (mWmService.mAccessibilityController != null) {
+            final int prevDisplayId = prevDc != null ? prevDc.getDisplayId() : INVALID_DISPLAY;
+            mWmService.mAccessibilityController.onSomeWindowResizedOrMovedLocked(prevDisplayId,
+                    getDisplayId());
+        }
     }
 
     void removeAppToken(IBinder binder) {
@@ -4388,7 +4394,7 @@
                         .show(mSplitScreenDividerAnchor);
                 scheduleAnimation();
             } else {
-                mWmService.mTransactionFactory.make()
+                mWmService.mTransactionFactory.get()
                         .remove(mAppAnimationLayer)
                         .remove(mBoostedAppAnimationLayer)
                         .remove(mHomeAppAnimationLayer)
diff --git a/services/core/java/com/android/server/wm/DragState.java b/services/core/java/com/android/server/wm/DragState.java
index c48f07c..17daabf 100644
--- a/services/core/java/com/android/server/wm/DragState.java
+++ b/services/core/java/com/android/server/wm/DragState.java
@@ -140,7 +140,7 @@
         mFlags = flags;
         mLocalWin = localWin;
         mNotifiedWindows = new ArrayList<WindowState>();
-        mTransaction = service.mTransactionFactory.make();
+        mTransaction = service.mTransactionFactory.get();
     }
 
     boolean isClosing() {
@@ -695,7 +695,8 @@
             implements ValueAnimator.AnimatorUpdateListener, Animator.AnimatorListener {
         @Override
         public void onAnimationUpdate(ValueAnimator animation) {
-            try (final SurfaceControl.Transaction transaction = new SurfaceControl.Transaction()) {
+            try (SurfaceControl.Transaction transaction =
+                         mService.mTransactionFactory.get()) {
                 transaction.setPosition(
                         mSurfaceControl,
                         (float) animation.getAnimatedValue(ANIMATED_PROPERTY_X),
diff --git a/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java b/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
index 7cb4a43..f64592f 100644
--- a/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
+++ b/services/core/java/com/android/server/wm/EmulatorDisplayOverlay.java
@@ -32,6 +32,8 @@
 import android.view.Surface.OutOfResourcesException;
 import android.view.SurfaceControl;
 
+import java.util.function.Supplier;
+
 class EmulatorDisplayOverlay {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "EmulatorDisplayOverlay" : TAG_WM;
 
@@ -39,7 +41,7 @@
     private Point mScreenSize;
 
     private final SurfaceControl mSurfaceControl;
-    private final Surface mSurface = new Surface();
+    private final Surface mSurface;
     private int mLastDW;
     private int mLastDH;
     private boolean mDrawNeeded;
@@ -47,8 +49,9 @@
     private int mRotation;
     private boolean mVisible;
 
-    public EmulatorDisplayOverlay(Context context, DisplayContent dc,
+    EmulatorDisplayOverlay(Supplier<Surface> surfaceFactory, Context context, DisplayContent dc,
             int zOrder) {
+        mSurface = surfaceFactory.get();
         final Display display = dc.getDisplay();
         mScreenSize = new Point();
         display.getSize(mScreenSize);
diff --git a/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java b/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java
index 315de91..8ae740d 100644
--- a/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java
+++ b/services/core/java/com/android/server/wm/HighRefreshRateBlacklist.java
@@ -16,7 +16,7 @@
 
 package com.android.server.wm;
 
-import static android.provider.DeviceConfig.WindowManager.KEY_HIGH_REFRESH_RATE_BLACKLIST;
+import static android.hardware.display.DisplayManager.DeviceConfig.KEY_HIGH_REFRESH_RATE_BLACKLIST;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -58,9 +58,9 @@
     @VisibleForTesting
     HighRefreshRateBlacklist(Resources r, DeviceConfigInterface deviceConfig) {
         mDefaultBlacklist = r.getStringArray(R.array.config_highRefreshRateBlacklist);
-        deviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+        deviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
                 BackgroundThread.getExecutor(), new OnPropertiesChangedListener());
-        final String property = deviceConfig.getProperty(DeviceConfig.NAMESPACE_WINDOW_MANAGER,
+        final String property = deviceConfig.getProperty(DeviceConfig.NAMESPACE_DISPLAY_MANAGER,
                 KEY_HIGH_REFRESH_RATE_BLACKLIST);
         updateBlacklist(property);
     }
diff --git a/services/core/java/com/android/server/wm/InputMonitor.java b/services/core/java/com/android/server/wm/InputMonitor.java
index 2eec926..dd9000e 100644
--- a/services/core/java/com/android/server/wm/InputMonitor.java
+++ b/services/core/java/com/android/server/wm/InputMonitor.java
@@ -153,7 +153,7 @@
         mService = service;
         mDisplayContent = mService.mRoot.getDisplayContent(displayId);
         mDisplayId = displayId;
-        mInputTransaction = mService.mTransactionFactory.make();
+        mInputTransaction = mService.mTransactionFactory.get();
         mHandler = AnimationThread.getHandler();
         mUpdateInputForAllWindowsConsumer = new UpdateInputForAllWindowsConsumer();
     }
diff --git a/services/core/java/com/android/server/wm/Letterbox.java b/services/core/java/com/android/server/wm/Letterbox.java
index bb035d5..1bd2493 100644
--- a/services/core/java/com/android/server/wm/Letterbox.java
+++ b/services/core/java/com/android/server/wm/Letterbox.java
@@ -41,7 +41,8 @@
     private static final Rect EMPTY_RECT = new Rect();
     private static final Point ZERO_POINT = new Point(0, 0);
 
-    private final Supplier<SurfaceControl.Builder> mFactory;
+    private final Supplier<SurfaceControl.Builder> mSurfaceControlFactory;
+    private final Supplier<SurfaceControl.Transaction> mTransactionFactory;
     private final Rect mOuter = new Rect();
     private final Rect mInner = new Rect();
     private final LetterboxSurface mTop = new LetterboxSurface("top");
@@ -55,8 +56,10 @@
      *
      * @param surfaceControlFactory a factory for creating the managed {@link SurfaceControl}s
      */
-    public Letterbox(Supplier<SurfaceControl.Builder> surfaceControlFactory) {
-        mFactory = surfaceControlFactory;
+    public Letterbox(Supplier<SurfaceControl.Builder> surfaceControlFactory,
+            Supplier<SurfaceControl.Transaction> transactionFactory) {
+        mSurfaceControlFactory = surfaceControlFactory;
+        mTransactionFactory = transactionFactory;
     }
 
     /**
@@ -245,7 +248,7 @@
         }
 
         private void createSurface() {
-            mSurface = mFactory.get().setName("Letterbox - " + mType)
+            mSurface = mSurfaceControlFactory.get().setName("Letterbox - " + mType)
                     .setFlags(HIDDEN).setColorLayer().build();
             mSurface.setLayer(-1);
             mSurface.setColor(new float[]{0, 0, 0});
@@ -261,7 +264,7 @@
 
         public void remove() {
             if (mSurface != null) {
-                new SurfaceControl.Transaction().remove(mSurface).apply();
+                mTransactionFactory.get().remove(mSurface).apply();
                 mSurface = null;
             }
             if (mInputInterceptor != null) {
diff --git a/services/core/java/com/android/server/wm/RecentsAnimationController.java b/services/core/java/com/android/server/wm/RecentsAnimationController.java
index 8752f37..f4280a2 100644
--- a/services/core/java/com/android/server/wm/RecentsAnimationController.java
+++ b/services/core/java/com/android/server/wm/RecentsAnimationController.java
@@ -592,7 +592,7 @@
             return null;
         }
 
-        final TaskScreenshotAnimatable animatable = new TaskScreenshotAnimatable(task,
+        final TaskScreenshotAnimatable animatable = new TaskScreenshotAnimatable(mService.mSurfaceControlFactory, task,
                 new SurfaceControl.ScreenshotGraphicBuffer(taskSnapshot.getSnapshot(),
                         taskSnapshot.getColorSpace(), false /* containsSecureLayers */));
         mRecentScreenshotAnimator = new SurfaceAnimator(
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 968d02b..d0b6fc8 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -134,7 +134,7 @@
 
     // Only a separate transaction until we separate the apply surface changes
     // transaction from the global transaction.
-    private final SurfaceControl.Transaction mDisplayTransaction = new SurfaceControl.Transaction();
+    private final SurfaceControl.Transaction mDisplayTransaction;
 
     private final Consumer<WindowState> mCloseSystemDialogsConsumer = w -> {
         if (w.mHasSurface) {
@@ -154,6 +154,7 @@
 
     RootWindowContainer(WindowManagerService service) {
         super(service);
+        mDisplayTransaction = service.mTransactionFactory.get();
         mHandler = new MyHandler(service.mH.getLooper());
     }
 
diff --git a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
index 82dde0d..cbaf098 100644
--- a/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/core/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -127,7 +127,7 @@
         mOriginalWidth = originalWidth;
         mOriginalHeight = originalHeight;
 
-        final SurfaceControl.Transaction t = mService.mTransactionFactory.make();
+        final SurfaceControl.Transaction t = mService.mTransactionFactory.get();
         try {
             mSurfaceControl = displayContent.makeOverlay()
                     .setName("ScreenshotSurface")
@@ -137,13 +137,13 @@
 
             // In case display bounds change, screenshot buffer and surface may mismatch so set a
             // scaling mode.
-            SurfaceControl.Transaction t2 = mService.mTransactionFactory.make();
+            SurfaceControl.Transaction t2 = mService.mTransactionFactory.get();
             t2.setOverrideScalingMode(mSurfaceControl, Surface.SCALING_MODE_SCALE_TO_WINDOW);
             t2.apply(true /* sync */);
 
             // Capture a screenshot into the surface we just created.
             final int displayId = display.getDisplayId();
-            final Surface surface = mService.mSurfaceFactory.make();
+            final Surface surface = mService.mSurfaceFactory.get();
             surface.copyFrom(mSurfaceControl);
             SurfaceControl.ScreenshotGraphicBuffer gb =
                     mService.mDisplayManagerInternal.screenshot(displayId);
@@ -427,7 +427,7 @@
                 Slog.i(TAG_WM,
                         "  FREEZE " + mSurfaceControl + ": DESTROY");
             }
-            mService.mTransactionFactory.make().remove(mSurfaceControl).apply();
+            mService.mTransactionFactory.get().remove(mSurfaceControl).apply();
             mSurfaceControl = null;
         }
         if (mExitingBlackFrame != null) {
diff --git a/services/core/java/com/android/server/wm/StrictModeFlash.java b/services/core/java/com/android/server/wm/StrictModeFlash.java
index 82f2ad8..9e5d9ca 100644
--- a/services/core/java/com/android/server/wm/StrictModeFlash.java
+++ b/services/core/java/com/android/server/wm/StrictModeFlash.java
@@ -27,17 +27,20 @@
 import android.view.Surface.OutOfResourcesException;
 import android.view.SurfaceControl;
 
+import java.util.function.Supplier;
+
 class StrictModeFlash {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "StrictModeFlash" : TAG_WM;
 
     private final SurfaceControl mSurfaceControl;
-    private final Surface mSurface = new Surface();
+    private final Surface mSurface;
     private int mLastDW;
     private int mLastDH;
     private boolean mDrawNeeded;
     private final int mThickness = 20;
 
-    public StrictModeFlash(DisplayContent dc) {
+    StrictModeFlash(Supplier<Surface> surfaceFactory, DisplayContent dc) {
+        mSurface = surfaceFactory.get();
         SurfaceControl ctrl = null;
         try {
             ctrl = dc.makeOverlay()
diff --git a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
index 85176be..bbd986f 100644
--- a/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
+++ b/services/core/java/com/android/server/wm/SurfaceAnimationRunner.java
@@ -39,6 +39,8 @@
 import com.android.server.AnimationThread;
 import com.android.server.wm.LocalAnimationAdapter.AnimationSpec;
 
+import java.util.function.Supplier;
+
 /**
  * Class to run animations without holding the window manager lock.
  */
@@ -73,9 +75,10 @@
     @GuardedBy("mLock")
     private boolean mAnimationStartDeferred;
 
-    SurfaceAnimationRunner(PowerManagerInternal powerManagerInternal) {
-        this(null /* callbackProvider */, null /* animatorFactory */, new Transaction(),
-                powerManagerInternal);
+    SurfaceAnimationRunner(Supplier<Transaction> transactionFactory,
+            PowerManagerInternal powerManagerInternal) {
+        this(null /* callbackProvider */, null /* animatorFactory */,
+                transactionFactory.get(), powerManagerInternal);
     }
 
     @VisibleForTesting
diff --git a/services/core/java/com/android/server/wm/SurfaceFactory.java b/services/core/java/com/android/server/wm/SurfaceFactory.java
deleted file mode 100644
index 076b7df..0000000
--- a/services/core/java/com/android/server/wm/SurfaceFactory.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.server.wm;
-
-import android.view.Surface;
-
-/**
- * Helper class to inject custom {@link Surface} objects into window manager.
- */
-interface SurfaceFactory {
-    Surface make();
-};
-
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index ede2f56..e25ca73 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -71,7 +71,6 @@
 import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING;
 import static com.android.server.wm.ActivityStack.REMOVE_TASK_MODE_MOVING_TO_TOP;
 import static com.android.server.wm.ActivityStackSupervisor.ON_TOP;
-import static com.android.server.wm.ActivityStackSupervisor.PAUSE_IMMEDIATELY;
 import static com.android.server.wm.ActivityStackSupervisor.PRESERVE_WINDOWS;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_ADD_REMOVE;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.DEBUG_LOCKTASK;
@@ -702,7 +701,7 @@
                 && toStack.topRunningActivityLocked() != null) {
             // Pause the resumed activity on the target stack while re-parenting task on top of it.
             toStack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */,
-                    null /* resuming */, false /* pauseImmediately */);
+                    null /* resuming */);
         }
 
         final int toStackWindowingMode = toStack.getWindowingMode();
@@ -1405,8 +1404,7 @@
      * Completely remove all activities associated with an existing
      * task starting at a specified index.
      */
-    final void performClearTaskAtIndexLocked(int activityNdx, boolean pauseImmediately,
-            String reason) {
+    final void performClearTaskAtIndexLocked(int activityNdx, String reason) {
         int numActivities = mActivities.size();
         for ( ; activityNdx < numActivities; ++activityNdx) {
             final ActivityRecord r = mActivities.get(activityNdx);
@@ -1419,8 +1417,8 @@
                 mActivities.remove(activityNdx);
                 --activityNdx;
                 --numActivities;
-            } else if (r.finishIfPossible(Activity.RESULT_CANCELED,
-                    null /* resultData */, reason, false /* oomAdj */, pauseImmediately)
+            } else if (r.finishIfPossible(Activity.RESULT_CANCELED, null /* resultData */, reason,
+                    false /* oomAdj */)
                     == FINISH_RESULT_REMOVED) {
                 --activityNdx;
                 --numActivities;
@@ -1433,7 +1431,7 @@
      */
     void performClearTaskLocked() {
         mReuseTask = true;
-        performClearTaskAtIndexLocked(0, !PAUSE_IMMEDIATELY, "clear-task-all");
+        performClearTaskAtIndexLocked(0, "clear-task-all");
         mReuseTask = false;
     }
 
@@ -1501,9 +1499,9 @@
         return null;
     }
 
-    void removeTaskActivitiesLocked(boolean pauseImmediately, String reason) {
+    void removeTaskActivitiesLocked(String reason) {
         // Just remove the entire task.
-        performClearTaskAtIndexLocked(0, pauseImmediately, reason);
+        performClearTaskAtIndexLocked(0, reason);
     }
 
     String lockTaskAuthToString() {
diff --git a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
index d6c2f66..d36ebf0 100644
--- a/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
+++ b/services/core/java/com/android/server/wm/TaskScreenshotAnimatable.java
@@ -23,6 +23,8 @@
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 
+import java.util.function.Function;
+
 /**
  * Class used by {@link RecentsAnimationController} to create a surface control with taking
  * screenshot of task when canceling recents animation.
@@ -36,7 +38,7 @@
     private int mWidth;
     private int mHeight;
 
-    TaskScreenshotAnimatable(Task task,
+    TaskScreenshotAnimatable(Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory, Task task,
             SurfaceControl.ScreenshotGraphicBuffer screenshotBuffer) {
         GraphicBuffer buffer = screenshotBuffer == null
                 ? null : screenshotBuffer.getGraphicBuffer();
@@ -47,7 +49,7 @@
             Slog.d(TAG, "Creating TaskScreenshotAnimatable: task: " + task
                     + "width: " + mWidth + "height: " + mHeight);
         }
-        mSurfaceControl = new SurfaceControl.Builder(new SurfaceSession())
+        mSurfaceControl = surfaceControlFactory.apply(new SurfaceSession())
                 .setName("RecentTaskScreenshotSurface")
                 .setBufferSize(mWidth, mHeight)
                 .build();
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 1b3e4c1..7456f0d 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -237,7 +237,7 @@
             int sysUiVis, int windowFlags, int windowPrivateFlags, Rect taskBounds,
             int currentOrientation) {
         mService = service;
-        mSurface = new Surface();
+        mSurface = service.mSurfaceFactory.get();
         mHandler = new Handler(mService.mH.getLooper());
         mSession = WindowManagerGlobal.getWindowSession();
         mWindow = window;
@@ -325,13 +325,13 @@
                 - ((float) mFrame.width() / mFrame.height())) > 0.01f;
 
         // Keep a reference to it such that it doesn't get destroyed when finalized.
-        mChildSurfaceControl = new SurfaceControl.Builder(session)
+        mChildSurfaceControl = mService.mSurfaceControlFactory.apply(session)
                 .setName(mTitle + " - task-snapshot-surface")
                 .setBufferSize(buffer.getWidth(), buffer.getHeight())
                 .setFormat(buffer.getFormat())
                 .setParent(mSurfaceControl)
                 .build();
-        Surface surface = new Surface();
+        Surface surface = mService.mSurfaceFactory.get();
         surface.copyFrom(mChildSurfaceControl);
 
         final Rect frame;
diff --git a/services/core/java/com/android/server/wm/TaskStack.java b/services/core/java/com/android/server/wm/TaskStack.java
index cc2112e..814bec6 100644
--- a/services/core/java/com/android/server/wm/TaskStack.java
+++ b/services/core/java/com/android/server/wm/TaskStack.java
@@ -1009,7 +1009,7 @@
         EventLog.writeEvent(EventLogTags.WM_STACK_REMOVED, mStackId);
 
         if (mAnimationBackgroundSurface != null) {
-            mWmService.mTransactionFactory.make().remove(mAnimationBackgroundSurface).apply();
+            mWmService.mTransactionFactory.get().remove(mAnimationBackgroundSurface).apply();
             mAnimationBackgroundSurface = null;
         }
 
diff --git a/services/core/java/com/android/server/wm/TransactionFactory.java b/services/core/java/com/android/server/wm/TransactionFactory.java
deleted file mode 100644
index 067f083..0000000
--- a/services/core/java/com/android/server/wm/TransactionFactory.java
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.server.wm;
-
-import android.view.SurfaceControl.Transaction;
-
-/**
- * Helper class to inject custom transaction objects into window manager.
- */
-interface TransactionFactory {
-    Transaction make();
-};
-
diff --git a/services/core/java/com/android/server/wm/Watermark.java b/services/core/java/com/android/server/wm/Watermark.java
index e6ac059..729cfc0 100644
--- a/services/core/java/com/android/server/wm/Watermark.java
+++ b/services/core/java/com/android/server/wm/Watermark.java
@@ -33,6 +33,8 @@
 import android.view.Surface.OutOfResourcesException;
 import android.view.SurfaceControl;
 
+import java.util.function.Supplier;
+
 /**
  * Displays a watermark on top of the window manager's windows.
  */
@@ -47,19 +49,20 @@
     private final int mDeltaY;
 
     private final SurfaceControl mSurfaceControl;
-    private final Surface mSurface = new Surface();
+    private final Surface mSurface;
     private int mLastDW;
     private int mLastDH;
     private boolean mDrawNeeded;
 
-    Watermark(DisplayContent dc, DisplayMetrics dm, String[] tokens) {
+    Watermark(Supplier<Surface> surfaceFactory, DisplayContent dc, DisplayMetrics dm,
+            String[] tokens) {
         if (false) {
             Log.i(TAG_WM, "*********************** WATERMARK");
             for (int i=0; i<tokens.length; i++) {
                 Log.i(TAG_WM, "  TOKEN #" + i + ": " + tokens[i]);
             }
         }
-
+        mSurface = surfaceFactory.get();
         mDisplay = dc.getDisplay();
         mTokens = tokens;
 
diff --git a/services/core/java/com/android/server/wm/WindowAnimator.java b/services/core/java/com/android/server/wm/WindowAnimator.java
index b8db98b..4fce46b 100644
--- a/services/core/java/com/android/server/wm/WindowAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowAnimator.java
@@ -83,12 +83,13 @@
     private final ArrayList<Runnable> mAfterPrepareSurfacesRunnables = new ArrayList<>();
     private boolean mInExecuteAfterPrepareSurfacesRunnables;
 
-    private final SurfaceControl.Transaction mTransaction = new SurfaceControl.Transaction();
+    private final SurfaceControl.Transaction mTransaction;
 
     WindowAnimator(final WindowManagerService service) {
         mService = service;
         mContext = service.mContext;
         mPolicy = service.mPolicy;
+        mTransaction = service.mTransactionFactory.get();
         AnimationThread.getHandler().runWithScissors(
                 () -> mChoreographer = Choreographer.getSfInstance(), 0 /* timeout */);
 
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 29d232f..e280a663 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -139,7 +139,7 @@
 
     WindowContainer(WindowManagerService wms) {
         mWmService = wms;
-        mPendingTransaction = wms.mTransactionFactory.make();
+        mPendingTransaction = wms.mTransactionFactory.get();
         mSurfaceAnimator = new SurfaceAnimator(this, this::onAnimationFinished, wms);
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index fa1ace6..8d3a107 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -286,6 +286,8 @@
 import java.util.Arrays;
 import java.util.Date;
 import java.util.List;
+import java.util.function.Function;
+import java.util.function.Supplier;
 
 /** {@hide} */
 public class WindowManagerService extends IWindowManager.Stub
@@ -911,9 +913,9 @@
     static WindowManagerThreadPriorityBooster sThreadPriorityBooster =
             new WindowManagerThreadPriorityBooster();
 
-    SurfaceBuilderFactory mSurfaceBuilderFactory = SurfaceControl.Builder::new;
-    TransactionFactory mTransactionFactory = SurfaceControl.Transaction::new;
-    SurfaceFactory mSurfaceFactory = Surface::new;
+    Function<SurfaceSession, SurfaceControl.Builder> mSurfaceControlFactory;
+    Supplier<SurfaceControl.Transaction> mTransactionFactory;
+    final Supplier<Surface> mSurfaceFactory;
 
     private final SurfaceControl.Transaction mTransaction;
 
@@ -1013,20 +1015,22 @@
             final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
             ActivityTaskManagerService atm) {
         return main(context, im, showBootMsgs, onlyCore, policy, atm,
-                SurfaceControl.Transaction::new);
+                SurfaceControl.Transaction::new, Surface::new, SurfaceControl.Builder::new);
     }
 
     /**
      * Creates and returns an instance of the WindowManagerService. This call allows the caller
-     * to override the {@link TransactionFactory} to stub functionality under test.
+     * to override factories that can be used to stub native calls during test.
      */
     @VisibleForTesting
     public static WindowManagerService main(final Context context, final InputManagerService im,
             final boolean showBootMsgs, final boolean onlyCore, WindowManagerPolicy policy,
-            ActivityTaskManagerService atm, TransactionFactory transactionFactory) {
+            ActivityTaskManagerService atm, Supplier<SurfaceControl.Transaction> transactionFactory,
+            Supplier<Surface> surfaceFactory,
+            Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
         DisplayThread.getHandler().runWithScissors(() ->
                 sInstance = new WindowManagerService(context, im, showBootMsgs, onlyCore, policy,
-                        atm, transactionFactory), 0);
+                        atm, transactionFactory, surfaceFactory, surfaceControlFactory), 0);
         return sInstance;
     }
 
@@ -1048,7 +1052,9 @@
 
     private WindowManagerService(Context context, InputManagerService inputManager,
             boolean showBootMsgs, boolean onlyCore, WindowManagerPolicy policy,
-            ActivityTaskManagerService atm, TransactionFactory transactionFactory) {
+            ActivityTaskManagerService atm, Supplier<SurfaceControl.Transaction> transactionFactory,
+            Supplier<Surface> surfaceFactory,
+            Function<SurfaceSession, SurfaceControl.Builder> surfaceControlFactory) {
         installLock(this, INDEX_WINDOW);
         mGlobalLock = atm.getGlobalLock();
         mAtmService = atm;
@@ -1076,10 +1082,13 @@
                 com.android.internal.R.bool.config_lowRamTaskSnapshotsAndRecents);
         mInputManager = inputManager; // Must be before createDisplayContentLocked.
         mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
-        mDisplayWindowSettings = new DisplayWindowSettings(this);
 
+        mSurfaceControlFactory = surfaceControlFactory;
         mTransactionFactory = transactionFactory;
-        mTransaction = mTransactionFactory.make();
+        mSurfaceFactory = surfaceFactory;
+        mTransaction = mTransactionFactory.get();
+
+        mDisplayWindowSettings = new DisplayWindowSettings(this);
         mPolicy = policy;
         mAnimator = new WindowAnimator(this);
         mRoot = new RootWindowContainer(this);
@@ -1183,7 +1192,8 @@
                 PowerManager.SCREEN_BRIGHT_WAKE_LOCK | PowerManager.ON_AFTER_RELEASE, TAG_WM);
         mHoldingScreenWakeLock.setReferenceCounted(false);
 
-        mSurfaceAnimationRunner = new SurfaceAnimationRunner(mPowerManagerInternal);
+        mSurfaceAnimationRunner = new SurfaceAnimationRunner(mTransactionFactory,
+                mPowerManagerInternal);
 
         mAllowTheaterModeWakeFromLayout = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_allowTheaterModeWakeFromWindowLayout);
@@ -3460,7 +3470,7 @@
                         int maskThickness = mContext.getResources().getDimensionPixelSize(
                                 com.android.internal.R.dimen.circular_display_mask_thickness);
 
-                        mCircularDisplayMask = new CircularDisplayMask(
+                        mCircularDisplayMask = new CircularDisplayMask(mSurfaceFactory,
                                 getDefaultDisplayContentLocked(),
                                 mPolicy.getWindowLayerFromTypeLw(
                                         WindowManager.LayoutParams.TYPE_POINTER)
@@ -3488,6 +3498,7 @@
             try {
                 if (mEmulatorDisplayOverlay == null) {
                     mEmulatorDisplayOverlay = new EmulatorDisplayOverlay(
+                            mSurfaceFactory,
                             mContext,
                             getDefaultDisplayContentLocked(),
                             mPolicy.getWindowLayerFromTypeLw(
@@ -3536,7 +3547,7 @@
             try {
                 // TODO(multi-display): support multiple displays
                 if (mStrictModeFlash == null) {
-                    mStrictModeFlash = new StrictModeFlash(
+                    mStrictModeFlash = new StrictModeFlash(mSurfaceFactory,
                             getDefaultDisplayContentLocked());
                 }
                 mStrictModeFlash.setVisibility(on);
@@ -5553,7 +5564,8 @@
                 if (toks != null && toks.length > 0) {
                     // TODO(multi-display): Show watermarks on secondary displays.
                     final DisplayContent displayContent = getDefaultDisplayContentLocked();
-                    mWatermark = new Watermark(displayContent, displayContent.mRealDisplayMetrics,
+                    mWatermark = new Watermark(mSurfaceFactory, displayContent,
+                            displayContent.mRealDisplayMetrics,
                             toks);
                 }
             }
@@ -7544,7 +7556,7 @@
     }
 
     SurfaceControl.Builder makeSurfaceBuilder(SurfaceSession s) {
-        return mSurfaceBuilderFactory.make(s);
+        return mSurfaceControlFactory.apply(s);
     }
 
     /**
@@ -7616,7 +7628,8 @@
             mRoot.forAllDisplays(displayContent ->
                     displayContent.getInputMonitor().updateInputWindowsImmediately());
         }
-        new SurfaceControl.Transaction().syncInputWindows().apply(true);
+
+        mTransactionFactory.get().syncInputWindows().apply(true);
     }
 
     private void waitForAnimationsToComplete() {
@@ -7738,7 +7751,7 @@
         h.replaceTouchableRegionWithCrop(null);
 
         SurfaceSession s = new SurfaceSession();
-        SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+        SurfaceControl.Transaction t = mTransactionFactory.get();
         t.setInputWindowInfo(surface, h);
         t.apply();
 
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 242b116..8c51452 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -620,7 +620,7 @@
                 final ActivityStack stack = mPreQTopResumedActivity.getActivityStack();
                 if (stack != null) {
                     stack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */,
-                            null /* resuming */, false /* pauseImmediately */);
+                            activity);
                 }
             }
             mPreQTopResumedActivity = activity;
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index ae3a10a..8e679d4 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -159,7 +159,7 @@
      * window is first added or shown, cleared when the callback has been made. */
     boolean mEnteringAnimation;
 
-    private final SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction();
+    private final SurfaceControl.Transaction mTmpTransaction;
 
     /** The pixel format of the underlying SurfaceControl */
     int mSurfaceFormat;
@@ -246,6 +246,7 @@
         final WindowManagerService service = win.mWmService;
 
         mService = service;
+        mTmpTransaction = service.mTransactionFactory.get();
         mAnimator = service.mAnimator;
         mPolicy = service.mPolicy;
         mContext = service.mContext;
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index bcefa8f..8cede6c 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -81,7 +81,7 @@
     private final int mWindowType;
     private final Session mWindowSession;
 
-    private final SurfaceControl.Transaction mTmpTransaction = new SurfaceControl.Transaction();
+    private final SurfaceControl.Transaction mTmpTransaction;
 
     public WindowSurfaceController(SurfaceSession s, String name, int w, int h, int format,
             int flags, WindowStateAnimator animator, int windowType, int ownerUid) {
@@ -96,6 +96,7 @@
         final WindowState win = animator.mWin;
         mWindowType = windowType;
         mWindowSession = win.mSession;
+        mTmpTransaction = mService.mTransactionFactory.get();
 
         Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER, "new SurfaceControl");
         final SurfaceControl.Builder b = win.makeSurface()
diff --git a/services/net/java/android/net/ConnectivityModuleConnector.java b/services/net/java/android/net/ConnectivityModuleConnector.java
index 7333f58..62f2c35 100644
--- a/services/net/java/android/net/ConnectivityModuleConnector.java
+++ b/services/net/java/android/net/ConnectivityModuleConnector.java
@@ -38,6 +38,7 @@
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 
 import java.io.File;
 import java.io.PrintWriter;
@@ -76,8 +77,17 @@
     private final SharedLog mLog = new SharedLog(TAG);
     @GuardedBy("mHealthListeners")
     private final ArraySet<ConnectivityModuleHealthListener> mHealthListeners = new ArraySet<>();
+    @NonNull
+    private final Dependencies mDeps;
 
-    private ConnectivityModuleConnector() { }
+    private ConnectivityModuleConnector() {
+        this(new DependenciesImpl());
+    }
+
+    @VisibleForTesting
+    ConnectivityModuleConnector(@NonNull Dependencies deps) {
+        mDeps = deps;
+    }
 
     /**
      * Get the {@link ConnectivityModuleConnector} singleton instance.
@@ -124,6 +134,59 @@
         void onModuleServiceConnected(@NonNull IBinder iBinder);
     }
 
+    /**
+     * Interface used to determine the intent to use to bind to the module. Useful for testing.
+     */
+    @VisibleForTesting
+    protected interface Dependencies {
+        /**
+         * Determine the intent to use to bind to the module.
+         * @return null if the intent could not be resolved, the intent otherwise.
+         */
+        @Nullable
+        Intent getModuleServiceIntent(
+                @NonNull PackageManager pm, @NonNull String serviceIntentBaseAction,
+                @NonNull String servicePermissionName, boolean inSystemProcess);
+    }
+
+    private static class DependenciesImpl implements Dependencies {
+        @Nullable
+        @Override
+        public Intent getModuleServiceIntent(
+                @NonNull PackageManager pm, @NonNull String serviceIntentBaseAction,
+                @NonNull String servicePermissionName, boolean inSystemProcess) {
+            final Intent intent =
+                    new Intent(inSystemProcess
+                            ? serviceIntentBaseAction + IN_PROCESS_SUFFIX
+                            : serviceIntentBaseAction);
+            final ComponentName comp = intent.resolveSystemService(pm, 0);
+            if (comp == null) {
+                return null;
+            }
+            intent.setComponent(comp);
+
+            final int uid;
+            try {
+                uid = pm.getPackageUidAsUser(comp.getPackageName(), UserHandle.USER_SYSTEM);
+            } catch (PackageManager.NameNotFoundException e) {
+                throw new SecurityException(
+                        "Could not check network stack UID; package not found.", e);
+            }
+
+            final int expectedUid =
+                    inSystemProcess ? Process.SYSTEM_UID : Process.NETWORK_STACK_UID;
+            if (uid != expectedUid) {
+                throw new SecurityException("Invalid network stack UID: " + uid);
+            }
+
+            if (!inSystemProcess) {
+                checkModuleServicePermission(pm, comp, servicePermissionName);
+            }
+
+            return intent;
+        }
+    }
+
 
     /**
      * Add a {@link ConnectivityModuleHealthListener} to listen to network stack health events.
@@ -156,13 +219,13 @@
         final PackageManager pm = mContext.getPackageManager();
 
         // Try to bind in-process if the device was shipped with an in-process version
-        Intent intent = getModuleServiceIntent(pm, serviceIntentBaseAction, servicePermissionName,
-                true /* inSystemProcess */);
+        Intent intent = mDeps.getModuleServiceIntent(pm, serviceIntentBaseAction,
+                servicePermissionName, true /* inSystemProcess */);
 
         // Otherwise use the updatable module version
         if (intent == null) {
-            intent = getModuleServiceIntent(pm, serviceIntentBaseAction, servicePermissionName,
-                false /* inSystemProcess */);
+            intent = mDeps.getModuleServiceIntent(pm, serviceIntentBaseAction,
+                    servicePermissionName, false /* inSystemProcess */);
             log("Starting networking module in network_stack process");
         } else {
             log("Starting networking module in system_server process");
@@ -219,41 +282,7 @@
         }
     }
 
-    @Nullable
-    private Intent getModuleServiceIntent(
-            @NonNull PackageManager pm, @NonNull String serviceIntentBaseAction,
-            @NonNull String servicePermissionName, boolean inSystemProcess) {
-        final Intent intent =
-                new Intent(inSystemProcess
-                        ? serviceIntentBaseAction + IN_PROCESS_SUFFIX
-                        : serviceIntentBaseAction);
-        final ComponentName comp = intent.resolveSystemService(pm, 0);
-        if (comp == null) {
-            return null;
-        }
-        intent.setComponent(comp);
-
-        int uid = -1;
-        try {
-            uid = pm.getPackageUidAsUser(comp.getPackageName(), UserHandle.USER_SYSTEM);
-        } catch (PackageManager.NameNotFoundException e) {
-            logWtf("Networking module package not found", e);
-            // Fall through
-        }
-
-        final int expectedUid = inSystemProcess ? Process.SYSTEM_UID : Process.NETWORK_STACK_UID;
-        if (uid != expectedUid) {
-            throw new SecurityException("Invalid network stack UID: " + uid);
-        }
-
-        if (!inSystemProcess) {
-            checkModuleServicePermission(pm, comp, servicePermissionName);
-        }
-
-        return intent;
-    }
-
-    private void checkModuleServicePermission(
+    private static void checkModuleServicePermission(
             @NonNull PackageManager pm, @NonNull ComponentName comp,
             @NonNull String servicePermissionName) {
         final int hasPermission =
diff --git a/services/net/java/android/net/NetworkStackClient.java b/services/net/java/android/net/NetworkStackClient.java
index abb4666..69e2406 100644
--- a/services/net/java/android/net/NetworkStackClient.java
+++ b/services/net/java/android/net/NetworkStackClient.java
@@ -35,6 +35,7 @@
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.annotations.VisibleForTesting;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -51,6 +52,9 @@
     private static NetworkStackClient sInstance;
 
     @NonNull
+    private final Dependencies mDependencies;
+
+    @NonNull
     @GuardedBy("mPendingNetStackRequests")
     private final ArrayList<NetworkStackCallback> mPendingNetStackRequests = new ArrayList<>();
     @Nullable
@@ -66,7 +70,50 @@
         void onNetworkStackConnected(INetworkStackConnector connector);
     }
 
-    private NetworkStackClient() { }
+    @VisibleForTesting
+    protected NetworkStackClient(@NonNull Dependencies dependencies) {
+        mDependencies = dependencies;
+    }
+
+    private NetworkStackClient() {
+        this(new DependenciesImpl());
+    }
+
+    @VisibleForTesting
+    protected interface Dependencies {
+        void addToServiceManager(@NonNull IBinder service);
+        void checkCallerUid();
+        ConnectivityModuleConnector getConnectivityModuleConnector();
+    }
+
+    private static class DependenciesImpl implements Dependencies {
+        @Override
+        public void addToServiceManager(@NonNull IBinder service) {
+            ServiceManager.addService(Context.NETWORK_STACK_SERVICE, service,
+                    false /* allowIsolated */, DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL);
+        }
+
+        @Override
+        public void checkCallerUid() {
+            final int caller = Binder.getCallingUid();
+            // This is a client lib so "caller" is the current UID in most cases. The check is done
+            // here in the caller's process just to provide a nicer error message to clients; more
+            // generic checks are also done in NetworkStackService.
+            // See PermissionUtil in NetworkStack for the actual check on the service side - the
+            // checks here should be kept in sync with PermissionUtil.
+            if (caller != Process.SYSTEM_UID
+                    && caller != Process.NETWORK_STACK_UID
+                    && !UserHandle.isSameApp(caller, Process.BLUETOOTH_UID)) {
+                throw new SecurityException(
+                        "Only the system server should try to bind to the network stack.");
+            }
+        }
+
+        @Override
+        public ConnectivityModuleConnector getConnectivityModuleConnector() {
+            return ConnectivityModuleConnector.getInstance();
+        }
+    }
 
     /**
      * Get the NetworkStackClient singleton instance.
@@ -150,9 +197,7 @@
 
     private void registerNetworkStackService(@NonNull IBinder service) {
         final INetworkStackConnector connector = INetworkStackConnector.Stub.asInterface(service);
-
-        ServiceManager.addService(Context.NETWORK_STACK_SERVICE, service, false /* allowIsolated */,
-                DUMP_FLAG_PRIORITY_HIGH | DUMP_FLAG_PRIORITY_NORMAL);
+        mDependencies.addToServiceManager(service);
         log("Network stack service registered");
 
         final ArrayList<NetworkStackCallback> requests;
@@ -185,7 +230,7 @@
      * started.
      */
     public void start() {
-        ConnectivityModuleConnector.getInstance().startModuleService(
+        mDependencies.getConnectivityModuleConnector().startModuleService(
                 INetworkStackConnector.class.getName(), PERMISSION_MAINLINE_NETWORK_STACK,
                 new NetworkStackConnection());
         log("Network stack service start requested");
@@ -251,16 +296,7 @@
     }
 
     private void requestConnector(@NonNull NetworkStackCallback request) {
-        // TODO: PID check.
-        final int caller = Binder.getCallingUid();
-        if (caller != Process.SYSTEM_UID
-                && caller != Process.NETWORK_STACK_UID
-                && !UserHandle.isSameApp(caller, Process.BLUETOOTH_UID)
-                && !UserHandle.isSameApp(caller, Process.PHONE_UID)) {
-            // Don't even attempt to obtain the connector and give a nice error message
-            throw new SecurityException(
-                    "Only the system server should try to bind to the network stack.");
-        }
+        mDependencies.checkCallerUid();
 
         if (!mWasSystemServerInitialized) {
             // The network stack is not being started in this process, e.g. this process is not
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 9670899..1685b04 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -1486,6 +1486,45 @@
                 SCHED_GROUP_DEFAULT);
     }
 
+    @SuppressWarnings("GuardedBy")
+    @Test
+    public void testUpdateOomAdj_DoAll_ServiceB() {
+        ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+                MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+        ProcessRecord app2 = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+                MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+        long now = SystemClock.uptimeMillis();
+        ServiceRecord s = bindService(app, app2, null, 0, mock(IBinder.class));
+        s.startRequested = true;
+        s.lastActivity = now;
+        s = bindService(app2, app, null, 0, mock(IBinder.class));
+        s.startRequested = true;
+        s.lastActivity = now;
+        ProcessRecord app3 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+                MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+        s = mock(ServiceRecord.class);
+        s.app = app3;
+        setFieldValue(ServiceRecord.class, s, "connections",
+                new ArrayMap<IBinder, ArrayList<ConnectionRecord>>());
+        app3.services.add(s);
+        doCallRealMethod().when(s).getConnections();
+        s.startRequested = true;
+        s.lastActivity = now;
+        ArrayList<ProcessRecord> lru = sService.mProcessList.mLruProcesses;
+        lru.clear();
+        lru.add(app3);
+        lru.add(app2);
+        lru.add(app);
+        sService.mWakefulness = PowerManagerInternal.WAKEFULNESS_AWAKE;
+        sService.mOomAdjuster.mNumServiceProcs = 3;
+        sService.mOomAdjuster.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
+        lru.clear();
+
+        assertEquals(SERVICE_B_ADJ, app3.setAdj);
+        assertEquals(SERVICE_ADJ, app2.setAdj);
+        assertEquals(SERVICE_ADJ, app.setAdj);
+    }
+
     private ProcessRecord makeDefaultProcessRecord(int pid, int uid, String processName,
             String packageName, boolean hasShownUi) {
         long now = SystemClock.uptimeMillis();
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
index 977dd8e..aaaa7a5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityMetricsLaunchObserverTests.java
@@ -47,6 +47,7 @@
 import org.mockito.ArgumentMatcher;
 
 import java.util.Arrays;
+import java.util.concurrent.TimeUnit;
 
 /**
  * Tests for the {@link ActivityMetricsLaunchObserver} class.
@@ -118,7 +119,7 @@
 
     static <T> T verifyAsync(T mock) {
         // AMLO callbacks happen on a separate thread than AML calls, so we need to use a timeout.
-        return verify(mock, timeout(100));
+        return verify(mock, timeout(TimeUnit.SECONDS.toMillis(5)));
     }
 
     @Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index f548225..7b06490 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -820,7 +820,7 @@
 
         mActivity.setState(RESUMED, "test");
         mActivity.finishIfPossible(0 /* resultCode */, null /* resultData */, "test",
-                false /* oomAdj */, false /* pauseImmediately */);
+                false /* oomAdj */);
 
         assertTrue(stack1.isTopStackOnDisplay());
     }
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 c83e5cb..2a8b4c8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityStackTests.java
@@ -25,6 +25,7 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.app.WindowConfiguration.WINDOWING_MODE_UNDEFINED;
+import static android.content.pm.ActivityInfo.FLAG_RESUME_WHILE_PAUSING;
 
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
 import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn;
@@ -980,6 +981,19 @@
     }
 
     @Test
+    public void testCompletePauseOnResumeWhilePausingActivity() {
+        final ActivityRecord bottomActivity = new ActivityBuilder(mService).setTask(mTask).build();
+        doReturn(true).when(bottomActivity).attachedToProcess();
+        mStack.mPausingActivity = null;
+        mStack.mResumedActivity = bottomActivity;
+        final ActivityRecord topActivity = new ActivityBuilder(mService).setTask(mTask).build();
+        topActivity.info.flags |= FLAG_RESUME_WHILE_PAUSING;
+
+        mStack.startPausingLocked(false /* userLeaving */, false /* uiSleeping */, topActivity);
+        verify(mStack).completePauseLocked(anyBoolean(), eq(topActivity));
+    }
+
+    @Test
     public void testAdjustFocusedStackToHomeWhenNoActivity() {
         final ActivityStack homeStask = mDefaultDisplay.getHomeStack();
         TaskRecord homeTask = homeStask.topTask();
diff --git a/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java b/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java
index daee911..fa83f85 100644
--- a/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/HighRefreshRateBlacklistTest.java
@@ -16,7 +16,7 @@
 
 package com.android.server.wm;
 
-import static android.provider.DeviceConfig.WindowManager.KEY_HIGH_REFRESH_RATE_BLACKLIST;
+import static android.hardware.display.DisplayManager.DeviceConfig.KEY_HIGH_REFRESH_RATE_BLACKLIST;
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
@@ -128,9 +128,9 @@
 
         @Override
         public String getProperty(String namespace, String name) {
-            if (!DeviceConfig.NAMESPACE_WINDOW_MANAGER.equals(namespace)
+            if (!DeviceConfig.NAMESPACE_DISPLAY_MANAGER.equals(namespace)
                     || !KEY_HIGH_REFRESH_RATE_BLACKLIST.equals(name)) {
-                throw new IllegalArgumentException("Only things in NAMESPACE_WINDOW_MANAGER "
+                throw new IllegalArgumentException("Only things in NAMESPACE_DISPLAY_MANAGER "
                         + "supported.");
             }
             return mBlacklist;
@@ -140,8 +140,8 @@
         public void addOnPropertiesChangedListener(String namespace, Executor executor,
                 DeviceConfig.OnPropertiesChangedListener listener) {
 
-            if (!DeviceConfig.NAMESPACE_WINDOW_MANAGER.equals(namespace)) {
-                throw new IllegalArgumentException("Only things in NAMESPACE_WINDOW_MANAGER "
+            if (!DeviceConfig.NAMESPACE_DISPLAY_MANAGER.equals(namespace)) {
+                throw new IllegalArgumentException("Only things in NAMESPACE_DISPLAY_MANAGER "
                         + "supported.");
             }
             mListeners.add(new Pair<>(listener, executor));
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
index c52c8d7..2d0416d 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxTest.java
@@ -48,7 +48,7 @@
     @Before
     public void setUp() throws Exception {
         mSurfaces = new SurfaceControlMocker();
-        mLetterbox = new Letterbox(mSurfaces);
+        mLetterbox = new Letterbox(mSurfaces, () -> mock(SurfaceControl.Transaction.class));
         mTransaction = mock(SurfaceControl.Transaction.class);
     }
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
index 21ed285..43c6b35 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SystemServicesTestRule.java
@@ -257,17 +257,14 @@
         // Suppress StrictMode violation (DisplayWindowSettings) to avoid log flood.
         DisplayThread.getHandler().post(StrictMode::allowThreadDiskWritesMask);
         mWmService = WindowManagerService.main(
-                mContext, mImService, false, false, mWMPolicy, mAtmService, StubTransaction::new);
+                mContext, mImService, false, false, mWMPolicy, mAtmService, StubTransaction::new,
+                () -> mock(Surface.class), (unused) -> new MockSurfaceControlBuilder());
         spyOn(mWmService);
 
         // Setup factory classes to prevent calls to native code.
         mTransaction = spy(StubTransaction.class);
         // Return a spied Transaction class than can be used to verify calls.
         mWmService.mTransactionFactory = () -> mTransaction;
-        // Return a SurfaceControl.Builder class that creates mocked SurfaceControl instances.
-        mWmService.mSurfaceBuilderFactory = (unused) -> new MockSurfaceControlBuilder();
-        // Return mocked Surface instances.
-        mWmService.mSurfaceFactory = () -> mock(Surface.class);
         mWmService.mSurfaceAnimationRunner = new SurfaceAnimationRunner(
                 null, null, mTransaction, mWmService.mPowerManagerInternal);
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
index 7d7c398..2105ab0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
@@ -51,6 +51,7 @@
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.LinkedList;
+import java.util.function.Function;
 
 /**
  * Tests for the {@link DisplayContent#assignChildLayers(SurfaceControl.Transaction)} method.
@@ -131,7 +132,8 @@
         }
     }
 
-    private static class HierarchyRecordingBuilderFactory implements SurfaceBuilderFactory {
+    private static class HierarchyRecordingBuilderFactory implements Function<SurfaceSession,
+                SurfaceControl.Builder> {
         private LayerRecordingTransaction mTransaction;
 
         HierarchyRecordingBuilderFactory(LayerRecordingTransaction transaction) {
@@ -139,7 +141,7 @@
         }
 
         @Override
-        public SurfaceControl.Builder make(SurfaceSession s) {
+        public SurfaceControl.Builder apply(SurfaceSession s) {
             final LayerRecordingTransaction transaction = mTransaction;
             return new HierarchyRecorder(s, transaction);
         }
@@ -153,7 +155,7 @@
         // which is after construction of the DisplayContent, meaning the HierarchyRecorder
         // would miss construction of the top-level layers.
         mTransaction = new LayerRecordingTransaction();
-        mWm.mSurfaceBuilderFactory = new HierarchyRecordingBuilderFactory(mTransaction);
+        mWm.mSurfaceControlFactory = new HierarchyRecordingBuilderFactory(mTransaction);
         mWm.mTransactionFactory = () -> mTransaction;
     }
 
diff --git a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
index a8cafb3..1dd3972 100644
--- a/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
+++ b/services/voiceinteraction/java/com/android/server/soundtrigger/SoundTriggerService.java
@@ -666,6 +666,23 @@
                 return ret;
             }
         }
+
+        @Override
+        @Nullable
+        public ModuleProperties getModuleProperties() {
+            enforceCallingPermission(Manifest.permission.MANAGE_SOUND_TRIGGER);
+            if (!isInitialized()) return null;
+            if (DEBUG) {
+                Slog.i(TAG, "getModuleProperties()");
+            }
+
+            synchronized (mLock) {
+                ModuleProperties properties = mSoundTriggerHelper.getModuleProperties();
+                sEventLogger.log(new SoundTriggerLogger.StringEvent(
+                        "getModuleProperties(): " + properties.toString()));
+                return properties;
+            }
+        }
     }
 
     /**
diff --git a/startop/scripts/app_startup/lib/adb_utils.py b/startop/scripts/app_startup/lib/adb_utils.py
index e56a968..3cebc9a 100644
--- a/startop/scripts/app_startup/lib/adb_utils.py
+++ b/startop/scripts/app_startup/lib/adb_utils.py
@@ -42,8 +42,8 @@
 def vm_drop_cache():
   """Free pagecache and slab object."""
   cmd_utils.run_adb_shell_command('echo 3 > /proc/sys/vm/drop_caches')
-  # Sleep a little bit to provide enougth time for cache cleanup.
-  time.sleep(2)
+  # Sleep a little bit to provide enough time for cache cleanup.
+  time.sleep(1)
 
 def root():
   """Roots adb and successive adb commands will run under root."""
diff --git a/startop/scripts/iorap/compiler.py b/startop/scripts/iorap/compiler.py
index c940fe9..17b58c1 100755
--- a/startop/scripts/iorap/compiler.py
+++ b/startop/scripts/iorap/compiler.py
@@ -190,6 +190,7 @@
       MmFilemapAddToPageCache.raw_ftrace_entry).order_by(
       RawFtraceEntry.timestamp).first()
 
+  # total_seconds() will return a float number.
   return first_event.raw_ftrace_entry.timestamp + trace_duration.total_seconds()
 
 def query_add_to_page_cache(trace2db: Trace2Db, trace_duration: Optional[timedelta]):
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 475563d..f25b012 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -3132,19 +3132,62 @@
      */
     @SystemApi
     public int getSimCardState() {
-        int simCardState = getSimState();
-        switch (simCardState) {
+        int simState = getSimState();
+        return getSimCardStateFromSimState(simState);
+    }
+
+    /**
+     * Returns a constant indicating the state of the device SIM card in a physical slot.
+     *
+     * @param physicalSlotIndex physical slot index
+     *
+     * @see #SIM_STATE_UNKNOWN
+     * @see #SIM_STATE_ABSENT
+     * @see #SIM_STATE_CARD_IO_ERROR
+     * @see #SIM_STATE_CARD_RESTRICTED
+     * @see #SIM_STATE_PRESENT
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public int getSimCardState(int physicalSlotIndex) {
+        int simState = getSimState(getLogicalSlotIndex(physicalSlotIndex));
+        return getSimCardStateFromSimState(simState);
+    }
+
+    /**
+     * Converts SIM state to SIM card state.
+     * @param simState
+     * @return SIM card state
+     */
+    private int getSimCardStateFromSimState(int simState) {
+        switch (simState) {
             case SIM_STATE_UNKNOWN:
             case SIM_STATE_ABSENT:
             case SIM_STATE_CARD_IO_ERROR:
             case SIM_STATE_CARD_RESTRICTED:
-                return simCardState;
+                return simState;
             default:
                 return SIM_STATE_PRESENT;
         }
     }
 
     /**
+     * Converts a physical slot index to logical slot index.
+     * @param physicalSlotIndex physical slot index
+     * @return logical slot index
+     */
+    private int getLogicalSlotIndex(int physicalSlotIndex) {
+        UiccSlotInfo[] slotInfos = getUiccSlotsInfo();
+        if (slotInfos != null && physicalSlotIndex >= 0 && physicalSlotIndex < slotInfos.length) {
+            return slotInfos[physicalSlotIndex].getLogicalSlotIdx();
+        }
+
+        return SubscriptionManager.INVALID_SIM_SLOT_INDEX;
+    }
+
+    /**
      * Returns a constant indicating the state of the card applications on the default SIM card.
      *
      * @see #SIM_STATE_UNKNOWN
@@ -3159,8 +3202,41 @@
      */
     @SystemApi
     public int getSimApplicationState() {
-        int simApplicationState = getSimStateIncludingLoaded();
-        switch (simApplicationState) {
+        int simState = getSimStateIncludingLoaded();
+        return getSimApplicationStateFromSimState(simState);
+    }
+
+    /**
+     * Returns a constant indicating the state of the card applications on the device SIM card in
+     * a physical slot.
+     *
+     * @param physicalSlotIndex physical slot index
+     *
+     * @see #SIM_STATE_UNKNOWN
+     * @see #SIM_STATE_PIN_REQUIRED
+     * @see #SIM_STATE_PUK_REQUIRED
+     * @see #SIM_STATE_NETWORK_LOCKED
+     * @see #SIM_STATE_NOT_READY
+     * @see #SIM_STATE_PERM_DISABLED
+     * @see #SIM_STATE_LOADED
+     *
+     * @hide
+     */
+    @SystemApi
+    @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+    public int getSimApplicationState(int physicalSlotIndex) {
+        int simState =
+                SubscriptionManager.getSimStateForSlotIndex(getLogicalSlotIndex(physicalSlotIndex));
+        return getSimApplicationStateFromSimState(simState);
+    }
+
+    /**
+     * Converts SIM state to SIM application state.
+     * @param simState
+     * @return SIM application state
+     */
+    private int getSimApplicationStateFromSimState(int simState) {
+        switch (simState) {
             case SIM_STATE_UNKNOWN:
             case SIM_STATE_ABSENT:
             case SIM_STATE_CARD_IO_ERROR:
@@ -3171,14 +3247,14 @@
                 // NOT_READY to either LOCKED or LOADED.
                 return SIM_STATE_NOT_READY;
             default:
-                return simApplicationState;
+                return simState;
         }
     }
 
     /**
-     * Returns a constant indicating the state of the device SIM card in a slot.
+     * Returns a constant indicating the state of the device SIM card in a logical slot.
      *
-     * @param slotIndex
+     * @param slotIndex logical slot index
      *
      * @see #SIM_STATE_UNKNOWN
      * @see #SIM_STATE_ABSENT
diff --git a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
index da32c8c..28b331b 100644
--- a/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/gsm/SmsMessage.java
@@ -1496,7 +1496,7 @@
      *
      * @return true if this is a USIM data download message; false otherwise
      */
-    boolean isUsimDataDownload() {
+    public boolean isUsimDataDownload() {
         return messageClass == MessageClass.CLASS_2 &&
                 (mProtocolIdentifier == 0x7f || mProtocolIdentifier == 0x7c);
     }
diff --git a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
index c42201f..47fefae 100644
--- a/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
+++ b/tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java
@@ -782,7 +782,7 @@
         Handler handler = new Handler(mTestLooper.getLooper());
         PackageWatchdog watchdog =
                 new PackageWatchdog(mSpyContext, policyFile, handler, handler, controller,
-                        mConnectivityModuleConnector);
+                        mConnectivityModuleConnector, android.os.SystemClock::uptimeMillis);
         // Verify controller is not automatically started
         assertFalse(controller.mIsEnabled);
         if (withPackagesReady) {
diff --git a/tests/net/java/com/android/server/ConnectivityServiceTest.java b/tests/net/java/com/android/server/ConnectivityServiceTest.java
index 6ae639a..caa3203 100644
--- a/tests/net/java/com/android/server/ConnectivityServiceTest.java
+++ b/tests/net/java/com/android/server/ConnectivityServiceTest.java
@@ -184,6 +184,7 @@
 import android.util.SparseArray;
 
 import androidx.test.InstrumentationRegistry;
+import androidx.test.filters.FlakyTest;
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
@@ -2187,6 +2188,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 140306320)
     public void testPartialConnectivity() throws Exception {
         // Register network callback.
         NetworkRequest request = new NetworkRequest.Builder()
@@ -3633,6 +3635,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 140305589)
     public void testPacketKeepalives() throws Exception {
         InetAddress myIPv4 = InetAddress.getByName("192.0.2.129");
         InetAddress notMyIPv4 = InetAddress.getByName("192.0.2.35");
@@ -5697,6 +5700,7 @@
     }
 
     @Test
+    @FlakyTest(bugId = 140305678)
     public void testTcpBufferReset() throws Exception {
         final String testTcpBufferSizes = "1,2,3,4,5,6";
         final NetworkRequest networkRequest = new NetworkRequest.Builder()