Merge "Remove flags for wallet and alarm" into sc-dev
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
index 0c07fa0..0709ff5 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/AppSearchManagerService.java
@@ -17,11 +17,10 @@
 
 import static android.app.appsearch.AppSearchResult.throwableToFailedResult;
 import static android.os.Process.INVALID_UID;
-import static android.os.UserHandle.USER_NULL;
 
+import android.Manifest;
 import android.annotation.ElapsedRealtimeLong;
 import android.annotation.NonNull;
-import android.app.ActivityManager;
 import android.app.appsearch.AppSearchBatchResult;
 import android.app.appsearch.AppSearchMigrationHelper;
 import android.app.appsearch.AppSearchResult;
@@ -63,6 +62,7 @@
 import com.android.server.appsearch.external.localstorage.stats.CallStats;
 import com.android.server.appsearch.stats.LoggerInstanceManager;
 import com.android.server.appsearch.stats.PlatformLogger;
+import com.android.server.appsearch.util.PackageUtil;
 import com.android.server.usage.StorageStatsManagerLocal;
 import com.android.server.usage.StorageStatsManagerLocal.StorageStatsAugmenter;
 
@@ -124,8 +124,10 @@
     }
 
     private void registerReceivers() {
-        mContext.registerReceiverAsUser(new UserActionReceiver(), UserHandle.ALL,
-                new IntentFilter(Intent.ACTION_USER_REMOVED), /*broadcastPermission=*/ null,
+        mContext.registerReceiverForAllUsers(
+                new UserActionReceiver(),
+                new IntentFilter(Intent.ACTION_USER_REMOVED),
+                /*broadcastPermission=*/ null,
                 /*scheduler=*/ null);
 
         //TODO(b/145759910) Add a direct callback when user clears the data instead of relying on
@@ -135,8 +137,10 @@
         packageChangedFilter.addAction(Intent.ACTION_PACKAGE_DATA_CLEARED);
         packageChangedFilter.addDataScheme("package");
         packageChangedFilter.setPriority(IntentFilter.SYSTEM_HIGH_PRIORITY);
-        mContext.registerReceiverAsUser(new PackageChangedReceiver(), UserHandle.ALL,
-                packageChangedFilter, /*broadcastPermission=*/ null,
+        mContext.registerReceiverForAllUsers(
+                new PackageChangedReceiver(),
+                packageChangedFilter,
+                /*broadcastPermission=*/ null,
                 /*scheduler=*/ null);
     }
 
@@ -148,12 +152,13 @@
 
             switch (intent.getAction()) {
                 case Intent.ACTION_USER_REMOVED:
-                    int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, USER_NULL);
-                    if (userId == USER_NULL) {
-                        Log.e(TAG, "userId is missing in the intent: " + intent);
+                    UserHandle userHandle = intent.getParcelableExtra(Intent.EXTRA_USER);
+                    if (userHandle == null) {
+                        Log.e(TAG, "Extra "
+                                + Intent.EXTRA_USER + " is missing in the intent: " + intent);
                         return;
                     }
-                    handleUserRemoved(UserHandle.of(userId));
+                    handleUserRemoved(userHandle);
                     break;
                 default:
                     Log.e(TAG, "Received unknown intent: " + intent);
@@ -1183,13 +1188,9 @@
             Objects.requireNonNull(actualCallingUser);
             Objects.requireNonNull(claimedCallingPackage);
 
-            int claimedCallingUid;
-            try {
-                Context claimedCallingContext =
-                        mContext.createContextAsUser(actualCallingUser, /*flags=*/ 0);
-                claimedCallingUid = claimedCallingContext.getPackageManager().getPackageUid(
-                        claimedCallingPackage, /*flags=*/ 0);
-            } catch (PackageManager.NameNotFoundException e) {
+            int claimedCallingUid = PackageUtil.getPackageUidAsUser(
+                    mContext, claimedCallingPackage, actualCallingUser);
+            if (claimedCallingUid == INVALID_UID) {
                 throw new SecurityException(
                         "Specified calling package [" + claimedCallingPackage + "] not found");
             }
@@ -1257,23 +1258,44 @@
      *
      * <p>Takes care of checking permissions and converting USER_CURRENT to the actual current user.
      *
+     * @param requestedUser The user which the caller is requesting to execute as.
+     * @param callingUid The actual uid of the caller as determined by Binder.
      * @return the user handle that the call should run as. Will always be a concrete user.
      */
     // TODO(b/173553485) verifying that the caller has permission to access target user's data
     // TODO(b/173553485) Handle ACTION_USER_REMOVED broadcast
     // TODO(b/173553485) Implement SystemService.onUserStopping()
     @NonNull
-    private static UserHandle handleIncomingUser(@NonNull UserHandle userHandle, int callingUid) {
+    private UserHandle handleIncomingUser(@NonNull UserHandle requestedUser, int callingUid) {
         int callingPid = Binder.getCallingPid();
-        int finalUserId = ActivityManager.handleIncomingUser(
+        UserHandle callingUser = UserHandle.getUserHandleForUid(callingUid);
+        if (callingUser.equals(requestedUser)) {
+            return requestedUser;
+        }
+        // Duplicates UserController#ensureNotSpecialUser
+        if (requestedUser.getIdentifier() < 0) {
+            throw new IllegalArgumentException(
+                    "Call does not support special user " + requestedUser);
+        }
+        boolean canInteractAcrossUsers = mContext.checkPermission(
+                Manifest.permission.INTERACT_ACROSS_USERS,
                 callingPid,
-                callingUid,
-                userHandle.getIdentifier(),
-                /*allowAll=*/ false,
-                /*requireFull=*/ false,
-                /*name=*/ null,
-                /*callerPackage=*/ null);
-        return UserHandle.of(finalUserId);
+                callingUid) == PackageManager.PERMISSION_GRANTED;
+        if (!canInteractAcrossUsers) {
+            canInteractAcrossUsers = mContext.checkPermission(
+                    Manifest.permission.INTERACT_ACROSS_USERS_FULL,
+                    callingPid,
+                    callingUid) == PackageManager.PERMISSION_GRANTED;
+        }
+        if (canInteractAcrossUsers) {
+            return requestedUser;
+        }
+        throw new SecurityException(
+                "Permission denied while calling from uid " + callingUid
+                        + " with " + requestedUser + "; Need to run as either the calling user ("
+                        + callingUser + "), or with one of the following permissions: "
+                        + Manifest.permission.INTERACT_ACROSS_USERS + " or "
+                        + Manifest.permission.INTERACT_ACROSS_USERS_FULL);
     }
 
     // TODO(b/179160886): Cache the previous storage stats.
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java b/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java
index beb4d24..0775272 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/ImplInstanceManager.java
@@ -172,11 +172,6 @@
             @Nullable AppSearchLogger logger)
             throws AppSearchException {
         File appSearchDir = getAppSearchDir(userHandle);
-        // TODO(b/181787682): Swap AppSearchImpl and VisibilityStore to accept a UserHandle too
-        return AppSearchImpl.create(
-                appSearchDir,
-                userContext,
-                userHandle.getIdentifier(),
-                /*logger=*/ null);
+        return AppSearchImpl.create(appSearchDir, userContext, /*logger=*/ null);
     }
 }
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
index a940dde..29cb57c 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/external/localstorage/AppSearchImpl.java
@@ -201,7 +201,6 @@
     public static AppSearchImpl create(
             @NonNull File icingDir,
             @NonNull Context userContext,
-            int userId,
             @Nullable AppSearchLogger logger)
             throws AppSearchException {
         Objects.requireNonNull(icingDir);
@@ -213,8 +212,7 @@
             initStatsBuilder = new InitializeStats.Builder();
         }
 
-        AppSearchImpl appSearchImpl =
-                new AppSearchImpl(icingDir, userContext, userId, initStatsBuilder);
+        AppSearchImpl appSearchImpl = new AppSearchImpl(icingDir, userContext, initStatsBuilder);
 
         long prepareVisibilityStoreLatencyStartMillis = SystemClock.elapsedRealtime();
         appSearchImpl.initializeVisibilityStore();
@@ -238,7 +236,6 @@
     private AppSearchImpl(
             @NonNull File icingDir,
             @NonNull Context userContext,
-            int userId,
             @Nullable InitializeStats.Builder initStatsBuilder)
             throws AppSearchException {
         mReadWriteLock.writeLock().lock();
@@ -256,7 +253,7 @@
                     "Constructing IcingSearchEngine, response",
                     Objects.hashCode(mIcingSearchEngineLocked));
 
-            mVisibilityStoreLocked = new VisibilityStore(this, userContext, userId);
+            mVisibilityStoreLocked = new VisibilityStore(this, userContext);
 
             // The core initialization procedure. If any part of this fails, we bail into
             // resetLocked(), deleting all data (but hopefully allowing AppSearchImpl to come up).
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java b/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java
index 7d0ce41..c857fb6 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/stats/PlatformLogger.java
@@ -20,7 +20,6 @@
 import android.annotation.Nullable;
 import android.app.appsearch.exceptions.AppSearchException;
 import android.content.Context;
-import android.content.pm.PackageManager;
 import android.os.Process;
 import android.os.SystemClock;
 import android.os.UserHandle;
@@ -36,6 +35,7 @@
 import com.android.server.appsearch.external.localstorage.stats.PutDocumentStats;
 import com.android.server.appsearch.external.localstorage.stats.RemoveStats;
 import com.android.server.appsearch.external.localstorage.stats.SearchStats;
+import com.android.server.appsearch.util.PackageUtil;
 
 import java.io.UnsupportedEncodingException;
 import java.security.MessageDigest;
@@ -493,21 +493,13 @@
     @GuardedBy("mLock")
     private int getPackageUidAsUserLocked(@NonNull String packageName) {
         Integer packageUid = mPackageUidCacheLocked.get(packageName);
-        if (packageUid != null) {
-            return packageUid;
+        if (packageUid == null) {
+            packageUid = PackageUtil.getPackageUidAsUser(mContext, packageName, mUserHandle);
+            if (packageUid != Process.INVALID_UID) {
+                mPackageUidCacheLocked.put(packageName, packageUid);
+            }
         }
-
-        // TODO(b/173532925) since VisibilityStore has the same method, we can make this a
-        //  utility function
-        try {
-            packageUid = mContext.getPackageManager().getPackageUidAsUser(
-                    packageName, mUserHandle.getIdentifier());
-            mPackageUidCacheLocked.put(packageName, packageUid);
-            return packageUid;
-        } catch (PackageManager.NameNotFoundException e) {
-            // Package doesn't exist, continue
-        }
-        return Process.INVALID_UID;
+        return packageUid;
     }
 
     //
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/util/PackageUtil.java b/apex/appsearch/service/java/com/android/server/appsearch/util/PackageUtil.java
new file mode 100644
index 0000000..53a1bed
--- /dev/null
+++ b/apex/appsearch/service/java/com/android/server/appsearch/util/PackageUtil.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.appsearch.util;
+
+import android.annotation.NonNull;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.os.Process;
+import android.os.UserHandle;
+
+/**
+ * Utilities for interacting with {@link android.content.pm.PackageManager},
+ * {@link android.os.UserHandle}, and other parts of dealing with apps and binder.
+ *
+ * @hide
+ */
+public class PackageUtil {
+    private PackageUtil() {}
+
+    /**
+     * Finds the UID of the {@code packageName}. Returns {@link Process#INVALID_UID} if unable to
+     * find the UID.
+     */
+    public static int getPackageUidAsUser(
+            @NonNull Context context, @NonNull String packageName, @NonNull UserHandle user) {
+        Context userContext = context.createContextAsUser(user, /*flags=*/ 0);
+        return getPackageUid(userContext, packageName);
+    }
+
+    /**
+     * Finds the UID of the {@code packageName} in the given {@code context}. Returns
+     * {@link Process#INVALID_UID} if unable to find the UID.
+     */
+    public static int getPackageUid(@NonNull Context context, @NonNull String packageName) {
+        try {
+            return context.getPackageManager().getPackageUid(packageName, /*flags=*/ 0);
+        } catch (PackageManager.NameNotFoundException e) {
+            return Process.INVALID_UID;
+        }
+    }
+}
diff --git a/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibilityStore.java b/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibilityStore.java
index acff792..95ed368 100644
--- a/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibilityStore.java
+++ b/apex/appsearch/service/java/com/android/server/appsearch/visibilitystore/VisibilityStore.java
@@ -18,7 +18,6 @@
 import static android.Manifest.permission.READ_GLOBAL_APP_SEARCH_DATA;
 
 import android.annotation.NonNull;
-import android.annotation.UserIdInt;
 import android.app.appsearch.AppSearchResult;
 import android.app.appsearch.AppSearchSchema;
 import android.app.appsearch.GenericDocument;
@@ -27,7 +26,6 @@
 import android.app.appsearch.exceptions.AppSearchException;
 import android.content.Context;
 import android.content.pm.PackageManager;
-import android.os.Process;
 import android.os.UserHandle;
 import android.util.ArrayMap;
 import android.util.ArraySet;
@@ -35,6 +33,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.server.appsearch.external.localstorage.AppSearchImpl;
 import com.android.server.appsearch.external.localstorage.util.PrefixUtil;
+import com.android.server.appsearch.util.PackageUtil;
 
 import com.google.android.icing.proto.PersistType;
 
@@ -67,9 +66,6 @@
  * @hide
  */
 public class VisibilityStore {
-
-    private static final String TAG = "AppSearchVisibilityStore";
-
     /** No-op user id that won't have any visibility settings. */
     public static final int NO_OP_USER_ID = -1;
 
@@ -95,9 +91,6 @@
     // Context of the user that the call is being made as.
     private final Context mUserContext;
 
-    // User ID of the caller who we're checking visibility settings for.
-    private final int mUserId;
-
     /** Stores the schemas that are platform-hidden. All values are prefixed. */
     private final NotPlatformSurfaceableMap mNotPlatformSurfaceableMap =
             new NotPlatformSurfaceableMap();
@@ -112,13 +105,9 @@
      * @param appSearchImpl AppSearchImpl instance
      * @param userContext Context of the user that the call is being made as
      */
-    public VisibilityStore(
-            @NonNull AppSearchImpl appSearchImpl,
-            @NonNull Context userContext,
-            @UserIdInt int userId) {
+    public VisibilityStore(@NonNull AppSearchImpl appSearchImpl, @NonNull Context userContext) {
         mAppSearchImpl = appSearchImpl;
-        mUserContext = userContext;
-        mUserId = userId;
+        mUserContext = Objects.requireNonNull(userContext);
     }
 
     /**
@@ -348,6 +337,9 @@
         Set<PackageIdentifier> packageIdentifiers =
                 mPackageAccessibleMap.getAccessiblePackages(
                         packageName, databaseName, prefixedSchema);
+        if (packageIdentifiers.isEmpty()) {
+            return false;
+        }
         for (PackageIdentifier packageIdentifier : packageIdentifiers) {
             // TODO(b/169883602): Consider caching the UIDs of packages. Looking this up in the
             // package manager could be costly. We would also need to update the cache on
@@ -357,9 +349,10 @@
             // the callerUid since clients can createContextAsUser with some other user, and then
             // make calls to us. So just check if the appId portion of the uid is the same. This is
             // essentially UserHandle.isSameApp, but that's not a system API for us to use.
-            int callerAppId = UserHandle.getAppId((callerUid));
-            int userAppId =
-                    UserHandle.getAppId(getPackageUidAsUser(packageIdentifier.getPackageName()));
+            int callerAppId = UserHandle.getAppId(callerUid);
+            int packageUid =
+                    PackageUtil.getPackageUid(mUserContext, packageIdentifier.getPackageName());
+            int userAppId = UserHandle.getAppId(packageUid);
             if (callerAppId != userAppId) {
                 continue;
             }
@@ -401,17 +394,4 @@
             @NonNull String packageName, @NonNull String databaseName) {
         return ID_PREFIX + PrefixUtil.createPrefix(packageName, databaseName);
     }
-
-    /**
-     * Finds the UID of the {@code packageName}. Returns {@link Process#INVALID_UID} if unable to
-     * find the UID.
-     */
-    private int getPackageUidAsUser(@NonNull String packageName) {
-        try {
-            return mUserContext.getPackageManager().getPackageUidAsUser(packageName, mUserId);
-        } catch (PackageManager.NameNotFoundException e) {
-            // Package doesn't exist, continue
-        }
-        return Process.INVALID_UID;
-    }
 }
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java
index 25fd254..7cb8bc0 100644
--- a/core/java/android/app/ActivityManagerInternal.java
+++ b/core/java/android/app/ActivityManagerInternal.java
@@ -604,6 +604,14 @@
             String ownerPkgName, int ownerUid);
 
     /**
+     * Effectively PendingIntent.getActivityForUser(), but the PendingIntent is
+     * owned by the given uid rather than by the caller (i.e. the system).
+     */
+    public abstract PendingIntent getPendingIntentActivityAsApp(
+            int requestCode, @NonNull Intent[] intents, int flags, Bundle options,
+            String ownerPkgName, int ownerUid);
+
+    /**
      * @return mBootTimeTempAllowlistDuration of ActivityManagerConstants.
      */
     public abstract long getBootTimeTempAllowListDuration();
diff --git a/core/java/android/app/compat/CompatChanges.java b/core/java/android/app/compat/CompatChanges.java
index 24ca72c..0e31567 100644
--- a/core/java/android/app/compat/CompatChanges.java
+++ b/core/java/android/app/compat/CompatChanges.java
@@ -119,7 +119,7 @@
                 ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE));
         CompatibilityOverrideConfig config = new CompatibilityOverrideConfig(overrides);
         try {
-            platformCompat.setOverridesOnReleaseBuilds(config, packageName);
+            platformCompat.putOverridesOnReleaseBuilds(config, packageName);
         } catch (RemoteException e) {
             e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
index 76b9865..1e650a8 100644
--- a/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
+++ b/core/java/android/content/pm/parsing/ApkLiteParseUtils.java
@@ -40,7 +40,6 @@
 import android.util.Pair;
 import android.util.Slog;
 
-import com.android.internal.R;
 import com.android.internal.util.ArrayUtils;
 
 import libcore.io.IoUtils;
@@ -357,14 +356,14 @@
                 "versionCodeMajor",
                 0);
         int revisionCode = parser.getAttributeIntValue(ANDROID_RES_NAMESPACE, "revisionCode", 0);
-        boolean coreApp = parser.getAttributeBooleanValue("", "coreApp", false);
+        boolean coreApp = parser.getAttributeBooleanValue(null, "coreApp", false);
         boolean isolatedSplits = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
                 "isolatedSplits", false);
         boolean isFeatureSplit = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
                 "isFeatureSplit", false);
         boolean isSplitRequired = parser.getAttributeBooleanValue(ANDROID_RES_NAMESPACE,
                 "isSplitRequired", false);
