Merge "[RESTRICT AUTOMERGE] Revert "Persist destroyed staged sessions until they are cleaned up"" into qt-dev
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index a67475b..325a54b 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -1180,27 +1180,18 @@
                     mContext.getUserId());
             if (fd != null) {
                 FileOutputStream fos = null;
-                final Bitmap tmp = BitmapFactory.decodeStream(resources.openRawResource(resid));
+                boolean ok = false;
                 try {
-                    // If the stream can't be decoded, treat it as an invalid input.
-                    if (tmp != null) {
-                        fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
-                        tmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
-                        // The 'close()' is the trigger for any server-side image manipulation,
-                        // so we must do that before waiting for completion.
-                        fos.close();
-                        completion.waitForCompletion();
-                    } else {
-                        throw new IllegalArgumentException(
-                                "Resource 0x" + Integer.toHexString(resid) + " is invalid");
-                    }
+                    fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
+                    copyStreamToWallpaperFile(resources.openRawResource(resid), fos);
+                    // The 'close()' is the trigger for any server-side image manipulation,
+                    // so we must do that before waiting for completion.
+                    fos.close();
+                    completion.waitForCompletion();
                 } finally {
                     // Might be redundant but completion shouldn't wait unless the write
                     // succeeded; this is a fallback if it threw past the close+wait.
                     IoUtils.closeQuietly(fos);
-                    if (tmp != null) {
-                        tmp.recycle();
-                    }
                 }
             }
         } catch (RemoteException e) {
@@ -1442,22 +1433,13 @@
                     result, which, completion, mContext.getUserId());
             if (fd != null) {
                 FileOutputStream fos = null;
-                final Bitmap tmp = BitmapFactory.decodeStream(bitmapData);
                 try {
-                    // If the stream can't be decoded, treat it as an invalid input.
-                    if (tmp != null) {
-                        fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
-                        tmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
-                        fos.close();
-                        completion.waitForCompletion();
-                    } else {
-                        throw new IllegalArgumentException("InputStream is invalid");
-                    }
+                    fos = new ParcelFileDescriptor.AutoCloseOutputStream(fd);
+                    copyStreamToWallpaperFile(bitmapData, fos);
+                    fos.close();
+                    completion.waitForCompletion();
                 } finally {
                     IoUtils.closeQuietly(fos);
-                    if (tmp != null) {
-                        tmp.recycle();
-                    }
                 }
             }
         } catch (RemoteException e) {
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 08527c79..1458705 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -19,6 +19,7 @@
 import static com.android.internal.util.function.pooled.PooledLambda.obtainMessage;
 
 import android.Manifest.permission;
+import android.accounts.Account;
 import android.annotation.CallbackExecutor;
 import android.annotation.ColorInt;
 import android.annotation.IntDef;
@@ -151,6 +152,26 @@
         this(context, service, false);
     }
 