-        String configForSplit = parser.getAttributeValue(ANDROID_RES_NAMESPACE, "configForSplit");
+        String configForSplit = parser.getAttributeValue(null, "configForSplit");
 
         int targetSdkVersion = DEFAULT_TARGET_SDK_VERSION;
         int minSdkVersion = DEFAULT_MIN_SDK_VERSION;
diff --git a/core/java/android/os/incremental/IncrementalMetrics.java b/core/java/android/os/incremental/IncrementalMetrics.java
index c44b7d9..534525a 100644
--- a/core/java/android/os/incremental/IncrementalMetrics.java
+++ b/core/java/android/os/incremental/IncrementalMetrics.java
@@ -90,7 +90,7 @@
      * @return total duration in milliseconds of delayed reads
      */
     public long getTotalDelayedReadsDurationMillis() {
-        return mData.getInt(IIncrementalService.METRICS_TOTAL_DELAYED_READS_MILLIS, -1);
+        return mData.getLong(IIncrementalService.METRICS_TOTAL_DELAYED_READS_MILLIS, -1);
     }
 
     /**
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index 941e9aa..603df1e 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -157,7 +157,7 @@
     private static final int NOTIFY_COLORS_RATE_LIMIT_MS = 1000;
 
     private static final boolean ENABLE_WALLPAPER_DIMMING =
-            SystemProperties.getBoolean("persist.debug.enable_wallpaper_dimming", false);
+            SystemProperties.getBoolean("persist.debug.enable_wallpaper_dimming", true);
 
     private final ArrayList<Engine> mActiveEngines
             = new ArrayList<Engine>();
diff --git a/core/java/com/android/internal/compat/IPlatformCompat.aidl b/core/java/com/android/internal/compat/IPlatformCompat.aidl
index f718d40..418d16e 100644
--- a/core/java/com/android/internal/compat/IPlatformCompat.aidl
+++ b/core/java/com/android/internal/compat/IPlatformCompat.aidl
@@ -168,7 +168,7 @@
      * @param packageName the package name of the app whose changes will be overridden
      * @throws SecurityException if overriding changes is not permitted
      */
-    void setOverridesOnReleaseBuilds(in CompatibilityOverrideConfig overrides, in String packageName);
+    void putOverridesOnReleaseBuilds(in CompatibilityOverrideConfig overrides, in String packageName);
 
     /**
      * Adds overrides to compatibility changes.
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index bf59f4d..5ac2336 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -4980,6 +4980,11 @@
     <!-- List containing the allowed install sources for accessibility service. -->
     <string-array name="config_accessibility_allowed_install_source" translatable="false"/>
 
+    <!-- Default value for Settings.ASSIST_LONG_PRESS_HOME_ENABLED -->
+    <bool name="config_assistLongPressHomeEnabledDefault">true</bool>
+    <!-- Default value for Settings.ASSIST_TOUCH_GESTURE_ENABLED -->
+    <bool name="config_assistTouchGestureEnabledDefault">true</bool>
+
     <!-- The amount of dimming to apply to wallpapers with mid range luminance. 0 displays
          the wallpaper at full brightness. 1 displays the wallpaper as fully black. -->
     <item name="config_wallpaperDimAmount" format="float" type="dimen">0.05</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 7006d93..b574415 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -4394,5 +4394,8 @@
   <java-symbol type="dimen" name="starting_surface_icon_size" />
   <java-symbol type="dimen" name="starting_surface_default_icon_size" />
 
+  <java-symbol type="bool" name="config_assistLongPressHomeEnabledDefault" />
+  <java-symbol type="bool" name="config_assistTouchGestureEnabledDefault" />
+
   <java-symbol type="dimen" name="config_wallpaperDimAmount" />
 </resources>
diff --git a/data/fonts/fonts.xml b/data/fonts/fonts.xml
index 1163536..d757a8c 100644
--- a/data/fonts/fonts.xml
+++ b/data/fonts/fonts.xml
@@ -39,11 +39,7 @@
           <axis tag="wdth" stylevalue="100" />
           <axis tag="wght" stylevalue="300" />
         </font>
-        <font weight="400" style="normal">Roboto-Regular.ttf
-          <axis tag="ital" stylevalue="0" />
-          <axis tag="wdth" stylevalue="100" />
-          <axis tag="wght" stylevalue="400" />
-        </font>
+        <font weight="400" style="normal">RobotoStatic-Regular.ttf</font>
         <font weight="500" style="normal">Roboto-Regular.ttf
           <axis tag="ital" stylevalue="0" />
           <axis tag="wdth" stylevalue="100" />
diff --git a/graphics/java/android/graphics/Typeface.java b/graphics/java/android/graphics/Typeface.java
index b88751a..61f7fac 100644
--- a/graphics/java/android/graphics/Typeface.java
+++ b/graphics/java/android/graphics/Typeface.java
@@ -1387,6 +1387,7 @@
     static {
         // Preload Roboto-Regular.ttf in Zygote for improving app launch performance.
         preloadFontFile("/system/fonts/Roboto-Regular.ttf");
+        preloadFontFile("/system/fonts/RobotoStatic-Regular.ttf");
 
         String locale = SystemProperties.get("persist.sys.locale", "en-US");
         String script = ULocale.addLikelySubtags(ULocale.forLanguageTag(locale)).getScript();
diff --git a/keystore/java/android/security/keystore/AttestationUtils.java b/keystore/java/android/security/keystore/AttestationUtils.java
index 4da2a28..67484d4 100644
--- a/keystore/java/android/security/keystore/AttestationUtils.java
+++ b/keystore/java/android/security/keystore/AttestationUtils.java
@@ -21,18 +21,13 @@
 import android.annotation.RequiresPermission;
 import android.annotation.SystemApi;
 import android.content.Context;
-import android.os.Build;
-import android.security.keymaster.KeymasterArguments;
 import android.security.keymaster.KeymasterCertificateChain;
-import android.security.keymaster.KeymasterDefs;
-import android.telephony.TelephonyManager;
-import android.util.ArraySet;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
-import java.nio.charset.StandardCharsets;
 import java.security.KeyPairGenerator;
 import java.security.KeyStore;
+import java.security.ProviderException;
 import java.security.SecureRandom;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateFactory;
@@ -41,7 +36,6 @@
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Random;
-import java.util.Set;
 
 /**
  * Utilities for attesting the device's hardware identifiers.
@@ -110,92 +104,6 @@
         }
     }
 
-    @NonNull private static KeymasterArguments prepareAttestationArgumentsForDeviceId(
-            Context context, @NonNull int[] idTypes, @NonNull byte[] attestationChallenge) throws
-            DeviceIdAttestationException {
-        // Verify that device ID attestation types are provided.
-        if (idTypes == null) {
-            throw new NullPointerException("Missing id types");
-        }
-
-        return prepareAttestationArguments(context, idTypes, attestationChallenge);
-    }
-
-    /**
-     * Prepares Keymaster Arguments with attestation data.
-     * @hide should only be used by KeyChain.
-     */
-    @NonNull public static KeymasterArguments prepareAttestationArguments(Context context,
-            @NonNull int[] idTypes, @NonNull byte[] attestationChallenge) throws
-            DeviceIdAttestationException {
-        // Check method arguments, retrieve requested device IDs and prepare attestation arguments.
-        if (attestationChallenge == null) {
-            throw new NullPointerException("Missing attestation challenge");
-        }
-        final KeymasterArguments attestArgs = new KeymasterArguments();
-        attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_CHALLENGE, attestationChallenge);
-        // Return early if the caller did not request any device identifiers to be included in the
-        // attestation record.
-        if (idTypes == null) {
-            return attestArgs;
-        }
-        final Set<Integer> idTypesSet = new ArraySet<>(idTypes.length);
-        for (int idType : idTypes) {
-            idTypesSet.add(idType);
-        }
-        TelephonyManager telephonyService = null;
-        if (idTypesSet.contains(ID_TYPE_IMEI) || idTypesSet.contains(ID_TYPE_MEID)) {
-            telephonyService = (TelephonyManager) context.getSystemService(
-                    Context.TELEPHONY_SERVICE);
-            if (telephonyService == null) {
-                throw new DeviceIdAttestationException("Unable to access telephony service");
-            }
-        }
-        for (final Integer idType : idTypesSet) {
-            switch (idType) {
-                case ID_TYPE_SERIAL:
-                    attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_SERIAL,
-                            Build.getSerial().getBytes(StandardCharsets.UTF_8));
-                    break;
-                case ID_TYPE_IMEI: {
-                    final String imei = telephonyService.getImei(0);
-                    if (imei == null) {
-                        throw new DeviceIdAttestationException("Unable to retrieve IMEI");
-                    }
-                    attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_IMEI,
-                            imei.getBytes(StandardCharsets.UTF_8));
-                    break;
-                }
-                case ID_TYPE_MEID: {
-                    final String meid = telephonyService.getMeid(0);
-                    if (meid == null) {
-                        throw new DeviceIdAttestationException("Unable to retrieve MEID");
-                    }
-                    attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_MEID,
-                            meid.getBytes(StandardCharsets.UTF_8));
-                    break;
-                }
-                case USE_INDIVIDUAL_ATTESTATION: {
-                    attestArgs.addBoolean(KeymasterDefs.KM_TAG_DEVICE_UNIQUE_ATTESTATION);
-                    break;
-                }
-                default:
-                    throw new IllegalArgumentException("Unknown device ID type " + idType);
-            }
-        }
-        attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_BRAND,
-                Build.BRAND.getBytes(StandardCharsets.UTF_8));
-        attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_DEVICE,
-                Build.DEVICE.getBytes(StandardCharsets.UTF_8));
-        attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_PRODUCT,
-                Build.PRODUCT.getBytes(StandardCharsets.UTF_8));
-        attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_MANUFACTURER,
-                Build.MANUFACTURER.getBytes(StandardCharsets.UTF_8));
-        attestArgs.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_ID_MODEL,
-                Build.MODEL.getBytes(StandardCharsets.UTF_8));
-        return attestArgs;
-    }
-
     /**
      * Performs attestation of the device's identifiers. This method returns a certificate chain
      * whose first element contains the requested device identifiers in an extension. The device's
@@ -229,6 +137,13 @@
     @NonNull public static X509Certificate[] attestDeviceIds(Context context,
             @NonNull int[] idTypes, @NonNull byte[] attestationChallenge) throws
             DeviceIdAttestationException {
+        if (attestationChallenge == null) {
+            throw new NullPointerException("Missing attestation challenge");
+        }
+        if (idTypes == null) {
+            throw new NullPointerException("Missing id types");
+        }
+
         String keystoreAlias = generateRandomAlias();
         KeyGenParameterSpec.Builder builder =
                 new KeyGenParameterSpec.Builder(keystoreAlias, KeyProperties.PURPOSE_SIGN)
@@ -265,6 +180,12 @@
             if (e.getCause() instanceof DeviceIdAttestationException) {
                 throw (DeviceIdAttestationException) e.getCause();
             }
+            // Illegal argument errors are wrapped up by a ProviderException. Catch those so that
+            // we can unwrap them into a more meaningful exception type for the caller.
+            if (e instanceof ProviderException
+                    && e.getCause() instanceof IllegalArgumentException) {
+                throw (IllegalArgumentException) e.getCause();
+            }
             throw new DeviceIdAttestationException("Unable to perform attestation", e);
         }
     }
diff --git a/libs/WindowManager/Shell/res/values/dimen.xml b/libs/WindowManager/Shell/res/values/dimen.xml
index dddf2c1..70f03d2 100644
--- a/libs/WindowManager/Shell/res/values/dimen.xml
+++ b/libs/WindowManager/Shell/res/values/dimen.xml
@@ -44,7 +44,7 @@
     <dimen name="pip_bottom_offset_buffer">1dp</dimen>
 
     <!-- The corner radius for PiP window. -->
-    <dimen name="pip_corner_radius">8dp</dimen>
+    <dimen name="pip_corner_radius">16dp</dimen>
 
     <!-- The bottom margin of the PIP drag to dismiss info text shown when moving a PIP. -->
     <dimen name="pip_dismiss_text_bottom_margin">24dp</dimen>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
index a2c6567..c46b559 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipAnimationController.java
@@ -435,7 +435,8 @@
                         SurfaceControl.Transaction tx, float fraction) {
                     final float alpha = getStartValue() * (1 - fraction) + getEndValue() * fraction;
                     setCurrentValue(alpha);
-                    getSurfaceTransactionHelper().alpha(tx, leash, alpha);
+                    getSurfaceTransactionHelper().alpha(tx, leash, alpha)
+                            .round(tx, leash, shouldApplyCornerRadius());
                     tx.apply();
                 }
 
@@ -526,16 +527,22 @@
                     float angle = (1.0f - fraction) * startingAngle;
                     setCurrentValue(bounds);
                     if (inScaleTransition() || sourceHintRect == null) {
-
                         if (isOutPipDirection) {
                             getSurfaceTransactionHelper().scale(tx, leash, end, bounds);
                         } else {
-                            getSurfaceTransactionHelper().scale(tx, leash, base, bounds, angle);
+                            getSurfaceTransactionHelper().scale(tx, leash, base, bounds, angle)
+                                    .round(tx, leash, base, bounds);
                         }
                     } else {
                         final Rect insets = computeInsets(fraction);
                         getSurfaceTransactionHelper().scaleAndCrop(tx, leash,
                                 initialSourceValue, bounds, insets);
+                        if (shouldApplyCornerRadius()) {
+                            final Rect destinationBounds = new Rect(bounds);
+                            destinationBounds.inset(insets);
+                            getSurfaceTransactionHelper().round(tx, leash,
+                                    initialContainerRect, destinationBounds);
+                        }
                     }
                     if (!handlePipTransaction(leash, tx, bounds)) {
                         tx.apply();
@@ -564,9 +571,11 @@
                         x = fraction * (end.left - start.left) + start.left;
                         y = fraction * (end.bottom - start.top) + start.top;
                     }
-                    getSurfaceTransactionHelper().rotateAndScaleWithCrop(tx, leash,
-                            initialContainerRect, bounds, insets, degree, x, y, isOutPipDirection,
-                            rotationDelta == ROTATION_270 /* clockwise */);
+                    getSurfaceTransactionHelper()
+                            .rotateAndScaleWithCrop(tx, leash, initialContainerRect, bounds,
+                                    insets, degree, x, y, isOutPipDirection,
+                                    rotationDelta == ROTATION_270 /* clockwise */)
+                            .round(tx, leash, initialContainerRect, bounds);
                     tx.apply();
                 }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java
index 48a15d8..9fa3f69 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipSurfaceTransactionHelper.java
@@ -186,6 +186,18 @@
     }
 
     /**
+     * Operates the round corner radius on a given transaction and leash, scaled by bounds
+     * @return same {@link PipSurfaceTransactionHelper} instance for method chaining
+     */
+    public PipSurfaceTransactionHelper round(SurfaceControl.Transaction tx, SurfaceControl leash,
+            Rect fromBounds, Rect toBounds) {
+        final float scale = (float) (Math.hypot(fromBounds.width(), fromBounds.height())
+                / Math.hypot(toBounds.width(), toBounds.height()));
+        tx.setCornerRadius(leash, mCornerRadius * scale);
+        return this;
+    }
+
+    /**
      * Re-parents the snapshot to the parent's surface control and shows it.
      */
     public PipSurfaceTransactionHelper reparentAndShowSurfaceSnapshot(
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index e1b198c..7d032ad 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -184,6 +184,7 @@
                 mTaskOrganizer.applyTransaction(wct);
                 // The final task bounds will be applied by onFixedRotationFinished so that all
                 // coordinates are in new rotation.
+                mSurfaceTransactionHelper.round(tx, mLeash, isInPip());
                 mDeferredAnimEndTransaction = tx;
                 return;
             }
@@ -1041,7 +1042,9 @@
         }
 
         final SurfaceControl.Transaction tx = mSurfaceControlTransactionFactory.getTransaction();
-        mSurfaceTransactionHelper.scale(tx, mLeash, startBounds, toBounds, degrees);
+        mSurfaceTransactionHelper
+                .scale(tx, mLeash, startBounds, toBounds, degrees)
+                .round(tx, mLeash, startBounds, toBounds);
         if (mPipMenuController.isMenuVisible()) {
             mPipMenuController.movePipMenu(mLeash, tx, toBounds);
         } else {
@@ -1216,6 +1219,7 @@
             // Just a resize in PIP
             taskBounds = destinationBounds;
         }
+        mSurfaceTransactionHelper.round(tx, mLeash, isInPip());
 
         wct.setBounds(mToken, taskBounds);
         wct.setBoundsChangeTransaction(mToken, tx);
diff --git a/libs/hwui/pipeline/skia/ShaderCache.cpp b/libs/hwui/pipeline/skia/ShaderCache.cpp
index c482fc1..e7432ac 100644
--- a/libs/hwui/pipeline/skia/ShaderCache.cpp
+++ b/libs/hwui/pipeline/skia/ShaderCache.cpp
@@ -31,7 +31,7 @@
 
 // Cache size limits.
 static const size_t maxKeySize = 1024;
-static const size_t maxValueSize = 512 * 1024;
+static const size_t maxValueSize = 2 * 1024 * 1024;
 static const size_t maxTotalSize = 1024 * 1024;
 
 ShaderCache::ShaderCache() {
diff --git a/media/java/android/media/IMediaRoute2ProviderServiceCallback.aidl b/media/java/android/media/IMediaRoute2ProviderServiceCallback.aidl
index 1755657..63c52a1 100644
--- a/media/java/android/media/IMediaRoute2ProviderServiceCallback.aidl
+++ b/media/java/android/media/IMediaRoute2ProviderServiceCallback.aidl
@@ -26,9 +26,9 @@
  */
 oneway interface IMediaRoute2ProviderServiceCallback {
     // TODO: Change it to updateRoutes?
-    void updateState(in MediaRoute2ProviderInfo providerInfo);
+    void notifyProviderUpdated(in MediaRoute2ProviderInfo providerInfo);
     void notifySessionCreated(long requestId, in RoutingSessionInfo sessionInfo);
-    void notifySessionUpdated(in RoutingSessionInfo sessionInfo);
+    void notifySessionsUpdated(in List<RoutingSessionInfo> sessionInfo);
     void notifySessionReleased(in RoutingSessionInfo sessionInfo);
     void notifyRequestFailed(long requestId, int reason);
 }
diff --git a/media/java/android/media/MediaRoute2ProviderService.java b/media/java/android/media/MediaRoute2ProviderService.java
index 93fe06a..49e0411 100644
--- a/media/java/android/media/MediaRoute2ProviderService.java
+++ b/media/java/android/media/MediaRoute2ProviderService.java
@@ -141,6 +141,7 @@
     private final Object mSessionLock = new Object();
     private final Object mRequestIdsLock = new Object();
     private final AtomicBoolean mStatePublishScheduled = new AtomicBoolean(false);
+    private final AtomicBoolean mSessionUpdateScheduled = new AtomicBoolean(false);
     private MediaRoute2ProviderServiceStub mStub;
     private IMediaRoute2ProviderServiceCallback mRemoteCallback;
     private volatile MediaRoute2ProviderInfo mProviderInfo;
@@ -287,16 +288,8 @@
                 Log.w(TAG, "notifySessionUpdated: Ignoring unknown session info.");
                 return;
             }
-
-            if (mRemoteCallback == null) {
-                return;
-            }
-            try {
-                mRemoteCallback.notifySessionUpdated(sessionInfo);
-            } catch (RemoteException ex) {
-                Log.w(TAG, "Failed to notify session info changed.");
-            }
         }
+        scheduleUpdateSessions();
     }
 
     /**
@@ -479,6 +472,7 @@
     void setCallback(IMediaRoute2ProviderServiceCallback callback) {
         mRemoteCallback = callback;
         schedulePublishState();
+        scheduleUpdateSessions();
     }
 
     void schedulePublishState() {
@@ -497,12 +491,40 @@
         }
 
         try {
-            mRemoteCallback.updateState(mProviderInfo);
+            mRemoteCallback.notifyProviderUpdated(mProviderInfo);
         } catch (RemoteException ex) {
             Log.w(TAG, "Failed to publish provider state.", ex);
         }
     }
 
+    void scheduleUpdateSessions() {
+        if (mSessionUpdateScheduled.compareAndSet(false, true)) {
+            mHandler.post(this::updateSessions);
+        }
+    }
+
+    private void updateSessions() {
+        if (!mSessionUpdateScheduled.compareAndSet(true, false)) {
+            return;
+        }
+
+        if (mRemoteCallback == null) {
+            return;
+        }
+
+        List<RoutingSessionInfo> sessions;
+        synchronized (mSessionLock) {
+            sessions = new ArrayList<>(mSessionInfo.values());
+        }
+
+        try {
+            mRemoteCallback.notifySessionsUpdated(sessions);
+        } catch (RemoteException ex) {
+            Log.w(TAG, "Failed to notify session info changed.");
+        }
+
+    }
+
     /**
      * Adds a requestId in the request ID list whose max size is {@link #MAX_REQUEST_IDS_SIZE}.
      * When the max size is reached, the first element is removed (FIFO).
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
index 7f645ba..31d848d 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
@@ -35,43 +35,11 @@
         android:clipChildren="false"
         android:clipToPadding="false"
         android:orientation="vertical">
-        <TextView
-            android:id="@+id/logout"
-            android:layout_height="@dimen/logout_button_layout_height"
-            android:layout_width="wrap_content"
-            android:layout_gravity="center_horizontal"
-            android:layout_centerHorizontal="true"
-            android:layout_marginBottom="@dimen/logout_button_margin_bottom"
-            android:gravity="center"
-            android:paddingLeft="@dimen/logout_button_padding_horizontal"
-            android:paddingRight="@dimen/logout_button_padding_horizontal"
-            android:background="@drawable/logout_button_background"
-            android:fontFamily="@*android:string/config_bodyFontFamilyMedium"
-            android:textAllCaps="true"
-            android:textColor="?android:attr/textColorPrimary"
-            android:textSize="13sp"
-            android:text="@*android:string/global_action_logout" />
-
         <include
             layout="@layout/keyguard_clock_switch"
             android:id="@+id/keyguard_clock_container"
             android:layout_width="match_parent"
             android:layout_height="wrap_content" />
-
-        <TextView
-            android:id="@+id/owner_info"
-            android:layout_marginLeft="16dp"
-            android:layout_marginRight="16dp"
-            android:layout_width="wrap_content"
-            android:layout_height="wrap_content"
-            android:layout_marginTop="@dimen/date_owner_info_margin"
-            android:layout_gravity="center_horizontal"
-            android:layout_centerHorizontal="true"
-            android:textColor="?attr/wallpaperTextColorSecondary"
-            android:textSize="@dimen/widget_label_font_size"
-            android:letterSpacing="0.05"
-            android:ellipsize="marquee"
-            android:singleLine="true" />
         <FrameLayout
             android:id="@+id/status_view_media_container"
             android:layout_width="wrap_content"
diff --git a/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml b/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml
index d0e3d3c..51cab0a 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_header_date_privacy.xml
@@ -29,12 +29,12 @@
     android:paddingTop="@dimen/status_bar_padding_top"
     android:minHeight="48dp">
 
-    <LinearLayout
+    <FrameLayout
+        android:id="@+id/date_container"
         android:layout_width="0dp"
         android:layout_height="match_parent"
         android:minHeight="48dp"
         android:layout_weight="1"
-        android:orientation="horizontal"
         android:gravity="center_vertical|start" >
 
         <com.android.systemui.statusbar.policy.DateView
@@ -46,7 +46,7 @@
             android:singleLine="true"
             android:textAppearance="@style/TextAppearance.QS.Status"
             systemui:datePattern="@string/abbrev_wday_month_day_no_year_alarm" />
-    </LinearLayout>
+    </FrameLayout>
 
     <android.widget.Space
         android:id="@+id/space"
@@ -59,21 +59,22 @@
     <FrameLayout
         android:id="@+id/header_text_container"
         android:layout_height="match_parent"
-        android:layout_width="wrap_content"
+        android:layout_width="0dp"
+        android:layout_weight="1"
         android:paddingStart="16dp"
         android:paddingEnd="16dp"
         android:gravity="center"
     />
 
-    <LinearLayout
+    <FrameLayout
+        android:id="@+id/privacy_container"
         android:layout_width="0dp"
         android:layout_height="match_parent"
         android:minHeight="48dp"
         android:layout_weight="1"
-        android:orientation="horizontal"
         android:gravity="center_vertical|end" >
 
     <include layout="@layout/ongoing_privacy_chip" />
 
-    </LinearLayout>
+    </FrameLayout>
 </LinearLayout>
diff --git a/packages/SystemUI/res/values-land/integers.xml b/packages/SystemUI/res/values-land/integers.xml
new file mode 100644
index 0000000..5937a07
--- /dev/null
+++ b/packages/SystemUI/res/values-land/integers.xml
@@ -0,0 +1,19 @@
+<!--
+  ~ Copyright (C) 2021 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<resources>
+    <integer name="qs_security_footer_maxLines">1</integer>
+</resources>
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 96eda3d..2362a1a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -20,17 +20,10 @@
 import android.app.IActivityManager;
 import android.content.Context;
 import android.graphics.Color;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.text.TextUtils;
 import android.util.AttributeSet;
-import android.util.Log;
-import android.util.TypedValue;
 import android.view.View;
 import android.view.ViewGroup;
 import android.widget.GridLayout;
-import android.widget.TextView;
 
 import androidx.core.graphics.ColorUtils;
 
@@ -45,26 +38,18 @@
 /**
  * View consisting of:
  * - keyguard clock
- * - logout button (on certain managed devices)
- * - owner information (if set)
  * - media player (split shade mode only)
  */
 public class KeyguardStatusView extends GridLayout {
     private static final boolean DEBUG = KeyguardConstants.DEBUG;
     private static final String TAG = "KeyguardStatusView";
-    private static final int MARQUEE_DELAY_MS = 2000;
 
     private final LockPatternUtils mLockPatternUtils;
     private final IActivityManager mIActivityManager;
 
     private ViewGroup mStatusViewContainer;
-    private TextView mLogoutView;
     private KeyguardClockSwitch mClockView;
-    private TextView mOwnerInfo;
-    private boolean mCanShowOwnerInfo = true; // by default, try to show the owner information here
     private KeyguardSliceView mKeyguardSlice;
-    private Runnable mPendingMarqueeStart;
-    private Handler mHandler;
     private View mMediaHostContainer;
 
     private float mDarkAmount = 0;
@@ -91,64 +76,17 @@
         super(context, attrs, defStyle);
         mIActivityManager = ActivityManager.getService();
         mLockPatternUtils = new LockPatternUtils(getContext());
-        mHandler = new Handler();
-        onDensityOrFontScaleChanged();
-    }
-
-    void setEnableMarquee(boolean enabled) {
-        if (DEBUG) Log.v(TAG, "Schedule setEnableMarquee: " + (enabled ? "Enable" : "Disable"));
-        if (enabled) {
-            if (mPendingMarqueeStart == null) {
-                mPendingMarqueeStart = () -> {
-                    setEnableMarqueeImpl(true);
-                    mPendingMarqueeStart = null;
-                };
-                mHandler.postDelayed(mPendingMarqueeStart, MARQUEE_DELAY_MS);
-            }
-        } else {
-            if (mPendingMarqueeStart != null) {
-                mHandler.removeCallbacks(mPendingMarqueeStart);
-                mPendingMarqueeStart = null;
-            }
-            setEnableMarqueeImpl(false);
-        }
-    }
-
-    private void setEnableMarqueeImpl(boolean enabled) {
-        if (DEBUG) Log.v(TAG, (enabled ? "Enable" : "Disable") + " transport text marquee");
-        if (mOwnerInfo != null) mOwnerInfo.setSelected(enabled);
-    }
-
-    void setCanShowOwnerInfo(boolean canShowOwnerInfo) {
-        mCanShowOwnerInfo = canShowOwnerInfo;
-        mOwnerInfo = findViewById(R.id.owner_info);
-        if (mOwnerInfo != null) {
-            if (mCanShowOwnerInfo) {
-                mOwnerInfo.setVisibility(VISIBLE);
-                updateOwnerInfo();
-            } else {
-                mOwnerInfo.setVisibility(GONE);
-                mOwnerInfo = null;
-            }
-        }
     }
 
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
         mStatusViewContainer = findViewById(R.id.status_view_container);
-        mLogoutView = findViewById(R.id.logout);
-        if (mLogoutView != null) {
-            mLogoutView.setOnClickListener(this::onLogoutClicked);
-        }
 
         mClockView = findViewById(R.id.keyguard_clock_container);
         if (KeyguardClockAccessibilityDelegate.isNeeded(mContext)) {
             mClockView.setAccessibilityDelegate(new KeyguardClockAccessibilityDelegate(mContext));
         }
-        if (mCanShowOwnerInfo) {
-            mOwnerInfo = findViewById(R.id.owner_info);
-        }
 
         mKeyguardSlice = findViewById(R.id.keyguard_status_area);
         mTextColor = mClockView.getCurrentTextColor();
@@ -158,7 +96,6 @@
 
         mMediaHostContainer = findViewById(R.id.status_view_media_container);
 
-        updateOwnerInfo();
         updateDark();
     }
 