+    /**
+     * Called when a managed profile has been provisioned.
+     *
+     * @throws SecurityException if the caller does not hold
+     * {@link android.Manifest.permission#MANAGE_PROFILE_AND_DEVICE_OWNERS}.
+     * @hide
+     */
+    @RequiresPermission(android.Manifest.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)
+    public void finalizeWorkProfileProvisioning(
+            @NonNull UserHandle managedProfileUser, @Nullable Account migratedAccount) {
+        if (mService == null) {
+            throw new IllegalStateException("Could not find DevicePolicyManagerService");
+        }
+        try {
+            mService.finalizeWorkProfileProvisioning(managedProfileUser, migratedAccount);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
     /** @hide */
     @VisibleForTesting
     protected DevicePolicyManager(Context context, IDevicePolicyManager service,
diff --git a/core/java/android/app/admin/IDevicePolicyManager.aidl b/core/java/android/app/admin/IDevicePolicyManager.aidl
index 2b96419..bf24580 100644
--- a/core/java/android/app/admin/IDevicePolicyManager.aidl
+++ b/core/java/android/app/admin/IDevicePolicyManager.aidl
@@ -17,6 +17,7 @@
 
 package android.app.admin;
 
+import android.accounts.Account;
 import android.app.admin.NetworkEvent;
 import android.app.IApplicationThread;
 import android.app.IServiceConnection;
@@ -87,6 +88,8 @@
     int getCurrentFailedPasswordAttempts(int userHandle, boolean parent);
     int getProfileWithMinimumFailedPasswordsForWipe(int userHandle, boolean parent);
 
+    void finalizeWorkProfileProvisioning(in UserHandle managedProfileUser, in Account migratedAccount);
+
     void setMaximumFailedPasswordsForWipe(in ComponentName admin, int num, boolean parent);
     int getMaximumFailedPasswordsForWipe(in ComponentName admin, int userHandle, boolean parent);
 
diff --git a/core/java/android/content/AbstractThreadedSyncAdapter.java b/core/java/android/content/AbstractThreadedSyncAdapter.java
index a086a30..da4ecdd 100644
--- a/core/java/android/content/AbstractThreadedSyncAdapter.java
+++ b/core/java/android/content/AbstractThreadedSyncAdapter.java
@@ -21,6 +21,7 @@
 import android.accounts.Account;
 import android.annotation.MainThread;
 import android.annotation.NonNull;
+import android.os.Binder;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
@@ -171,8 +172,20 @@
     }
 
     private class ISyncAdapterImpl extends ISyncAdapter.Stub {
+        private boolean isCallerSystem() {
+            final long callingUid = Binder.getCallingUid();
+            if (callingUid != Process.SYSTEM_UID) {
+                android.util.EventLog.writeEvent(0x534e4554, "203229608", -1, "");
+                return false;
+            }
+            return true;
+        }
+
         @Override
         public void onUnsyncableAccount(ISyncAdapterUnsyncableAccountCallback cb) {
+            if (!isCallerSystem()) {
+                return;
+            }
             Handler.getMain().sendMessage(obtainMessage(
                     AbstractThreadedSyncAdapter::handleOnUnsyncableAccount,
                     AbstractThreadedSyncAdapter.this, cb));
@@ -181,12 +194,16 @@
         @Override
         public void startSync(ISyncContext syncContext, String authority, Account account,
                 Bundle extras) {
+            if (!isCallerSystem()) {
+                return;
+            }
             if (ENABLE_LOG) {
                 if (extras != null) {
                     extras.size(); // Unparcel so its toString() will show the contents.
                 }
                 Log.d(TAG, "startSync() start " + authority + " " + account + " " + extras);
             }
+
             try {
                 final SyncContext syncContextClient = new SyncContext(syncContext);
 
@@ -242,6 +259,9 @@
 
         @Override
         public void cancelSync(ISyncContext syncContext) {
+            if (!isCallerSystem()) {
+                return;
+            }
             try {
                 // synchronize to make sure that mSyncThreads doesn't change between when we
                 // check it and when we use it
diff --git a/core/java/android/content/pm/IPackageInstallerSession.aidl b/core/java/android/content/pm/IPackageInstallerSession.aidl
index 04e15c7..b26a240 100644
--- a/core/java/android/content/pm/IPackageInstallerSession.aidl
+++ b/core/java/android/content/pm/IPackageInstallerSession.aidl
@@ -46,4 +46,5 @@
     int getParentSessionId();
 
     boolean isStaged();
+    int getInstallFlags();
 }
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 44842c6..b44b6d9 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -1176,6 +1176,18 @@
         }
 
         /**
+         * @return Session's {@link SessionParams#installFlags}.
+         * @hide
+         */
+        public int getInstallFlags() {
+            try {
+                return mSession.getInstallFlags();
+            } catch (RemoteException e) {
+                throw e.rethrowFromSystemServer();
+            }
+        }
+
+        /**
          * @return the session ID of the multi-package session that this belongs to or
          * {@link SessionInfo#INVALID_ID} if it does not belong to a multi-package session.
          */
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index b377678..1ea6e11 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -89,6 +89,7 @@
 import android.util.Base64;
 import android.util.ByteStringUtils;
 import android.util.DisplayMetrics;
+import android.util.EventLog;
 import android.util.Log;
 import android.util.PackageUtils;
 import android.util.Pair;
@@ -132,6 +133,7 @@
 import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Objects;
 import java.util.Set;
 import java.util.UUID;
 import java.util.concurrent.atomic.AtomicInteger;
@@ -2501,6 +2503,12 @@
             }
         }
 
+        if (declareDuplicatePermission(pkg)) {
+            outError[0] = "Found duplicate permission with a different attribute value.";
+            mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
+            return null;
+        }
+
         if (supportsSmallScreens < 0 || (supportsSmallScreens > 0
                 && pkg.applicationInfo.targetSdkVersion
                         >= android.os.Build.VERSION_CODES.DONUT)) {
@@ -2540,6 +2548,51 @@
         return pkg;
     }
 
+    /**
+     * @return {@code true} if the package declares malformed duplicate permissions.
+     */
+    public static boolean declareDuplicatePermission(@NonNull Package pkg) {
+        final List<Permission> permissions = pkg.permissions;
+        final int size = permissions.size();
+        if (size > 0) {
+            final ArrayMap<String, Permission> checkDuplicatePerm = new ArrayMap<>(size);
+            for (int i = 0; i < size; i++) {
+                final Permission permissionDefinition = permissions.get(i);
+                final String name = permissionDefinition.info.name;
+                final Permission perm = checkDuplicatePerm.get(name);
+                if (isMalformedDuplicate(permissionDefinition, perm)) {
+                    // Fix for b/213323615
+                    EventLog.writeEvent(0x534e4554, "213323615",
+                            "The package " + pkg.packageName + " seems malicious");
+                    return true;
+                }
+                checkDuplicatePerm.put(name, permissionDefinition);
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Determines if a duplicate permission is malformed .i.e. defines different protection level
+     * or group.
+     */
+    private static boolean isMalformedDuplicate(Permission p1, Permission p2) {
+        // Since a permission tree is also added as a permission with normal protection
+        // level, we need to skip if the parsedPermission is a permission tree.
+        if (p1 == null || p2 == null || p1.tree || p2.tree) {
+            return false;
+        }
+
+        if (p1.info.getProtection() != p2.info.getProtection()) {
+            return true;
+        }
+        if (!Objects.equals(p1.info.group, p2.info.group)) {
+            return true;
+        }
+
+        return false;
+    }
+
     private boolean checkOverlayRequiredSystemProperty(String propName, String propValue) {
 
         if (TextUtils.isEmpty(propName) || TextUtils.isEmpty(propValue)) {
diff --git a/core/java/android/hardware/location/GeofenceHardwareRequestParcelable.java b/core/java/android/hardware/location/GeofenceHardwareRequestParcelable.java
index df13ade..bd25b8f 100644
--- a/core/java/android/hardware/location/GeofenceHardwareRequestParcelable.java
+++ b/core/java/android/hardware/location/GeofenceHardwareRequestParcelable.java
@@ -16,9 +16,9 @@
 
 package android.hardware.location;
 
+import android.os.BadParcelableException;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.util.Log;
 
 /**
  * Geofence Hardware Request used for internal location services communication.
@@ -139,11 +139,8 @@
         @Override
         public GeofenceHardwareRequestParcelable createFromParcel(Parcel parcel) {
             int geofenceType = parcel.readInt();
-            if(geofenceType != GeofenceHardwareRequest.GEOFENCE_TYPE_CIRCLE) {
-                Log.e(
-                        "GeofenceHardwareRequest",
-                        String.format("Invalid Geofence type: %d", geofenceType));
-                return null;
+            if (geofenceType != GeofenceHardwareRequest.GEOFENCE_TYPE_CIRCLE) {
+                throw new BadParcelableException("Invalid Geofence type: " + geofenceType);
             }
 
             GeofenceHardwareRequest request = GeofenceHardwareRequest.createCircularGeofence(
diff --git a/core/java/android/os/UserManagerInternal.java b/core/java/android/os/UserManagerInternal.java
index 1f6c3cc..674dcc0 100644
--- a/core/java/android/os/UserManagerInternal.java
+++ b/core/java/android/os/UserManagerInternal.java
@@ -221,4 +221,12 @@
      */
     public abstract boolean isSettingRestrictedForUser(String setting, int userId, String value,
             int callingUid);
+
+    /**
+     * Returns {@code true} if the system should ignore errors when preparing
+     * the storage directories for the user with ID {@code userId}. This will
+     * return {@code false} for all new users; it will only return {@code true}
+     * for users that already existed on-disk from an older version of Android.
+     */
+    public abstract boolean shouldIgnorePrepareStorageErrors(int userId);
 }
diff --git a/core/java/android/service/gatekeeper/GateKeeperResponse.java b/core/java/android/service/gatekeeper/GateKeeperResponse.java
index 66fee1e..6b7a1e1 100644
--- a/core/java/android/service/gatekeeper/GateKeeperResponse.java
+++ b/core/java/android/service/gatekeeper/GateKeeperResponse.java
@@ -103,7 +103,7 @@
             dest.writeInt(mTimeout);
         } else if (mResponseCode == RESPONSE_OK) {
             dest.writeInt(mShouldReEnroll ? 1 : 0);
-            if (mPayload != null) {
+            if (mPayload != null && mPayload.length > 0) {
                 dest.writeInt(mPayload.length);
                 dest.writeByteArray(mPayload);
             } else {
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index d302c2b..3ba4d91 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -2841,7 +2841,7 @@
     @UnsupportedAppUsage
     public int getInputMethodWindowVisibleHeight() {
         try {
-            return mService.getInputMethodWindowVisibleHeight();
+            return mService.getInputMethodWindowVisibleHeight(mClient);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/com/android/internal/app/HarmfulAppWarningActivity.java b/core/java/com/android/internal/app/HarmfulAppWarningActivity.java
index ce2d229..33209e1 100644
--- a/core/java/com/android/internal/app/HarmfulAppWarningActivity.java
+++ b/core/java/com/android/internal/app/HarmfulAppWarningActivity.java
@@ -16,6 +16,8 @@
 
 package com.android.internal.app;
 
+import static android.view.WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+
 import android.content.Context;
 import android.content.DialogInterface;
 import android.content.Intent;
@@ -27,6 +29,7 @@
 import android.util.Log;
 import android.view.View;
 import android.widget.TextView;
+
 import com.android.internal.R;
 
 /**
@@ -48,6 +51,7 @@
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
 
+        getWindow().addSystemFlags(SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
         final Intent intent = getIntent();
         mPackageName = intent.getStringExtra(Intent.EXTRA_PACKAGE_NAME);
         mTarget = intent.getParcelableExtra(Intent.EXTRA_INTENT);
diff --git a/core/java/com/android/internal/notification/NotificationAccessConfirmationActivityContract.java b/core/java/com/android/internal/notification/NotificationAccessConfirmationActivityContract.java
index 4ce6f60..fdf0e90 100644
--- a/core/java/com/android/internal/notification/NotificationAccessConfirmationActivityContract.java
+++ b/core/java/com/android/internal/notification/NotificationAccessConfirmationActivityContract.java
@@ -17,6 +17,7 @@
 package com.android.internal.notification;
 
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
 
 public final class NotificationAccessConfirmationActivityContract {
@@ -25,13 +26,14 @@
             "com.android.settings.notification.NotificationAccessConfirmationActivity");
     public static final String EXTRA_USER_ID = "user_id";
     public static final String EXTRA_COMPONENT_NAME = "component_name";
-    public static final String EXTRA_PACKAGE_TITLE = "package_title";
 
-    public static Intent launcherIntent(int userId, ComponentName component, String packageTitle) {
+    /**
+     * Creates a launcher intent for NotificationAccessConfirmationActivity.
+     */
+    public static Intent launcherIntent(Context context, int userId, ComponentName component) {
         return new Intent()
                 .setComponent(COMPONENT_NAME)
                 .putExtra(EXTRA_USER_ID, userId)
-                .putExtra(EXTRA_COMPONENT_NAME, component)
-                .putExtra(EXTRA_PACKAGE_TITLE, packageTitle);
+                .putExtra(EXTRA_COMPONENT_NAME, component);
     }
 }
diff --git a/core/java/com/android/internal/view/IInputMethodManager.aidl b/core/java/com/android/internal/view/IInputMethodManager.aidl
index c29e823..19731b2 100644
--- a/core/java/com/android/internal/view/IInputMethodManager.aidl
+++ b/core/java/com/android/internal/view/IInputMethodManager.aidl
@@ -67,7 +67,7 @@
     void setAdditionalInputMethodSubtypes(String id, in InputMethodSubtype[] subtypes);
     // This is kept due to @UnsupportedAppUsage.
     // TODO(Bug 113914148): Consider removing this.
-    int getInputMethodWindowVisibleHeight();
+    int getInputMethodWindowVisibleHeight(in IInputMethodClient client);
 
     void reportActivityView(in IInputMethodClient parentClient, int childDisplayId,
             in float[] matrixValues);
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 4528985..442df34 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -95,6 +95,7 @@
     <protected-broadcast android:name="android.intent.action.USER_ACTIVITY_NOTIFICATION" />
     <protected-broadcast android:name="android.intent.action.MY_PACKAGE_SUSPENDED" />
     <protected-broadcast android:name="android.intent.action.MY_PACKAGE_UNSUSPENDED" />
+    <protected-broadcast android:name="android.app.action.MANAGED_PROFILE_PROVISIONED" />
 
     <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGED" />
     <protected-broadcast android:name="android.os.action.POWER_SAVE_MODE_CHANGING" />
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 8600326..af15503 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -707,6 +707,9 @@
     @VisibleForTesting
     @ShadeViewRefactor(RefactorComponent.SHADE_VIEW)
     public void updateFooter() {
+        if (mFooterView == null) {
+            return;
+        }
         boolean showDismissView = mClearAllEnabled && hasActiveClearableNotifications(ROWS_ALL);
         boolean showFooterView = (showDismissView ||
                 mEntryManager.getNotificationData().getActiveNotifications().size() != 0)
diff --git a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
index d7d4573..c11a9b05 100644
--- a/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
+++ b/services/companion/java/com/android/server/companion/CompanionDeviceManagerService.java
@@ -39,7 +39,6 @@
 import android.content.ServiceConnection;
 import android.content.pm.FeatureInfo;
 import android.content.pm.PackageInfo;
-import android.content.pm.PackageItemInfo;
 import android.content.pm.PackageManager;
 import android.net.NetworkPolicyManager;
 import android.os.Binder;
@@ -310,20 +309,12 @@
             String callingPackage = component.getPackageName();
             checkCanCallNotificationApi(callingPackage);
             int userId = getCallingUserId();
-            String packageTitle = BidiFormatter.getInstance().unicodeWrap(
-                    getPackageInfo(callingPackage, userId)
-                            .applicationInfo
-                            .loadSafeLabel(getContext().getPackageManager(),
-                                    PackageItemInfo.DEFAULT_MAX_LABEL_SIZE_PX,
-                                    PackageItemInfo.SAFE_LABEL_FLAG_TRIM
-                                            | PackageItemInfo.SAFE_LABEL_FLAG_FIRST_LINE)
-                            .toString());
-            long identity = Binder.clearCallingIdentity();
+            final long identity = Binder.clearCallingIdentity();
             try {
                 return PendingIntent.getActivity(getContext(),
                         0 /* request code */,
                         NotificationAccessConfirmationActivityContract.launcherIntent(
-                                userId, component, packageTitle),
+                                getContext(), userId, component),
                         PendingIntent.FLAG_IMMUTABLE | PendingIntent.FLAG_ONE_SHOT
                                 | PendingIntent.FLAG_CANCEL_CURRENT);
             } finally {
diff --git a/services/core/java/com/android/server/StorageManagerService.java b/services/core/java/com/android/server/StorageManagerService.java
index deff7ef..a252ba4 100644
--- a/services/core/java/com/android/server/StorageManagerService.java
+++ b/services/core/java/com/android/server/StorageManagerService.java
@@ -117,6 +117,7 @@
 import android.util.ArrayMap;
 import android.util.AtomicFile;
 import android.util.DataUnit;
+import android.util.EventLog;
 import android.util.Log;
 import android.util.Pair;
 import android.util.Slog;
@@ -2848,7 +2849,21 @@
         try {
             mVold.prepareUserStorage(volumeUuid, userId, serialNumber, flags);
         } catch (Exception e) {
+            EventLog.writeEvent(0x534e4554, "224585613", -1, "");
             Slog.wtf(TAG, e);
+            // Make sure to re-throw this exception; we must not ignore failure
+            // to prepare the user storage as it could indicate that encryption
+            // wasn't successfully set up.
+            //
+            // Very unfortunately, these errors need to be ignored for broken
+            // users that already existed on-disk from older Android versions.
+            UserManagerInternal umInternal = LocalServices.getService(UserManagerInternal.class);
+            if (umInternal.shouldIgnorePrepareStorageErrors(userId)) {
+                Slog.wtf(TAG, "ignoring error preparing storage for existing user " + userId
+                        + "; device may be insecure!");
+                return;
+            }
+            throw new RuntimeException(e);
         }
     }
 
diff --git a/services/core/java/com/android/server/connectivity/PacManager.java b/services/core/java/com/android/server/connectivity/PacManager.java
index f6ce2dc..621c9c7 100644
--- a/services/core/java/com/android/server/connectivity/PacManager.java
+++ b/services/core/java/com/android/server/connectivity/PacManager.java
@@ -37,6 +37,7 @@
 import android.os.SystemProperties;
 import android.provider.Settings;
 import android.util.Log;
+import android.webkit.URLUtil;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.TrafficStatsConstants;
@@ -215,8 +216,22 @@
      * @throws IOException if the URL is malformed, or the PAC file is too big.
      */
     private static String get(Uri pacUri) throws IOException {
-        URL url = new URL(pacUri.toString());
-        URLConnection urlConnection = url.openConnection(java.net.Proxy.NO_PROXY);
+        if (!URLUtil.isValidUrl(pacUri.toString()))  {
+            throw new IOException("Malformed URL:" + pacUri);
+        }
+
+        final URL url = new URL(pacUri.toString());
+        URLConnection urlConnection;
+        try {
+            urlConnection = url.openConnection(java.net.Proxy.NO_PROXY);
+            // Catch the possible exceptions and rethrow as IOException to not to crash the system
+            // for illegal input.
+        } catch (IllegalArgumentException e) {
+            throw new IOException("Incorrect proxy type for " + pacUri);
+        } catch (UnsupportedOperationException e) {
+            throw new IOException("Unsupported URL connection type for " + pacUri);
+        }
+
         long contentLength = -1;
         try {
             contentLength = Long.parseLong(urlConnection.getHeaderField("Content-Length"));
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 6330270..cbecebb 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -100,6 +100,7 @@
 import android.util.Printer;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.SparseBooleanArray;
 import android.view.ContextThemeWrapper;
 import android.view.DisplayInfo;
 import android.view.IWindowManager;
@@ -303,6 +304,8 @@
     final InputMethodSettings mSettings;
     final SettingsObserver mSettingsObserver;
     final IWindowManager mIWindowManager;
+    private final SparseBooleanArray mLoggedDeniedGetInputMethodWindowVisibleHeightForUid =
+            new SparseBooleanArray(0);
     final WindowManagerInternal mWindowManagerInternal;
     private final DisplayManagerInternal mDisplayManagerInternal;
     final HandlerCaller mCaller;
@@ -1219,6 +1222,13 @@
             clearPackageChangeState();
         }
 
+        @Override
+        public void onUidRemoved(int uid) {
+            synchronized (mMethodMap) {
+                mLoggedDeniedGetInputMethodWindowVisibleHeightForUid.delete(uid);
+            }
+        }
+
         private void clearPackageChangeState() {
             // No need to lock them because we access these fields only on getRegisteredHandler().
             mChangedPackages.clear();
@@ -2754,20 +2764,8 @@
             }
             final long ident = Binder.clearCallingIdentity();
             try {
-                if (mCurClient == null || client == null
-                        || mCurClient.client.asBinder() != client.asBinder()) {
-                    // We need to check if this is the current client with
-                    // focus in the window manager, to allow this call to
-                    // be made before input is started in it.
-                    final ClientState cs = mClients.get(client.asBinder());
-                    if (cs == null) {
-                        throw new IllegalArgumentException("unknown client " + client.asBinder());
-                    }
-                    if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid,
-                            cs.selfReportedDisplayId)) {
-                        Slog.w(TAG, "Ignoring showSoftInput of uid " + uid + ": " + client);
-                        return false;
-                    }
+                if (!canInteractWithImeLocked(uid, client, "showSoftInput")) {
+                    return false;
                 }
                 if (DEBUG) Slog.v(TAG, "Client requesting input be shown");
                 return showCurrentInputLocked(flags, resultReceiver);
@@ -3462,9 +3460,46 @@
      * @return {@link WindowManagerInternal#getInputMethodWindowVisibleHeight()}
      */
     @Override
-    public int getInputMethodWindowVisibleHeight() {
-        // TODO(yukawa): Should we verify the display ID?
-        return mWindowManagerInternal.getInputMethodWindowVisibleHeight(mCurTokenDisplayId);
+    @Deprecated
+    public int getInputMethodWindowVisibleHeight(@NonNull IInputMethodClient client) {
+        int callingUid = Binder.getCallingUid();
+        return Binder.withCleanCallingIdentity(() -> {
+            final int curTokenDisplayId;
+            synchronized (mMethodMap) {
+                if (!canInteractWithImeLocked(callingUid, client,
+                        "getInputMethodWindowVisibleHeight")) {
+                    if (!mLoggedDeniedGetInputMethodWindowVisibleHeightForUid.get(callingUid)) {
+                        EventLog.writeEvent(0x534e4554, "204906124", callingUid, "");
+                        mLoggedDeniedGetInputMethodWindowVisibleHeightForUid.put(callingUid, true);
+                    }
+                    return 0;
+                }
+                // This should probably use the caller's display id, but because this is unsupported
+                // and maintained only for compatibility, there's no point in fixing it.
+                curTokenDisplayId = mCurTokenDisplayId;
+            }
+            return mWindowManagerInternal.getInputMethodWindowVisibleHeight(curTokenDisplayId);
+        });
+    }
+
+    private boolean canInteractWithImeLocked(int callingUid, IInputMethodClient client,
+            String method) {
+        if (mCurClient == null || client == null
+                || mCurClient.client.asBinder() != client.asBinder()) {
+            // We need to check if this is the current client with
+            // focus in the window manager, to allow this call to
+            // be made before input is started in it.
+            final ClientState cs = mClients.get(client.asBinder());
+            if (cs == null) {
+                throw new IllegalArgumentException("unknown client " + client.asBinder());
+            }
+            if (!mWindowManagerInternal.isInputMethodClientFocus(cs.uid, cs.pid,
+                    cs.selfReportedDisplayId)) {
+                Slog.w(TAG, "Ignoring " + method + " of uid " + callingUid + ": " + client);
+                return false;
+            }
+        }
+        return true;
     }
 
     @Override
diff --git a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
index 3dd7304..bd4ea08 100644
--- a/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/MultiClientInputMethodManagerService.java
@@ -1694,7 +1694,7 @@
 
         @BinderThread
         @Override
-        public int getInputMethodWindowVisibleHeight() {
+        public int getInputMethodWindowVisibleHeight(IInputMethodClient client) {
             reportNotSupported();
             return 0;
         }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 8c0cf51..55f890d 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -202,6 +202,7 @@
 import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
+import android.util.SparseBooleanArray;
 import android.util.StatsLog;
 import android.util.Xml;
 import android.util.proto.ProtoOutputStream;
@@ -227,6 +228,7 @@
 import com.android.internal.util.Preconditions;
 import com.android.internal.util.XmlUtils;
 import com.android.internal.util.function.TriPredicate;
+import com.android.internal.widget.LockPatternUtils;
 import com.android.server.DeviceIdleController;
 import com.android.server.EventLogTags;
 import com.android.server.IoThread;
@@ -509,16 +511,27 @@
             return mBuffer.descendingIterator();
         }
 
-        public StatusBarNotification[] getArray(int count) {
+
+        public StatusBarNotification[] getArray(UserManager um, int count) {
+            ArrayList<Integer> currentUsers = new ArrayList<>();
+            currentUsers.add(UserHandle.USER_ALL);
+            Binder.withCleanCallingIdentity(() -> {
+                for (int user : um.getProfileIds(ActivityManager.getCurrentUser(), false)) {
+                    currentUsers.add(user);
+                }
+            });
             if (count == 0) count = mBufferSize;
-            final StatusBarNotification[] a
-                    = new StatusBarNotification[Math.min(count, mBuffer.size())];
+            List<StatusBarNotification> a = new ArrayList();
             Iterator<StatusBarNotification> iter = descendingIterator();
             int i=0;
             while (iter.hasNext() && i < count) {
-                a[i++] = iter.next();
+                StatusBarNotification sbn = iter.next();
+                if (currentUsers.contains(sbn.getUserId())) {
+                    i++;
+                    a.add(sbn);
+                }
             }
-            return a;
+            return a.toArray(new StatusBarNotification[a.size()]);
         }
 
     }
@@ -1449,6 +1462,53 @@
         return out;
     }
 
+    protected class StrongAuthTracker extends LockPatternUtils.StrongAuthTracker {
+
+        SparseBooleanArray mUserInLockDownMode = new SparseBooleanArray();
+        boolean mIsInLockDownMode = false;
+
+        StrongAuthTracker(Context context) {
+            super(context);
+        }
+
+        private boolean containsFlag(int haystack, int needle) {
+            return (haystack & needle) != 0;
+        }
+
+        public boolean isInLockDownMode() {
+            return mIsInLockDownMode;
+        }
+
+        @Override
+        public synchronized void onStrongAuthRequiredChanged(int userId) {
+            boolean userInLockDownModeNext = containsFlag(getStrongAuthForUser(userId),
+                    STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
+            mUserInLockDownMode.put(userId, userInLockDownModeNext);
+            boolean isInLockDownModeNext = mUserInLockDownMode.indexOfValue(true) != -1;
+
+            if (mIsInLockDownMode == isInLockDownModeNext) {
+                return;
+            }
+
+            if (isInLockDownModeNext) {
+                cancelNotificationsWhenEnterLockDownMode();
+            }
+
+            // When the mIsInLockDownMode is true, both notifyPostedLocked and
+            // notifyRemovedLocked will be dismissed. So we shall call
+            // cancelNotificationsWhenEnterLockDownMode before we set mIsInLockDownMode
+            // as true and call postNotificationsWhenExitLockDownMode after we set
+            // mIsInLockDownMode as false.
+            mIsInLockDownMode = isInLockDownModeNext;
+
+            if (!isInLockDownModeNext) {
+                postNotificationsWhenExitLockDownMode();
+            }
+        }
+    }
+
+    private StrongAuthTracker mStrongAuthTracker;
+
     public NotificationManagerService(Context context) {
         this(context, new InjectableSystemClockImpl());
     }
@@ -1469,6 +1529,11 @@
     }
 
     @VisibleForTesting
+    void setStrongAuthTracker(StrongAuthTracker strongAuthTracker) {
+        mStrongAuthTracker = strongAuthTracker;
+    }
+
+    @VisibleForTesting
     void setKeyguardManager(KeyguardManager keyguardManager) {
         mKeyguardManager = keyguardManager;
     }
@@ -1643,6 +1708,7 @@
 
         mHandler = new WorkerHandler(looper);
         mRankingThread.start();
+        mStrongAuthTracker = new StrongAuthTracker(getContext());
         String[] extractorNames;
         try {
             extractorNames = resources.getStringArray(R.array.config_notificationSignalExtractors);
@@ -1790,7 +1856,8 @@
         init(Looper.myLooper(),
                 AppGlobals.getPackageManager(), getContext().getPackageManager(),
                 getLocalService(LightsManager.class),
-                new NotificationListeners(AppGlobals.getPackageManager()),
+                new NotificationListeners(getContext(), mNotificationLock, mUserProfiles,
+                        AppGlobals.getPackageManager()),
                 new NotificationAssistants(getContext(), mNotificationLock, mUserProfiles,
                         AppGlobals.getPackageManager()),
                 new ConditionProviders(getContext(), mUserProfiles, AppGlobals.getPackageManager()),
@@ -1933,6 +2000,7 @@
             mRoleObserver = new RoleObserver(getContext().getSystemService(RoleManager.class),
                     mPackageManager, getContext().getMainExecutor());
             mRoleObserver.init();
+            new LockPatternUtils(getContext()).registerStrongAuthTracker(mStrongAuthTracker);
         } else if (phase == SystemService.PHASE_THIRD_PARTY_APPS_CAN_START) {
             // This observer will force an update when observe is called, causing us to
             // bind to listener services.
@@ -3001,21 +3069,31 @@
                     android.Manifest.permission.ACCESS_NOTIFICATIONS,
                     "NotificationManagerService.getActiveNotifications");
 
-            StatusBarNotification[] tmp = null;
+            ArrayList<StatusBarNotification> tmp = new ArrayList<>();
             int uid = Binder.getCallingUid();
 
+            ArrayList<Integer> currentUsers = new ArrayList<>();
+            currentUsers.add(UserHandle.USER_ALL);
+            Binder.withCleanCallingIdentity(() -> {
+                for (int user : mUm.getProfileIds(ActivityManager.getCurrentUser(), false)) {
+                    currentUsers.add(user);
+                }
+            });
+
             // noteOp will check to make sure the callingPkg matches the uid
             if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_NOTIFICATIONS, uid, callingPkg)
                     == AppOpsManager.MODE_ALLOWED) {
                 synchronized (mNotificationLock) {
-                    tmp = new StatusBarNotification[mNotificationList.size()];
                     final int N = mNotificationList.size();
-                    for (int i=0; i<N; i++) {
-                        tmp[i] = mNotificationList.get(i).sbn;
+                    for (int i = 0; i < N; i++) {
+                        final StatusBarNotification sbn = mNotificationList.get(i).sbn;
+                        if (currentUsers.contains(sbn.getUserId())) {
+                            tmp.add(sbn);
+                        }
                     }
                 }
             }
-            return tmp;
+            return tmp.toArray(new StatusBarNotification[tmp.size()]);
         }
 
         /**
@@ -3111,7 +3189,7 @@
             if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_NOTIFICATIONS, uid, callingPkg)
                     == AppOpsManager.MODE_ALLOWED) {
                 synchronized (mArchive) {
-                    tmp = mArchive.getArray(count);
+                    tmp = mArchive.getArray(mUm, count);
                 }
             }
             return tmp;
@@ -4768,8 +4846,11 @@
         try {
             fixNotification(notification, pkg, userId);
 
-        } catch (NameNotFoundException e) {
-            Slog.e(TAG, "Cannot create a context for sending app", e);
+        } catch (Exception e) {
+            if (notification.isForegroundService()) {
+                throw new SecurityException("Invalid FGS notification", e);
+            }
+            Slog.e(TAG, "Cannot fix notification", e);
             return;
         }
 
@@ -7289,6 +7370,29 @@
         }
     }
 
+    private void cancelNotificationsWhenEnterLockDownMode() {
+        synchronized (mNotificationLock) {
+            int numNotifications = mNotificationList.size();
+            for (int i = 0; i < numNotifications; i++) {
+                NotificationRecord rec = mNotificationList.get(i);
+                mListeners.notifyRemovedLocked(rec, REASON_CANCEL_ALL,
+                        rec.getStats());
+            }
+
+        }
+    }
+
+    private void postNotificationsWhenExitLockDownMode() {
+        synchronized (mNotificationLock) {
+            int numNotifications = mNotificationList.size();
+            for (int i = 0; i < numNotifications; i++) {
+                NotificationRecord rec = mNotificationList.get(i);
+                mListeners.notifyPostedLocked(rec, rec);
+            }
+
+        }
+    }
+
     private void updateNotificationPulse() {
         synchronized (mNotificationLock) {
             updateLightsLocked();
@@ -7498,6 +7602,10 @@
                 rankings.toArray(new NotificationListenerService.Ranking[0]));
     }
 
+    boolean isInLockDownMode() {
+        return mStrongAuthTracker.isInLockDownMode();
+    }
+
     boolean hasCompanionDevice(ManagedServiceInfo info) {
         if (mCompanionManager == null) {
             mCompanionManager = getCompanionManager();
@@ -8005,9 +8113,9 @@
 
         private final ArraySet<ManagedServiceInfo> mLightTrimListeners = new ArraySet<>();
 
-        public NotificationListeners(IPackageManager pm) {
-            super(getContext(), mNotificationLock, mUserProfiles, pm);
-
+        public NotificationListeners(Context context, Object lock, UserProfiles userProfiles,
+                IPackageManager pm) {
+            super(context, lock, userProfiles, pm);
         }
 
         @Override
@@ -8116,8 +8224,12 @@
          *                           targetting <= O_MR1
          */
         @GuardedBy("mNotificationLock")
-        private void notifyPostedLocked(NotificationRecord r, NotificationRecord old,
+        void notifyPostedLocked(NotificationRecord r, NotificationRecord old,
                 boolean notifyAllListeners) {
+            if (isInLockDownMode()) {
+                return;
+            }
+
             // Lazily initialized snapshots of the notification.
             StatusBarNotification sbn = r.sbn;
             StatusBarNotification oldSbn = (old != null) ? old.sbn : null;
@@ -8180,8 +8292,11 @@
         @GuardedBy("mNotificationLock")
         public void notifyRemovedLocked(NotificationRecord r, int reason,
                 NotificationStats notificationStats) {
-            final StatusBarNotification sbn = r.sbn;
+            if (isInLockDownMode()) {
+                return;
+            }
 
+            final StatusBarNotification sbn = r.sbn;
             // make a copy in case changes are made to the underlying Notification object
             // NOTE: this copy is lightweight: it doesn't include heavyweight parts of the
             // notification
@@ -8232,6 +8347,10 @@
          */
         @GuardedBy("mNotificationLock")
         public void notifyRankingUpdateLocked(List<NotificationRecord> changedHiddenNotifications) {
+            if (isInLockDownMode()) {
+                return;
+            }
+
             boolean isHiddenRankingUpdate = changedHiddenNotifications != null
                     && changedHiddenNotifications.size() > 0;
 
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 7b45a1b..417314a 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -589,6 +589,9 @@
             if (r == null) {
                 throw new IllegalArgumentException("Invalid package");
             }
+            if (fromTargetApp) {
+                group.setBlocked(false);
+            }
             final NotificationChannelGroup oldGroup = r.groups.get(group.getId());
             if (!group.equals(oldGroup)) {
                 // will log for new entries as well as name/description changes
diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java
index ebc4191..48f76e1 100644
--- a/services/core/java/com/android/server/notification/ZenModeHelper.java
+++ b/services/core/java/com/android/server/notification/ZenModeHelper.java
@@ -92,6 +92,7 @@
 
     // The amount of time rules instances can exist without their owning app being installed.
     private static final int RULE_INSTANCE_GRACE_PERIOD = 1000 * 60 * 60 * 72;
+    static final int RULE_LIMIT_PER_PACKAGE = 100;
 
     private final Context mContext;
     private final H mHandler;
@@ -305,10 +306,10 @@
             int newRuleInstanceCount = getCurrentInstanceCount(automaticZenRule.getOwner())
                     + getCurrentInstanceCount(automaticZenRule.getConfigurationActivity())
                     + 1;
-            if (ruleInstanceLimit > 0 && ruleInstanceLimit < newRuleInstanceCount) {
+            if (newRuleInstanceCount > RULE_LIMIT_PER_PACKAGE
+                    || (ruleInstanceLimit > 0 && ruleInstanceLimit < newRuleInstanceCount)) {
                 throw new IllegalArgumentException("Rule instance limit exceeded");
             }
-
         }
 
         ZenModeConfig newConfig;
diff --git a/services/core/java/com/android/server/pm/PackageInstallerService.java b/services/core/java/com/android/server/pm/PackageInstallerService.java
index 2bd561a..df3f116 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerService.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerService.java
@@ -332,7 +332,10 @@
                     // Their staging dirs will be removed too
                     PackageInstallerSession root = !session.hasParentSessionId()
                             ? session : mSessions.get(session.getParentSessionId());
-                    if (!root.isDestroyed() && 
+                    if (root == null) {
+                        Slog.e(TAG, "freeStageDirs: found an orphaned session: "
+                                + session.sessionId + " parent=" + session.getParentSessionId());
+                    } else if (!root.isDestroyed() && 
                             (!root.isStaged() || (root.isStaged() && root.isStagedSessionReady()))) 
                     {
                         root.abandon();
diff --git a/services/core/java/com/android/server/pm/PackageInstallerSession.java b/services/core/java/com/android/server/pm/PackageInstallerSession.java
index d40eae5..3232692 100644
--- a/services/core/java/com/android/server/pm/PackageInstallerSession.java
+++ b/services/core/java/com/android/server/pm/PackageInstallerSession.java
@@ -91,6 +91,7 @@
 import android.system.StructStat;
 import android.text.TextUtils;
 import android.util.ArraySet;
+import android.util.EventLog;
 import android.util.ExceptionUtils;
 import android.util.MathUtils;
 import android.util.Slog;
@@ -1702,6 +1703,11 @@
                     resolveInheritedFile(baseDexMetadataFile);
                 }
                 baseApk = existingBase;
+            } else if ((params.installFlags & PackageManager.INSTALL_DONT_KILL_APP) != 0) {
+                EventLog.writeEvent(0x534e4554, "219044664");
+
+                // Installing base.apk. Make sure the app is restarted.
+                params.setDontKillApp(false);
             }
 
             // Inherit splits if not overridden
@@ -2134,6 +2140,11 @@
     }
 
     @Override
+    public int getInstallFlags() {
+        return params.installFlags;
+    }
+
+    @Override
     public int[] getChildSessionIds() {
         final int[] childSessionIds = mChildSessionIds.copyKeys();
         if (childSessionIds != null) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index b2e88c2..3549db4 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -18690,6 +18690,16 @@
                 return PackageManager.DELETE_FAILED_INTERNAL_ERROR;
             }
 
+            if (isSystemApp(uninstalledPs)) {
+                UserInfo userInfo = sUserManager.getUserInfo(userId);
+                if (userInfo == null || !userInfo.isAdmin()) {
+                    Slog.w(TAG, "Not removing package " + packageName
+                            + " as only admin user may downgrade system apps");
+                    EventLog.writeEvent(0x534e4554, "170646036", -1, packageName);
+                    return PackageManager.DELETE_FAILED_USER_RESTRICTED;
+                }
+            }
+
             disabledSystemPs = mSettings.getDisabledSystemPkgLPr(packageName);
             // Save the enabled state before we delete the package. When deleting a stub
             // application we always set the enabled state to 'disabled'.
diff --git a/services/core/java/com/android/server/pm/UserDataPreparer.java b/services/core/java/com/android/server/pm/UserDataPreparer.java
index 045a295..95482d7 100644
--- a/services/core/java/com/android/server/pm/UserDataPreparer.java
+++ b/services/core/java/com/android/server/pm/UserDataPreparer.java
@@ -22,6 +22,7 @@
 import android.content.pm.UserInfo;
 import android.os.Environment;
 import android.os.FileUtils;
+import android.os.RecoverySystem;
 import android.os.storage.StorageManager;
 import android.os.storage.VolumeInfo;
 import android.os.SystemProperties;
@@ -115,6 +116,16 @@
                 // Try one last time; if we fail again we're really in trouble
                 prepareUserDataLI(volumeUuid, userId, userSerial,
                     flags | StorageManager.FLAG_STORAGE_DE, false);
+            } else {
+                try {
+                    Log.wtf(TAG, "prepareUserData failed for user " + userId, e);
+                    if (userId == UserHandle.USER_SYSTEM) {
+                        RecoverySystem.rebootPromptAndWipeUserData(mContext,
+                                "prepareUserData failed for system user");
+                    }
+                } catch (IOException e2) {
+                    throw new RuntimeException("error rebooting into recovery", e2);
+                }
             }
         }
     }
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index e2ebd73..15fdc5e 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -180,6 +180,8 @@
     private static final String TAG_SEED_ACCOUNT_OPTIONS = "seedAccountOptions";
     private static final String TAG_LAST_REQUEST_QUIET_MODE_ENABLED_CALL =
             "lastRequestQuietModeEnabledCall";
+    private static final String TAG_IGNORE_PREPARE_STORAGE_ERRORS =
+            "ignorePrepareStorageErrors";
     private static final String ATTR_KEY = "key";
     private static final String ATTR_VALUE_TYPE = "type";
     private static final String ATTR_MULTIPLE = "m";
@@ -278,6 +280,14 @@
 
         private long mLastRequestQuietModeEnabledMillis;
 
+        /**
+         * {@code true} if the system should ignore errors when preparing the
+         * storage directories for this user. This is {@code false} for all new
+         * users; it will only be {@code true} for users that already existed
+         * on-disk from an older version of Android.
+         */
+        private boolean mIgnorePrepareStorageErrors;
+
         void setLastRequestQuietModeEnabledMillis(long millis) {
             mLastRequestQuietModeEnabledMillis = millis;
         }
@@ -286,6 +296,14 @@
             return mLastRequestQuietModeEnabledMillis;
         }
 
+        boolean getIgnorePrepareStorageErrors() {
+            return mIgnorePrepareStorageErrors;
+        }
+
+        void setIgnorePrepareStorageErrors() {
+            mIgnorePrepareStorageErrors = true;
+        }
+
         void clearSeedAccountData() {
             seedAccountName = null;
             seedAccountType = null;
@@ -2380,6 +2398,10 @@
             serializer.endTag(/* namespace */ null, TAG_LAST_REQUEST_QUIET_MODE_ENABLED_CALL);
         }
 
+        serializer.startTag(/* namespace */ null, TAG_IGNORE_PREPARE_STORAGE_ERRORS);
+        serializer.text(String.valueOf(userData.getIgnorePrepareStorageErrors()));
+        serializer.endTag(/* namespace */ null, TAG_IGNORE_PREPARE_STORAGE_ERRORS);
+
         serializer.endTag(null, TAG_USER);
 
         serializer.endDocument();
@@ -2488,6 +2510,7 @@
         Bundle baseRestrictions = null;
         Bundle localRestrictions = null;
         Bundle globalRestrictions = null;
+        boolean ignorePrepareStorageErrors = true; // default is true for old users
 
         XmlPullParser parser = Xml.newPullParser();
         parser.setInput(is, StandardCharsets.UTF_8.name());
@@ -2566,6 +2589,11 @@
                     if (type == XmlPullParser.TEXT) {
                         lastRequestQuietModeEnabledTimestamp = Long.parseLong(parser.getText());
                     }
+                } else if (TAG_IGNORE_PREPARE_STORAGE_ERRORS.equals(tag)) {
+                    type = parser.next();
+                    if (type == XmlPullParser.TEXT) {
+                        ignorePrepareStorageErrors = Boolean.parseBoolean(parser.getText());
+                    }
                 }
             }
         }
@@ -2591,6 +2619,9 @@
         userData.persistSeedData = persistSeedData;
         userData.seedAccountOptions = seedAccountOptions;
         userData.setLastRequestQuietModeEnabledMillis(lastRequestQuietModeEnabledTimestamp);
+        if (ignorePrepareStorageErrors) {
+            userData.setIgnorePrepareStorageErrors();
+        }
 
         synchronized (mRestrictionsLock) {
             if (baseRestrictions != null) {
@@ -3767,6 +3798,9 @@
                             pw.println();
                         }
                     }
+
+                    pw.println("    Ignore errors preparing storage: "
+                            + userData.getIgnorePrepareStorageErrors());
                 }
             }
             pw.println();
@@ -4111,6 +4145,14 @@
             return UserRestrictionsUtils.isSettingRestrictedForUser(mContext, setting, userId,
                     value, callingUid);
         }
+
+        @Override
+        public boolean shouldIgnorePrepareStorageErrors(int userId) {
+            synchronized (mUsersLock) {
+                UserData userData = mUsers.get(userId);
+                return userData != null && userData.getIgnorePrepareStorageErrors();
+            }
+        }
     }
 
     /* Remove all the users except of the system one. */
diff --git a/services/core/java/com/android/server/slice/SliceManagerService.java b/services/core/java/com/android/server/slice/SliceManagerService.java
index 5fd2ab87..b1728cd 100644
--- a/services/core/java/com/android/server/slice/SliceManagerService.java
+++ b/services/core/java/com/android/server/slice/SliceManagerService.java
@@ -237,6 +237,8 @@
         if (autoGrantPermissions != null && callingPkg != null) {
             // Need to own the Uri to call in with permissions to grant.
             enforceOwner(callingPkg, uri, userId);
+            // b/208232850: Needs to verify caller before granting slice access
+            verifyCaller(callingPkg);
             for (String perm : autoGrantPermissions) {
                 if (mContext.checkPermission(perm, pid, uid) == PERMISSION_GRANTED) {
                     int providerUser = ContentProvider.getUserIdFromUri(uri, userId);
diff --git a/services/core/java/com/android/server/wm/ActivityStack.java b/services/core/java/com/android/server/wm/ActivityStack.java
index 764b929..81fbcbf 100644
--- a/services/core/java/com/android/server/wm/ActivityStack.java
+++ b/services/core/java/com/android/server/wm/ActivityStack.java
@@ -2145,7 +2145,9 @@
             boolean aboveTop = top != null;
             final boolean stackShouldBeVisible = shouldBeVisible(starting);
             boolean behindFullscreenActivity = !stackShouldBeVisible;
-            boolean resumeNextActivity = isFocusable() && isInStackLocked(starting) == null;
+            boolean resumeNextActivity = isFocusable()
+                    && getVisibility(starting) == STACK_VISIBILITY_VISIBLE
+                    && isInStackLocked(starting) == null;
             for (int taskNdx = mTaskHistory.size() - 1; taskNdx >= 0; --taskNdx) {
                 final TaskRecord task = mTaskHistory.get(taskNdx);
                 final ArrayList<ActivityRecord> activities = task.mActivities;
diff --git a/services/core/java/com/android/server/wm/TaskRecord.java b/services/core/java/com/android/server/wm/TaskRecord.java
index 3fd4e83..361f66e 100644
--- a/services/core/java/com/android/server/wm/TaskRecord.java
+++ b/services/core/java/com/android/server/wm/TaskRecord.java
@@ -110,6 +110,7 @@
 import android.content.res.Configuration;
 import android.graphics.Rect;
 import android.os.Debug;
+import android.os.Process;
 import android.os.RemoteException;
 import android.os.SystemClock;
 import android.os.Trace;
@@ -204,6 +205,11 @@
     static final int REPARENT_LEAVE_STACK_IN_PLACE = 2;
 
     /**
+     * Used to identify if the activity that is installed from device's system image.
+     */
+    boolean mIsEffectivelySystemApp;
+
+    /**
      * The factory used to create {@link TaskRecord}. This allows OEM subclass {@link TaskRecord}.
      */
     private static TaskRecordFactory sTaskRecordFactory;
@@ -869,17 +875,25 @@
 
     /** Sets the original intent, and the calling uid and package. */
     void setIntent(ActivityRecord r) {
-        mCallingUid = r.launchedFromUid;
-        mCallingPackage = r.launchedFromPackage;
-        setIntent(r.intent, r.info);
+        boolean updateIdentity = false;
+        if (this.intent == null) {
+            updateIdentity = true;
+        } else if (!mNeverRelinquishIdentity) {
+            updateIdentity = (effectiveUid == Process.SYSTEM_UID || mIsEffectivelySystemApp
+                    || effectiveUid == r.info.applicationInfo.uid);
+        }
+        if (updateIdentity) {
+            mCallingUid = r.launchedFromUid;
+            mCallingPackage = r.launchedFromPackage;
+            setIntent(r.intent, r.info);
+        }
         setLockTaskAuth(r);
     }
 
     /** Sets the original intent, _without_ updating the calling uid or package. */
     private void setIntent(Intent _intent, ActivityInfo info) {
         if (intent == null) {
-            mNeverRelinquishIdentity =
-                    (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
+            mNeverRelinquishIdentity = (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
         } else if (mNeverRelinquishIdentity) {
             return;
         }
@@ -892,6 +906,7 @@
             rootAffinity = affinity;
         }
         effectiveUid = info.applicationInfo.uid;
+        mIsEffectivelySystemApp = info.applicationInfo.isSystemApp();
         stringName = null;
 
         if (info.targetActivity == null) {
@@ -1662,12 +1677,12 @@
         // utility activities.
         int activityNdx;
         final int numActivities = mActivities.size();
-        final boolean relinquish = numActivities != 0 &&
-                (mActivities.get(0).info.flags & FLAG_RELINQUISH_TASK_IDENTITY) != 0;
-        for (activityNdx = Math.min(numActivities, 1); activityNdx < numActivities;
-                ++activityNdx) {
+        for (activityNdx = 0; activityNdx < numActivities; ++activityNdx) {
             final ActivityRecord r = mActivities.get(activityNdx);
-            if (relinquish && (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
+            if ((r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0
+                    || (r.info.applicationInfo.uid != Process.SYSTEM_UID
+                    && !r.info.applicationInfo.isSystemApp()
+                    && r.info.applicationInfo.uid != effectiveUid)) {
                 // This will be the top activity for determining taskDescription. Pre-inc to
                 // overcome initial decrement below.
                 ++activityNdx;
@@ -1739,15 +1754,27 @@
     int findEffectiveRootIndex() {
         int effectiveNdx = 0;
         final int topActivityNdx = mActivities.size() - 1;
+        ActivityRecord root = null;
         for (int activityNdx = 0; activityNdx <= topActivityNdx; ++activityNdx) {
             final ActivityRecord r = mActivities.get(activityNdx);
             if (r.finishing) {
                 continue;
             }
-            effectiveNdx = activityNdx;
-            if ((r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0) {
+
+            if (root == null) {
+                // Set this as the candidate root since it isn't finishing.
+                root = r;
+                effectiveNdx = activityNdx;
+            }
+            final int uid = root == r ? effectiveUid : r.info.applicationInfo.uid;
+            if ((root.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0
+                || (root.info.applicationInfo.uid != Process.SYSTEM_UID
+                    && !root.info.applicationInfo.isSystemApp()
+                    && root.info.applicationInfo.uid != uid)) {
                 break;
             }
+            effectiveNdx = activityNdx;
+            root = r;
         }
         return effectiveNdx;
     }
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
index 72fc189..64e245d 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotPersister.java
@@ -28,12 +28,14 @@
 import android.graphics.Bitmap.Config;
 import android.os.Process;
 import android.os.SystemClock;
+import android.os.UserManagerInternal;
 import android.util.ArraySet;
 import android.util.Slog;
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.os.AtomicFile;
+import com.android.server.LocalServices;
 import com.android.server.wm.nano.WindowManagerProtos.TaskSnapshotProto;
 
 import java.io.File;
@@ -74,6 +76,7 @@
     private final Object mLock = new Object();
     private final DirectoryResolver mDirectoryResolver;
     private final float mReducedScale;
+    private final UserManagerInternal mUserManagerInternal;
 
     /**
      * The list of ids of the tasks that have been persisted since {@link #removeObsoleteFiles} was
@@ -84,6 +87,9 @@
 
     TaskSnapshotPersister(WindowManagerService service, DirectoryResolver resolver) {
         mDirectoryResolver = resolver;
+
+        mUserManagerInternal = LocalServices.getService(UserManagerInternal.class);
+
         if (service.mLowRamTaskSnapshotsAndRecents) {
             // Use very low res snapshots if we are using Go version of recents.
             mReducedScale = LOW_RAM_RECENTS_REDUCED_SCALE;
@@ -172,7 +178,7 @@
                     return;
                 }
             }
-            SystemClock.sleep(100);
+            SystemClock.sleep(DELAY_MS);
         }
     }
 
@@ -218,7 +224,7 @@
 
     private boolean createDirectory(int userId) {
         final File dir = getDirectory(userId);
-        return dir.exists() || dir.mkdirs();
+        return dir.exists() || dir.mkdir();
     }
 
     private void deleteSnapshot(int taskId, int userId) {
@@ -243,18 +249,26 @@
             android.os.Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
             while (true) {
                 WriteQueueItem next;
+                boolean isReadyToWrite = false;
                 synchronized (mLock) {
                     if (mPaused) {
                         next = null;
                     } else {
                         next = mWriteQueue.poll();
                         if (next != null) {
-                            next.onDequeuedLocked();
+                            if (next.isReady()) {
+                                isReadyToWrite = true;
+                                next.onDequeuedLocked();
+                            } else {
+                                mWriteQueue.addLast(next);
+                            }
                         }
                     }
                 }
                 if (next != null) {
-                    next.write();
+                    if (isReadyToWrite) {
+                        next.write();
+                    }
                     SystemClock.sleep(DELAY_MS);
                 }
                 synchronized (mLock) {
@@ -274,6 +288,13 @@
     };
 
     private abstract class WriteQueueItem {
+        /**
+         * @return {@code true} if item is ready to have {@link WriteQueueItem#write} called
+         */
+        boolean isReady() {
+            return true;
+        }
+
         abstract void write();
 
         /**
@@ -313,6 +334,11 @@
         }
 
         @Override
+        boolean isReady() {
+            return mUserManagerInternal.isUserUnlocked(mUserId);
+        }
+
+        @Override
         void write() {
             if (!createDirectory(mUserId)) {
                 Slog.e(TAG, "Unable to create snapshot directory for user dir="
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
index cfa9944..4eec7ef 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/BaseIDevicePolicyManager.java
@@ -15,7 +15,9 @@
  */
 package com.android.server.devicepolicy;
 
+import android.accounts.Account;
 import android.app.admin.IDevicePolicyManager;
+import android.os.UserHandle;
 
 import com.android.server.SystemService;
 
@@ -56,4 +58,9 @@
 
     public void clearSystemUpdatePolicyFreezePeriodRecord() {
     }
+
+    public void finalizeWorkProfileProvisioning(
+            UserHandle managedProfileUser, Account migratedAccount) {
+
+    }
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 37931be..3b1f5a9 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -21,6 +21,7 @@
 import static android.Manifest.permission.REQUEST_PASSWORD_COMPLEXITY;
 import static android.app.ActivityManager.LOCK_TASK_MODE_NONE;
 import static android.app.admin.DeviceAdminReceiver.EXTRA_TRANSFER_OWNERSHIP_ADMIN_EXTRAS_BUNDLE;
+import static android.app.admin.DevicePolicyManager.ACTION_MANAGED_PROFILE_PROVISIONED;
 import static android.app.admin.DevicePolicyManager.ACTION_PROVISION_MANAGED_USER;
 import static android.app.admin.DevicePolicyManager.CODE_ACCOUNTS_NOT_EMPTY;
 import static android.app.admin.DevicePolicyManager.CODE_ADD_MANAGED_PROFILE_DISALLOWED;
@@ -48,6 +49,7 @@
 import static android.app.admin.DevicePolicyManager.DELEGATION_NETWORK_LOGGING;
 import static android.app.admin.DevicePolicyManager.DELEGATION_PACKAGE_ACCESS;
 import static android.app.admin.DevicePolicyManager.DELEGATION_PERMISSION_GRANT;
+import static android.app.admin.DevicePolicyManager.EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE;
 import static android.app.admin.DevicePolicyManager.ID_TYPE_BASE_INFO;
 import static android.app.admin.DevicePolicyManager.ID_TYPE_IMEI;
 import static android.app.admin.DevicePolicyManager.ID_TYPE_MEID;
@@ -9629,6 +9631,37 @@
     }
 
     @Override
+    public void finalizeWorkProfileProvisioning(UserHandle managedProfileUser,
+            Account migratedAccount) {
+        if (mContext.checkCallingOrSelfPermission(permission.MANAGE_PROFILE_AND_DEVICE_OWNERS)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Calling identity is not authorized");
+        }
+
+        if (!isManagedProfile(managedProfileUser.getIdentifier())) {
+            throw new IllegalStateException("Given user is not a managed profile");
+        }
+        ComponentName profileOwnerComponent =
+                mOwners.getProfileOwnerComponent(managedProfileUser.getIdentifier());
+        if (profileOwnerComponent == null) {
+            throw new IllegalStateException("There is no profile owner on the given profile");
+        }
+        Intent primaryProfileSuccessIntent = new Intent(ACTION_MANAGED_PROFILE_PROVISIONED);
+        primaryProfileSuccessIntent.setPackage(profileOwnerComponent.getPackageName());
+        primaryProfileSuccessIntent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES
+                | Intent.FLAG_RECEIVER_FOREGROUND);
+        primaryProfileSuccessIntent.putExtra(Intent.EXTRA_USER, managedProfileUser);
+
+        if (migratedAccount != null) {
+            primaryProfileSuccessIntent.putExtra(EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE,
+                    migratedAccount);
+        }
+
+        mContext.sendBroadcastAsUser(primaryProfileSuccessIntent,
+                UserHandle.of(getProfileParentId(managedProfileUser.getIdentifier())));
+    }
+
+    @Override
     public UserHandle createAndManageUser(ComponentName admin, String name,
             ComponentName profileOwner, PersistableBundle adminExtras, int flags) {
         Preconditions.checkNotNull(admin, "admin is null");
diff --git a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
index 6890017..6f6a260 100644
--- a/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/locksettings/recoverablekeystore/RecoverableKeyStoreManagerTest.java
@@ -70,6 +70,7 @@
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Ignore;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 import org.mockito.Mock;
@@ -516,6 +517,7 @@
         }
     }
 
+    @Ignore("Causing breakages so ignoring to resolve, b/231667368")
     @Test
     public void initRecoveryService_alwaysUpdatesCertsWhenTestRootCertIsUsed() throws Exception {
         int uid = Binder.getCallingUid();
@@ -539,6 +541,7 @@
                 testRootCertAlias)).isEqualTo(TestData.getInsecureCertPathForEndpoint2());
     }
 
+    @Ignore("Causing breakages so ignoring to resolve, b/231667368")
     @Test
     public void initRecoveryService_updatesCertsIndependentlyForDifferentRoots() throws Exception {
         int uid = Binder.getCallingUid();
diff --git a/services/tests/uiservicestests/AndroidManifest.xml b/services/tests/uiservicestests/AndroidManifest.xml
index 7453c48..5b926e0 100644
--- a/services/tests/uiservicestests/AndroidManifest.xml
+++ b/services/tests/uiservicestests/AndroidManifest.xml
@@ -31,6 +31,7 @@
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.OBSERVE_ROLE_HOLDERS" />
     <uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT"/>
+    <uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" />
 
     <application android:debuggable="true">
         <uses-library android:name="android.test.runner" />
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java
new file mode 100644
index 0000000..793739b
--- /dev/null
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationListenersTest.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.notification;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.INotificationManager;
+import android.content.pm.IPackageManager;
+import android.content.pm.PackageManager;
+import android.service.notification.NotificationStats;
+import android.service.notification.StatusBarNotification;
+import android.testing.TestableContext;
+
+import com.android.server.UiServiceTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.internal.util.reflection.FieldSetter;
+
+import java.util.List;
+
+public class NotificationListenersTest extends UiServiceTestCase {
+
+    @Mock
+    private PackageManager mPm;
+    @Mock
+    private IPackageManager miPm;
+
+    @Mock
+    NotificationManagerService mNm;
+    @Mock
+    private INotificationManager mINm;
+    private TestableContext mContext = spy(getContext());
+
+    NotificationManagerService.NotificationListeners mListeners;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+        getContext().setMockPackageManager(mPm);
+        doNothing().when(mContext).sendBroadcastAsUser(any(), any(), any());
+
+        mListeners = spy(mNm.new NotificationListeners(
+                mContext, new Object(), mock(ManagedServices.UserProfiles.class), miPm));
+        when(mNm.getBinderService()).thenReturn(mINm);
+    }
+
+    @Test
+    public void testNotifyPostedLockedInLockdownMode() {
+        NotificationRecord r = mock(NotificationRecord.class);
+        NotificationRecord old = mock(NotificationRecord.class);
+
+        // before the lockdown mode
+        when(mNm.isInLockDownMode()).thenReturn(false);
+        mListeners.notifyPostedLocked(r, old, true);
+        mListeners.notifyPostedLocked(r, old, false);
+        verify(mListeners, times(2)).getServices();
+
+        // in the lockdown mode
+        reset(r);
+        reset(old);
+        reset(mListeners);
+        when(mNm.isInLockDownMode()).thenReturn(true);
+        mListeners.notifyPostedLocked(r, old, true);
+        mListeners.notifyPostedLocked(r, old, false);
+        verify(mListeners, never()).getServices();
+    }
+
+    @Test
+    public void testnotifyRankingUpdateLockedInLockdownMode() {
+        List chn = mock(List.class);
+
+        // before the lockdown mode
+        when(mNm.isInLockDownMode()).thenReturn(false);
+        mListeners.notifyRankingUpdateLocked(chn);
+        verify(chn, times(1)).size();
+
+        // in the lockdown mode
+        reset(chn);
+        when(mNm.isInLockDownMode()).thenReturn(true);
+        mListeners.notifyRankingUpdateLocked(chn);
+        verify(chn, never()).size();
+    }
+
+    @Test
+    public void testNotifyRemovedLockedInLockdownMode() throws NoSuchFieldException {
+        StatusBarNotification sbn = mock(StatusBarNotification.class);
+        NotificationRecord r = mock(NotificationRecord.class);
+        NotificationStats rs = mock(NotificationStats.class);
+        FieldSetter.setField(r,
+                NotificationRecord.class.getDeclaredField("sbn"),
+                sbn);
+        FieldSetter.setField(mNm,
+                NotificationManagerService.class.getDeclaredField("mHandler"),
+                mock(NotificationManagerService.WorkerHandler.class));
+
+        // before the lockdown mode
+        when(mNm.isInLockDownMode()).thenReturn(false);
+        mListeners.notifyRemovedLocked(r, 0, rs);
+        mListeners.notifyRemovedLocked(r, 0, rs);
+        verify(sbn, times(2)).cloneLight();
+
+        // in the lockdown mode
+        reset(sbn);
+        reset(r);
+        reset(rs);
+        when(mNm.isInLockDownMode()).thenReturn(true);
+        mListeners.notifyRemovedLocked(r, 0, rs);
+        mListeners.notifyRemovedLocked(r, 0, rs);
+        verify(sbn, never()).cloneLight();
+    }
+}
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 90a680b..200e83d 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -45,9 +45,12 @@
 import static android.os.Build.VERSION_CODES.P;
 import static android.service.notification.Adjustment.KEY_IMPORTANCE;
 import static android.service.notification.Adjustment.KEY_USER_SENTIMENT;
+import static android.service.notification.NotificationListenerService.REASON_CANCEL_ALL;
 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
 
+import static com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN;
+
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertNotNull;
@@ -343,8 +346,26 @@
             // Tests for this not being true are in CTS NotificationManagerTest
             return true;
         }
+
+        class StrongAuthTrackerFake extends NotificationManagerService.StrongAuthTracker {
+            private int mGetStrongAuthForUserReturnValue = 0;
+            StrongAuthTrackerFake(Context context) {
+                super(context);
+            }
+
+            public void setGetStrongAuthForUserReturnValue(int val) {
+                mGetStrongAuthForUserReturnValue = val;
+            }
+
+            @Override
+            public int getStrongAuthForUser(int userId) {
+                return mGetStrongAuthForUserReturnValue;
+            }
+        }
     }
 
+    TestableNotificationManagerService.StrongAuthTrackerFake mStrongAuthTracker;
+
     private class TestableToastCallback extends ITransientNotification.Stub {
         @Override
         public void show(IBinder windowToken) {
@@ -394,6 +415,7 @@
         when(mPackageManager.getPackagesForUid(mUid)).thenReturn(new String[]{PKG});
         when(mPackageManagerClient.getPackagesForUid(anyInt())).thenReturn(new String[]{PKG});
         mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
+        when(mUm.getProfileIds(0, false)).thenReturn(new int[]{0});
 
         // write to a test file; the system file isn't readable from tests
         mFile = new File(mContext.getCacheDir(), "test.xml");
@@ -432,6 +454,9 @@
 
         mService.setAudioManager(mAudioManager);
 
+        mStrongAuthTracker = mService.new StrongAuthTrackerFake(mContext);
+        mService.setStrongAuthTracker(mStrongAuthTracker);
+
         // Tests call directly into the Binder.
         mBinderService = mService.getBinderService();
         mInternalService = mService.getInternalService();
@@ -498,6 +523,18 @@
         return generateNotificationRecord(channel, extender, false /* isBubble */);
     }
 
+    private NotificationRecord generateNotificationRecord(NotificationChannel channel, int userId) {
+        if (channel == null) {
+            channel = mTestNotificationChannel;
+        }
+        Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
+                .setContentTitle("foo")
+                .setSmallIcon(android.R.drawable.sym_def_app_icon);
+        StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
+                nb.build(), new UserHandle(userId), null, 0);
+        return new NotificationRecord(mContext, sbn, channel);
+    }
+
     private NotificationRecord generateNotificationRecord(NotificationChannel channel,
             Notification.TvExtender extender, boolean isBubble) {
         if (channel == null) {
@@ -5342,4 +5379,73 @@
         assertEquals(1, notifsAfter.length);
         assertEquals((notifsAfter[0].getNotification().flags & FLAG_BUBBLE), 0);
     }
+
+    @Test
+    public void testGetActiveNotification_filtersUsers() throws Exception {
+        when(mUm.getProfileIds(0, false)).thenReturn(new int[]{0, 10});
+
+        NotificationRecord nr0 =
+                generateNotificationRecord(mTestNotificationChannel, 0);
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag0",
+                nr0.sbn.getId(), nr0.sbn.getNotification(), nr0.sbn.getUserId());
+
+        NotificationRecord nr10 =
+                generateNotificationRecord(mTestNotificationChannel, 10);
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag10",
+                nr10.sbn.getId(), nr10.sbn.getNotification(), nr10.sbn.getUserId());
+
+        NotificationRecord nr11 =
+                generateNotificationRecord(mTestNotificationChannel, 11);
+        mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag11",
+                nr11.sbn.getId(), nr11.sbn.getNotification(), nr11.sbn.getUserId());
+        waitForIdle();
+
+        StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
+        assertEquals(2, notifs.length);
+        for (StatusBarNotification sbn : notifs) {
+            if (sbn.getUserId() == 11) {
+                fail("leaked data across users");
+            }
+        }
+    }
+
+    @Test
+    public void testStrongAuthTracker_isInLockDownMode() {
+        mStrongAuthTracker.setGetStrongAuthForUserReturnValue(
+                STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
+        mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId());
+        assertTrue(mStrongAuthTracker.isInLockDownMode());
+        mStrongAuthTracker.setGetStrongAuthForUserReturnValue(0);
+        mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId());
+        assertFalse(mStrongAuthTracker.isInLockDownMode());
+    }
+
+    @Test
+    public void testCancelAndPostNotificationsWhenEnterAndExitLockDownMode() {
+        // post 2 notifications from 2 packages
+        NotificationRecord pkgA = new NotificationRecord(mContext,
+                generateSbn("a", 1000, 9, 0), mTestNotificationChannel);
+        mService.addNotification(pkgA);
+        NotificationRecord pkgB = new NotificationRecord(mContext,
+                generateSbn("b", 1001, 9, 0), mTestNotificationChannel);
+        mService.addNotification(pkgB);
+
+        // when entering the lockdown mode, cancel the 2 notifications.
+        mStrongAuthTracker.setGetStrongAuthForUserReturnValue(
+                STRONG_AUTH_REQUIRED_AFTER_USER_LOCKDOWN);
+        mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId());
+        assertTrue(mStrongAuthTracker.isInLockDownMode());
+
+        // the notifyRemovedLocked function is called twice due to REASON_LOCKDOWN.
+        ArgumentCaptor<Integer> captor = ArgumentCaptor.forClass(Integer.class);
+        verify(mListeners, times(2)).notifyRemovedLocked(any(), captor.capture(), any());
+        assertEquals(REASON_CANCEL_ALL, captor.getValue().intValue());
+
+        // exit lockdown mode.
+        mStrongAuthTracker.setGetStrongAuthForUserReturnValue(0);
+        mStrongAuthTracker.onStrongAuthRequiredChanged(mContext.getUserId());
+
+        // the notifyPostedLocked function is called twice.
+        verify(mListeners, times(2)).notifyPostedLocked(any(), any());
+    }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index 8f8b746..6482082 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -2031,6 +2031,19 @@
     }
 
     @Test
+    public void testIsGroupBlocked_appCannotCreateAsBlocked() throws Exception {
+        NotificationChannelGroup group = new NotificationChannelGroup("id", "name");
+        group.setBlocked(true);
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true);
+        assertFalse(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId()));
+
+        NotificationChannelGroup group3 = group.clone();
+        group3.setBlocked(false);
+        mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group3, true);
+        assertFalse(mHelper.isGroupBlocked(PKG_N_MR1, UID_N_MR1, group.getId()));
+    }
+
+    @Test
     public void testIsGroup_appCannotResetBlock() throws Exception {
         NotificationChannelGroup group = new NotificationChannelGroup("id", "name");
         mHelper.createNotificationChannelGroup(PKG_N_MR1, UID_N_MR1, group, true);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
index 8936450..cac6f09 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ZenModeHelperTest.java
@@ -20,10 +20,13 @@
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_LIGHTS;
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK;
+import static com.android.server.notification.ZenModeHelper.RULE_LIMIT_PER_PACKAGE;
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
 import static junit.framework.TestCase.assertTrue;
+import static junit.framework.TestCase.fail;
 
 import static org.junit.Assert.assertNotEquals;
 import static org.mockito.ArgumentMatchers.any;
@@ -48,7 +51,9 @@
 import android.content.ComponentName;
 import android.content.ContentResolver;
 import android.content.Context;
+import android.content.pm.ActivityInfo;
 import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
 import android.content.res.Resources;
 import android.content.res.XmlResourceParser;
 import android.media.AudioAttributes;
@@ -77,6 +82,8 @@
 import com.android.server.UiServiceTestCase;
 import com.android.server.notification.ManagedServices.UserProfiles;
 
+import com.google.common.collect.ImmutableList;
+
 import org.junit.Before;
 import org.junit.Test;
 import org.junit.runner.RunWith;
@@ -102,9 +109,12 @@
 
     private static final String EVENTS_DEFAULT_RULE_ID = "EVENTS_DEFAULT_RULE";
     private static final String SCHEDULE_DEFAULT_RULE_ID = "EVERY_NIGHT_DEFAULT_RULE";
+    private static final String CUSTOM_PKG_NAME = "not.android";
+    private static final int CUSTOM_PKG_UID = 1;
 
     ConditionProviders mConditionProviders;
     @Mock NotificationManager mNotificationManager;
+    @Mock PackageManager mPackageManager;
     private Resources mResources;
     private TestableLooper mTestableLooper;
     private ZenModeHelper mZenModeHelperSpy;
@@ -113,7 +123,7 @@
     @Mock AppOpsManager mAppOps;
 
     @Before
-    public void setUp() {
+    public void setUp() throws PackageManager.NameNotFoundException {
         MockitoAnnotations.initMocks(this);
 
         mTestableLooper = TestableLooper.get(this);
@@ -135,6 +145,16 @@
         mConditionProviders.addSystemProvider(new CountdownConditionProvider());
         mZenModeHelperSpy = spy(new ZenModeHelper(mContext, mTestableLooper.getLooper(),
                 mConditionProviders));
+
+        ResolveInfo ri = new ResolveInfo();
+        ri.activityInfo = new ActivityInfo();
+        when(mPackageManager.queryIntentActivitiesAsUser(any(), anyInt(), anyInt())).thenReturn(
+                ImmutableList.of(ri));
+        when(mPackageManager.getPackageUidAsUser(eq(CUSTOM_PKG_NAME), anyInt()))
+                .thenReturn(CUSTOM_PKG_UID);
+        when(mPackageManager.getPackagesForUid(anyInt())).thenReturn(
+                new String[] {getContext().getPackageName()});
+        mZenModeHelperSpy.mPm = mPackageManager;
     }
 
     private XmlResourceParser getDefaultConfigParser() throws IOException, XmlPullParserException {
@@ -1346,6 +1366,34 @@
         assertEquals(zenRule.getName(), ruleInConfig.name);
     }
 
+    @Test
+    public void testAddAutomaticZenRule_beyondSystemLimit() {
+        for (int i = 0; i < RULE_LIMIT_PER_PACKAGE; i++) {
+            ScheduleInfo si = new ScheduleInfo();
+            si.startHour = i;
+            AutomaticZenRule zenRule = new AutomaticZenRule("name" + i,
+                    null,
+                    new ComponentName("android", "ScheduleConditionProvider"),
+                    ZenModeConfig.toScheduleConditionId(si),
+                    new ZenPolicy.Builder().build(),
+                    NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+            String id = mZenModeHelperSpy.addAutomaticZenRule(zenRule, "test");
+            assertNotNull(id);
+        }
+        try {
+            AutomaticZenRule zenRule = new AutomaticZenRule("name",
+                    null,
+                    new ComponentName("android", "ScheduleConditionProvider"),
+                    ZenModeConfig.toScheduleConditionId(new ScheduleInfo()),
+                    new ZenPolicy.Builder().build(),
+                    NotificationManager.INTERRUPTION_FILTER_PRIORITY, true);
+            String id = mZenModeHelperSpy.addAutomaticZenRule(zenRule, "test");
+            fail("allowed too many rules to be created");
+        } catch (IllegalArgumentException e) {
+            // yay
+        }
+    }
+
     private void setupZenConfig() {
         mZenModeHelperSpy.mZenMode = Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
         mZenModeHelperSpy.mConfig.allowAlarms = false;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
index e004cd3..f25110f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskSnapshotPersisterTestBase.java
@@ -23,6 +23,9 @@
 
 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
 
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
 import android.app.ActivityManager.TaskSnapshot;
 import android.content.ComponentName;
 import android.graphics.Canvas;
@@ -32,9 +35,14 @@
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.os.UserManager;
+import android.os.UserManagerInternal;
+
+import com.android.server.LocalServices;
 
 import org.junit.After;
+import org.junit.AfterClass;
 import org.junit.Before;
+import org.junit.BeforeClass;
 
 import java.io.File;
 
@@ -50,10 +58,26 @@
     TaskSnapshotLoader mLoader;
     int mTestUserId;
 
+    @BeforeClass
+    public static void setUpOnce() {
+        final UserManagerInternal userManager = mock(UserManagerInternal.class);
+        LocalServices.addService(UserManagerInternal.class, userManager);
+    }
+
+    @AfterClass
+    public static void tearDownOnce() {
+        LocalServices.removeServiceForTest(UserManagerInternal.class);
+    }
+
     @Before
     public void setUp() {
         final UserManager um = UserManager.get(getInstrumentation().getTargetContext());
         mTestUserId = um.getUserHandle();
+
+        final UserManagerInternal userManagerInternal =
+                LocalServices.getService(UserManagerInternal.class);
+        when(userManagerInternal.isUserUnlocked(mTestUserId)).thenReturn(true);
+
         mPersister = new TaskSnapshotPersister(mWm, userId -> FILES_DIR);
         mLoader = new TaskSnapshotLoader(mPersister);
         mPersister.start();
diff --git a/telecomm/java/android/telecom/TelecomManager.java b/telecomm/java/android/telecom/TelecomManager.java
index 6409203..af5d50d 100644
--- a/telecomm/java/android/telecom/TelecomManager.java
+++ b/telecomm/java/android/telecom/TelecomManager.java
@@ -1125,9 +1125,14 @@
      * when placing calls. The user may still need to enable the {@link PhoneAccount} within
      * the phone app settings before the account is usable.
      * <p>
+     * Note: Each package is limited to 10 {@link PhoneAccount} registrations.
+     * <p>
      * A {@link SecurityException} will be thrown if an app tries to register a
      * {@link PhoneAccountHandle} where the package name specified within
      * {@link PhoneAccountHandle#getComponentName()} does not match the package name of the app.
+     * <p>
+     * A {@link IllegalArgumentException} will be thrown if an app tries to register a
+     * {@link PhoneAccount} when the upper bound limit, 10, has already been reached.
      *
      * @param account The complete {@link PhoneAccount}.
      */