@@ -173,60 +110,6 @@
         mShowingHeader = hasHeader;
     }
 
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        super.onLayout(changed, left, top, right, bottom);
-        layoutOwnerInfo();
-    }
-
-    int getLogoutButtonHeight() {
-        if (mLogoutView == null) {
-            return 0;
-        }
-        return mLogoutView.getVisibility() == VISIBLE ? mLogoutView.getHeight() : 0;
-    }
-
-    int getOwnerInfoHeight() {
-        if (mOwnerInfo == null) {
-            return 0;
-        }
-        return mOwnerInfo.getVisibility() == VISIBLE ? mOwnerInfo.getHeight() : 0;
-    }
-
-    void updateLogoutView(boolean shouldShowLogout) {
-        if (mLogoutView == null) {
-            return;
-        }
-        mLogoutView.setVisibility(shouldShowLogout ? VISIBLE : GONE);
-        // Logout button will stay in language of user 0 if we don't set that manually.
-        mLogoutView.setText(mContext.getResources().getString(
-                com.android.internal.R.string.global_action_logout));
-    }
-
-    void onDensityOrFontScaleChanged() {
-        if (mOwnerInfo != null) {
-            mOwnerInfo.setTextSize(TypedValue.COMPLEX_UNIT_PX,
-                    getResources().getDimensionPixelSize(
-                            com.android.systemui.R.dimen.widget_label_font_size));
-            loadBottomMargin();
-        }
-    }
-
-    void updateOwnerInfo() {
-        if (mOwnerInfo == null) return;
-        String info = mLockPatternUtils.getDeviceOwnerInfo();
-        if (info == null) {
-            // Use the current user owner information if enabled.
-            final boolean ownerInfoEnabled = mLockPatternUtils.isOwnerInfoEnabled(
-                    KeyguardUpdateMonitor.getCurrentUser());
-            if (ownerInfoEnabled) {
-                info = mLockPatternUtils.getOwnerInfo(KeyguardUpdateMonitor.getCurrentUser());
-            }
-        }
-        mOwnerInfo.setText(info);
-        updateDark();
-    }
-
     void setDarkAmount(float darkAmount) {
         if (mDarkAmount == darkAmount) {
             return;
@@ -238,17 +121,6 @@
     }
 
     void updateDark() {
-        boolean dark = mDarkAmount == 1;
-        if (mLogoutView != null) {
-            mLogoutView.setAlpha(dark ? 0 : 1);
-        }
-
-        if (mOwnerInfo != null) {
-            boolean hasText = !TextUtils.isEmpty(mOwnerInfo.getText());
-            mOwnerInfo.setVisibility(hasText ? VISIBLE : GONE);
-            layoutOwnerInfo();
-        }
-
         final int blendedTextColor = ColorUtils.blendARGB(mTextColor, Color.WHITE, mDarkAmount);
         mKeyguardSlice.setDarkAmount(mDarkAmount);
         mClockView.setTextColor(blendedTextColor);
@@ -277,13 +149,8 @@
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("KeyguardStatusView:");
-        pw.println("  mOwnerInfo: " + (mOwnerInfo == null
-                ? "null" : mOwnerInfo.getVisibility() == VISIBLE));
         pw.println("  mDarkAmount: " + mDarkAmount);
         pw.println("  mTextColor: " + Integer.toHexString(mTextColor));
-        if (mLogoutView != null) {
-            pw.println("  logout visible: " + (mLogoutView.getVisibility() == VISIBLE));
-        }
         if (mClockView != null) {
             mClockView.dump(fd, pw, args);
         }
@@ -297,28 +164,4 @@
         mIconTopMarginWithHeader = getResources().getDimensionPixelSize(
                 R.dimen.widget_vertical_padding_with_header);
     }
-
-    private void layoutOwnerInfo() {
-        if (mOwnerInfo != null && mOwnerInfo.getVisibility() != GONE) {
-            // Animate owner info during wake-up transition
-            mOwnerInfo.setAlpha(1f - mDarkAmount);
-
-            float ratio = mDarkAmount;
-            // Calculate how much of it we should crop in order to have a smooth transition
-            int collapsed = mOwnerInfo.getTop() - mOwnerInfo.getPaddingTop();
-            int expanded = mOwnerInfo.getBottom() + mOwnerInfo.getPaddingBottom();
-            int toRemove = (int) ((expanded - collapsed) * ratio);
-            setBottom(getMeasuredHeight() - toRemove);
-        }
-    }
-
-    private void onLogoutClicked(View view) {
-        int currentUserId = KeyguardUpdateMonitor.getCurrentUser();
-        try {
-            mIActivityManager.switchUser(UserHandle.USER_SYSTEM);
-            mIActivityManager.stopUser(currentUserId, true /*force*/, null);
-        } catch (RemoteException re) {
-            Log.e(TAG, "Failed to logout user", re);
-        }
-    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index e4cabcb..32935c2 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -17,7 +17,6 @@
 package com.android.keyguard;
 
 import android.graphics.Rect;
-import android.os.UserHandle;
 import android.util.Slog;
 
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
@@ -97,8 +96,6 @@
     @Override
     public void onInit() {
         mKeyguardClockSwitchController.init();
-        mView.setEnableMarquee(mKeyguardUpdateMonitor.isDeviceInteractive());
-        mView.updateLogoutView(shouldShowLogout());
     }
 
     @Override
@@ -143,20 +140,6 @@
     }
 
     /**
-     * Get the height of the logout button.
-     */
-    public int getLogoutButtonHeight() {
-        return mView.getLogoutButtonHeight();
-    }
-
-    /**
-     * Get the height of the owner information view.
-     */
-    public int getOwnerInfoHeight() {
-        return mView.getOwnerInfoHeight();
-    }
-
-    /**
      * Set keyguard status view alpha.
      */
     public void setAlpha(float alpha) {
@@ -254,11 +237,6 @@
         mKeyguardClockSwitchController.refresh();
     }
 
-    private boolean shouldShowLogout() {
-        return mKeyguardUpdateMonitor.isLogoutEnabled()
-                && KeyguardUpdateMonitor.getCurrentUser() != UserHandle.USER_SYSTEM;
-    }
-
     private final ConfigurationController.ConfigurationListener mConfigurationListener =
             new ConfigurationController.ConfigurationListener() {
         @Override
@@ -269,7 +247,6 @@
         @Override
         public void onDensityOrFontScaleChanged() {
             mKeyguardClockSwitchController.onDensityOrFontScaleChanged();
-            mView.onDensityOrFontScaleChanged();
         }
     };
 
@@ -277,8 +254,6 @@
         @Override
         public void onLockScreenModeChanged(int mode) {
             mKeyguardSliceViewController.updateLockScreenMode(mode);
-            mView.setCanShowOwnerInfo(false);
-            mView.updateLogoutView(false);
         }
 
         @Override
@@ -301,31 +276,12 @@
             if (showing) {
                 if (DEBUG) Slog.v(TAG, "refresh statusview showing:" + showing);
                 refreshTime();
-                mView.updateOwnerInfo();
-                mView.updateLogoutView(shouldShowLogout());
             }
         }
 
         @Override
-        public void onStartedWakingUp() {
-            mView.setEnableMarquee(true);
-        }
-
-        @Override
-        public void onFinishedGoingToSleep(int why) {
-            mView.setEnableMarquee(false);
-        }
-
-        @Override
         public void onUserSwitchComplete(int userId) {
             mKeyguardClockSwitchController.refreshFormat();
-            mView.updateOwnerInfo();
-            mView.updateLogoutView(shouldShowLogout());
-        }
-
-        @Override
-        public void onLogoutEnabledChanged() {
-            mView.updateLogoutView(shouldShowLogout());
         }
     };
 
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
index 4418696..ff3cb21 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeUi.java
@@ -62,6 +62,7 @@
     private final DozeParameters mDozeParameters;
     private final DozeLog mDozeLog;
     private final Lazy<StatusBarStateController> mStatusBarStateController;
+    private final TunerService mTunerService;
 
     private boolean mKeyguardShowing;
     private final KeyguardUpdateMonitorCallback mKeyguardVisibilityCallback =
@@ -102,8 +103,15 @@
         mTimeTicker = new AlarmTimeout(alarmManager, this::onTimeTick, "doze_time_tick", handler);
         keyguardUpdateMonitor.registerCallback(mKeyguardVisibilityCallback);
         mDozeLog = dozeLog;
-        tunerService.addTunable(this, Settings.Secure.DOZE_ALWAYS_ON);
+        mTunerService = tunerService;
         mStatusBarStateController = statusBarStateController;
+
+        mTunerService.addTunable(this, Settings.Secure.DOZE_ALWAYS_ON);
+    }
+
+    @Override
+    public void destroy() {
+        mTunerService.removeTunable(this);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index a159984..56efafb 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1651,14 +1651,19 @@
         Trace.endSection();
     }
 
-    /** Hide the keyguard and let {@code runner} handle the animation. */
+    /**
+     * Hide the keyguard and let {@code runner} handle the animation.
+     *
+     * This method should typically be called after {@link ViewMediatorCallback#keyguardDonePending}
+     * was called, when we are ready to hide the keyguard.
+     */
     public void hideWithAnimation(IRemoteAnimationRunner runner) {
-        if (!mShowing) {
+        if (!mKeyguardDonePending) {
             return;
         }
 
         mKeyguardExitAnimationRunner = runner;
-        hideLocked();
+        mViewMediatorCallback.readyForKeyguardDone();
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
index d8b342a..3e5e140 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/NavigationBar.java
@@ -1447,10 +1447,14 @@
     private void updateAssistantEntrypoints() {
         mAssistantAvailable = mAssistManagerLazy.get()
                 .getAssistInfoForUser(UserHandle.USER_CURRENT) != null;
+        boolean longPressDefault = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_assistLongPressHomeEnabledDefault);
         mLongPressHomeEnabled = Settings.Secure.getInt(mContentResolver,
-                Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED, 1) != 0;
+                Settings.Secure.ASSIST_LONG_PRESS_HOME_ENABLED, longPressDefault ? 1 : 0) != 0;
+        boolean gestureDefault = mContext.getResources().getBoolean(
+                com.android.internal.R.bool.config_assistTouchGestureEnabledDefault);
         mAssistantTouchGestureEnabled = Settings.Secure.getInt(mContentResolver,
-                Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED, 1) != 0;
+                Settings.Secure.ASSIST_TOUCH_GESTURE_ENABLED, gestureDefault ? 1 : 0) != 0;
         if (mOverviewProxyService.getProxy() != null) {
             try {
                 mOverviewProxyService.getProxy().onAssistantAvailable(mAssistantAvailable
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 01a6684..ad4886c 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -42,6 +42,7 @@
 import com.android.systemui.statusbar.policy.BrightnessMirrorController;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
+import com.android.systemui.util.animation.UniqueObjectHostView;
 
 import java.util.ArrayList;
 import java.util.List;
@@ -384,12 +385,17 @@
     private void switchSecurityFooter() {
         if (mSecurityFooter != null) {
             if (mContext.getResources().getConfiguration().orientation
-                    == Configuration.ORIENTATION_LANDSCAPE && mHeaderContainer != null
-                    && !mSecurityFooter.getParent().equals(mHeaderContainer)) {
+                    == Configuration.ORIENTATION_LANDSCAPE && mHeaderContainer != null) {
                 // Adding the security view to the header, that enables us to avoid scrolling
                 switchToParent(mSecurityFooter, mHeaderContainer, 0);
             } else {
-                switchToParent(mSecurityFooter, this, -1);
+                // Where should this go? If there's media, right before it. Otherwise, at the end.
+                View mediaView = findViewByPredicate(v -> v instanceof UniqueObjectHostView);
+                int index = -1;
+                if (mediaView != null) {
+                    index = indexOfChild(mediaView);
+                }
+                switchToParent(mSecurityFooter, this, index);
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index f668722..08a68bc 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -68,7 +68,9 @@
     private Space mDatePrivacySeparator;
     private View mClockIconsSeparator;
     private boolean mShowClockIconsSeparator;
-    private ViewGroup mRightLayout;
+    private View mRightLayout;
+    private View mDateContainer;
+    private View mPrivacyContainer;
 
     private BatteryMeterView mBatteryRemainingIcon;
     private StatusIconContainer mIconContainer;
@@ -129,6 +131,8 @@
         mSecurityHeaderView = findViewById(R.id.header_text_container);
         mClockIconsSeparator = findViewById(R.id.separator);
         mRightLayout = findViewById(R.id.rightLayout);
+        mDateContainer = findViewById(R.id.date_container);
+        mPrivacyContainer = findViewById(R.id.privacy_container);
 
         mClockView = findViewById(R.id.clock);
         mDatePrivacySeparator = findViewById(R.id.space);
@@ -179,6 +183,7 @@
     protected void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
         updateResources();
+        setDatePrivacyContainersWidth(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE);
     }
 
     @Override
@@ -187,6 +192,18 @@
         updateResources();
     }
 
+    private void setDatePrivacyContainersWidth(boolean landscape) {
+        LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mDateContainer.getLayoutParams();
+        lp.width = landscape ? WRAP_CONTENT : 0;
+        lp.weight = landscape ? 0f : 1f;
+        mDateContainer.setLayoutParams(lp);
+
+        lp = (LinearLayout.LayoutParams) mPrivacyContainer.getLayoutParams();
+        lp.width = landscape ? WRAP_CONTENT : 0;
+        lp.weight = landscape ? 0f : 1f;
+        mPrivacyContainer.setLayoutParams(lp);
+    }
+
     void updateResources() {
         Resources resources = mContext.getResources();
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
index b18f191..4136624 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ActivatableNotificationView.java
@@ -61,12 +61,6 @@
     private static final float HORIZONTAL_ANIMATION_END = 0.2f;
 
     /**
-     * At which point from [0,1] does the alpha animation end (or start when
-     * expanding)? 1.0 meaning that it ends immediately and 0.0 that it is continuously animated.
-     */
-    private static final float ALPHA_ANIMATION_END = 0.0f;
-
-    /**
      * At which point from [0,1] does the horizontal collapse animation start (or start when
      * expanding)? 1.0 meaning that it starts immediately and 0.0 that it is animated at all.
      */
@@ -497,10 +491,10 @@
 
         float targetValue;
         if (isAppearing) {
-            mCurrentAppearInterpolator = mSlowOutFastInInterpolator;
+            mCurrentAppearInterpolator = Interpolators.FAST_OUT_SLOW_IN;
             targetValue = 1.0f;
         } else {
-            mCurrentAppearInterpolator = Interpolators.FAST_OUT_SLOW_IN;
+            mCurrentAppearInterpolator = mSlowOutFastInInterpolator;
             targetValue = 0.0f;
         }
         mAppearAnimator = ValueAnimator.ofFloat(mAppearAnimationFraction,
@@ -584,19 +578,21 @@
     }
 
     private void updateAppearRect() {
-        float inverseFraction = (1.0f - mAppearAnimationFraction);
-        float translationFraction = mCurrentAppearInterpolator.getInterpolation(inverseFraction);
-        float translateYTotalAmount = translationFraction * mAnimationTranslationY;
-        mAppearAnimationTranslation = translateYTotalAmount;
+        float interpolatedFraction = mCurrentAppearInterpolator.getInterpolation(
+                mAppearAnimationFraction);
+        mAppearAnimationTranslation = (1.0f - interpolatedFraction) * mAnimationTranslationY;
         final int actualHeight = getActualHeight();
-        float bottom = actualHeight * mAppearAnimationFraction;
+        float bottom = actualHeight * interpolatedFraction;
 
-        setOutlineRect(0, mAppearAnimationTranslation,
-                getWidth(), bottom + mAppearAnimationTranslation);
+        setOutlineRect(0, mAppearAnimationTranslation, getWidth(),
+                bottom + mAppearAnimationTranslation);
     }
 
-    private float getAppearAnimationFraction() {
-        return mAppearAnimationFraction >= 0 ? mAppearAnimationFraction : 1;
+    private float getInterpolatedAppearAnimationFraction() {
+        if (mAppearAnimationFraction >= 0) {
+            return mCurrentAppearInterpolator.getInterpolation(mAppearAnimationFraction);
+        }
+        return 1.0f;
     }
 
     private void updateAppearAnimationAlpha() {
@@ -629,18 +625,14 @@
 
     @Override
     public float getCurrentBackgroundRadiusTop() {
-        float fraction = getAppearAnimationFraction();
-        return isHeadsUpAnimatingAway() || isHeadsUp()
-                ? mOutlineRadius * fraction
-                : super.getCurrentBackgroundRadiusTop();
+        float fraction = getInterpolatedAppearAnimationFraction();
+        return MathUtils.lerp(0, super.getCurrentBackgroundRadiusTop(), fraction);
     }
 
     @Override
     public float getCurrentBackgroundRadiusBottom() {
-        float fraction = getAppearAnimationFraction();
-        return isHeadsUpAnimatingAway() || isHeadsUp()
-                ? mOutlineRadius * fraction
-                : super.getCurrentBackgroundRadiusBottom();
+        float fraction = getInterpolatedAppearAnimationFraction();
+        return MathUtils.lerp(0, super.getCurrentBackgroundRadiusBottom(), fraction);
     }
 
     private void applyBackgroundRoundness(float topRadius, float bottomRadius) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
index 3728388..5134c62 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableOutlineView.java
@@ -249,9 +249,18 @@
     @Override
     public boolean setTopRoundness(float topRoundness, boolean animate) {
         if (mTopRoundness != topRoundness) {
+            float diff = Math.abs(topRoundness - mTopRoundness);
             mTopRoundness = topRoundness;
+            boolean shouldAnimate = animate;
+            if (PropertyAnimator.isAnimating(this, TOP_ROUNDNESS) && diff > 0.5f) {
+                // Fail safe:
+                // when we've been animating previously and we're now getting an update in the
+                // other direction, make sure to animate it too, otherwise, the localized updating
+                // may make the start larger than 1.0.
+                shouldAnimate = true;
+            }
             PropertyAnimator.setProperty(this, TOP_ROUNDNESS, topRoundness,
-                    ROUNDNESS_PROPERTIES, animate);
+                    ROUNDNESS_PROPERTIES, shouldAnimate);
             return true;
         }
         return false;
@@ -286,9 +295,18 @@
     @Override
     public boolean setBottomRoundness(float bottomRoundness, boolean animate) {
         if (mBottomRoundness != bottomRoundness) {
+            float diff = Math.abs(bottomRoundness - mBottomRoundness);
             mBottomRoundness = bottomRoundness;
+            boolean shouldAnimate = animate;
+            if (PropertyAnimator.isAnimating(this, BOTTOM_ROUNDNESS) && diff > 0.5f) {
+                // Fail safe:
+                // when we've been animating previously and we're now getting an update in the
+                // other direction, make sure to animate it too, otherwise, the localized updating
+                // may make the start larger than 1.0.
+                shouldAnimate = true;
+            }
             PropertyAnimator.setProperty(this, BOTTOM_ROUNDNESS, bottomRoundness,
-                    ROUNDNESS_PROPERTIES, animate);
+                    ROUNDNESS_PROPERTIES, shouldAnimate);
             return true;
         }
         return false;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/HeadsUpAppearInterpolator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/HeadsUpAppearInterpolator.java
deleted file mode 100644
index 24e1f32..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/HeadsUpAppearInterpolator.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2015 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License
- */
-
-package com.android.systemui.statusbar.notification.stack;
-
-import android.graphics.Path;
-import android.view.animation.PathInterpolator;
-
-/**
- * An interpolator specifically designed for the appear animation of heads up notifications.
- */
-public class HeadsUpAppearInterpolator extends PathInterpolator {
-
-    private static float X1 = 250f;
-    private static float X2 = 200f;
-    private static float XTOT = (X1 + X2);;
-
-    public HeadsUpAppearInterpolator() {
-        super(getAppearPath());
-    }
-
-    private static Path getAppearPath() {
-        Path path = new Path();
-        path.moveTo(0, 0);
-        float y1 = 90f;
-        float y2 = 80f;
-        path.cubicTo(X1 * 0.8f / XTOT, y1 / y2,
-                X1 * 0.8f / XTOT, y1 / y2,
-                X1 / XTOT, y1 / y2);
-        path.cubicTo((X1 + X2 * 0.4f) / XTOT, y1 / y2,
-                (X1 + X2 * 0.2f) / XTOT, 1.0f,
-                1.0f , 1.0f);
-        return path;
-    }
-
-    public static float getFractionUntilOvershoot() {
-        return X1 / XTOT;
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
index 4b49e3a..23aefd9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationRoundnessManager.java
@@ -18,7 +18,6 @@
 
 import android.content.res.Resources;
 import android.util.MathUtils;
-import android.view.View;
 
 import com.android.systemui.R;
 import com.android.systemui.dagger.SysUISingleton;
@@ -199,7 +198,7 @@
         mExpanded = expandedHeight != 0.0f;
         mAppearFraction = appearFraction;
         if (mTrackedHeadsUp != null) {
-            updateView(mTrackedHeadsUp, true);
+            updateView(mTrackedHeadsUp, false /* animate */);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index a6bba93..dec9888 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -548,7 +548,11 @@
 
                 @Override
                 public void onHeadsUpUnPinned(NotificationEntry entry) {
-                    mNotificationRoundnessManager.updateView(entry.getRow(), true /* animate */);
+                    ExpandableNotificationRow row = entry.getRow();
+                    // update the roundedness posted, because we might be animating away the
+                    // headsup soon, so no need to set the roundedness to 0 and then back to 1.
+                    row.post(() -> mNotificationRoundnessManager.updateView(row,
+                            true /* animate */));
                 }
 
                 @Override
@@ -557,7 +561,9 @@
                     NotificationEntry topEntry = mHeadsUpManager.getTopEntry();
                     mView.setNumHeadsUp(numEntries);
                     mView.setTopHeadsUpEntry(topEntry);
-                    mNotificationRoundnessManager.updateView(entry.getRow(), false /* animate */);
+                    generateHeadsUpAnimation(entry, isHeadsUp);
+                    ExpandableNotificationRow row = entry.getRow();
+                    mNotificationRoundnessManager.updateView(row, true /* animate */);
                 }
             };
 
@@ -1234,7 +1240,7 @@
         return mView.getFirstChildNotGone();
     }
 
-    public void generateHeadsUpAnimation(NotificationEntry entry, boolean isHeadsUp) {
+    private void generateHeadsUpAnimation(NotificationEntry entry, boolean isHeadsUp) {
         mView.generateHeadsUpAnimation(entry, isHeadsUp);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
index 83dc6df..4fd2064 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackStateAnimator.java
@@ -21,7 +21,6 @@
 import android.animation.ValueAnimator;
 import android.util.Property;
 import android.view.View;
-import android.view.animation.Interpolator;
 
 import com.android.keyguard.KeyguardSliceView;
 import com.android.systemui.R;
@@ -50,11 +49,8 @@
     public static final int ANIMATION_DURATION_SWIPE = 260;
     public static final int ANIMATION_DURATION_DIMMED_ACTIVATED = 220;
     public static final int ANIMATION_DURATION_CLOSE_REMOTE_INPUT = 150;
-    public static final int ANIMATION_DURATION_HEADS_UP_APPEAR = 550;
-    public static final int ANIMATION_DURATION_HEADS_UP_APPEAR_CLOSED
-            = (int) (ANIMATION_DURATION_HEADS_UP_APPEAR
-                    * HeadsUpAppearInterpolator.getFractionUntilOvershoot());
-    public static final int ANIMATION_DURATION_HEADS_UP_DISAPPEAR = 300;
+    public static final int ANIMATION_DURATION_HEADS_UP_APPEAR = 400;
+    public static final int ANIMATION_DURATION_HEADS_UP_DISAPPEAR = 400;
     public static final int ANIMATION_DURATION_PULSE_APPEAR =
             KeyguardSliceView.DEFAULT_ANIM_DURATION;
     public static final int ANIMATION_DURATION_BLOCKING_HELPER_FADE = 240;
@@ -64,8 +60,6 @@
     public static final int ANIMATION_DELAY_PER_ELEMENT_GO_TO_FULL_SHADE = 48;
     public static final int DELAY_EFFECT_MAX_INDEX_DIFFERENCE = 2;
     private static final int MAX_STAGGER_COUNT = 5;
-    private static final HeadsUpAppearInterpolator HEADS_UP_APPEAR_INTERPOLATOR =
-            new HeadsUpAppearInterpolator();
 
     private final int mGoToFullShadeAppearingTranslation;
     private final int mPulsingAppearingTranslation;
@@ -115,14 +109,6 @@
             public boolean wasAdded(View view) {
                 return mNewAddChildren.contains(view);
             }
-
-            @Override
-            public Interpolator getCustomInterpolator(View child, Property property) {
-                if (mHeadsUpAppearChildren.contains(child) && View.TRANSLATION_Y.equals(property)) {
-                    return HEADS_UP_APPEAR_INTERPOLATOR;
-                }
-                return null;
-            }
         };
     }
 
@@ -422,7 +408,7 @@
                 if (event.headsUpFromBottom) {
                     mTmpState.yTranslation = mHeadsUpAppearHeightBottom;
                 } else {
-                    changingView.performAddAnimation(0, ANIMATION_DURATION_HEADS_UP_APPEAR_CLOSED,
+                    changingView.performAddAnimation(0, ANIMATION_DURATION_HEADS_UP_APPEAR,
                             true /* isHeadsUpAppear */);
                 }
                 mHeadsUpAppearChildren.add(changingView);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index e30c53f..fda24c1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -1319,8 +1319,7 @@
                 mNotificationStackScrollLayoutController.getHeight()
                         - minPadding
                         - shelfSize
-                        - bottomPadding
-                        - mKeyguardStatusViewController.getLogoutButtonHeight();
+                        - bottomPadding;
 
         int count = 0;
         ExpandableView previousView = null;
@@ -4150,11 +4149,6 @@
                 entry.setHeadsUpIsVisible();
             }
         }
-
-        @Override
-        public void onHeadsUpStateChanged(NotificationEntry entry, boolean isHeadsUp) {
-            mNotificationStackScrollLayoutController.generateHeadsUpAnimation(entry, isHeadsUp);
-        }
     }
 
     private class HeightListener implements QS.HeightListener {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 06aedaa..09779d1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -2118,7 +2118,12 @@
             return;
         }
 
-        mKeyguardViewMediator.hideWithAnimation(runner);
+        // We post to the main thread for 2 reasons:
+        //   1. KeyguardViewMediator is not thread-safe.
+        //   2. To ensure that ViewMediatorCallback#keyguardDonePending is called before
+        //      ViewMediatorCallback#readyForKeyguardDone. The wrong order could occur when doing
+        //      dismissKeyguardThenExecute { hideKeyguardWithAnimation(runner) }.
+        mMainThreadHandler.post(() -> mKeyguardViewMediator.hideWithAnimation(runner));
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/util/CarrierConfigTracker.java b/packages/SystemUI/src/com/android/systemui/util/CarrierConfigTracker.java
index 02a07e4..de5a363 100644
--- a/packages/SystemUI/src/com/android/systemui/util/CarrierConfigTracker.java
+++ b/packages/SystemUI/src/com/android/systemui/util/CarrierConfigTracker.java
@@ -37,20 +37,16 @@
     private final SparseArray<Boolean> mCallStrengthConfigs = new SparseArray<>();
     private final SparseArray<Boolean> mNoCallingConfigs = new SparseArray<>();
     private final CarrierConfigManager mCarrierConfigManager;
-    private final boolean mDefaultCallStrengthConfig;
-    private final boolean mDefaultNoCallingConfig;
+    private boolean mDefaultCallStrengthConfigLoaded;
+    private boolean mDefaultCallStrengthConfig;
+    private boolean mDefaultNoCallingConfigLoaded;
+    private boolean mDefaultNoCallingConfig;
 
     @Inject
     public CarrierConfigTracker(Context context) {
         mCarrierConfigManager = context.getSystemService(CarrierConfigManager.class);
         context.registerReceiver(
                 this, new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
-        mDefaultCallStrengthConfig =
-                CarrierConfigManager.getDefaultConfig().getBoolean(
-                        CarrierConfigManager.KEY_DISPLAY_CALL_STRENGTH_INDICATOR_BOOL);
-        mDefaultNoCallingConfig =
-                CarrierConfigManager.getDefaultConfig().getBoolean(
-                        CarrierConfigManager.KEY_USE_IP_FOR_CALLING_INDICATOR_BOOL);
     }
 
     @Override
@@ -81,6 +77,12 @@
         if (mCallStrengthConfigs.indexOfKey(subId) >= 0) {
             return mCallStrengthConfigs.get(subId);
         }
+        if (!mDefaultCallStrengthConfigLoaded) {
+            mDefaultCallStrengthConfig =
+                    CarrierConfigManager.getDefaultConfig().getBoolean(
+                            CarrierConfigManager.KEY_DISPLAY_CALL_STRENGTH_INDICATOR_BOOL);
+            mDefaultCallStrengthConfigLoaded = true;
+        }
         return mDefaultCallStrengthConfig;
     }
 
@@ -91,6 +93,12 @@
         if (mNoCallingConfigs.indexOfKey(subId) >= 0) {
             return mNoCallingConfigs.get(subId);
         }
+        if (!mDefaultNoCallingConfigLoaded) {
+            mDefaultNoCallingConfig =
+                    CarrierConfigManager.getDefaultConfig().getBoolean(
+                            CarrierConfigManager.KEY_USE_IP_FOR_CALLING_INDICATOR_BOOL);
+            mDefaultNoCallingConfigLoaded = true;
+        }
         return mDefaultNoCallingConfig;
     }
 }
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 86b5287..c994d7c 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -7842,7 +7842,9 @@
                 incrementalMetrics != null ? incrementalMetrics.getMillisSinceLastReadError()
                         : -1,
                 incrementalMetrics != null ? incrementalMetrics.getLastReadErrorNumber()
-                        : 0
+                        : 0,
+                incrementalMetrics != null ? incrementalMetrics.getTotalDelayedReadsDurationMillis()
+                        : -1
         );
 
         final int relaunchReason = r == null ? RELAUNCH_REASON_NONE
@@ -16176,6 +16178,14 @@
         public PendingIntent getPendingIntentActivityAsApp(
                 int requestCode, @NonNull Intent intent, int flags, Bundle options,
                 String ownerPkg, int ownerUid) {
+            return getPendingIntentActivityAsApp(requestCode, new Intent[] { intent }, flags,
+                    options, ownerPkg, ownerUid);
+        }
+
+        @Override
+        public PendingIntent getPendingIntentActivityAsApp(
+                int requestCode, @NonNull Intent[] intents, int flags, Bundle options,
+                String ownerPkg, int ownerUid) {
             // system callers must explicitly set mutability state
             final boolean flagImmutableSet = (flags & PendingIntent.FLAG_IMMUTABLE) != 0;
             final boolean flagMutableSet = (flags & PendingIntent.FLAG_MUTABLE) != 0;
@@ -16185,15 +16195,21 @@
             }
 
             final Context context = ActivityManagerService.this.mContext;
-            String resolvedType = intent.resolveTypeIfNeeded(context.getContentResolver());
-            intent.migrateExtraStreamToClipData(context);
-            intent.prepareToLeaveProcess(context);
+            final ContentResolver resolver = context.getContentResolver();
+            final int len = intents.length;
+            final String[] resolvedTypes = new String[len];
+            for (int i = 0; i < len; i++) {
+                final Intent intent = intents[i];
+                resolvedTypes[i] = intent.resolveTypeIfNeeded(resolver);
+                intent.migrateExtraStreamToClipData(context);
+                intent.prepareToLeaveProcess(context);
+            }
             IIntentSender target =
                     ActivityManagerService.this.getIntentSenderWithFeatureAsApp(
                             INTENT_SENDER_ACTIVITY, ownerPkg,
                             context.getAttributionTag(), null, null, requestCode,
-                            new Intent[] { intent },
-                            resolvedType != null ? new String[] { resolvedType } : null,
+                            intents,
+                            resolvedTypes,
                             flags, options, UserHandle.getUserId(ownerUid), ownerUid);
             return target != null ? new PendingIntent(target) : null;
         }
diff --git a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
index 508bd06..b2266f6 100644
--- a/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
+++ b/services/core/java/com/android/server/am/ProcessErrorStateRecord.java
@@ -470,7 +470,9 @@
                 incrementalMetrics != null ? incrementalMetrics.getMillisSinceLastReadError()
                         : -1,
                 incrementalMetrics != null ? incrementalMetrics.getLastReadErrorNumber()
-                        : 0);
+                        : 0,
+                incrementalMetrics != null ? incrementalMetrics.getTotalDelayedReadsDurationMillis()
+                        : -1);
         final ProcessRecord parentPr = parentProcess != null
                 ? (ProcessRecord) parentProcess.mOwner : null;
         mService.addErrorToDropBox("anr", mApp, mApp.processName, activityShortComponentName,
diff --git a/services/core/java/com/android/server/app/GameManagerService.java b/services/core/java/com/android/server/app/GameManagerService.java
index 96db1ad..75367d2 100644
--- a/services/core/java/com/android/server/app/GameManagerService.java
+++ b/services/core/java/com/android/server/app/GameManagerService.java
@@ -647,9 +647,9 @@
             final CompatibilityOverrideConfig changeConfig = new CompatibilityOverrideConfig(
                     overrides);
             try {
-                mPlatformCompat.setOverridesOnReleaseBuilds(changeConfig, packageName);
+                mPlatformCompat.putOverridesOnReleaseBuilds(changeConfig, packageName);
             } catch (RemoteException e) {
-                Slog.e(TAG, "Failed to call IPlatformCompat#setOverridesOnReleaseBuilds", e);
+                Slog.e(TAG, "Failed to call IPlatformCompat#putOverridesOnReleaseBuilds", e);
             }
         } finally {
             Binder.restoreCallingIdentity(uid);
@@ -671,9 +671,9 @@
             final CompatibilityOverrideConfig changeConfig = new CompatibilityOverrideConfig(
                     overrides);
             try {
-                mPlatformCompat.setOverridesOnReleaseBuilds(changeConfig, packageName);
+                mPlatformCompat.putOverridesOnReleaseBuilds(changeConfig, packageName);
             } catch (RemoteException e) {
-                Slog.e(TAG, "Failed to call IPlatformCompat#setOverridesOnReleaseBuilds", e);
+                Slog.e(TAG, "Failed to call IPlatformCompat#putOverridesOnReleaseBuilds", e);
             }
         } finally {
             Binder.restoreCallingIdentity(uid);
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 2a1c055..55128be 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -4502,8 +4502,12 @@
                         Slog.i("AppOpsDebug", "tag " + attributionTag + " found in "
                                 + packageName);
                     } else {
+                        ArrayList<String> tagList = new ArrayList<>();
+                        for (int i = 0; i < pkg.getAttributions().size(); i++) {
+                            tagList.add(pkg.getAttributions().get(i).tag);
+                        }
                         Slog.i("AppOpsDebug", "tag " + attributionTag + " missing from "
-                                + packageName);
+                                + packageName + ", tags: " + tagList);
                     }
                 }
 
diff --git a/services/core/java/com/android/server/compat/PlatformCompat.java b/services/core/java/com/android/server/compat/PlatformCompat.java
index eba53fb..2cd68b0 100644
--- a/services/core/java/com/android/server/compat/PlatformCompat.java
+++ b/services/core/java/com/android/server/compat/PlatformCompat.java
@@ -207,15 +207,6 @@
     }
 
     @Override
-    public void setOverridesOnReleaseBuilds(CompatibilityOverrideConfig overrides,
-            String packageName) {
-        // TODO(b/183630314): Unify the permission enforcement with the other setOverrides* methods.
-        checkCompatChangeOverrideOverridablePermission();
-        checkAllCompatOverridesAreOverridable(overrides.overrides.keySet());
-        mCompatConfig.addOverrides(overrides, packageName);
-    }
-
-    @Override
     public void setOverridesForTest(CompatibilityChangeConfig overrides, String packageName) {
         checkCompatChangeOverridePermission();
         Map<Long, PackageOverride> overridesMap = new HashMap<>();
@@ -230,6 +221,15 @@
     }
 
     @Override
+    public void putOverridesOnReleaseBuilds(CompatibilityOverrideConfig overrides,
+            String packageName) {
+        // TODO(b/183630314): Unify the permission enforcement with the other setOverrides* methods.
+        checkCompatChangeOverrideOverridablePermission();
+        checkAllCompatOverridesAreOverridable(overrides.overrides.keySet());
+        mCompatConfig.addOverrides(overrides, packageName);
+    }
+
+    @Override
     public int enableTargetSdkChanges(String packageName, int targetSdkVersion) {
         checkCompatChangeOverridePermission();
         int numChanges =
diff --git a/services/core/java/com/android/server/media/MediaRoute2Provider.java b/services/core/java/com/android/server/media/MediaRoute2Provider.java
index edc9d7c..204ebfc 100644
--- a/services/core/java/com/android/server/media/MediaRoute2Provider.java
+++ b/services/core/java/com/android/server/media/MediaRoute2Provider.java
@@ -47,7 +47,7 @@
         mUniqueId = componentName.flattenToShortString();
     }
 
-    public void setCallback(MediaRoute2ProviderServiceProxy.Callback callback) {
+    public void setCallback(Callback callback) {
         mCallback = callback;
     }
 
diff --git a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
index ab38dca..21f61ca 100644
--- a/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
+++ b/services/core/java/com/android/server/media/MediaRoute2ProviderServiceProxy.java
@@ -16,6 +16,10 @@
 
 package com.android.server.media;
 
+import static android.media.MediaRoute2ProviderService.REQUEST_ID_NONE;
+
+import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
+
 import android.annotation.NonNull;
 import android.content.ComponentName;
 import android.content.Context;
@@ -43,6 +47,7 @@
 import java.io.PrintWriter;
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
 import java.util.Objects;
 
@@ -64,6 +69,7 @@
     private Connection mActiveConnection;
     private boolean mConnectionReady;
 
+    private boolean mIsManagerScanning;
     private RouteDiscoveryPreference mLastDiscoveryPreference = null;
 
     @GuardedBy("mLock")
@@ -86,6 +92,13 @@
         pw.println(prefix + "  mConnectionReady=" + mConnectionReady);
     }
 
+    public void setManagerScanning(boolean managerScanning) {
+        if (mIsManagerScanning != managerScanning) {
+            mIsManagerScanning = managerScanning;
+            updateBinding();
+        }
+    }
+
     @Override
     public void requestCreateSession(long requestId, String packageName, String routeId,
             Bundle sessionHints) {
@@ -209,7 +222,8 @@
             // Bind when there is a discovery preference or an active route session.
             return (mLastDiscoveryPreference != null
                     && !mLastDiscoveryPreference.getPreferredFeatures().isEmpty())
-                    || !getSessionInfos().isEmpty();
+                    || !getSessionInfos().isEmpty()
+                    || mIsManagerScanning;
         }
         return false;
     }
@@ -311,13 +325,12 @@
         }
     }
 
-    private void onProviderStateUpdated(Connection connection,
-            MediaRoute2ProviderInfo providerInfo) {
+    private void onProviderUpdated(Connection connection, MediaRoute2ProviderInfo providerInfo) {
         if (mActiveConnection != connection) {
             return;
         }
         if (DEBUG) {
-            Slog.d(TAG, this + ": State changed ");
+            Slog.d(TAG, this + ": updated");
         }
         setAndNotifyProviderState(providerInfo);
     }
@@ -350,40 +363,44 @@
         mCallback.onSessionCreated(this, requestId, newSession);
     }
 
-    private void onSessionUpdated(Connection connection, RoutingSessionInfo updatedSession) {
+    private int findSessionByIdLocked(RoutingSessionInfo session) {
+        for (int i = 0; i < mSessionInfos.size(); i++) {
+            if (TextUtils.equals(mSessionInfos.get(i).getId(), session.getId())) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+
+    private void onSessionsUpdated(Connection connection, List<RoutingSessionInfo> sessions) {
         if (mActiveConnection != connection) {
             return;
         }
-        if (updatedSession == null) {
-            Slog.w(TAG, "onSessionUpdated: Ignoring null session sent from "
-                    + mComponentName);
-            return;
-        }
 
-        updatedSession = assignProviderIdForSession(updatedSession);
-
-        boolean found = false;
+        int targetIndex = 0;
         synchronized (mLock) {
-            for (int i = 0; i < mSessionInfos.size(); i++) {
-                if (mSessionInfos.get(i).getId().equals(updatedSession.getId())) {
-                    mSessionInfos.set(i, updatedSession);
-                    found = true;
-                    break;
+            for (RoutingSessionInfo session : sessions) {
+                if (session == null) continue;
+                session = assignProviderIdForSession(session);
+
+                int sourceIndex = findSessionByIdLocked(session);
+                if (sourceIndex < 0) {
+                    mSessionInfos.add(targetIndex++, session);
+                    dispatchSessionCreated(REQUEST_ID_NONE, session);
+                } else if (sourceIndex < targetIndex) {
+                    Slog.w(TAG, "Ignoring duplicate session ID: " + session.getId());
+                } else {
+                    mSessionInfos.set(sourceIndex, session);
+                    Collections.swap(mSessionInfos, sourceIndex, targetIndex++);
+                    dispatchSessionUpdated(session);
                 }
             }
-
-            if (!found) {
-                for (RoutingSessionInfo releasingSession : mReleasingSessions) {
-                    if (TextUtils.equals(releasingSession.getId(), updatedSession.getId())) {
-                        return;
-                    }
-                }
-                Slog.w(TAG, "onSessionUpdated: Matching session info not found");
-                return;
+            for (int i = mSessionInfos.size() - 1; i >= targetIndex; i--) {
+                RoutingSessionInfo releasedSession = mSessionInfos.remove(i);
+                dispatchSessionReleased(releasedSession);
             }
         }
-
-        mCallback.onSessionUpdated(this, updatedSession);
     }
 
     private void onSessionReleased(Connection connection, RoutingSessionInfo releaedSession) {
@@ -424,6 +441,21 @@
         mCallback.onSessionReleased(this, releaedSession);
     }
 
+    private void dispatchSessionCreated(long requestId, RoutingSessionInfo session) {
+        mHandler.sendMessage(
+                obtainMessage(mCallback::onSessionCreated, this, requestId, session));
+    }
+
+    private void dispatchSessionUpdated(RoutingSessionInfo session) {
+        mHandler.sendMessage(
+                obtainMessage(mCallback::onSessionUpdated, this, session));
+    }
+
+    private void dispatchSessionReleased(RoutingSessionInfo session) {
+        mHandler.sendMessage(
+                obtainMessage(mCallback::onSessionReleased, this, session));
+    }
+
     private RoutingSessionInfo assignProviderIdForSession(RoutingSessionInfo sessionInfo) {
         return new RoutingSessionInfo.Builder(sessionInfo)
                 .setOwnerPackageName(mComponentName.getPackageName())
@@ -436,7 +468,7 @@
             return;
         }
 
-        if (requestId == MediaRoute2ProviderService.REQUEST_ID_NONE) {
+        if (requestId == REQUEST_ID_NONE) {
             Slog.w(TAG, "onRequestFailed: Ignoring requestId REQUEST_ID_NONE");
             return;
         }
@@ -561,16 +593,16 @@
             mHandler.post(() -> onConnectionDied(Connection.this));
         }
 
-        void postProviderStateUpdated(MediaRoute2ProviderInfo providerInfo) {
-            mHandler.post(() -> onProviderStateUpdated(Connection.this, providerInfo));
+        void postProviderUpdated(MediaRoute2ProviderInfo providerInfo) {
+            mHandler.post(() -> onProviderUpdated(Connection.this, providerInfo));
         }
 
         void postSessionCreated(long requestId, RoutingSessionInfo sessionInfo) {
             mHandler.post(() -> onSessionCreated(Connection.this, requestId, sessionInfo));
         }
 
-        void postSessionUpdated(RoutingSessionInfo sessionInfo) {
-            mHandler.post(() -> onSessionUpdated(Connection.this, sessionInfo));
+        void postSessionsUpdated(List<RoutingSessionInfo> sessionInfo) {
+            mHandler.post(() -> onSessionsUpdated(Connection.this, sessionInfo));
         }
 
         void postSessionReleased(RoutingSessionInfo sessionInfo) {
@@ -595,10 +627,10 @@
         }
 
         @Override
-        public void updateState(MediaRoute2ProviderInfo providerInfo) {
+        public void notifyProviderUpdated(MediaRoute2ProviderInfo providerInfo) {
             Connection connection = mConnectionRef.get();
             if (connection != null) {
-                connection.postProviderStateUpdated(providerInfo);
+                connection.postProviderUpdated(providerInfo);
             }
         }
 
@@ -611,10 +643,10 @@
         }
 
         @Override
-        public void notifySessionUpdated(RoutingSessionInfo sessionInfo) {
+        public void notifySessionsUpdated(List<RoutingSessionInfo> sessionInfo) {
             Connection connection = mConnectionRef.get();
             if (connection != null) {
-                connection.postSessionUpdated(sessionInfo);
+                connection.postSessionsUpdated(sessionInfo);
             }
         }
 
diff --git a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
index 1dbc8a9..168ca55 100644
--- a/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
+++ b/services/core/java/com/android/server/media/MediaRouter2ServiceImpl.java
@@ -2156,6 +2156,8 @@
             List<RouterRecord> routerRecords = getRouterRecords();
             List<ManagerRecord> managerRecords = getManagerRecords();
 
+            boolean shouldBindProviders = false;
+
             if (service.mPowerManager.isInteractive()) {
                 boolean isManagerScanning = managerRecords.stream().anyMatch(manager ->
                         manager.mIsScanning && service.mActivityManager
@@ -2166,6 +2168,7 @@
                     discoveryPreferences = routerRecords.stream()
                             .map(record -> record.mDiscoveryPreference)
                             .collect(Collectors.toList());
+                    shouldBindProviders = true;
                 } else {
                     discoveryPreferences = routerRecords.stream().filter(record ->
                             service.mActivityManager.getPackageImportance(record.mPackageName)
@@ -2175,6 +2178,13 @@
                 }
             }
 
+            for (MediaRoute2Provider provider : mRouteProviders) {
+                if (provider instanceof MediaRoute2ProviderServiceProxy) {
+                    ((MediaRoute2ProviderServiceProxy) provider)
+                            .setManagerScanning(shouldBindProviders);
+                }
+            }
+
             synchronized (service.mLock) {
                 RouteDiscoveryPreference newPreference =
                         new RouteDiscoveryPreference.Builder(discoveryPreferences).build();
diff --git a/services/core/java/com/android/server/pm/LauncherAppsService.java b/services/core/java/com/android/server/pm/LauncherAppsService.java
index b135e88..9370b14 100644
--- a/services/core/java/com/android/server/pm/LauncherAppsService.java
+++ b/services/core/java/com/android/server/pm/LauncherAppsService.java
@@ -698,14 +698,13 @@
             }
             final long ident = Binder.clearCallingIdentity();
             try {
-                return injectCreatePendingIntent(mContext.createPackageContextAsUser(packageName,
-                        0, user), 0 /* requestCode */, intents, FLAG_MUTABLE, opts, user);
-            } catch (PackageManager.NameNotFoundException e) {
-                Slog.e(TAG, "Cannot create pending intent from shortcut " + shortcutId, e);
+                return injectCreatePendingIntent(0 /* requestCode */, intents,
+                        FLAG_MUTABLE, opts, packageName, mPackageManagerInternal.getPackageUid(
+                                packageName, PackageManager.MATCH_DIRECT_BOOT_AUTO,
+                                user.getIdentifier()));
             } finally {
                 Binder.restoreCallingIdentity(ident);
             }
-            return null;
         }
 
         @Override
@@ -812,10 +811,10 @@
         }
 
         @VisibleForTesting
-        PendingIntent injectCreatePendingIntent(Context context, int requestCode,
-                @NonNull Intent[] intents, int flags, Bundle options, UserHandle user) {
-            return PendingIntent.getActivitiesAsUser(context, requestCode, intents, flags, options,
-                    user);
+        PendingIntent injectCreatePendingIntent(int requestCode, @NonNull Intent[] intents,
+                int flags, Bundle options, String ownerPackage, int ownerUserId) {
+            return mActivityManagerInternal.getPendingIntentActivityAsApp(requestCode, intents,
+                    flags, options, ownerPackage, ownerUserId);
         }
 
         @Override
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index d58a6aa..c812fc8 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -22340,7 +22340,7 @@
 
         UserManagerInternal umInternal = mInjector.getUserManagerInternal();
         final int flags;
-        if (umInternal.isUserUnlockingOrUnlocked(userId)) {
+        if (StorageManager.isUserKeyUnlocked(userId)) {
             flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
         } else if (umInternal.isUserRunning(userId)) {
             flags = StorageManager.FLAG_STORAGE_DE;
@@ -25246,7 +25246,7 @@
         UserManagerInternal umInternal = mInjector.getUserManagerInternal();
         for (UserInfo user : mUserManager.getUsers(false /* includeDying */)) {
             final int flags;
-            if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
+            if (StorageManager.isUserKeyUnlocked(user.id)) {
                 flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
             } else if (umInternal.isUserRunning(user.id)) {
                 flags = StorageManager.FLAG_STORAGE_DE;
@@ -25586,7 +25586,7 @@
         StorageManagerInternal smInternal = mInjector.getLocalService(StorageManagerInternal.class);
         for (UserInfo user : mUserManager.getUsers(false /*excludeDying*/)) {
             final int flags;
-            if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
+            if (StorageManager.isUserKeyUnlocked(user.id)) {
                 flags = StorageManager.FLAG_STORAGE_DE | StorageManager.FLAG_STORAGE_CE;
             } else if (umInternal.isUserRunning(user.id)) {
                 flags = StorageManager.FLAG_STORAGE_DE;
@@ -25600,7 +25600,7 @@
                     // Note: this code block is executed with the Installer lock
                     // already held, since it's invoked as a side-effect of
                     // executeBatchLI()
-                    if (umInternal.isUserUnlockingOrUnlocked(user.id)) {
+                    if (StorageManager.isUserKeyUnlocked(user.id)) {
                         // Prepare app data on external storage; currently this is used to
                         // setup any OBB dirs that were created by the installer correctly.
                         int uid = UserHandle.getUid(user.id, UserHandle.getAppId(pkg.getUid()));
diff --git a/services/core/java/com/android/server/policy/AppOpsPolicy.java b/services/core/java/com/android/server/policy/AppOpsPolicy.java
index a6c93de..70b5c62 100644
--- a/services/core/java/com/android/server/policy/AppOpsPolicy.java
+++ b/services/core/java/com/android/server/policy/AppOpsPolicy.java
@@ -64,6 +64,11 @@
             "android:activity_recognition_allow_listed_tags";
     private static final String ACTIVITY_RECOGNITION_TAGS_SEPARATOR = ";";
 
+    private static ArraySet<String> sExpectedTags = new ArraySet<>(new String[] {
+            "awareness_provider", "activity_recognition_provider", "network_location_provider",
+            "network_location_calibration", "fused_location_provider", "geofencer_provider"});
+
+
     @NonNull
     private final Object mLock = new Object();
 
@@ -222,8 +227,14 @@
         if (resolvedCode != code) {
             if (isDatasourceAttributionTag(uid, packageName, attributionTag,
                     mLocationTags)) {
+                if (packageName.equals("com.google.android.gms")
+                        && !sExpectedTags.contains(attributionTag)) {
+                    Log.i("AppOpsDebugRemapping", "remapping " + packageName + " location "
+                            + "for tag " + attributionTag);
+                }
                 return resolvedCode;
-            } else if (packageName.equals("com.google.android.gms")) {
+            } else if (packageName.equals("com.google.android.gms")
+                    && sExpectedTags.contains(attributionTag)) {
                 Log.i("AppOpsDebugRemapping", "NOT remapping " + packageName + " code "
                         + code + " for tag " + attributionTag);
             }
@@ -232,10 +243,14 @@
             if (resolvedCode != code) {
                 if (isDatasourceAttributionTag(uid, packageName, attributionTag,
                         mActivityRecognitionTags)) {
-                    Log.i("AppOpsDebugRemapping", "remapping " + packageName + " code "
-                            + code + " to " + resolvedCode + " for tag " + attributionTag);
+                    if (packageName.equals("com.google.android.gms")
+                            && !sExpectedTags.contains(attributionTag)) {
+                        Log.i("AppOpsDebugRemapping", "remapping " + packageName + " "
+                                + "activity recognition for tag " + attributionTag);
+                    }
                     return resolvedCode;
-                } else if (packageName.equals("com.google.android.gms")) {
+                } else if (packageName.equals("com.google.android.gms")
+                        && sExpectedTags.contains(attributionTag)) {
                     Log.i("AppOpsDebugRemapping", "NOT remapping " + packageName
                             + " code " + code + " for tag " + attributionTag);
                 }
@@ -351,13 +366,15 @@
         if (appIdTags != null) {
             final ArraySet<String> packageTags = appIdTags.get(packageName);
             if (packageTags != null && packageTags.contains(attributionTag)) {
-                if (packageName.equals("com.google.android.gms")) {
+                if (packageName.equals("com.google.android.gms")
+                        && !sExpectedTags.contains(attributionTag)) {
                     Log.i("AppOpsDebugRemapping", packageName + " tag "
                             + attributionTag + " in " + packageTags);
                 }
                 return true;
             }
-            if (packageName.equals("com.google.android.gms")) {
+            if (packageName.equals("com.google.android.gms")
+                    && sExpectedTags.contains(attributionTag)) {
                 Log.i("AppOpsDebugRemapping", packageName + " tag " + attributionTag
                         + " NOT in " + packageTags);
             }
diff --git a/services/core/java/com/android/server/wm/PinnedTaskController.java b/services/core/java/com/android/server/wm/PinnedTaskController.java
index 7b4b23e..31e2ede 100644
--- a/services/core/java/com/android/server/wm/PinnedTaskController.java
+++ b/services/core/java/com/android/server/wm/PinnedTaskController.java
@@ -268,7 +268,9 @@
                 matrix.postRotate(90);
             }
             matrix.postTranslate(dx, dy);
-            t.setMatrix(pinnedTask.getSurfaceControl(), matrix, new float[9]);
+            final SurfaceControl leash = pinnedTask.getSurfaceControl();
+            t.setMatrix(leash, matrix, new float[9])
+                    .setCornerRadius(leash, pipTx.mCornerRadius);
             Slog.i(TAG, "Seamless rotation PiP tx=" + pipTx + " pos=" + dx + "," + dy);
             return;
         }
diff --git a/services/core/jni/stats/SurfaceFlingerPuller.cpp b/services/core/jni/stats/SurfaceFlingerPuller.cpp
index 0e28da7..8873673 100644
--- a/services/core/jni/stats/SurfaceFlingerPuller.cpp
+++ b/services/core/jni/stats/SurfaceFlingerPuller.cpp
@@ -158,7 +158,8 @@
                                       atom.total_jank_frames_sf_prediction_error(),
                                       atom.total_jank_frames_app_buffer_stuffing(),
                                       atom.display_refresh_rate_bucket(), atom.render_rate_bucket(),
-                                      frameRateVote.value(), appDeadlineMisses.value());
+                                      frameRateVote.value(), appDeadlineMisses.value(),
+                                      atom.game_mode());
     }
     return AStatsManager_PULL_SUCCESS;
 }
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java b/services/tests/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java
index 755795d..3bcbcbdb 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/AppSearchImplPlatformTest.java
@@ -25,11 +25,18 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.annotation.NonNull;
 import android.app.appsearch.AppSearchSchema;
 import android.app.appsearch.PackageIdentifier;
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.pm.PackageManager;
+import android.os.UserHandle;
+import android.util.ArrayMap;
 
 import androidx.test.core.app.ApplicationProvider;
 
@@ -43,13 +50,15 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
+import org.mockito.Mockito;
 
 import java.util.Collections;
+import java.util.Map;
 
 /** This tests AppSearchImpl when it's running with a platform-backed VisibilityStore. */
 public class AppSearchImplPlatformTest {
     @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
-    private MockPackageManager mMockPackageManager = new MockPackageManager();
+    private final Map<UserHandle, PackageManager> mMockPackageManagers = new ArrayMap<>();
     private Context mContext;
     private AppSearchImpl mAppSearchImpl;
     private int mGlobalQuerierUid;
@@ -57,20 +66,28 @@
     @Before
     public void setUp() throws Exception {
         Context context = ApplicationProvider.getApplicationContext();
-        mContext =
-                new ContextWrapper(context) {
+        mContext = new ContextWrapper(context) {
+            @Override
+            public Context createContextAsUser(UserHandle user, int flags) {
+                return new ContextWrapper(super.createContextAsUser(user, flags)) {
                     @Override
                     public PackageManager getPackageManager() {
-                        return mMockPackageManager.getMockPackageManager();
+                        return getMockPackageManager(user);
                     }
                 };
+            }
+
+            @Override
+            public PackageManager getPackageManager() {
+                return createContextAsUser(getUser(), /*flags=*/ 0).getPackageManager();
+            }
+        };
 
         // Give ourselves global query permissions
         mAppSearchImpl =
                 AppSearchImpl.create(
                         mTemporaryFolder.newFolder(),
                         mContext,
-                        mContext.getUserId(),
                         /*logger=*/ null);
 
         mGlobalQuerierUid =
@@ -85,14 +102,19 @@
         int uidFoo = 1;
 
         // Make sure foo package will pass package manager checks.
-        mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
-        mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+        PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+        when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+                .thenReturn(uidFoo);
+        when(mockPackageManager.hasSigningCertificate(
+                packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+                .thenReturn(true);
 
         // Make sure we have global query privileges and "foo" doesn't
-        mMockPackageManager.mockCheckPermission(
-                READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName(), PERMISSION_GRANTED);
-        mMockPackageManager.mockCheckPermission(
-                READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo, PERMISSION_DENIED);
+        when(mockPackageManager.checkPermission(
+                READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
+                .thenReturn(PERMISSION_GRANTED);
+        when(mockPackageManager.checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo))
+                .thenReturn(PERMISSION_DENIED);
 
         // Set schema1
         String prefix = PrefixUtil.createPrefix("package", "database");
@@ -145,19 +167,16 @@
                 /*schemaVersion=*/ 0);
 
         // Check that "schema1" still has the same visibility settings
-        SystemUtil.runWithShellPermissionIdentity(
-                () -> {
-                    assertThat(
-                                    mAppSearchImpl
-                                            .getVisibilityStoreLocked()
-                                            .isSchemaSearchableByCaller(
-                                                    "package",
-                                                    "database",
-                                                    prefix + "schema1",
-                                                    mContext.getPackageName(),
-                                                    mGlobalQuerierUid))
-                            .isFalse();
-                },
+        SystemUtil.runWithShellPermissionIdentity(() -> assertThat(
+                mAppSearchImpl
+                        .getVisibilityStoreLocked()
+                        .isSchemaSearchableByCaller(
+                                "package",
+                                "database",
+                                prefix + "schema1",
+                                mContext.getPackageName(),
+                                mGlobalQuerierUid))
+                        .isFalse(),
                 READ_GLOBAL_APP_SEARCH_DATA);
 
         assertThat(
@@ -172,19 +191,16 @@
                 .isTrue();
 
         // "schema2" has default visibility settings
-        SystemUtil.runWithShellPermissionIdentity(
-                () -> {
-                    assertThat(
-                                    mAppSearchImpl
-                                            .getVisibilityStoreLocked()
-                                            .isSchemaSearchableByCaller(
-                                                    "package",
-                                                    "database",
-                                                    prefix + "schema2",
-                                                    mContext.getPackageName(),
-                                                    mGlobalQuerierUid))
-                            .isTrue();
-                },
+        SystemUtil.runWithShellPermissionIdentity(() -> assertThat(
+                mAppSearchImpl
+                        .getVisibilityStoreLocked()
+                        .isSchemaSearchableByCaller(
+                                "package",
+                                "database",
+                                prefix + "schema2",
+                                mContext.getPackageName(),
+                                mGlobalQuerierUid))
+                        .isTrue(),
                 READ_GLOBAL_APP_SEARCH_DATA);
 
         assertThat(
@@ -207,14 +223,19 @@
         int uidFoo = 1;
 
         // Make sure foo package will pass package manager checks.
-        mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
-        mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+        PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+        when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+                .thenReturn(uidFoo);
+        when(mockPackageManager.hasSigningCertificate(
+                packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+                .thenReturn(true);
 
         // Make sure we have global query privileges and "foo" doesn't
-        mMockPackageManager.mockCheckPermission(
-                READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName(), PERMISSION_GRANTED);
-        mMockPackageManager.mockCheckPermission(
-                READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo, PERMISSION_DENIED);
+        when(mockPackageManager.checkPermission(
+                READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
+                .thenReturn(PERMISSION_GRANTED);
+        when(mockPackageManager.checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo))
+                .thenReturn(PERMISSION_DENIED);
 
         String prefix = PrefixUtil.createPrefix("package", "database");
         mAppSearchImpl.setSchema(
@@ -320,8 +341,10 @@
     @Test
     public void testSetSchema_defaultPlatformVisible() throws Exception {
         // Make sure we have global query privileges
-        mMockPackageManager.mockCheckPermission(
-                READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName(), PERMISSION_GRANTED);
+        PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+        when(mockPackageManager.checkPermission(
+                READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
+                .thenReturn(PERMISSION_GRANTED);
 
         String prefix = PrefixUtil.createPrefix("package", "database");
         mAppSearchImpl.setSchema(
@@ -348,8 +371,10 @@
     @Test
     public void testSetSchema_platformHidden() throws Exception {
         // Make sure we have global query privileges
-        mMockPackageManager.mockCheckPermission(
-                READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName(), PERMISSION_GRANTED);
+        PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+        when(mockPackageManager.checkPermission(
+                READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
+                .thenReturn(PERMISSION_GRANTED);
 
         String prefix = PrefixUtil.createPrefix("package", "database");
         mAppSearchImpl.setSchema(
@@ -378,8 +403,9 @@
         String packageName = "com.package";
 
         // Make sure package doesn't global query privileges
-        mMockPackageManager.mockCheckPermission(
-                READ_GLOBAL_APP_SEARCH_DATA, packageName, PERMISSION_DENIED);
+        PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+        when(mockPackageManager.checkPermission(
+                READ_GLOBAL_APP_SEARCH_DATA, packageName)).thenReturn(PERMISSION_DENIED);
 
         String prefix = PrefixUtil.createPrefix("package", "database");
         mAppSearchImpl.setSchema(
@@ -410,12 +436,16 @@
         int uidFoo = 1;
 
         // Make sure foo package will pass package manager checks.
-        mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
-        mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+        PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+        when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+                .thenReturn(uidFoo);
+        when(mockPackageManager.hasSigningCertificate(
+                packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+                .thenReturn(true);
 
         // Make sure foo doesn't have global query privileges
-        mMockPackageManager.mockCheckPermission(
-                READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo, PERMISSION_DENIED);
+        when(mockPackageManager.checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo))
+                .thenReturn(PERMISSION_DENIED);
 
         String prefix = PrefixUtil.createPrefix("package", "database");
         mAppSearchImpl.setSchema(
@@ -439,4 +469,14 @@
                                         uidFoo))
                 .isTrue();
     }
+
+    @NonNull
+    private PackageManager getMockPackageManager(@NonNull UserHandle user) {
+        PackageManager pm = mMockPackageManagers.get(user);
+        if (pm == null) {
+            pm = Mockito.mock(PackageManager.class);
+            mMockPackageManagers.put(user, pm);
+        }
+        return pm;
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/MockPackageManager.java b/services/tests/servicestests/src/com/android/server/appsearch/MockPackageManager.java
deleted file mode 100644
index 60e1a8f..0000000
--- a/services/tests/servicestests/src/com/android/server/appsearch/MockPackageManager.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2021 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-// TODO(b/169883602): This is purposely a different package from the path so that AppSearchImplTest
-// can use it without an extra import. This should be moved into a proper package once
-// AppSearchImpl-VisibilityStore's dependencies are refactored.
-package com.android.server.appsearch.external.localstorage;
-
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.when;
-
-import android.annotation.NonNull;
-import android.annotation.UserIdInt;
-import android.content.pm.PackageManager;
-
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-
-/** Mock to help test package name, UID, and certificate verification. */
-public class MockPackageManager {
-
-    @Mock private PackageManager mMockPackageManager;
-
-    public MockPackageManager() {
-        MockitoAnnotations.initMocks(this);
-    }
-
-    @NonNull
-    public PackageManager getMockPackageManager() {
-        return mMockPackageManager;
-    }
-
-    /** Mock a checkPermission call. */
-    public void mockCheckPermission(String permission, String packageName, int permissionResult) {
-        when(mMockPackageManager.checkPermission(permission, packageName))
-                .thenReturn(permissionResult);
-    }
-
-    /** Mock a NameNotFoundException if the package name isn't installed. */
-    public void mockThrowsNameNotFoundException(String packageName) {
-        try {
-            when(mMockPackageManager.getPackageUidAsUser(eq(packageName), /*userId=*/ anyInt()))
-                    .thenThrow(new PackageManager.NameNotFoundException());
-            when(mMockPackageManager.getPackageUidAsUser(
-                            eq(packageName), /*flags=*/ anyInt(), /*userId=*/ anyInt()))
-                    .thenThrow(new PackageManager.NameNotFoundException());
-        } catch (PackageManager.NameNotFoundException e) {
-            // Shouldn't ever happen since we're mocking the exception
-            e.printStackTrace();
-        }
-    }
-
-    /** Mocks that {@code uid} contains the {@code packageName} */
-    public void mockGetPackageUidAsUser(String packageName, @UserIdInt int callerUserId, int uid) {
-        try {
-            when(mMockPackageManager.getPackageUidAsUser(eq(packageName), eq(callerUserId)))
-                    .thenReturn(uid);
-            when(mMockPackageManager.getPackageUidAsUser(
-                            eq(packageName), /*flags=*/ anyInt(), eq(callerUserId)))
-                    .thenReturn(uid);
-        } catch (PackageManager.NameNotFoundException e) {
-            // Shouldn't ever happen since we're mocking the method.
-            e.printStackTrace();
-        }
-    }
-
-    /** Mocks that {@code packageName} has been signed with {@code sha256Cert}. */
-    public void mockAddSigningCertificate(String packageName, byte[] sha256Cert) {
-        when(mMockPackageManager.hasSigningCertificate(
-                        packageName, sha256Cert, PackageManager.CERT_INPUT_SHA256))
-                .thenReturn(true);
-    }
-
-    /** Mocks that {@code packageName} has NOT been signed with {@code sha256Cert}. */
-    public void mockRemoveSigningCertificate(String packageName, byte[] sha256Cert) {
-        when(mMockPackageManager.hasSigningCertificate(
-                        packageName, sha256Cert, PackageManager.CERT_INPUT_SHA256))
-                .thenReturn(false);
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java b/services/tests/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java
index d9cfc54..6ac4d13 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/VisibilityStoreTest.java
@@ -25,10 +25,17 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.when;
+
+import android.annotation.NonNull;
 import android.app.appsearch.PackageIdentifier;
 import android.content.Context;
 import android.content.ContextWrapper;
 import android.content.pm.PackageManager;
+import android.os.UserHandle;
+import android.util.ArrayMap;
 
 import androidx.test.core.app.ApplicationProvider;
 
@@ -43,39 +50,47 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
+import org.mockito.Mockito;
 
 import java.util.Collections;
+import java.util.Map;
 
 public class VisibilityStoreTest {
-
     @Rule public TemporaryFolder mTemporaryFolder = new TemporaryFolder();
-    private MockPackageManager mMockPackageManager = new MockPackageManager();
+    private final Map<UserHandle, PackageManager> mMockPackageManagers = new ArrayMap<>();
     private Context mContext;
-    private AppSearchImpl mAppSearchImpl;
     private VisibilityStore mVisibilityStore;
     private int mUid;
 
     @Before
     public void setUp() throws Exception {
         Context context = ApplicationProvider.getApplicationContext();
-        mContext =
-                new ContextWrapper(context) {
+        mContext = new ContextWrapper(context) {
+            @Override
+            public Context createContextAsUser(UserHandle user, int flags) {
+                return new ContextWrapper(super.createContextAsUser(user, flags)) {
                     @Override
                     public PackageManager getPackageManager() {
-                        return mMockPackageManager.getMockPackageManager();
+                        return getMockPackageManager(user);
                     }
                 };
+            }
+
+            @Override
+            public PackageManager getPackageManager() {
+                return createContextAsUser(getUser(), /*flags=*/ 0).getPackageManager();
+            }
+        };
 
         // Give ourselves global query permissions
-        mAppSearchImpl =
+        AppSearchImpl appSearchImpl =
                 AppSearchImpl.create(
                         mTemporaryFolder.newFolder(),
                         mContext,
-                        mContext.getUserId(),
                         /*logger=*/ null);
 
         mUid = mContext.getPackageManager().getPackageUid(mContext.getPackageName(), /*flags=*/ 0);
-        mVisibilityStore = mAppSearchImpl.getVisibilityStoreLocked();
+        mVisibilityStore = appSearchImpl.getVisibilityStoreLocked();
     }
 
     /**
@@ -103,8 +118,10 @@
     @Test
     public void testSetVisibility_platformSurfaceable() throws Exception {
         // Make sure we have global query privileges
-        mMockPackageManager.mockCheckPermission(
-                READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName(), PERMISSION_GRANTED);
+        PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+        when(mockPackageManager
+                .checkPermission(READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
+                .thenReturn(PERMISSION_GRANTED);
 
         mVisibilityStore.setVisibility(
                 "package",
@@ -210,10 +227,13 @@
         int uidNotFooOrBar = 3;
 
         // Make sure none of them have global query privileges
-        mMockPackageManager.mockCheckPermission(
-                READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo, PERMISSION_DENIED);
-        mMockPackageManager.mockCheckPermission(
-                READ_GLOBAL_APP_SEARCH_DATA, packageNameBar, PERMISSION_DENIED);
+        PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+        when(mockPackageManager
+                .checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo))
+                .thenReturn(PERMISSION_DENIED);
+        when(mockPackageManager
+                .checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameBar))
+                .thenReturn(PERMISSION_DENIED);
 
         // By default, a schema isn't package accessible.
         assertThat(
@@ -237,32 +257,43 @@
                         ImmutableList.of(new PackageIdentifier(packageNameBar, sha256CertBar))));
 
         // Should fail if PackageManager doesn't see that it has the proper certificate
-        mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
-        mMockPackageManager.mockRemoveSigningCertificate(packageNameFoo, sha256CertFoo);
+        when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+                .thenReturn(uidFoo);
+        when(mockPackageManager.hasSigningCertificate(
+                packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+                .thenReturn(false);
         assertThat(
                         mVisibilityStore.isSchemaSearchableByCaller(
                                 "package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
                 .isFalse();
 
         // Should fail if PackageManager doesn't think the package belongs to the uid
-        mMockPackageManager.mockGetPackageUidAsUser(
-                packageNameFoo, mContext.getUserId(), uidNotFooOrBar);
-        mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+        when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+                .thenReturn(uidNotFooOrBar);
+        when(mockPackageManager.hasSigningCertificate(
+                packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+                .thenReturn(true);
         assertThat(
                         mVisibilityStore.isSchemaSearchableByCaller(
                                 "package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
                 .isFalse();
 
         // But if uid and certificate match, then we should have access
-        mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
-        mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+        when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+                .thenReturn(uidFoo);
+        when(mockPackageManager.hasSigningCertificate(
+                packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+                .thenReturn(true);
         assertThat(
                         mVisibilityStore.isSchemaSearchableByCaller(
                                 "package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
                 .isTrue();
 
-        mMockPackageManager.mockGetPackageUidAsUser(packageNameBar, mContext.getUserId(), uidBar);
-        mMockPackageManager.mockAddSigningCertificate(packageNameBar, sha256CertBar);
+        when(mockPackageManager.getPackageUid(eq(packageNameBar), /*flags=*/ anyInt()))
+                .thenReturn(uidBar);
+        when(mockPackageManager.hasSigningCertificate(
+                packageNameBar, sha256CertBar, PackageManager.CERT_INPUT_SHA256))
+                .thenReturn(true);
         assertThat(
                         mVisibilityStore.isSchemaSearchableByCaller(
                                 "package", "database", "prefix/schemaBar", packageNameBar, uidBar))
@@ -278,15 +309,21 @@
                         "prefix/schemaFoo",
                         ImmutableList.of(new PackageIdentifier(packageNameFoo, sha256CertFoo))));
 
-        mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
-        mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+        when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+                .thenReturn(uidFoo);
+        when(mockPackageManager.hasSigningCertificate(
+                packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+                .thenReturn(true);
         assertThat(
                         mVisibilityStore.isSchemaSearchableByCaller(
                                 "package", "database", "prefix/schemaFoo", packageNameFoo, uidFoo))
                 .isTrue();
 
-        mMockPackageManager.mockGetPackageUidAsUser(packageNameBar, mContext.getUserId(), uidBar);
-        mMockPackageManager.mockAddSigningCertificate(packageNameBar, sha256CertBar);
+        when(mockPackageManager.getPackageUid(eq(packageNameBar), /*flags=*/ anyInt()))
+                .thenReturn(uidBar);
+        when(mockPackageManager.hasSigningCertificate(
+                packageNameBar, sha256CertBar, PackageManager.CERT_INPUT_SHA256))
+                .thenReturn(true);
         assertThat(
                         mVisibilityStore.isSchemaSearchableByCaller(
                                 "package", "database", "prefix/schemaBar", packageNameBar, uidBar))
@@ -302,11 +339,13 @@
         int uidFoo = 1;
 
         // Pretend we can't find the Foo package.
-        mMockPackageManager.mockThrowsNameNotFoundException(packageNameFoo);
+        PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+        when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+                .thenThrow(new PackageManager.NameNotFoundException());
 
         // Make sure "foo" doesn't have global query privileges
-        mMockPackageManager.mockCheckPermission(
-                READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo, PERMISSION_DENIED);
+        when(mockPackageManager.checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo))
+                .thenReturn(PERMISSION_DENIED);
 
         // Grant package access
         mVisibilityStore.setVisibility(
@@ -332,10 +371,12 @@
         int uidFoo = 1;
 
         // Set it up such that the test package has global query privileges, but "foo" doesn't.
-        mMockPackageManager.mockCheckPermission(
-                READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName(), PERMISSION_GRANTED);
-        mMockPackageManager.mockCheckPermission(
-                READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo, PERMISSION_DENIED);
+        PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+        when(mockPackageManager.checkPermission(
+                READ_GLOBAL_APP_SEARCH_DATA, mContext.getPackageName()))
+                .thenReturn(PERMISSION_GRANTED);
+        when(mockPackageManager.checkPermission(READ_GLOBAL_APP_SEARCH_DATA, packageNameFoo))
+                .thenReturn(PERMISSION_DENIED);
 
         mVisibilityStore.setVisibility(
                 /*packageName=*/ "",
@@ -354,8 +395,11 @@
                                 mUid))
                 .isTrue();
 
-        mMockPackageManager.mockGetPackageUidAsUser(packageNameFoo, mContext.getUserId(), uidFoo);
-        mMockPackageManager.mockAddSigningCertificate(packageNameFoo, sha256CertFoo);
+        when(mockPackageManager.getPackageUid(eq(packageNameFoo), /*flags=*/ anyInt()))
+                .thenReturn(uidFoo);
+        when(mockPackageManager.hasSigningCertificate(
+                packageNameFoo, sha256CertFoo, PackageManager.CERT_INPUT_SHA256))
+                .thenReturn(true);
         assertThat(
                         mVisibilityStore.isSchemaSearchableByCaller(
                                 /*packageName=*/ "",
@@ -365,4 +409,14 @@
                                 uidFoo))
                 .isTrue();
     }
+
+    @NonNull
+    private PackageManager getMockPackageManager(@NonNull UserHandle user) {
+        PackageManager pm = mMockPackageManagers.get(user);
+        if (pm == null) {
+            pm = Mockito.mock(PackageManager.class);
+            mMockPackageManagers.put(user, pm);
+        }
+        return pm;
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
index 031532b..5a8c44c 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchImplTest.java
@@ -86,7 +86,6 @@
                 AppSearchImpl.create(
                         mTemporaryFolder.newFolder(),
                         context,
-                        VisibilityStore.NO_OP_USER_ID,
                         /*logger=*/ null);
     }
 
@@ -494,9 +493,7 @@
         // Setup the index
         Context context = ApplicationProvider.getApplicationContext();
         File appsearchDir = mTemporaryFolder.newFolder();
-        AppSearchImpl appSearchImpl =
-                AppSearchImpl.create(
-                        appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+        AppSearchImpl appSearchImpl = AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
 
         // Insert schema
         List<AppSearchSchema> schemas =
@@ -557,9 +554,7 @@
 
         // Initialize AppSearchImpl. This should cause a reset.
         appSearchImpl.close();
-        appSearchImpl =
-                AppSearchImpl.create(
-                        appsearchDir, context, VisibilityStore.NO_OP_USER_ID, testLogger);
+        appSearchImpl = AppSearchImpl.create(appsearchDir, context, testLogger);
 
         // Check recovery state
         InitializeStats initStats = testLogger.mInitializeStats;
@@ -1688,7 +1683,6 @@
                 AppSearchImpl.create(
                         mTemporaryFolder.newFolder(),
                         context,
-                        VisibilityStore.NO_OP_USER_ID,
                         /*logger=*/ null);
 
         // Initial check that we could do something at first.
@@ -1836,9 +1830,7 @@
         // Setup the index
         Context context = ApplicationProvider.getApplicationContext();
         File appsearchDir = mTemporaryFolder.newFolder();
-        AppSearchImpl appSearchImpl =
-                AppSearchImpl.create(
-                        appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+        AppSearchImpl appSearchImpl = AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
 
         List<AppSearchSchema> schemas =
                 Collections.singletonList(new AppSearchSchema.Builder("type").build());
@@ -1864,8 +1856,7 @@
 
         // That document should be visible even from another instance.
         AppSearchImpl appSearchImpl2 =
-                AppSearchImpl.create(
-                        appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+                AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
         getResult =
                 appSearchImpl2.getDocument(
                         "package", "database", "namespace1", "id1", Collections.emptyMap());
@@ -1877,9 +1868,7 @@
         // Setup the index
         Context context = ApplicationProvider.getApplicationContext();
         File appsearchDir = mTemporaryFolder.newFolder();
-        AppSearchImpl appSearchImpl =
-                AppSearchImpl.create(
-                        appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+        AppSearchImpl appSearchImpl = AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
 
         List<AppSearchSchema> schemas =
                 Collections.singletonList(new AppSearchSchema.Builder("type").build());
@@ -1929,8 +1918,7 @@
 
         // Only the second document should be retrievable from another instance.
         AppSearchImpl appSearchImpl2 =
-                AppSearchImpl.create(
-                        appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+                AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
         expectThrows(
                 AppSearchException.class,
                 () ->
@@ -1951,9 +1939,7 @@
         // Setup the index
         Context context = ApplicationProvider.getApplicationContext();
         File appsearchDir = mTemporaryFolder.newFolder();
-        AppSearchImpl appSearchImpl =
-                AppSearchImpl.create(
-                        appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+        AppSearchImpl appSearchImpl = AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
 
         List<AppSearchSchema> schemas =
                 Collections.singletonList(new AppSearchSchema.Builder("type").build());
@@ -2011,8 +1997,7 @@
 
         // Only the second document should be retrievable from another instance.
         AppSearchImpl appSearchImpl2 =
-                AppSearchImpl.create(
-                        appsearchDir, context, VisibilityStore.NO_OP_USER_ID, /*logger=*/ null);
+                AppSearchImpl.create(appsearchDir, context, /*logger=*/ null);
         expectThrows(
                 AppSearchException.class,
                 () ->
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java
index d1ca759..f0a6ef1 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/external/localstorage/AppSearchLoggerTest.java
@@ -40,7 +40,6 @@
 import com.android.server.appsearch.proto.QueryStatsProto;
 import com.android.server.appsearch.proto.ScoringSpecProto;
 import com.android.server.appsearch.proto.TermMatchType;
-import com.android.server.appsearch.visibilitystore.VisibilityStore;
 
 import org.junit.Before;
 import org.junit.Rule;
@@ -64,7 +63,6 @@
                 AppSearchImpl.create(
                         mTemporaryFolder.newFolder(),
                         context,
-                        VisibilityStore.NO_OP_USER_ID,
                         /*logger=*/ null);
         mLogger = new TestLogger();
     }
@@ -292,7 +290,6 @@
                 AppSearchImpl.create(
                         mTemporaryFolder.newFolder(),
                         context,
-                        VisibilityStore.NO_OP_USER_ID,
                         mLogger);
 
         InitializeStats iStats = mLogger.mInitializeStats;
diff --git a/services/tests/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java b/services/tests/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java
index 734f05a..7e1639e 100644
--- a/services/tests/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java
+++ b/services/tests/servicestests/src/com/android/server/appsearch/stats/PlatformLoggerTest.java
@@ -22,6 +22,7 @@
 import static org.mockito.Mockito.eq;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
 
 import android.annotation.NonNull;
 import android.content.Context;
@@ -29,46 +30,46 @@
 import android.content.pm.PackageManager;
 import android.os.SystemClock;
 import android.os.UserHandle;
+import android.util.ArrayMap;
 import android.util.SparseIntArray;
 
 import androidx.test.core.app.ApplicationProvider;
 
-import com.android.server.appsearch.external.localstorage.MockPackageManager;
 import com.android.server.appsearch.external.localstorage.stats.CallStats;
 
 import org.junit.Before;
 import org.junit.Test;
+import org.mockito.Mockito;
 
 import java.io.UnsupportedEncodingException;
 import java.math.BigInteger;
+import java.nio.charset.StandardCharsets;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
+import java.util.Map;
 
 public class PlatformLoggerTest {
     private static final int TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS = 100;
     private static final int TEST_DEFAULT_SAMPLING_INTERVAL = 10;
     private static final String TEST_PACKAGE_NAME = "packageName";
-    private MockPackageManager mMockPackageManager = new MockPackageManager();
+
+    private final Map<UserHandle, PackageManager> mMockPackageManagers = new ArrayMap<>();
     private Context mContext;
 
     @Before
     public void setUp() throws Exception {
         Context context = ApplicationProvider.getApplicationContext();
-        mContext =
-                new ContextWrapper(context) {
+        mContext = new ContextWrapper(context) {
+            @Override
+            public Context createContextAsUser(UserHandle user, int flags) {
+                return new ContextWrapper(super.createContextAsUser(user, flags)) {
                     @Override
                     public PackageManager getPackageManager() {
-                        return mMockPackageManager.getMockPackageManager();
+                        return getMockPackageManager(user);
                     }
                 };
-    }
-
-    static int calculateHashCodeMd5withBigInteger(@NonNull String str) throws
-            NoSuchAlgorithmException, UnsupportedEncodingException {
-        MessageDigest md = MessageDigest.getInstance("MD5");
-        md.update(str.getBytes(/*charsetName=*/ "UTF-8"));
-        byte[] digest = md.digest();
-        return new BigInteger(digest).intValue();
+            }
+        };
     }
 
     @Test
@@ -294,39 +295,51 @@
                         TEST_MIN_TIME_INTERVAL_BETWEEN_SAMPLES_MILLIS,
                         TEST_DEFAULT_SAMPLING_INTERVAL,
                         /*samplingIntervals=*/ new SparseIntArray()));
-        mMockPackageManager.mockGetPackageUidAsUser(testPackageName, mContext.getUserId(), testUid);
+        PackageManager mockPackageManager = getMockPackageManager(mContext.getUser());
+        when(mockPackageManager.getPackageUid(testPackageName, /*flags=*/0)).thenReturn(testUid);
 
-        //
         // First time, no cache
-        //
         PlatformLogger.ExtraStats extraStats = logger.createExtraStatsLocked(testPackageName,
                 CallStats.CALL_TYPE_PUT_DOCUMENT);
-
-        verify(mMockPackageManager.getMockPackageManager(), times(1)).getPackageUidAsUser(
-                eq(testPackageName), /*userId=*/ anyInt());
+        verify(mockPackageManager, times(1))
+                .getPackageUid(eq(testPackageName), /*flags=*/ anyInt());
         assertThat(extraStats.mPackageUid).isEqualTo(testUid);
 
-        //
         // Second time, we have cache
-        //
         extraStats = logger.createExtraStatsLocked(testPackageName,
                 CallStats.CALL_TYPE_PUT_DOCUMENT);
 
         // Count is still one since we will use the cache
-        verify(mMockPackageManager.getMockPackageManager(), times(1)).getPackageUidAsUser(
-                eq(testPackageName), /*userId=*/ anyInt());
+        verify(mockPackageManager, times(1))
+                .getPackageUid(eq(testPackageName), /*flags=*/ anyInt());
         assertThat(extraStats.mPackageUid).isEqualTo(testUid);
 
-        //
         // Remove the cache and try again
-        //
         assertThat(logger.removeCachedUidForPackage(testPackageName)).isEqualTo(testUid);
         extraStats = logger.createExtraStatsLocked(testPackageName,
                 CallStats.CALL_TYPE_PUT_DOCUMENT);
 
         // count increased by 1 since cache is cleared
-        verify(mMockPackageManager.getMockPackageManager(), times(2)).getPackageUidAsUser(
-                eq(testPackageName), /*userId=*/ anyInt());
+        verify(mockPackageManager, times(2))
+                .getPackageUid(eq(testPackageName), /*flags=*/ anyInt());
         assertThat(extraStats.mPackageUid).isEqualTo(testUid);
     }
+
+    private static int calculateHashCodeMd5withBigInteger(@NonNull String str)
+            throws NoSuchAlgorithmException {
+        MessageDigest md = MessageDigest.getInstance("MD5");
+        md.update(str.getBytes(StandardCharsets.UTF_8));
+        byte[] digest = md.digest();
+        return new BigInteger(digest).intValue();
+    }
+
+    @NonNull
+    private PackageManager getMockPackageManager(@NonNull UserHandle user) {
+        PackageManager pm = mMockPackageManagers.get(user);
+        if (pm == null) {
+            pm = Mockito.mock(PackageManager.class);
+            mMockPackageManagers.put(user, pm);
+        }
+        return pm;
+    }
 }
diff --git a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
index f6baa6bb..7df2dd6 100644
--- a/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/BaseShortcutManagerTest.java
@@ -635,8 +635,8 @@
         }
 
         @Override
-        PendingIntent injectCreatePendingIntent(Context context, int requestCode,
-                @NonNull Intent[] intents, int flags, Bundle options, UserHandle user) {
+        PendingIntent injectCreatePendingIntent(int requestCode, @NonNull Intent[] intents,
+                int flags, Bundle options, String ownerPackage, int ownerUserId) {
             return new PendingIntent(mock(IIntentSender.class));
         }
     }