Merge "Fallback BUTTON_MODE to HOME"
diff --git a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
index 043b7f9..a826ec7 100644
--- a/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
+++ b/cmds/bmgr/src/com/android/commands/bmgr/Bmgr.java
@@ -845,6 +845,7 @@
         System.err.println("       bmgr fullbackup PACKAGE...");
         System.err.println("       bmgr backupnow [--monitor|--monitor-verbose] --all|PACKAGE...");
         System.err.println("       bmgr cancel backups");
+        System.err.println("       bmgr init TRANSPORT...");
         System.err.println("");
         System.err.println("The 'backup' command schedules a backup pass for the named package.");
         System.err.println("Note that the backup pass will effectively be a no-op if the package");
@@ -902,7 +903,11 @@
         System.err.println("For each package it will run key/value or full data backup ");
         System.err.println("depending on the package's manifest declarations.");
         System.err.println("The data is sent via the currently active transport.");
+        System.err.println("");
         System.err.println("The 'cancel backups' command cancels all running backups.");
+        System.err.println("");
+        System.err.println("The 'init' command initializes the given transports, wiping all data");
+        System.err.println("from their backing data stores.");
     }
 
     private static class BackupMonitor extends IBackupManagerMonitor.Stub {
diff --git a/core/java/android/annotation/UnsupportedAppUsage.java b/core/java/android/annotation/UnsupportedAppUsage.java
index 05de3e8..fbba6da 100644
--- a/core/java/android/annotation/UnsupportedAppUsage.java
+++ b/core/java/android/annotation/UnsupportedAppUsage.java
@@ -51,6 +51,39 @@
     long trackingBug() default 0;
 
     /**
+     * Indicates that usage of this API is limited to apps based on their target SDK version.
+     *
+     * Access to the API is allowed if the targetSdkVersion in the apps manifest is no greater than
+     * this value. Access checks are performed at runtime.
+     *
+     * This is used to give app developers a grace period to migrate off a non-SDK interface. When
+     * making Android version N, existing APIs can have a maxTargetSdk of N-1 added to them.
+     * Developers must then migrate off the API when their app is updated in future, but it will
+     * continue working in the meantime.
+     *
+     * Possible values are:
+     * <ul>
+     *     <li>
+     *         {@link android.os.Build.VERSION_CODES#O} or {@link android.os.Build.VERSION_CODES#P},
+     *         to limit access to apps targeting these SDKs (or earlier).
+     *     </li>
+     *     <li>
+     *         absent (default value) - All apps can access this API, but doing so may result in
+     *         warnings in the log, UI warnings (on developer builds) and/or strictmode violations.
+     *         The API is likely to be further restricted in future.
+     *     </li>
+     *
+     * </ul>
+     *
+     * Note, if this is set to {@link android.os.Build.VERSION_CODES#O}, apps targeting O
+     * maintenance releases will also be allowed to use the API, and similarly for any future
+     * maintenance releases of P.
+     *
+     * @return The maximum value for an apps targetSdkVersion in order to access this API.
+     */
+    int maxTargetSdk() default Integer.MAX_VALUE;
+
+    /**
      * For debug use only. The expected dex signature to be generated for this API, used to verify
      * parts of the build process.
      *
diff --git a/core/java/android/bluetooth/BluetoothA2dp.java b/core/java/android/bluetooth/BluetoothA2dp.java
index 966f902..d21f76d 100644
--- a/core/java/android/bluetooth/BluetoothA2dp.java
+++ b/core/java/android/bluetooth/BluetoothA2dp.java
@@ -30,6 +30,7 @@
 import android.os.IBinder;
 import android.os.ParcelUuid;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
@@ -270,7 +271,7 @@
         ComponentName comp = intent.resolveSystemService(mContext.getPackageManager(), 0);
         intent.setComponent(comp);
         if (comp == null || !mContext.bindServiceAsUser(intent, mConnection, 0,
-                mContext.getUser())) {
+                UserHandle.CURRENT_OR_SELF)) {
             Log.e(TAG, "Could not bind to Bluetooth A2DP Service with " + intent);
             return false;
         }
diff --git a/core/java/android/bluetooth/le/BluetoothLeScanner.java b/core/java/android/bluetooth/le/BluetoothLeScanner.java
index f5e2a09..ac126ae 100644
--- a/core/java/android/bluetooth/le/BluetoothLeScanner.java
+++ b/core/java/android/bluetooth/le/BluetoothLeScanner.java
@@ -275,7 +275,9 @@
     }
 
     /**
-     * Stops an ongoing Bluetooth LE scan started using a PendingIntent.
+     * Stops an ongoing Bluetooth LE scan started using a PendingIntent. When creating the
+     * PendingIntent parameter, please do not use the FLAG_CANCEL_CURRENT flag. Otherwise, the stop
+     * scan may have no effect.
      *
      * @param callbackIntent The PendingIntent that was used to start the scan.
      * @see #startScan(List, ScanSettings, PendingIntent)
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index a6b81b5..8c2b76f 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2250,6 +2250,7 @@
      * <p>Includes the following extras:
      * <ul>
      * <li> {@link #EXTRA_CHANGED_PACKAGE_LIST} is the set of packages which have been suspended
+     * <li> {@link #EXTRA_CHANGED_UID_LIST} is the set of uids which have been suspended
      * </ul>
      *
      * <p class="note">This is a protected intent that can only be sent
@@ -2262,6 +2263,7 @@
      * <p>Includes the following extras:
      * <ul>
      * <li> {@link #EXTRA_CHANGED_PACKAGE_LIST} is the set of packages which have been unsuspended
+     * <li> {@link #EXTRA_CHANGED_UID_LIST} is the set of uids which have been unsuspended
      * </ul>
      *
      * <p class="note">This is a protected intent that can only be sent
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 83e287a..b7a5352 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -615,6 +615,13 @@
     public static final int PRIVATE_FLAG_PRODUCT = 1 << 19;
 
     /**
+     * Value for {@link #privateFlags}: whether this app is pre-installed on the
+     * google partition of the system image.
+     * @hide
+     */
+    public static final int PRIVATE_FLAG_PRODUCT_SERVICES = 1 << 21;
+
+    /**
      * Value for {@link #privateFlags}: whether this app is signed with the
      * platform key.
      * @hide
@@ -639,6 +646,7 @@
             PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE,
             PRIVATE_FLAG_PRIVILEGED,
             PRIVATE_FLAG_PRODUCT,
+            PRIVATE_FLAG_PRODUCT_SERVICES,
             PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER,
             PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY,
             PRIVATE_FLAG_STATIC_SHARED_LIBRARY,
@@ -1888,6 +1896,11 @@
         return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
     }
 
+    /** @hide */
+    public boolean isProductServices() {
+        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES) != 0;
+    }
+
     /**
      * Returns whether or not this application was installed as a virtual preload.
      */
diff --git a/core/java/android/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 823d995..20e1454e 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -649,14 +649,13 @@
     public abstract boolean isDataRestoreSafe(@NonNull Signature restoringFromSig,
             @NonNull String packageName);
 
-
     /**
-     * Returns true if the the signing information for {@code clientUid} is sufficient to gain
-     * access gated by {@code capability}.  This can happen if the two UIDs have the same signing
-     * information, if the signing information {@code clientUid} indicates that it has the signing
-     * certificate for {@code serverUid} in its signing history (if it was previously signed by it),
-     * or if the signing certificate for {@code clientUid} is in ths signing history for {@code
-     * serverUid} and with the {@code capability} specified.
+     * Returns {@code true} if the the signing information for {@code clientUid} is sufficient
+     * to gain access gated by {@code capability}.  This can happen if the two UIDs have the
+     * same signing information, if the signing information {@code clientUid} indicates that
+     * it has the signing certificate for {@code serverUid} in its signing history (if it was
+     * previously signed by it), or if the signing certificate for {@code clientUid} is in the
+     * signing history for {@code serverUid} and with the {@code capability} specified.
      */
     public abstract boolean hasSignatureCapability(int serverUid, int clientUid,
             @PackageParser.SigningDetails.CertCapabilities int capability);
@@ -697,4 +696,10 @@
      */
     public abstract void freeStorage(String volumeUuid, long bytes, int storageFlags)
             throws IOException;
+
+    /** Returns {@code true} if the specified component is enabled and matches the given flags. */
+    public abstract boolean isEnabledAndMatches(@NonNull ComponentInfo info, int flags, int userId);
+
+    /** Returns {@code true} if the given user requires extra badging for icons. */
+    public abstract boolean userNeedsBadging(int userId);
 }
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 876cf2b..83757c4 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -6785,6 +6785,11 @@
         }
 
         /** @hide */
+        public boolean isProductServices() {
+            return applicationInfo.isProductServices();
+        }
+
+        /** @hide */
         public boolean isPrivileged() {
             return applicationInfo.isPrivilegedApp();
         }
diff --git a/core/java/android/hardware/location/ContextHubManager.java b/core/java/android/hardware/location/ContextHubManager.java
index de13c81..12d0531 100644
--- a/core/java/android/hardware/location/ContextHubManager.java
+++ b/core/java/android/hardware/location/ContextHubManager.java
@@ -549,7 +549,7 @@
      * Set a callback to receive messages from the context hub
      *
      * @param callback Callback object
-     * @param handler Handler object
+     * @param handler Handler object, if null uses the Handler of the main Looper
      *
      * @see Callback
      *
@@ -568,7 +568,7 @@
                 return -1;
             }
             mCallback = callback;
-            mCallbackHandler = handler;
+            mCallbackHandler = (handler == null) ? new Handler(mMainLooper) : handler;
         }
         return 0;
     }
@@ -722,26 +722,31 @@
         return 0;
     }
 
+    /**
+     * Invokes the ContextHubManager.Callback callback registered with the ContextHubManager.
+     *
+     * @param hubId The ID of the Context Hub the message came from
+     * @param nanoAppId The instance ID of the nanoapp the message came from
+     * @param message The message to provide the callback
+     */
+    private synchronized void invokeOnMessageReceiptCallback(
+            int hubId, int nanoAppId, ContextHubMessage message) {
+        if (mCallback != null) {
+            mCallback.onMessageReceipt(hubId, nanoAppId, message);
+        }
+    }
+
     private final IContextHubCallback.Stub mClientCallback = new IContextHubCallback.Stub() {
         @Override
-        public void onMessageReceipt(final int hubId, final int nanoAppId,
-                final ContextHubMessage message) {
-            if (mCallback != null) {
-                synchronized(this) {
-                    final Callback callback = mCallback;
-                    Handler handler = mCallbackHandler == null ?
-                            new Handler(mMainLooper) : mCallbackHandler;
-                    handler.post(new Runnable() {
-                        @Override
-                        public void run() {
-                            callback.onMessageReceipt(hubId, nanoAppId, message);
-                        }
-                    });
-                }
-            } else if (mLocalCallback != null) {
-                // we always ensure that mCallback takes precedence, because mLocalCallback is only
-                // for internal compatibility
-                synchronized (this) {
+        public void onMessageReceipt(
+                final int hubId, final int nanoAppId, final ContextHubMessage message) {
+            synchronized (ContextHubManager.this) {
+                if (mCallback != null) {
+                    mCallbackHandler.post(
+                            () -> invokeOnMessageReceiptCallback(hubId, nanoAppId, message));
+                } else if (mLocalCallback != null) {
+                    // We always ensure that mCallback takes precedence, because mLocalCallback is
+                    // only for internal compatibility
                     mLocalCallback.onMessageReceipt(hubId, nanoAppId, message);
                 }
             }
diff --git a/core/java/android/os/Environment.java b/core/java/android/os/Environment.java
index e32ed9d..347f60f 100644
--- a/core/java/android/os/Environment.java
+++ b/core/java/android/os/Environment.java
@@ -45,6 +45,7 @@
     private static final String ENV_ODM_ROOT = "ODM_ROOT";
     private static final String ENV_VENDOR_ROOT = "VENDOR_ROOT";
     private static final String ENV_PRODUCT_ROOT = "PRODUCT_ROOT";
+    private static final String ENV_PRODUCT_SERVICES_ROOT = "PRODUCT_SERVICES_ROOT";
 
     /** {@hide} */
     public static final String DIR_ANDROID = "Android";
@@ -67,6 +68,8 @@
     private static final File DIR_ODM_ROOT = getDirectory(ENV_ODM_ROOT, "/odm");
     private static final File DIR_VENDOR_ROOT = getDirectory(ENV_VENDOR_ROOT, "/vendor");
     private static final File DIR_PRODUCT_ROOT = getDirectory(ENV_PRODUCT_ROOT, "/product");
+    private static final File DIR_PRODUCT_SERVICES_ROOT = getDirectory(ENV_PRODUCT_SERVICES_ROOT,
+                                                           "/product_services");
 
     private static UserEnvironment sCurrentUser;
     private static boolean sUserRequired;
@@ -196,6 +199,16 @@
     }
 
     /**
+     * Return root directory of the "product_services" partition holding middleware
+     * services if any. If present, the partition is mounted read-only.
+     *
+     * @hide
+     */
+    public static File getProductServicesDirectory() {
+        return DIR_PRODUCT_SERVICES_ROOT;
+    }
+
+    /**
      * Return the system directory for a user. This is for use by system
      * services to store files relating to the user. This directory will be
      * automatically deleted when the user is removed.
diff --git a/core/java/android/preference/SeekBarVolumizer.java b/core/java/android/preference/SeekBarVolumizer.java
index ad7b103..e8daf21 100644
--- a/core/java/android/preference/SeekBarVolumizer.java
+++ b/core/java/android/preference/SeekBarVolumizer.java
@@ -104,7 +104,7 @@
 
     @UnsupportedAppUsage
     public SeekBarVolumizer(Context context, int streamType, Uri defaultUri, Callback callback) {
-        this(context, streamType, defaultUri, callback, true);
+        this(context, streamType, defaultUri, callback, true /* playSample */);
     }
 
     public SeekBarVolumizer(
diff --git a/core/java/android/service/autofill/InternalOnClickAction.java b/core/java/android/service/autofill/InternalOnClickAction.java
index 6dc49b6..6602f2d 100644
--- a/core/java/android/service/autofill/InternalOnClickAction.java
+++ b/core/java/android/service/autofill/InternalOnClickAction.java
@@ -30,7 +30,7 @@
 public abstract class InternalOnClickAction implements OnClickAction, Parcelable {
 
     /**
-     * Applies the action to the children of the {@rootView} when clicked.
+     * Applies the action to the children of the {@code rootView} when clicked.
      */
     public abstract void onClick(@NonNull ViewGroup rootView);
 }
diff --git a/core/java/android/service/autofill/VisibilitySetterAction.java b/core/java/android/service/autofill/VisibilitySetterAction.java
index cdd7102..9f977d7 100644
--- a/core/java/android/service/autofill/VisibilitySetterAction.java
+++ b/core/java/android/service/autofill/VisibilitySetterAction.java
@@ -80,7 +80,7 @@
          * @param id view resource id of the children view.
          * @param visibility one of {@link View#VISIBLE}, {@link View#INVISIBLE}, or
          *            {@link View#GONE}.
-         * @throw {@link IllegalArgumentException} if visibility is not one of {@link View#VISIBLE},
+         * @throws IllegalArgumentException if visibility is not one of {@link View#VISIBLE},
          * {@link View#INVISIBLE}, or {@link View#GONE}.
          */
         public Builder(@IdRes int id, @Visibility int visibility) {
@@ -93,7 +93,7 @@
          * @param id view resource id of the children view.
          * @param visibility one of {@link View#VISIBLE}, {@link View#INVISIBLE}, or
          *            {@link View#GONE}.
-         * @throw {@link IllegalArgumentException} if visibility is not one of {@link View#VISIBLE},
+         * @throws IllegalArgumentException if visibility is not one of {@link View#VISIBLE},
          * {@link View#INVISIBLE}, or {@link View#GONE}.
          */
         public Builder setVisibility(@IdRes int id, @Visibility int visibility) {
diff --git a/core/java/android/service/notification/NotificationStats.java b/core/java/android/service/notification/NotificationStats.java
index 76d5328..9e23de1 100644
--- a/core/java/android/service/notification/NotificationStats.java
+++ b/core/java/android/service/notification/NotificationStats.java
@@ -52,7 +52,7 @@
     /**
      * Notification has not been dismissed yet.
      */
-    public static final int DISMISSAL_NOT_DISMISSED = -1;
+    public static final int DISMISSAL_NOT_DISMISSED = -1000;
     /**
      * Notification has been dismissed from a {@link NotificationListenerService} or the app
      * itself.
@@ -71,6 +71,37 @@
      */
     public static final int DISMISSAL_SHADE = 3;
 
+    /** @hide */
+    @IntDef(prefix = { "DISMISS_SENTIMENT_" }, value = {
+            DISMISS_SENTIMENT_UNKNOWN, DISMISS_SENTIMENT_NEGATIVE, DISMISS_SENTIMENT_NEUTRAL,
+            DISMISS_SENTIMENT_POSITIVE
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    public @interface DismissalSentiment {}
+
+    /**
+     * No information is available about why this notification was dismissed, or the notification
+     * isn't dismissed yet.
+     */
+    public static final int DISMISS_SENTIMENT_UNKNOWN = -1000;
+    /**
+     * The user indicated while dismissing that they did not like the notification.
+     */
+    public static final int DISMISS_SENTIMENT_NEGATIVE = 0;
+    /**
+     * The user didn't indicate one way or another how they felt about the notification while
+     * dismissing it.
+     */
+    public static final int DISMISS_SENTIMENT_NEUTRAL = 1;
+    /**
+     * The user indicated while dismissing that they did like the notification.
+     */
+    public static final int DISMISS_SENTIMENT_POSITIVE = 2;
+
+
+    private @DismissalSentiment
+    int mDismissalSentiment = DISMISS_SENTIMENT_UNKNOWN;
+
     public NotificationStats() {
     }
 
@@ -82,6 +113,7 @@
         mViewedSettings = in.readByte() != 0;
         mInteracted = in.readByte() != 0;
         mDismissalSurface = in.readInt();
+        mDismissalSentiment = in.readInt();
     }
 
     @Override
@@ -93,6 +125,7 @@
         dest.writeByte((byte) (mViewedSettings ? 1 : 0));
         dest.writeByte((byte) (mInteracted ? 1 : 0));
         dest.writeInt(mDismissalSurface);
+        dest.writeInt(mDismissalSentiment);
     }
 
     @Override
@@ -212,6 +245,21 @@
         mDismissalSurface = dismissalSurface;
     }
 
+    /**
+     * Records whether the user indicated how they felt about a notification before or
+     * during dismissal.
+     */
+    public void setDismissalSentiment(@DismissalSentiment int dismissalSentiment) {
+        mDismissalSentiment = dismissalSentiment;
+    }
+
+    /**
+     * Returns how the user indicated they felt about a notification before or during dismissal.
+     */
+    public @DismissalSentiment int getDismissalSentiment() {
+        return mDismissalSentiment;
+    }
+
     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
diff --git a/core/java/android/util/FeatureFlagUtils.java b/core/java/android/util/FeatureFlagUtils.java
index 0f8ca44..c037cd0 100644
--- a/core/java/android/util/FeatureFlagUtils.java
+++ b/core/java/android/util/FeatureFlagUtils.java
@@ -40,7 +40,6 @@
     static {
         DEFAULT_FLAGS = new HashMap<>();
         DEFAULT_FLAGS.put("settings_battery_display_app_list", "false");
-        DEFAULT_FLAGS.put("settings_condition_manager_v2", "true");
         DEFAULT_FLAGS.put("settings_bluetooth_while_driving", "false");
         DEFAULT_FLAGS.put("settings_audio_switcher", "true");
         DEFAULT_FLAGS.put("settings_systemui_theme", "true");
diff --git a/core/java/android/view/DisplayCutout.java b/core/java/android/view/DisplayCutout.java
index 496bc9f..5f80d31 100644
--- a/core/java/android/view/DisplayCutout.java
+++ b/core/java/android/view/DisplayCutout.java
@@ -325,6 +325,7 @@
      *
      * @hide
      */
+    @VisibleForTesting
     public static DisplayCutout fromBoundingRect(int left, int top, int right, int bottom) {
         Region r = Region.obtain();
         r.set(left, top, right, bottom);
@@ -422,8 +423,11 @@
         m.postTranslate(offsetX, 0);
         p.transform(m);
 
-        addToRegion(p, r);
+        final Rect tmpRect = new Rect();
+        toRectAndAddToRegion(p, r, tmpRect);
+        final int topInset = tmpRect.bottom;
 
+        final int bottomInset;
         if (bottomSpec != null) {
             final Path bottomPath;
             try {
@@ -436,10 +440,17 @@
             m.postTranslate(0, displayHeight);
             bottomPath.transform(m);
             p.addPath(bottomPath);
-            addToRegion(bottomPath, r);
+            toRectAndAddToRegion(bottomPath, r, tmpRect);
+            bottomInset = displayHeight - tmpRect.top;
+        } else {
+            bottomInset = 0;
         }
 
-        final Pair<Path, DisplayCutout> result = new Pair<>(p, fromBounds(r));
+        // Reuse tmpRect as the inset rect we store into the DisplayCutout instance.
+        tmpRect.set(0, topInset, 0, bottomInset);
+        final DisplayCutout cutout = new DisplayCutout(tmpRect, r, false /* copyArguments */);
+
+        final Pair<Path, DisplayCutout> result = new Pair<>(p, cutout);
         synchronized (CACHE_LOCK) {
             sCachedSpec = spec;
             sCachedDisplayWidth = displayWidth;
@@ -450,12 +461,11 @@
         return result;
     }
 
-    private static void addToRegion(Path p, Region r) {
+    private static void toRectAndAddToRegion(Path p, Region inoutRegion, Rect inoutRect) {
         final RectF rectF = new RectF();
-        final Rect rect = new Rect();
         p.computeBounds(rectF, false /* unused */);
-        rectF.round(rect);
-        r.op(rect, Op.UNION);
+        rectF.round(inoutRect);
+        inoutRegion.op(inoutRect, Op.UNION);
     }
 
     private static Region boundingRectsToRegion(List<Rect> rects) {
diff --git a/core/java/android/view/DisplayListCanvas.java b/core/java/android/view/DisplayListCanvas.java
index a7755a2..4b946d7 100644
--- a/core/java/android/view/DisplayListCanvas.java
+++ b/core/java/android/view/DisplayListCanvas.java
@@ -40,7 +40,7 @@
     // view hierarchy because display lists are generated recursively.
     private static final int POOL_LIMIT = 25;
 
-    private static final int MAX_BITMAP_SIZE = 100 * 1024 * 1024; // 100 MB
+    public static final int MAX_BITMAP_SIZE = 100 * 1024 * 1024; // 100 MB
 
     private static final SynchronizedPool<DisplayListCanvas> sPool =
             new SynchronizedPool<>(POOL_LIMIT);
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 6268a4a..0119d2e 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -8663,7 +8663,7 @@
          * Compare two views based on their bounds. Use the bounds of their children to break ties.
          *
          * @param holder1 Holder of first view to compare
-         * @param holder2 Holder of second view to compare. Must have the same root at holder1.
+         * @param holder2 Holder of second view to compare. Must have the same root as holder1.
          * @return The compare result, with equality if no good comparison was found.
          */
         private static int compareBoundsOfTree(
@@ -8756,6 +8756,7 @@
 
         private void clear() {
             mView = null;
+            mRoot = null;
             mLocation.set(0, 0, 0, 0);
         }
     }
diff --git a/core/java/android/widget/DatePickerSpinnerDelegate.java b/core/java/android/widget/DatePickerSpinnerDelegate.java
index dba74b1..f88a4e2 100644
--- a/core/java/android/widget/DatePickerSpinnerDelegate.java
+++ b/core/java/android/widget/DatePickerSpinnerDelegate.java
@@ -16,6 +16,7 @@
 
 package android.widget;
 
+import android.annotation.UnsupportedAppUsage;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.content.res.TypedArray;
@@ -502,6 +503,7 @@
                 || mCurrentDate.get(Calendar.DAY_OF_MONTH) != dayOfMonth);
     }
 
+    @UnsupportedAppUsage
     private void setDate(int year, int month, int dayOfMonth) {
         mCurrentDate.set(year, month, dayOfMonth);
         resetAutofilledValue();
@@ -512,6 +514,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void updateSpinners() {
         // set the spinner ranges respecting the min and max dates
         if (mCurrentDate.equals(mMinDate)) {
@@ -564,6 +567,7 @@
     /**
      * Updates the calendar view with the current date.
      */
+    @UnsupportedAppUsage
     private void updateCalendarView() {
         mCalendarView.setDate(mCurrentDate.getTimeInMillis(), false, false);
     }
@@ -572,6 +576,7 @@
     /**
      * Notifies the listener, if such, for a change in the selected date.
      */
+    @UnsupportedAppUsage
     private void notifyDateChanged() {
         mDelegator.sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED);
         if (mOnDateChangedListener != null) {
@@ -627,6 +632,7 @@
         }
     }
 
+    @UnsupportedAppUsage
     private void updateInputState() {
         // Make sure that if the user changes the value and the IME is active
         // for one of the inputs if this widget, the IME is closed. If the user
diff --git a/core/java/com/android/internal/app/WindowDecorActionBar.java b/core/java/com/android/internal/app/WindowDecorActionBar.java
index 1b3faf5..119f30d 100644
--- a/core/java/com/android/internal/app/WindowDecorActionBar.java
+++ b/core/java/com/android/internal/app/WindowDecorActionBar.java
@@ -33,6 +33,7 @@
 import android.animation.AnimatorSet;
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
+import android.annotation.UnsupportedAppUsage;
 import android.app.ActionBar;
 import android.app.Activity;
 import android.app.Dialog;
@@ -79,6 +80,7 @@
     private ActionBarOverlayLayout mOverlayLayout;
     private ActionBarContainer mContainerView;
     private DecorToolbar mDecorToolbar;
+    @UnsupportedAppUsage
     private ActionBarContextView mContextView;
     private ActionBarContainer mSplitView;
     private View mContentView;
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index a79e15a..b3af147 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -60,7 +60,7 @@
             int uid, int initialPid, String message, int userId);
     void onClearAllNotifications(int userId);
     void onNotificationClear(String pkg, String tag, int id, int userId, String key,
-            int dismissalSurface, in NotificationVisibility nv);
+            int dismissalSurface, int dismissalSentiment, in NotificationVisibility nv);
     void onNotificationVisibilityChanged( in NotificationVisibility[] newlyVisibleKeys,
             in NotificationVisibility[] noLongerVisibleKeys);
     void onNotificationExpansionChanged(in String key, in boolean userAction, in boolean expanded);
diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java
index c5be8e4..0a787b9 100644
--- a/core/java/com/android/server/SystemConfig.java
+++ b/core/java/com/android/server/SystemConfig.java
@@ -169,6 +169,10 @@
     final ArrayMap<String, ArraySet<String>> mProductPrivAppPermissions = new ArrayMap<>();
     final ArrayMap<String, ArraySet<String>> mProductPrivAppDenyPermissions = new ArrayMap<>();
 
+    final ArrayMap<String, ArraySet<String>> mProductServicesPrivAppPermissions = new ArrayMap<>();
+    final ArrayMap<String, ArraySet<String>> mProductServicesPrivAppDenyPermissions =
+            new ArrayMap<>();
+
     final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>();
 
     public static SystemConfig getInstance() {
@@ -276,6 +280,14 @@
         return mProductPrivAppDenyPermissions.get(packageName);
     }
 
+    public ArraySet<String> getProductServicesPrivAppPermissions(String packageName) {
+        return mProductServicesPrivAppPermissions.get(packageName);
+    }
+
+    public ArraySet<String> getProductServicesPrivAppDenyPermissions(String packageName) {
+        return mProductServicesPrivAppDenyPermissions.get(packageName);
+    }
+
     public Map<String, Boolean> getOemPermissions(String packageName) {
         final Map<String, Boolean> oemPermissions = mOemPermissions.get(packageName);
         if (oemPermissions != null) {
@@ -326,6 +338,17 @@
                 Environment.getProductDirectory(), "etc", "sysconfig"), productPermissionFlag);
         readPermissions(Environment.buildPath(
                 Environment.getProductDirectory(), "etc", "permissions"), productPermissionFlag);
+
+        // Allow /product_services to customize system configs around libs, features, permissions
+        // and apps.
+        int productServicesPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS |
+                ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS;
+        readPermissions(Environment.buildPath(
+                Environment.getProductServicesDirectory(), "etc", "sysconfig"),
+                productServicesPermissionFlag);
+        readPermissions(Environment.buildPath(
+                Environment.getProductServicesDirectory(), "etc", "permissions"),
+                productServicesPermissionFlag);
     }
 
     void readPermissions(File libraryDir, int permissionFlag) {
@@ -659,22 +682,27 @@
                     }
                     XmlUtils.skipCurrentTag(parser);
                 } else if ("privapp-permissions".equals(name) && allowPrivappPermissions) {
-                    // privapp permissions from system, vendor and product partitions are stored
-                    // separately. This is to prevent xml files in the vendor partition from
-                    // granting permissions to priv apps in the system partition and vice
-                    // versa.
+                    // privapp permissions from system, vendor, product and product_services
+                    // partitions are stored separately. This is to prevent xml files in the vendor
+                    // partition from granting permissions to priv apps in the system partition and
+                    // vice versa.
                     boolean vendor = permFile.toPath().startsWith(
-                            Environment.getVendorDirectory().toPath())
+                            Environment.getVendorDirectory().toPath() + "/")
                             || permFile.toPath().startsWith(
-                                Environment.getOdmDirectory().toPath());
+                                Environment.getOdmDirectory().toPath() + "/");
                     boolean product = permFile.toPath().startsWith(
-                            Environment.getProductDirectory().toPath());
+                            Environment.getProductDirectory().toPath() + "/");
+                    boolean productServices = permFile.toPath().startsWith(
+                            Environment.getProductServicesDirectory().toPath() + "/");
                     if (vendor) {
                         readPrivAppPermissions(parser, mVendorPrivAppPermissions,
                                 mVendorPrivAppDenyPermissions);
                     } else if (product) {
                         readPrivAppPermissions(parser, mProductPrivAppPermissions,
                                 mProductPrivAppDenyPermissions);
+                    } else if (productServices) {
+                        readPrivAppPermissions(parser, mProductServicesPrivAppPermissions,
+                                mProductServicesPrivAppDenyPermissions);
                     } else {
                         readPrivAppPermissions(parser, mPrivAppPermissions,
                                 mPrivAppDenyPermissions);
diff --git a/core/jni/android/graphics/Bitmap.cpp b/core/jni/android/graphics/Bitmap.cpp
index 02076bd..8083a6a 100755
--- a/core/jni/android/graphics/Bitmap.cpp
+++ b/core/jni/android/graphics/Bitmap.cpp
@@ -310,180 +310,17 @@
 using namespace android;
 using namespace android::bitmap;
 
-///////////////////////////////////////////////////////////////////////////////
-// Conversions to/from SkColor, for get/setPixels, and the create method, which
-// is basically like setPixels
-
-typedef void (*FromColorProc)(void* dst, const SkColor src[], int width,
-                              int x, int y);
-
-static void FromColor_F16(void* dst, const SkColor src[], int width,
-                          int, int) {
-    uint64_t* d = (uint64_t*)dst;
-
-    for (int i = 0; i < width; i++) {
-        *d++ = SkColor4f::FromColor(*src++).premul().toF16();
-    }
-}
-
-static void FromColor_F16_Raw(void* dst, const SkColor src[], int width,
-                          int, int) {
-    uint64_t* d = (uint64_t*)dst;
-
-    for (int i = 0; i < width; i++) {
-        const SkColor4f color = SkColor4f::FromColor(*src++);
-        uint16_t* scratch = reinterpret_cast<uint16_t*>(d++);
-        scratch[0] = SkFloatToHalf(color.fR);
-        scratch[1] = SkFloatToHalf(color.fG);
-        scratch[2] = SkFloatToHalf(color.fB);
-        scratch[3] = SkFloatToHalf(color.fA);
-    }
-}
-
-static void FromColor_D32(void* dst, const SkColor src[], int width,
-                          int, int) {
-    SkPMColor* d = (SkPMColor*)dst;
-
-    for (int i = 0; i < width; i++) {
-        *d++ = SkPreMultiplyColor(*src++);
-    }
-}
-
-static void FromColor_D32_Raw(void* dst, const SkColor src[], int width,
-                          int, int) {
-    // Needed to thwart the unreachable code detection from clang.
-    static const bool sk_color_ne_zero = SK_COLOR_MATCHES_PMCOLOR_BYTE_ORDER;
-
-    // SkColor's ordering may be different from SkPMColor
-    if (sk_color_ne_zero) {
-        memcpy(dst, src, width * sizeof(SkColor));
-        return;
-    }
-
-    // order isn't same, repack each pixel manually
-    SkPMColor* d = (SkPMColor*)dst;
-    for (int i = 0; i < width; i++) {
-        SkColor c = *src++;
-        *d++ = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
-                                   SkColorGetG(c), SkColorGetB(c));
-    }
-}
-
-static void FromColor_D565(void* dst, const SkColor src[], int width,
-                           int x, int y) {
-    uint16_t* d = (uint16_t*)dst;
-
-    DITHER_565_SCAN(y);
-    for (int stop = x + width; x < stop; x++) {
-        SkColor c = *src++;
-        *d++ = SkDitherRGBTo565(SkColorGetR(c), SkColorGetG(c), SkColorGetB(c),
-                                DITHER_VALUE(x));
-    }
-}
-
-static void FromColor_D4444(void* dst, const SkColor src[], int width,
-                            int x, int y) {
-    SkPMColor16* d = (SkPMColor16*)dst;
-
-    DITHER_4444_SCAN(y);
-    for (int stop = x + width; x < stop; x++) {
-        SkPMColor pmc = SkPreMultiplyColor(*src++);
-        *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
-//        *d++ = SkPixel32ToPixel4444(pmc);
-    }
-}
-
-static void FromColor_D4444_Raw(void* dst, const SkColor src[], int width,
-                            int x, int y) {
-    SkPMColor16* d = (SkPMColor16*)dst;
-
-    DITHER_4444_SCAN(y);
-    for (int stop = x + width; x < stop; x++) {
-        SkColor c = *src++;
-
-        // SkPMColor is used because the ordering is ARGB32, even though the target actually premultiplied
-        SkPMColor pmc = SkPackARGB32NoCheck(SkColorGetA(c), SkColorGetR(c),
-                                            SkColorGetG(c), SkColorGetB(c));
-        *d++ = SkDitherARGB32To4444(pmc, DITHER_VALUE(x));
-//        *d++ = SkPixel32ToPixel4444(pmc);
-    }
-}
-
-static void FromColor_DA8(void* dst, const SkColor src[], int width, int x, int y) {
-    uint8_t* d = (uint8_t*)dst;
-
-    for (int stop = x + width; x < stop; x++) {
-        *d++ = SkColorGetA(*src++);
-    }
-}
-
-// can return NULL
-static FromColorProc ChooseFromColorProc(const SkBitmap& bitmap) {
-    switch (bitmap.colorType()) {
-        case kN32_SkColorType:
-            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D32 : FromColor_D32_Raw;
-        case kARGB_4444_SkColorType:
-            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_D4444 :
-                    FromColor_D4444_Raw;
-        case kRGB_565_SkColorType:
-            return FromColor_D565;
-        case kAlpha_8_SkColorType:
-            return FromColor_DA8;
-        case kRGBA_F16_SkColorType:
-            return bitmap.alphaType() == kPremul_SkAlphaType ? FromColor_F16 : FromColor_F16_Raw;
-        default:
-            break;
-    }
-    return NULL;
-}
-
-static bool IsColorSpaceSRGB(SkColorSpace* colorSpace) {
-    return colorSpace == nullptr || colorSpace->isSRGB();
-}
-
 bool GraphicsJNI::SetPixels(JNIEnv* env, jintArray srcColors, int srcOffset, int srcStride,
-        int x, int y, int width, int height, const SkBitmap& dstBitmap) {
-    void* dst = dstBitmap.getPixels();
-    FromColorProc proc = ChooseFromColorProc(dstBitmap);
-
-    if (NULL == dst || NULL == proc) {
-        return false;
-    }
-
+        int x, int y, int width, int height, SkBitmap* dstBitmap) {
     const jint* array = env->GetIntArrayElements(srcColors, NULL);
     const SkColor* src = (const SkColor*)array + srcOffset;
 
-    // reset to to actual choice from caller
-    dst = dstBitmap.getAddr(x, y);
+    auto sRGB = SkColorSpace::MakeSRGB();
+    SkImageInfo srcInfo = SkImageInfo::Make(
+            width, height, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
+    SkPixmap srcPM(srcInfo, src, srcStride * 4);
 
-    SkColorSpace* colorSpace = dstBitmap.colorSpace();
-    if (dstBitmap.colorType() == kRGBA_F16_SkColorType || IsColorSpaceSRGB(colorSpace)) {
-        // now copy/convert each scanline
-        for (int y = 0; y < height; y++) {
-            proc(dst, src, width, x, y);
-            src += srcStride;
-            dst = (char*)dst + dstBitmap.rowBytes();
-        }
-    } else {
-        auto sRGB = SkColorSpace::MakeSRGB();
-        auto xform = SkColorSpaceXform::New(sRGB.get(), colorSpace);
-
-        std::unique_ptr<SkColor[]> row(new SkColor[width]);
-
-        // now copy/convert each scanline
-        for (int y = 0; y < height; y++) {
-            memcpy(row.get(), src, sizeof(SkColor) * width);
-            xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, row.get(),
-                    SkColorSpaceXform::kBGRA_8888_ColorFormat, row.get(), width,
-                    SkAlphaType::kUnpremul_SkAlphaType);
-
-            proc(dst, row.get(), width, x, y);
-            src += srcStride;
-            dst = (char*)dst + dstBitmap.rowBytes();
-        }
-    }
-
-    dstBitmap.notifyPixelsChanged();
+    dstBitmap->writePixels(srcPM, x, y);
 
     env->ReleaseIntArrayElements(srcColors, const_cast<jint*>(array), JNI_ABORT);
     return true;
@@ -491,90 +328,6 @@
 
 //////////////////// ToColor procs
 
-typedef void (*ToColorProc)(SkColor dst[], const void* src, int width);
-
-static void ToColor_F16_Alpha(SkColor dst[], const void* src, int width) {
-    SkASSERT(width > 0);
-    uint64_t* s = (uint64_t*)src;
-    do {
-        *dst++ = SkPM4f::FromF16((const uint16_t*) s++).unpremul().toSkColor();
-    } while (--width != 0);
-}
-
-static void ToColor_F16_Raw(SkColor dst[], const void* src, int width) {
-    SkASSERT(width > 0);
-    uint64_t* s = (uint64_t*)src;
-    do {
-        *dst++ = Sk4f_toS32(swizzle_rb(SkHalfToFloat_finite_ftz(*s++)));
-    } while (--width != 0);
-}
-
-static void ToColor_S32_Alpha(SkColor dst[], const void* src, int width) {
-    SkASSERT(width > 0);
-    const SkPMColor* s = (const SkPMColor*)src;
-    do {
-        *dst++ = SkUnPreMultiply::PMColorToColor(*s++);
-    } while (--width != 0);
-}
-
-static void ToColor_S32_Raw(SkColor dst[], const void* src, int width) {
-    SkASSERT(width > 0);
-    const SkPMColor* s = (const SkPMColor*)src;
-    do {
-        SkPMColor c = *s++;
-        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
-                                SkGetPackedG32(c), SkGetPackedB32(c));
-    } while (--width != 0);
-}
-
-static void ToColor_S32_Opaque(SkColor dst[], const void* src, int width) {
-    SkASSERT(width > 0);
-    const SkPMColor* s = (const SkPMColor*)src;
-    do {
-        SkPMColor c = *s++;
-        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
-                               SkGetPackedB32(c));
-    } while (--width != 0);
-}
-
-static void ToColor_S4444_Alpha(SkColor dst[], const void* src, int width) {
-    SkASSERT(width > 0);
-    const SkPMColor16* s = (const SkPMColor16*)src;
-    do {
-        *dst++ = SkUnPreMultiply::PMColorToColor(SkPixel4444ToPixel32(*s++));
-    } while (--width != 0);
-}
-
-static void ToColor_S4444_Raw(SkColor dst[], const void* src, int width) {
-    SkASSERT(width > 0);
-    const SkPMColor16* s = (const SkPMColor16*)src;
-    do {
-        SkPMColor c = SkPixel4444ToPixel32(*s++);
-        *dst++ = SkColorSetARGB(SkGetPackedA32(c), SkGetPackedR32(c),
-                                SkGetPackedG32(c), SkGetPackedB32(c));
-    } while (--width != 0);
-}
-
-static void ToColor_S4444_Opaque(SkColor dst[], const void* src, int width) {
-    SkASSERT(width > 0);
-    const SkPMColor16* s = (const SkPMColor16*)src;
-    do {
-        SkPMColor c = SkPixel4444ToPixel32(*s++);
-        *dst++ = SkColorSetRGB(SkGetPackedR32(c), SkGetPackedG32(c),
-                               SkGetPackedB32(c));
-    } while (--width != 0);
-}
-
-static void ToColor_S565(SkColor dst[], const void* src, int width) {
-    SkASSERT(width > 0);
-    const uint16_t* s = (const uint16_t*)src;
-    do {
-        uint16_t c = *s++;
-        *dst++ =  SkColorSetRGB(SkPacked16ToR32(c), SkPacked16ToG32(c),
-                                SkPacked16ToB32(c));
-    } while (--width != 0);
-}
-
 static void ToColor_SA8(SkColor dst[], const void* src, int width) {
     SkASSERT(width > 0);
     const uint8_t* s = (const uint8_t*)src;
@@ -584,52 +337,6 @@
     } while (--width != 0);
 }
 
-// can return NULL
-static ToColorProc ChooseToColorProc(const SkBitmap& src) {
-    switch (src.colorType()) {
-        case kN32_SkColorType:
-            switch (src.alphaType()) {
-                case kOpaque_SkAlphaType:
-                    return ToColor_S32_Opaque;
-                case kPremul_SkAlphaType:
-                    return ToColor_S32_Alpha;
-                case kUnpremul_SkAlphaType:
-                    return ToColor_S32_Raw;
-                default:
-                    return NULL;
-            }
-        case kARGB_4444_SkColorType:
-            switch (src.alphaType()) {
-                case kOpaque_SkAlphaType:
-                    return ToColor_S4444_Opaque;
-                case kPremul_SkAlphaType:
-                    return ToColor_S4444_Alpha;
-                case kUnpremul_SkAlphaType:
-                    return ToColor_S4444_Raw;
-                default:
-                    return NULL;
-            }
-        case kRGB_565_SkColorType:
-            return ToColor_S565;
-        case kAlpha_8_SkColorType:
-            return ToColor_SA8;
-        case kRGBA_F16_SkColorType:
-            switch (src.alphaType()) {
-                case kOpaque_SkAlphaType:
-                    return ToColor_F16_Raw;
-                case kPremul_SkAlphaType:
-                    return ToColor_F16_Alpha;
-                case kUnpremul_SkAlphaType:
-                    return ToColor_F16_Raw;
-                default:
-                    return NULL;
-            }
-        default:
-            break;
-    }
-    return NULL;
-}
-
 static void ToF16_SA8(void* dst, const void* src, int width) {
     SkASSERT(width > 0);
     uint64_t* d = (uint64_t*)dst;
@@ -694,7 +401,7 @@
     }
 
     if (jColors != NULL) {
-        GraphicsJNI::SetPixels(env, jColors, offset, stride, 0, 0, width, height, bitmap);
+        GraphicsJNI::SetPixels(env, jColors, offset, stride, 0, 0, width, height, &bitmap);
     }
 
     return createBitmap(env, nativeBitmap.release(), getPremulBitmapCreateFlags(isMutable));
@@ -1271,7 +978,7 @@
     if (!bitmapHolder.valid()) return JNI_TRUE;
 
     SkColorSpace* colorSpace = bitmapHolder->info().colorSpace();
-    return IsColorSpaceSRGB(colorSpace);
+    return colorSpace == nullptr || colorSpace->isSRGB();
 }
 
 static jboolean Bitmap_isSRGBLinear(JNIEnv* env, jobject, jlong bitmapHandle) {
@@ -1330,28 +1037,13 @@
     SkBitmap bitmap;
     reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
 
-    ToColorProc proc = ChooseToColorProc(bitmap);
-    if (NULL == proc) {
-        return 0;
-    }
-    const void* src = bitmap.getAddr(x, y);
-    if (NULL == src) {
-        return 0;
-    }
+    auto sRGB = SkColorSpace::MakeSRGB();
+    SkImageInfo dstInfo = SkImageInfo::Make(
+            1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
 
-    SkColor dst[1];
-    proc(dst, src, 1);
-
-    SkColorSpace* colorSpace = bitmap.colorSpace();
-    if (bitmap.colorType() != kRGBA_F16_SkColorType &&  !IsColorSpaceSRGB(colorSpace)) {
-        auto sRGB = SkColorSpace::MakeSRGB();
-        auto xform = SkColorSpaceXform::New(colorSpace, sRGB.get());
-        xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, &dst[0],
-                SkColorSpaceXform::kBGRA_8888_ColorFormat, &dst[0], 1,
-                SkAlphaType::kUnpremul_SkAlphaType);
-    }
-
-    return static_cast<jint>(dst[0]);
+    SkColor dst;
+    bitmap.readPixels(dstInfo, &dst, dstInfo.minRowBytes(), x, y);
+    return static_cast<jint>(dst);
 }
 
 static void Bitmap_getPixels(JNIEnv* env, jobject, jlong bitmapHandle,
@@ -1360,41 +1052,12 @@
     SkBitmap bitmap;
     reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
 
-    ToColorProc proc = ChooseToColorProc(bitmap);
-    if (NULL == proc) {
-        return;
-    }
-    const void* src = bitmap.getAddr(x, y);
-    if (NULL == src) {
-        return;
-    }
+    auto sRGB = SkColorSpace::MakeSRGB();
+    SkImageInfo dstInfo = SkImageInfo::Make(
+            width, height, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
 
     jint* dst = env->GetIntArrayElements(pixelArray, NULL);
-    SkColor* d = (SkColor*)dst + offset;
-
-    SkColorSpace* colorSpace = bitmap.colorSpace();
-    if (bitmap.colorType() == kRGBA_F16_SkColorType || IsColorSpaceSRGB(colorSpace)) {
-        while (--height >= 0) {
-            proc(d, src, width);
-            d += stride;
-            src = (void*)((const char*)src + bitmap.rowBytes());
-        }
-    } else {
-        auto sRGB = SkColorSpace::MakeSRGB();
-        auto xform = SkColorSpaceXform::New(colorSpace, sRGB.get());
-
-        while (--height >= 0) {
-            proc(d, src, width);
-
-            xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, d,
-                    SkColorSpaceXform::kBGRA_8888_ColorFormat, d, width,
-                    SkAlphaType::kUnpremul_SkAlphaType);
-
-            d += stride;
-            src = (void*)((const char*)src + bitmap.rowBytes());
-        }
-    }
-
+    bitmap.readPixels(dstInfo, dst + offset, stride * 4, x, y);
     env->ReleaseIntArrayElements(pixelArray, dst, 0);
 }
 
@@ -1405,26 +1068,13 @@
     SkBitmap bitmap;
     reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
     SkColor color = static_cast<SkColor>(colorHandle);
-    if (NULL == bitmap.getPixels()) {
-        return;
-    }
 
-    FromColorProc proc = ChooseFromColorProc(bitmap);
-    if (NULL == proc) {
-        return;
-    }
+    auto sRGB = SkColorSpace::MakeSRGB();
+    SkImageInfo srcInfo = SkImageInfo::Make(
+            1, 1, kBGRA_8888_SkColorType, kUnpremul_SkAlphaType, sRGB);
+    SkPixmap srcPM(srcInfo, &color, srcInfo.minRowBytes());
 
-    SkColorSpace* colorSpace = bitmap.colorSpace();
-    if (bitmap.colorType() != kRGBA_F16_SkColorType && !IsColorSpaceSRGB(colorSpace)) {
-        auto sRGB = SkColorSpace::MakeSRGB();
-        auto xform = SkColorSpaceXform::New(sRGB.get(), colorSpace);
-        xform->apply(SkColorSpaceXform::kBGRA_8888_ColorFormat, &color,
-                SkColorSpaceXform::kBGRA_8888_ColorFormat, &color, 1,
-                SkAlphaType::kUnpremul_SkAlphaType);
-    }
-
-    proc(bitmap.getAddr(x, y), &color, 1, x, y);
-    bitmap.notifyPixelsChanged();
+    bitmap.writePixels(srcPM, x, y);
 }
 
 static void Bitmap_setPixels(JNIEnv* env, jobject, jlong bitmapHandle,
@@ -1433,7 +1083,7 @@
     SkBitmap bitmap;
     reinterpret_cast<BitmapWrapper*>(bitmapHandle)->getSkBitmap(&bitmap);
     GraphicsJNI::SetPixels(env, pixelArray, offset, stride,
-            x, y, width, height, bitmap);
+            x, y, width, height, &bitmap);
 }
 
 static void Bitmap_copyPixelsToBuffer(JNIEnv* env, jobject,
diff --git a/core/jni/android/graphics/GraphicsJNI.h b/core/jni/android/graphics/GraphicsJNI.h
index 9d85cc2..cee3c46 100644
--- a/core/jni/android/graphics/GraphicsJNI.h
+++ b/core/jni/android/graphics/GraphicsJNI.h
@@ -102,7 +102,7 @@
     */
     static bool SetPixels(JNIEnv* env, jintArray colors, int srcOffset,
             int srcStride, int x, int y, int width, int height,
-            const SkBitmap& dstBitmap);
+            SkBitmap* dstBitmap);
 
     static SkColorSpaceTransferFn getNativeTransferParameters(JNIEnv* env, jobject transferParams);
     static SkMatrix44 getNativeXYZMatrix(JNIEnv* env, jfloatArray xyzD50);
diff --git a/core/jni/android_graphics_Canvas.cpp b/core/jni/android_graphics_Canvas.cpp
index db3bfe6..eba4c50 100644
--- a/core/jni/android_graphics_Canvas.cpp
+++ b/core/jni/android_graphics_Canvas.cpp
@@ -462,7 +462,7 @@
         return;
     }
 
-    if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, 0, 0, width, height, bitmap)) {
+    if (!GraphicsJNI::SetPixels(env, jcolors, offset, stride, 0, 0, width, height, &bitmap)) {
         return;
     }
 
diff --git a/core/jni/android_util_AssetManager.cpp b/core/jni/android_util_AssetManager.cpp
index fa9f445..830ca83 100644
--- a/core/jni/android_util_AssetManager.cpp
+++ b/core/jni/android_util_AssetManager.cpp
@@ -179,6 +179,10 @@
         argv[argc++] = AssetManager::PRODUCT_OVERLAY_DIR;
       }
 
+      if (stat(AssetManager::PRODUCT_SERVICES_OVERLAY_DIR, &st) == 0) {
+        argv[argc++] = AssetManager::PRODUCT_SERVICES_OVERLAY_DIR;
+      }
+
       // Finally, invoke idmap (if any overlay directory exists)
       if (argc > 5) {
         execv(AssetManager::IDMAP_BIN, (char* const*)argv);
diff --git a/core/jni/fd_utils.cpp b/core/jni/fd_utils.cpp
index c5904e0..f56f7ec 100644
--- a/core/jni/fd_utils.cpp
+++ b/core/jni/fd_utils.cpp
@@ -87,13 +87,17 @@
   static const char* kOverlaySubdir = "/system/vendor/overlay-subdir/";
   static const char* kSystemProductOverlayDir = "/system/product/overlay/";
   static const char* kProductOverlayDir = "/product/overlay";
+  static const char* kSystemProductServicesOverlayDir = "/system/product_services/overlay/";
+  static const char* kProductServicesOverlayDir = "/product_services/overlay";
   static const char* kApkSuffix = ".apk";
 
   if ((android::base::StartsWith(path, kOverlayDir)
        || android::base::StartsWith(path, kOverlaySubdir)
        || android::base::StartsWith(path, kVendorOverlayDir)
        || android::base::StartsWith(path, kSystemProductOverlayDir)
-       || android::base::StartsWith(path, kProductOverlayDir))
+       || android::base::StartsWith(path, kProductOverlayDir)
+       || android::base::StartsWith(path, kSystemProductServicesOverlayDir)
+       || android::base::StartsWith(path, kProductServicesOverlayDir))
       && android::base::EndsWith(path, kApkSuffix)
       && path.find("/../") == std::string::npos) {
     return true;
diff --git a/core/res/res/values-land/dimens_package_installer.xml b/core/res/res/values-land/dimens_permission_controller.xml
similarity index 100%
rename from core/res/res/values-land/dimens_package_installer.xml
rename to core/res/res/values-land/dimens_permission_controller.xml
diff --git a/core/res/res/values-night/themes_package_installer.xml b/core/res/res/values-night/themes_permission_controller.xml
similarity index 100%
rename from core/res/res/values-night/themes_package_installer.xml
rename to core/res/res/values-night/themes_permission_controller.xml
diff --git a/core/res/res/values-port/dimens_package_installer.xml b/core/res/res/values-port/dimens_permission_controller.xml
similarity index 100%
rename from core/res/res/values-port/dimens_package_installer.xml
rename to core/res/res/values-port/dimens_permission_controller.xml
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index b15c9c5..c6931aa 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2988,6 +2988,10 @@
          -->
     <bool name="config_fillMainBuiltInDisplayCutout">false</bool>
 
+    <!-- If true, and there is a cutout on the main built in display, the cutout will be masked
+         by shrinking the display such that it does not overlap the cutout area. -->
+    <bool name="config_maskMainBuiltInDisplayCutout">false</bool>
+
     <!-- Ultrasound support for Mic/speaker path -->
     <!-- Whether the default microphone audio source supports near-ultrasound frequencies
          (range of 18 - 21 kHz). -->
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 471170b..73cb59e 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -61,6 +61,15 @@
     <!-- Margin at the edge of the screen to ignore touch events for in the windowshade. -->
     <dimen name="status_bar_edge_ignore">5dp</dimen>
 
+    <!-- Default radius of the software rounded corners. -->
+    <dimen name="rounded_corner_radius">0dp</dimen>
+    <!-- Radius of the software rounded corners at the top of the display in its natural
+        orientation. If zero, the value of rounded_corner_radius is used. -->
+    <dimen name="rounded_corner_radius_top">0dp</dimen>
+    <!-- Radius of the software rounded corners at the bottom of the display in its natural
+        orientation. If zero, the value of rounded_corner_radius is used. -->
+    <dimen name="rounded_corner_radius_bottom">0dp</dimen>
+
     <!-- Width of the window of the divider bar used to resize docked stacks. -->
     <dimen name="docked_stack_divider_thickness">48dp</dimen>
 
diff --git a/core/res/res/values/styles_package_installer.xml b/core/res/res/values/styles_permission_controller.xml
similarity index 100%
rename from core/res/res/values/styles_package_installer.xml
rename to core/res/res/values/styles_permission_controller.xml
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 2271baa..7fbad16 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -3442,6 +3442,8 @@
   <java-symbol type="integer" name="config_defaultHapticFeedbackIntensity" />
   <java-symbol type="integer" name="config_defaultNotificationVibrationIntensity" />
 
+  <java-symbol type="bool" name="config_maskMainBuiltInDisplayCutout" />
+
   <java-symbol type="array" name="config_disableApksUnlessMatchedSku_apk_list" />
   <java-symbol type="array" name="config_disableApkUnlessMatchedSku_skus_list" />
 </resources>
diff --git a/core/res/res/values/themes_package_installer.xml b/core/res/res/values/themes_permission_controller.xml
similarity index 100%
rename from core/res/res/values/themes_package_installer.xml
rename to core/res/res/values/themes_permission_controller.xml
diff --git a/core/tests/coretests/src/android/view/DisplayCutoutTest.java b/core/tests/coretests/src/android/view/DisplayCutoutTest.java
index 6ee74cb..fe45fe7 100644
--- a/core/tests/coretests/src/android/view/DisplayCutoutTest.java
+++ b/core/tests/coretests/src/android/view/DisplayCutoutTest.java
@@ -19,6 +19,7 @@
 import static android.view.DisplayCutout.NO_CUTOUT;
 import static android.view.DisplayCutout.fromSpec;
 
+import static org.hamcrest.Matchers.equalTo;
 import static org.hamcrest.Matchers.not;
 import static org.hamcrest.Matchers.sameInstance;
 import static org.junit.Assert.assertEquals;
@@ -220,6 +221,19 @@
     }
 
     @Test
+    public void fromSpec_setsSafeInsets_top() {
+        DisplayCutout cutout = fromSpec("M -50,0 v 20 h 100 v -20 z", 200, 400, 2f);
+        assertThat(cutout.getSafeInsets(), equalTo(new Rect(0, 20, 0, 0)));
+    }
+
+    @Test
+    public void fromSpec_setsSafeInsets_top_and_bottom() {
+        DisplayCutout cutout = fromSpec("M -50,0 v 20 h 100 v -20 z"
+                + "@bottom M -50,0 v -10,0 h 100 v 20 z", 200, 400, 2f);
+        assertThat(cutout.getSafeInsets(), equalTo(new Rect(0, 20, 0, 10)));
+    }
+
+    @Test
     public void parcel_unparcel_nocutout() {
         Parcel p = Parcel.obtain();
 
diff --git a/libs/androidfw/AssetManager.cpp b/libs/androidfw/AssetManager.cpp
index fc625bb..843c146 100644
--- a/libs/androidfw/AssetManager.cpp
+++ b/libs/androidfw/AssetManager.cpp
@@ -74,6 +74,7 @@
 const char* AssetManager::IDMAP_BIN = "/system/bin/idmap";
 const char* AssetManager::OVERLAY_DIR = "/vendor/overlay";
 const char* AssetManager::PRODUCT_OVERLAY_DIR = "/product/overlay";
+const char* AssetManager::PRODUCT_SERVICES_OVERLAY_DIR = "/product_services/overlay";
 const char* AssetManager::OVERLAY_THEME_DIR_PROPERTY = "ro.boot.vendor.overlay.theme";
 const char* AssetManager::TARGET_PACKAGE_NAME = "android";
 const char* AssetManager::TARGET_APK_PATH = "/system/framework/framework-res.apk";
diff --git a/libs/androidfw/include/androidfw/AssetManager.h b/libs/androidfw/include/androidfw/AssetManager.h
index 08da731..cdb87bc 100644
--- a/libs/androidfw/include/androidfw/AssetManager.h
+++ b/libs/androidfw/include/androidfw/AssetManager.h
@@ -61,6 +61,7 @@
     static const char* IDMAP_BIN;
     static const char* OVERLAY_DIR;
     static const char* PRODUCT_OVERLAY_DIR;
+    static const char* PRODUCT_SERVICES_OVERLAY_DIR;
     /*
      * If OVERLAY_THEME_DIR_PROPERTY is set, search for runtime resource overlay
      * APKs in OVERLAY_DIR/<value of OVERLAY_THEME_DIR_PROPERTY> in addition to
diff --git a/media/OWNERS b/media/OWNERS
index 182f661..1ae2a7b 100644
--- a/media/OWNERS
+++ b/media/OWNERS
@@ -1,5 +1,8 @@
 elaurent@google.com
 etalvala@google.com
+gkasten@google.com
+hunga@google.com
+jmtrivi@google.com
 lajos@google.com
 marcone@google.com
 sungsoo@google.com
diff --git a/media/jni/audioeffect/android_media_AudioEffect.cpp b/media/jni/audioeffect/android_media_AudioEffect.cpp
index 8c9025b..693bd8b 100644
--- a/media/jni/audioeffect/android_media_AudioEffect.cpp
+++ b/media/jni/audioeffect/android_media_AudioEffect.cpp
@@ -824,21 +824,19 @@
 android_media_AudioEffect_native_queryPreProcessings(JNIEnv *env, jclass clazz __unused,
                                                      jint audioSession)
 {
-    effect_descriptor_t *descriptors = new effect_descriptor_t[AudioEffect::kMaxPreProcessing];
+    auto descriptors = std::make_unique<effect_descriptor_t[]>(AudioEffect::kMaxPreProcessing);
     uint32_t numEffects = AudioEffect::kMaxPreProcessing;
 
     status_t status = AudioEffect::queryDefaultPreProcessing((audio_session_t) audioSession,
-                                           descriptors,
+                                           descriptors.get(),
                                            &numEffects);
     if (status != NO_ERROR || numEffects == 0) {
-        delete[] descriptors;
         return NULL;
     }
     ALOGV("queryDefaultPreProcessing() got %d effects", numEffects);
 
     jobjectArray ret = env->NewObjectArray(numEffects, fields.clazzDesc, NULL);
     if (ret == NULL) {
-        delete[] descriptors;
         return ret;
     }
 
@@ -875,7 +873,7 @@
         if (jdesc == NULL) {
             ALOGE("env->NewObject(fields.clazzDesc, fields.midDescCstor)");
             env->DeleteLocalRef(ret);
-            return NULL;;
+            return NULL;
         }
 
         env->SetObjectArrayElement(ret, i, jdesc);
diff --git a/packages/CarrierDefaultApp/res/values-kn/strings.xml b/packages/CarrierDefaultApp/res/values-kn/strings.xml
index 73d0764..ea4b09a 100644
--- a/packages/CarrierDefaultApp/res/values-kn/strings.xml
+++ b/packages/CarrierDefaultApp/res/values-kn/strings.xml
@@ -8,7 +8,7 @@
     <string name="portal_notification_detail" msgid="2295729385924660881">"%s ವೆಬ್‌ಸೈಟ್‌ಗೆ ಭೇಟಿ ನೀಡಲು ಟ್ಯಾಪ್ ಮಾಡಿ"</string>
     <string name="no_data_notification_detail" msgid="3112125343857014825">"ನಿಮಗೆ ಸೇವೆ ಒದಗಿಸುವವರನ್ನು ದಯವಿಟ್ಟು ಸಂಪರ್ಕಿಸಿ %s"</string>
     <string name="no_mobile_data_connection_title" msgid="7449525772416200578">"ಮೊಬೈಲ್ ಡೇಟಾ ಸಂಪರ್ಕವಿಲ್ಲ"</string>
-    <string name="no_mobile_data_connection" msgid="544980465184147010">"%s ಮೂಲಕ ಡೇಟಾ ಅಥವಾ ರೋಮಿಂಗ್ ಪ್ಲ್ಯಾನ್ ಸೇರಿಸಿ"</string>
+    <string name="no_mobile_data_connection" msgid="544980465184147010">"%s ಮೂಲಕ ಡೇಟಾ ಅಥವಾ ರೋಮಿಂಗ್ ಪ್ಲಾನ್ ಸೇರಿಸಿ"</string>
     <string name="mobile_data_status_notification_channel_name" msgid="833999690121305708">"ಮೊಬೈಲ್ ಡೇಟಾ ಸ್ಥಿತಿ"</string>
     <string name="action_bar_label" msgid="4290345990334377177">"ಮೊಬೈಲ್ ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸೈನ್ ಇನ್ ಮಾಡಿ"</string>
     <string name="ssl_error_warning" msgid="3127935140338254180">"ನೀವು ಸೇರಬೇಕೆಂದಿರುವ ನೆಟ್‌ವರ್ಕ್, ಭದ್ರತೆ ಸಮಸ್ಯೆಗಳನ್ನು ಹೊಂದಿದೆ."</string>
diff --git a/packages/ExtServices/src/android/ext/services/notification/Assistant.java b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
index f0f31fb..3333e15 100644
--- a/packages/ExtServices/src/android/ext/services/notification/Assistant.java
+++ b/packages/ExtServices/src/android/ext/services/notification/Assistant.java
@@ -316,7 +316,7 @@
                 saveFile();
             }
         } catch (Throwable e) {
-            Slog.e(TAG, "Error occurred processing removal", e);
+            Slog.e(TAG, "Error occurred processing removal of " + sbn, e);
         }
     }
 
@@ -327,17 +327,21 @@
 
     @Override
     public void onNotificationsSeen(List<String> keys) {
-        if (keys == null) {
-            return;
-        }
-
-        for (String key : keys) {
-            NotificationEntry entry = mLiveNotifications.get(key);
-
-            if (entry != null) {
-                entry.setSeen();
-                mAgingHelper.onNotificationSeen(entry);
+        try {
+            if (keys == null) {
+                return;
             }
+
+            for (String key : keys) {
+                NotificationEntry entry = mLiveNotifications.get(key);
+
+                if (entry != null) {
+                    entry.setSeen();
+                    mAgingHelper.onNotificationSeen(entry);
+                }
+            }
+        } catch (Throwable e) {
+            Slog.e(TAG, "Error occurred processing seen", e);
         }
     }
 
diff --git a/packages/ExtServices/tests/AndroidTest.xml b/packages/ExtServices/tests/AndroidTest.xml
new file mode 100644
index 0000000..c3d32de
--- /dev/null
+++ b/packages/ExtServices/tests/AndroidTest.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+<configuration description="Runs Tests for ExtServices">
+    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
+        <option name="test-file-name" value="ExtServicesUnitTests.apk" />
+    </target_preparer>
+
+    <option name="test-suite-tag" value="apct" />
+    <option name="test-suite-tag" value="framework-base-presubmit" />
+    <option name="test-tag" value="ExtServicesUnitTests" />
+    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+        <option name="package" value="android.ext.services.tests.unit" />
+        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
+        <option name="hidden-api-checks" value="false"/>
+    </test>
+</configuration>
\ No newline at end of file
diff --git a/packages/OsuLogin/AndroidManifest.xml b/packages/OsuLogin/AndroidManifest.xml
index f6cd79b..bc32d10 100644
--- a/packages/OsuLogin/AndroidManifest.xml
+++ b/packages/OsuLogin/AndroidManifest.xml
@@ -23,6 +23,7 @@
     <uses-permission android:name="android.permission.INTERNET" />
 
     <application
+        android:networkSecurityConfig="@xml/network_security_config"
         android:enabled="true"
         android:label="@string/app_name"
         android:configChanges="keyboardHidden|orientation|screenSize"
diff --git a/packages/OsuLogin/res/xml/network_security_config.xml b/packages/OsuLogin/res/xml/network_security_config.xml
new file mode 100644
index 0000000..3ef4b84
--- /dev/null
+++ b/packages/OsuLogin/res/xml/network_security_config.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<network-security-config>
+<base-config cleartextTrafficPermitted="true">
+    <trust-anchors>
+        <certificates src="system" />
+        <certificates src="wfa" />
+    </trust-anchors>
+</base-config>
+</network-security-config>
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java b/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java
index 6d60a09..a6b2410 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/Tile.java
@@ -58,17 +58,13 @@
      */
     public ArrayList<UserHandle> userHandle = new ArrayList<>();
 
-    /**
-     * The metaData from the activity that defines this tile.
-     */
-    private final Bundle mMetaData;
-
     private final String mActivityPackage;
     private final String mActivityName;
     private final Intent mIntent;
+
     private ActivityInfo mActivityInfo;
     private CharSequence mSummaryOverride;
-
+    private Bundle mMetaData;
     private String mCategory;
 
     public Tile(ActivityInfo activityInfo, String category) {
@@ -234,6 +230,13 @@
         return summary;
     }
 
+    public void setMetaData(Bundle metaData) {
+        mMetaData = metaData;
+    }
+
+    /**
+     * The metaData from the activity that defines this tile.
+     */
     public Bundle getMetaData() {
         return mMetaData;
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
index ffd6791..67cfe6b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawer/TileUtils.java
@@ -20,10 +20,8 @@
 import android.content.IContentProvider;
 import android.content.Intent;
 import android.content.pm.ActivityInfo;
-import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ResolveInfo;
-import android.content.res.Resources;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.RemoteException;
@@ -43,7 +41,6 @@
 
 public class TileUtils {
 
-    private static final boolean DEBUG = false;
     private static final boolean DEBUG_TIMING = false;
 
     private static final String LOG_TAG = "TileUtils";
@@ -70,7 +67,7 @@
     /**
      * @See {@link #EXTRA_SETTINGS_ACTION}.
      */
-    private static final String IA_SETTINGS_ACTION = "com.android.settings.action.IA_SETTINGS";
+    public static final String IA_SETTINGS_ACTION = "com.android.settings.action.IA_SETTINGS";
 
     /**
      * Same as #EXTRA_SETTINGS_ACTION but used for the platform Settings activities.
@@ -205,12 +202,9 @@
 
     /**
      * Build a list of DashboardCategory.
-     *
-     * @param extraAction additional intent filter action to be usetileutild to build the dashboard
-     *                    categories
      */
     public static List<DashboardCategory> getCategories(Context context,
-            Map<Pair<String, String>, Tile> cache, String extraAction) {
+            Map<Pair<String, String>, Tile> cache) {
         final long startTime = System.currentTimeMillis();
         boolean setup = Global.getInt(context.getContentResolver(), Global.DEVICE_PROVISIONED, 0)
                 != 0;
@@ -222,16 +216,13 @@
                 // Only add Settings for this user.
                 getTilesForAction(context, user, SETTINGS_ACTION, cache, null, tiles, true);
                 getTilesForAction(context, user, OPERATOR_SETTINGS, cache,
-                        OPERATOR_DEFAULT_CATEGORY, tiles, false, true);
+                        OPERATOR_DEFAULT_CATEGORY, tiles, false);
                 getTilesForAction(context, user, MANUFACTURER_SETTINGS, cache,
-                        MANUFACTURER_DEFAULT_CATEGORY, tiles, false, true);
+                        MANUFACTURER_DEFAULT_CATEGORY, tiles, false);
             }
             if (setup) {
                 getTilesForAction(context, user, EXTRA_SETTINGS_ACTION, cache, null, tiles, false);
                 getTilesForAction(context, user, IA_SETTINGS_ACTION, cache, null, tiles, false);
-                if (extraAction != null) {
-                    getTilesForAction(context, user, extraAction, cache, null, tiles, false);
-                }
             }
         }
 
@@ -262,30 +253,15 @@
         return categories;
     }
 
-    private static void getTilesForAction(Context context,
+    @VisibleForTesting
+    static void getTilesForAction(Context context,
             UserHandle user, String action, Map<Pair<String, String>, Tile> addedCache,
-            String defaultCategory, ArrayList<Tile> outTiles, boolean requireSettings) {
-        getTilesForAction(context, user, action, addedCache, defaultCategory, outTiles,
-                requireSettings, requireSettings);
-    }
-
-    private static void getTilesForAction(Context context,
-            UserHandle user, String action, Map<Pair<String, String>, Tile> addedCache,
-            String defaultCategory, ArrayList<Tile> outTiles, boolean requireSettings,
-            boolean usePriority) {
-        Intent intent = new Intent(action);
+            String defaultCategory, List<Tile> outTiles, boolean requireSettings) {
+        final Intent intent = new Intent(action);
         if (requireSettings) {
             intent.setPackage(SETTING_PKG);
         }
-        getTilesForIntent(context, user, intent, addedCache, defaultCategory, outTiles,
-                usePriority);
-    }
-
-    public static void getTilesForIntent(
-            Context context, UserHandle user, Intent intent,
-            Map<Pair<String, String>, Tile> addedCache, String defaultCategory, List<Tile> outTiles,
-            boolean usePriority) {
-        PackageManager pm = context.getPackageManager();
+        final PackageManager pm = context.getPackageManager();
         List<ResolveInfo> results = pm.queryIntentActivitiesAsUser(intent,
                 PackageManager.GET_META_DATA, user.getIdentifier());
         for (ResolveInfo resolved : results) {
@@ -312,8 +288,9 @@
             Tile tile = addedCache.get(key);
             if (tile == null) {
                 tile = new Tile(activityInfo, categoryKey);
-                updateTileData(context, tile, activityInfo, activityInfo.applicationInfo, pm);
                 addedCache.put(key, tile);
+            } else {
+                tile.setMetaData(metaData);
             }
 
             if (!tile.userHandle.contains(user)) {
@@ -325,34 +302,6 @@
         }
     }
 
-    private static boolean updateTileData(Context context, Tile tile,
-            ActivityInfo activityInfo, ApplicationInfo applicationInfo, PackageManager pm) {
-        if (applicationInfo.isSystemApp()) {
-            String summary = null;
-
-            // Get the activity's meta-data
-            try {
-                Resources res = pm.getResourcesForApplication(applicationInfo.packageName);
-                Bundle metaData = activityInfo.metaData;
-
-                if (res != null && metaData != null) {
-                    if (metaData.containsKey(META_DATA_PREFERENCE_SUMMARY)) {
-                        if (metaData.get(META_DATA_PREFERENCE_SUMMARY) instanceof Integer) {
-                            summary = res.getString(metaData.getInt(META_DATA_PREFERENCE_SUMMARY));
-                        } else {
-                            summary = metaData.getString(META_DATA_PREFERENCE_SUMMARY);
-                        }
-                    }
-                }
-            } catch (PackageManager.NameNotFoundException | Resources.NotFoundException e) {
-                if (DEBUG) Log.d(LOG_TAG, "Couldn't find info", e);
-            }
-            return true;
-        }
-
-        return false;
-    }
-
     /**
      * Gets the icon package name and resource id from content provider.
      *
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
index 3eb273d..362ae4c 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/drawer/TileUtilsTest.java
@@ -16,6 +16,7 @@
 
 package com.android.settingslib.drawer;
 
+import static com.android.settingslib.drawer.TileUtils.IA_SETTINGS_ACTION;
 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON;
 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_ICON_URI;
 import static com.android.settingslib.drawer.TileUtils.META_DATA_PREFERENCE_KEYHINT;
@@ -24,9 +25,9 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.argThat;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.ArgumentMatchers.isNull;
 import static org.mockito.Mockito.atLeastOnce;
@@ -52,6 +53,7 @@
 import android.util.ArrayMap;
 import android.util.Pair;
 
+import com.android.settingslib.R;
 import com.android.settingslib.SettingsLibRobolectricTestRunner;
 
 import org.junit.Before;
@@ -98,15 +100,14 @@
     @Test
     public void getTilesForIntent_shouldParseCategory() {
         final String testCategory = "category1";
-        Intent intent = new Intent();
         Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
         List<Tile> outTiles = new ArrayList<>();
         List<ResolveInfo> info = new ArrayList<>();
         info.add(newInfo(true, testCategory));
-        when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
+        when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
                 .thenReturn(info);
 
-        TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
+        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
                 null /* defaultCategory */, outTiles, false /* usePriority */);
 
         assertThat(outTiles.size()).isEqualTo(1);
@@ -116,60 +117,37 @@
     @Test
     public void getTilesForIntent_shouldParseKeyHintForSystemApp() {
         String keyHint = "key";
-        Intent intent = new Intent();
         Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
         List<Tile> outTiles = new ArrayList<>();
         List<ResolveInfo> info = new ArrayList<>();
         ResolveInfo resolveInfo = newInfo(true, null /* category */, keyHint);
         info.add(resolveInfo);
 
-        when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
+        when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
                 .thenReturn(info);
 
-        TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
-                null /* defaultCategory */, outTiles, false /* usePriority */);
+        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+                null /* defaultCategory */, outTiles, false /* requiresSettings */);
 
-        assertThat(outTiles.size()).isEqualTo(1);
+        assertThat(outTiles).hasSize(1);
         assertThat(outTiles.get(0).getKey(mContext)).isEqualTo(keyHint);
     }
 
     @Test
     public void getTilesForIntent_shouldSkipNonSystemApp() {
         final String testCategory = "category1";
-        Intent intent = new Intent();
         Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
         List<Tile> outTiles = new ArrayList<>();
         List<ResolveInfo> info = new ArrayList<>();
         info.add(newInfo(false, testCategory));
 
-        when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
+        when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
                 .thenReturn(info);
 
-        TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
-                null /* defaultCategory */, outTiles, false /* usePriority */);
+        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION,
+                addedCache, null /* defaultCategory */, outTiles, false /* requiresSettings */);
 
-        assertThat(outTiles.isEmpty()).isTrue();
-    }
-
-    @Test
-    public void getCategories_shouldHandleExtraIntentAction() {
-        final String testCategory = "category1";
-        final String testAction = "action1";
-        Map<Pair<String, String>, Tile> cache = new ArrayMap<>();
-        List<ResolveInfo> info = new ArrayList<>();
-        info.add(newInfo(true, testCategory));
-        Global.putInt(mContext.getContentResolver(), Global.DEVICE_PROVISIONED, 1);
-        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
-        List<UserHandle> userHandleList = new ArrayList<>();
-        userHandleList.add(UserHandle.CURRENT);
-        when(mUserManager.getUserProfiles()).thenReturn(userHandleList);
-
-        when(mPackageManager.queryIntentActivitiesAsUser(argThat(
-                event -> testAction.equals(event.getAction())), anyInt(), anyInt()))
-                .thenReturn(info);
-
-        List<DashboardCategory> categoryList = TileUtils.getCategories(mContext, cache, testAction);
-        assertThat(categoryList.get(0).getTile(0).getCategory()).isEqualTo(testCategory);
+        assertThat(outTiles).isEmpty();
     }
 
     @Test
@@ -183,7 +161,7 @@
         userHandleList.add(new UserHandle(ActivityManager.getCurrentUser()));
         when(mUserManager.getUserProfiles()).thenReturn(userHandleList);
 
-        TileUtils.getCategories(mContext, cache, null /* action */);
+        TileUtils.getCategories(mContext, cache);
         verify(mPackageManager, atLeastOnce()).queryIntentActivitiesAsUser(
                 intentCaptor.capture(), anyInt(), anyInt());
 
@@ -193,7 +171,6 @@
 
     @Test
     public void getTilesForIntent_shouldReadMetadataTitleAsString() {
-        Intent intent = new Intent();
         Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
         List<Tile> outTiles = new ArrayList<>();
         List<ResolveInfo> info = new ArrayList<>();
@@ -201,10 +178,10 @@
                 URI_GET_SUMMARY, "my title", 0);
         info.add(resolveInfo);
 
-        when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
+        when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
                 .thenReturn(info);
 
-        TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
+        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
                 null /* defaultCategory */, outTiles, false /* usePriority */);
 
         assertThat(outTiles.size()).isEqualTo(1);
@@ -213,7 +190,6 @@
 
     @Test
     public void getTilesForIntent_shouldReadMetadataTitleFromResource() {
-        Intent intent = new Intent();
         Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
         List<Tile> outTiles = new ArrayList<>();
         List<ResolveInfo> info = new ArrayList<>();
@@ -221,13 +197,13 @@
                 URI_GET_SUMMARY, null, 123);
         info.add(resolveInfo);
 
-        when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
+        when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
                 .thenReturn(info);
 
         when(mResources.getString(eq(123)))
                 .thenReturn("my localized title");
 
-        TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
+        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
                 null /* defaultCategory */, outTiles, false /* usePriority */);
         assertThat(outTiles.size()).isEqualTo(1);
         assertThat(outTiles.get(0).getTitle(mContext)).isEqualTo("my localized title");
@@ -239,7 +215,6 @@
 
     @Test
     public void getTilesForIntent_shouldNotTintIconIfInSettingsPackage() {
-        Intent intent = new Intent();
         Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
         List<Tile> outTiles = new ArrayList<>();
         List<ResolveInfo> info = new ArrayList<>();
@@ -249,18 +224,50 @@
         resolveInfo.activityInfo.applicationInfo.packageName = "com.android.settings";
         info.add(resolveInfo);
 
-        when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
+        when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
                 .thenReturn(info);
 
-        TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
+        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
                 null /* defaultCategory */, outTiles, false /* usePriority */);
 
         assertThat(outTiles.get(0).isIconTintable(mContext)).isFalse();
     }
 
     @Test
+    public void getTilesForIntent_tileAlreadyInCache_shouldUpdateMetaData() {
+        final Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
+        final List<Tile> outTiles = new ArrayList<>();
+        final List<ResolveInfo> info = new ArrayList<>();
+        final ResolveInfo resolveInfo = newInfo(true, null /* category */, null, URI_GET_ICON,
+                URI_GET_SUMMARY, null, 123);
+        resolveInfo.activityInfo.packageName = "com.android.settings";
+        resolveInfo.activityInfo.applicationInfo.packageName = "com.android.settings";
+        info.add(resolveInfo);
+
+        when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
+                .thenReturn(info);
+
+        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+                null /* defaultCategory */, outTiles, false /* usePriority */);
+
+        assertThat(outTiles).hasSize(1);
+        final Bundle oldMetadata = outTiles.get(0).getMetaData();
+
+        resolveInfo.activityInfo.metaData = new Bundle(oldMetadata);
+        resolveInfo.activityInfo.metaData.putInt(META_DATA_PREFERENCE_ICON,
+                R.drawable.ic_bt_cellphone);
+        outTiles.clear();
+        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
+                null /* defaultCategory */, outTiles, false /* usePriority */);
+
+        assertThat(outTiles).hasSize(1);
+        final Bundle newMetaData = outTiles.get(0).getMetaData();
+        assertThat(newMetaData).isNotSameAs(oldMetadata);
+    }
+
+
+    @Test
     public void getTilesForIntent_shouldMarkIconTintableIfMetadataSet() {
-        Intent intent = new Intent();
         Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
         List<Tile> outTiles = new ArrayList<>();
         List<ResolveInfo> info = new ArrayList<>();
@@ -270,10 +277,10 @@
                 .putBoolean(TileUtils.META_DATA_PREFERENCE_ICON_TINTABLE, true);
         info.add(resolveInfo);
 
-        when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
+        when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
                 .thenReturn(info);
 
-        TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
+        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
                 null /* defaultCategory */, outTiles, false /* usePriority */);
 
         assertThat(outTiles.get(0).isIconTintable(mContext)).isTrue();
@@ -281,7 +288,6 @@
 
     @Test
     public void getTilesForIntent_shouldProcessUriContentForSystemApp() {
-        Intent intent = new Intent();
         Map<Pair<String, String>, Tile> addedCache = new ArrayMap<>();
         List<Tile> outTiles = new ArrayList<>();
         List<ResolveInfo> info = new ArrayList<>();
@@ -289,10 +295,10 @@
                 URI_GET_SUMMARY);
         info.add(resolveInfo);
 
-        when(mPackageManager.queryIntentActivitiesAsUser(eq(intent), anyInt(), anyInt()))
+        when(mPackageManager.queryIntentActivitiesAsUser(any(Intent.class), anyInt(), anyInt()))
                 .thenReturn(info);
 
-        TileUtils.getTilesForIntent(mContext, UserHandle.CURRENT, intent, addedCache,
+        TileUtils.getTilesForAction(mContext, UserHandle.CURRENT, IA_SETTINGS_ACTION, addedCache,
                 null /* defaultCategory */, outTiles, false /* usePriority */);
 
         assertThat(outTiles.size()).isEqualTo(1);
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index ca6b2d9..412e89a 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -945,9 +945,9 @@
     <dimen name="bottom_padding">48dp</dimen>
     <dimen name="edge_margin">8dp</dimen>
 
-    <dimen name="rounded_corner_radius">0dp</dimen>
-    <dimen name="rounded_corner_radius_top">0dp</dimen>
-    <dimen name="rounded_corner_radius_bottom">0dp</dimen>
+    <dimen name="rounded_corner_radius">@*android:dimen/rounded_corner_radius</dimen>
+    <dimen name="rounded_corner_radius_top">@*android:dimen/rounded_corner_radius_top</dimen>
+    <dimen name="rounded_corner_radius_bottom">@*android:dimen/rounded_corner_radius_bottom</dimen>
     <dimen name="rounded_corner_content_padding">0dp</dimen>
     <dimen name="nav_content_padding">0dp</dimen>
     <dimen name="nav_quick_scrub_track_edge_padding">24dp</dimen>
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 86e0e1f..e7fc3c9 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -55,7 +55,7 @@
 import com.android.systemui.statusbar.phone.ManagedProfileControllerImpl;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.phone.StatusBarIconControllerImpl;
-import com.android.systemui.statusbar.phone.StatusBarWindowManager;
+import com.android.systemui.statusbar.phone.StatusBarWindowController;
 import com.android.systemui.statusbar.policy.AccessibilityController;
 import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
 import com.android.systemui.statusbar.policy.BatteryController;
@@ -258,8 +258,8 @@
         mProviders.put(TunerService.class, () ->
                 new TunerServiceImpl(mContext));
 
-        mProviders.put(StatusBarWindowManager.class, () ->
-                new StatusBarWindowManager(mContext));
+        mProviders.put(StatusBarWindowController.class, () ->
+                new StatusBarWindowController(mContext));
 
         mProviders.put(DarkIconDispatcher.class, () ->
                 new DarkIconDispatcherImpl(mContext));
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index 50d862d..39e3155 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -30,6 +30,7 @@
 import android.util.Log;
 import android.view.Display;
 import android.view.DisplayInfo;
+import android.view.DisplayListCanvas;
 import android.view.Surface;
 import android.view.SurfaceHolder;
 import android.view.WindowManager;
@@ -366,7 +367,12 @@
                 protected Bitmap doInBackground(Void... params) {
                     Throwable exception;
                     try {
-                        return mWallpaperManager.getBitmap(true /* hardware */);
+                        Bitmap wallpaper = mWallpaperManager.getBitmap(true /* hardware */);
+                        if (wallpaper != null
+                                && wallpaper.getByteCount() > DisplayListCanvas.MAX_BITMAP_SIZE) {
+                            throw new RuntimeException("Wallpaper is too large to draw!");
+                        }
+                        return wallpaper;
                     } catch (RuntimeException | OutOfMemoryError e) {
                         exception = e;
                     }
diff --git a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
index 9bbcfbc..044cc5c 100644
--- a/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
+++ b/packages/SystemUI/src/com/android/systemui/ScreenDecorations.java
@@ -94,9 +94,9 @@
     private DisplayManager mDisplayManager;
     private DisplayManager.DisplayListener mDisplayListener;
 
-    private int mRoundedDefault;
-    private int mRoundedDefaultTop;
-    private int mRoundedDefaultBottom;
+    @VisibleForTesting protected int mRoundedDefault;
+    @VisibleForTesting protected int mRoundedDefaultTop;
+    @VisibleForTesting protected int mRoundedDefaultBottom;
     private View mOverlay;
     private View mBottomOverlay;
     private float mDensity;
@@ -125,12 +125,7 @@
     private void startOnScreenDecorationsThread() {
         mRotation = RotationUtils.getExactRotation(mContext);
         mWindowManager = mContext.getSystemService(WindowManager.class);
-        mRoundedDefault = mContext.getResources().getDimensionPixelSize(
-                R.dimen.rounded_corner_radius);
-        mRoundedDefaultTop = mContext.getResources().getDimensionPixelSize(
-                R.dimen.rounded_corner_radius_top);
-        mRoundedDefaultBottom = mContext.getResources().getDimensionPixelSize(
-                R.dimen.rounded_corner_radius_bottom);
+        updateRoundedCornerRadii();
         if (hasRoundedCorners() || shouldDrawCutout()) {
             setupDecorations();
         }
@@ -277,6 +272,7 @@
             int oldRotation = mRotation;
             mPendingRotationChange = false;
             updateOrientation();
+            updateRoundedCornerRadii();
             if (DEBUG) Log.i(TAG, "onConfigChanged from rot " + oldRotation + " to " + mRotation);
             if (shouldDrawCutout() && mOverlay == null) {
                 setupDecorations();
@@ -309,6 +305,26 @@
         }
     }
 
+    private void updateRoundedCornerRadii() {
+        final int newRoundedDefault = mContext.getResources().getDimensionPixelSize(
+                R.dimen.rounded_corner_radius);
+        final int newRoundedDefaultTop = mContext.getResources().getDimensionPixelSize(
+                R.dimen.rounded_corner_radius_top);
+        final int newRoundedDefaultBottom = mContext.getResources().getDimensionPixelSize(
+                R.dimen.rounded_corner_radius_bottom);
+
+        final boolean roundedCornersChanged = mRoundedDefault != newRoundedDefault
+                || mRoundedDefaultBottom != newRoundedDefaultBottom
+                || mRoundedDefaultTop != newRoundedDefaultTop;
+
+        if (roundedCornersChanged) {
+            mRoundedDefault = newRoundedDefault;
+            mRoundedDefaultTop = newRoundedDefaultTop;
+            mRoundedDefaultBottom = newRoundedDefaultBottom;
+            onTuningChanged(SIZE, null);
+        }
+    }
+
     private void updateViews() {
         View topLeft = mOverlay.findViewById(R.id.left);
         View topRight = mOverlay.findViewById(R.id.right);
diff --git a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
index 4e7c3ab..b96a604 100644
--- a/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
+++ b/packages/SystemUI/src/com/android/systemui/SystemUIApplication.java
@@ -36,7 +36,7 @@
 import com.android.systemui.plugins.PluginListener;
 import com.android.systemui.plugins.PluginManager;
 import com.android.systemui.statusbar.phone.StatusBar;
-import com.android.systemui.statusbar.phone.StatusBarWindowManager;
+import com.android.systemui.statusbar.phone.StatusBarWindowController;
 import com.android.systemui.util.NotificationChannels;
 
 import java.util.HashMap;
@@ -210,9 +210,9 @@
                         if (mOverlays == null) mOverlays = new ArraySet<>();
                         if (plugin.holdStatusBarOpen()) {
                             mOverlays.add(plugin);
-                            Dependency.get(StatusBarWindowManager.class).setStateListener(b ->
+                            Dependency.get(StatusBarWindowController.class).setStateListener(b ->
                                     mOverlays.forEach(o -> o.setCollapseDesired(b)));
-                            Dependency.get(StatusBarWindowManager.class).setForcePluginOpen(
+                            Dependency.get(StatusBarWindowController.class).setForcePluginOpen(
                                     mOverlays.size() != 0);
 
                         }
@@ -221,7 +221,7 @@
                     @Override
                     public void onPluginDisconnected(OverlayPlugin plugin) {
                         mOverlays.remove(plugin);
-                        Dependency.get(StatusBarWindowManager.class).setForcePluginOpen(
+                        Dependency.get(StatusBarWindowController.class).setForcePluginOpen(
                                 mOverlays.size() != 0);
                     }
                 }, OverlayPlugin.class, true /* Allow multiple plugins */);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
index 1393f8f..b655a6b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationEntryManager.java
@@ -414,7 +414,9 @@
             } else if (mListContainer.hasPulsingNotifications()) {
                 dismissalSurface = NotificationStats.DISMISSAL_AOD;
             }
-            mBarService.onNotificationClear(pkg, tag, id, userId, n.getKey(), dismissalSurface, nv);
+            int dismissalSentiment = NotificationStats.DISMISS_SENTIMENT_NEUTRAL;
+            mBarService.onNotificationClear(pkg, tag, id, userId, n.getKey(), dismissalSurface,
+                    dismissalSentiment, nv);
             removeNotification(n.getKey(), null);
 
         } catch (RemoteException ex) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 094912b..67db68d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -1307,6 +1307,7 @@
         }
         setDismissed(fromAccessibility);
         if (isClearable()) {
+            // TODO: track dismiss sentiment
             if (mOnDismissRunnable != null) {
                 mOnDismissRunnable.run();
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index ab47d33..e635976 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -28,12 +28,10 @@
 import android.content.pm.PackageManager;
 import android.content.res.Resources;
 import android.net.Uri;
-import android.os.RemoteException;
 import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.service.notification.StatusBarNotification;
-import androidx.annotation.VisibleForTesting;
 import android.util.ArraySet;
 import android.util.Log;
 import android.view.HapticFeedbackConstants;
@@ -45,15 +43,17 @@
 import com.android.systemui.Dependency;
 import com.android.systemui.Dumpable;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin;
-import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.NotificationLockscreenUserManager;
 import com.android.systemui.statusbar.NotificationPresenter;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 import com.android.systemui.statusbar.phone.StatusBar;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
+import androidx.annotation.VisibleForTesting;
+
 /**
  * Handles various NotificationGuts related tasks, such as binding guts to a row, opening and
  * closing guts, and keeping track of the currently exposed notification guts.
@@ -147,15 +147,15 @@
         }
     }
 
-    public void bindGuts(final ExpandableNotificationRow row) {
-        bindGuts(row, mGutsMenuItem);
+    public boolean bindGuts(final ExpandableNotificationRow row) {
+        row.inflateGuts();
+        return bindGuts(row, mGutsMenuItem);
     }
 
-    private void bindGuts(final ExpandableNotificationRow row,
+    private boolean bindGuts(final ExpandableNotificationRow row,
             NotificationMenuRowPlugin.MenuItem item) {
         StatusBarNotification sbn = row.getStatusBarNotification();
 
-        row.inflateGuts();
         row.setGutsView(item);
         row.setTag(sbn.getPackageName());
         row.getGuts().setClosedListener((NotificationGuts g) -> {
@@ -176,12 +176,18 @@
         });
 
         View gutsView = item.getGutsView();
-        if (gutsView instanceof NotificationSnooze) {
-            initializeSnoozeView(row, (NotificationSnooze) gutsView);
-        } else if (gutsView instanceof AppOpsInfo) {
-            initializeAppOpsInfo(row, (AppOpsInfo) gutsView);
-        } else if (gutsView instanceof NotificationInfo) {
-            initializeNotificationInfo(row, (NotificationInfo) gutsView);
+        try {
+            if (gutsView instanceof NotificationSnooze) {
+                initializeSnoozeView(row, (NotificationSnooze) gutsView);
+            } else if (gutsView instanceof AppOpsInfo) {
+                initializeAppOpsInfo(row, (AppOpsInfo) gutsView);
+            } else if (gutsView instanceof NotificationInfo) {
+                initializeNotificationInfo(row, (NotificationInfo) gutsView);
+            }
+            return true;
+        } catch (Exception e) {
+            Log.e(TAG, "error binding guts", e);
+            return false;
         }
     }
 
@@ -240,7 +246,7 @@
     @VisibleForTesting
     void initializeNotificationInfo(
             final ExpandableNotificationRow row,
-            NotificationInfo notificationInfoView) {
+            NotificationInfo notificationInfoView) throws Exception {
         NotificationGuts guts = row.getGuts();
         StatusBarNotification sbn = row.getStatusBarNotification();
         String packageName = sbn.getPackageName();
@@ -269,24 +275,21 @@
             };
         }
 
-        try {
-            notificationInfoView.bindNotification(
-                    pmUser,
-                    iNotificationManager,
-                    packageName,
-                    row.getEntry().channel,
-                    row.getNumUniqueChannels(),
-                    sbn,
-                    mCheckSaveListener,
-                    onSettingsClick,
-                    onAppSettingsClick,
-                    mPresenter.isDeviceProvisioned(),
-                    row.getIsNonblockable(),
-                    isForBlockingHelper,
-                    row.getEntry().userSentiment == USER_SENTIMENT_NEGATIVE);
-        } catch (RemoteException e) {
-            Log.e(TAG, e.toString());
-        }
+        notificationInfoView.bindNotification(
+                pmUser,
+                iNotificationManager,
+                packageName,
+                row.getEntry().channel,
+                row.getNumUniqueChannels(),
+                sbn,
+                mCheckSaveListener,
+                onSettingsClick,
+                onAppSettingsClick,
+                mPresenter.isDeviceProvisioned(),
+                row.getIsNonblockable(),
+                isForBlockingHelper,
+                row.getEntry().userSentiment == USER_SENTIMENT_NEGATIVE);
+
     }
 
     /**
@@ -356,8 +359,15 @@
                     true /* resetMenu */);
             return false;
         }
-        bindGuts(row, menuItem);
+
+        row.inflateGuts();
         NotificationGuts guts = row.getGuts();
+        mNotificationGutsExposed = guts;
+        if (!bindGuts(row, menuItem)) {
+            // exception occurred trying to fill in all the data, bail.
+            return false;
+        }
+
 
         // Assume we are a status_bar_notification_row
         if (guts == null) {
@@ -378,9 +388,6 @@
                             + "window");
                     return;
                 }
-                closeAndSaveGuts(true /* removeLeavebehind */, true /* force */,
-                        true /* removeControls */, -1 /* x */, -1 /* y */,
-                        false /* resetMenu */);
                 guts.setVisibility(View.VISIBLE);
 
                 final boolean needsFalsingProtection =
@@ -396,7 +403,6 @@
 
                 row.closeRemoteInput();
                 mListContainer.onHeightChanged(row, true /* needsAnimation */);
-                mNotificationGutsExposed = guts;
                 mGutsMenuItem = menuItem;
             }
         });
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index 2087a16..b57a366 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -101,7 +101,7 @@
     private KeyguardUpdateMonitor mUpdateMonitor;
     private int mMode;
     private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
-    private StatusBarWindowManager mStatusBarWindowManager;
+    private StatusBarWindowController mStatusBarWindowController;
     private DozeScrimController mDozeScrimController;
     private KeyguardViewMediator mKeyguardViewMediator;
     private ScrimController mScrimController;
@@ -125,7 +125,7 @@
         mUpdateMonitor.registerCallback(this);
         Dependency.get(WakefulnessLifecycle.class).addObserver(mWakefulnessObserver);
         Dependency.get(ScreenLifecycle.class).addObserver(mScreenObserver);
-        mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class);
+        mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
         mDozeScrimController = dozeScrimController;
         mKeyguardViewMediator = keyguardViewMediator;
         mScrimController = scrimController;
@@ -214,7 +214,7 @@
             // notifications would light up first, creating an unpleasant animation.
             // Defer changing the screen brightness by forcing doze brightness on our window
             // until the clock and the notifications are faded out.
-            mStatusBarWindowManager.setForceDozeBrightness(true);
+            mStatusBarWindowController.setForceDozeBrightness(true);
         }
         // During wake and unlock, we need to draw black before waking up to avoid abrupt
         // brightness changes due to display state transitions.
@@ -269,7 +269,7 @@
                     Trace.beginSection("MODE_WAKE_AND_UNLOCK_FROM_DREAM");
                     mUpdateMonitor.awakenFromDream();
                 }
-                mStatusBarWindowManager.setStatusBarFocusable(false);
+                mStatusBarWindowController.setStatusBarFocusable(false);
                 if (delayWakeUp) {
                     mHandler.postDelayed(wakeUp, 50);
                 } else {
@@ -384,7 +384,7 @@
         mHandler.postDelayed(new Runnable() {
             @Override
             public void run() {
-                mStatusBarWindowManager.setForceDozeBrightness(false);
+                mStatusBarWindowController.setForceDozeBrightness(false);
             }
         }, StatusBar.FADE_KEYGUARD_DURATION_PULSING);
     }
@@ -395,7 +395,7 @@
 
     private void resetMode() {
         mMode = MODE_NONE;
-        mStatusBarWindowManager.setForceDozeBrightness(false);
+        mStatusBarWindowController.setForceDozeBrightness(false);
         if (mStatusBar.getNavigationBarView() != null) {
             mStatusBar.getNavigationBarView().setWakeAndUnlocking(false);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index 3701eaf..dcd794d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -370,7 +370,7 @@
     protected StatusBarWindowView mStatusBarWindow;
     protected PhoneStatusBarView mStatusBarView;
     private int mStatusBarWindowState = WINDOW_STATE_SHOWING;
-    protected StatusBarWindowManager mStatusBarWindowManager;
+    protected StatusBarWindowController mStatusBarWindowController;
     protected UnlockMethodCache mUnlockMethodCache;
     private DozeServiceHost mDozeServiceHost = new DozeServiceHost();
     private boolean mWakeUpComingFromTouch;
@@ -515,7 +515,7 @@
             final boolean supportsAmbientMode = info != null &&
                     info.supportsAmbientMode();
 
-            mStatusBarWindowManager.setWallpaperSupportsAmbientMode(supportsAmbientMode);
+            mStatusBarWindowController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
             mScrimController.setWallpaperSupportsAmbientMode(supportsAmbientMode);
         }
     };
@@ -957,8 +957,8 @@
                 scrimBehind, scrimInFront, mLockscreenWallpaper,
                 (state, alpha, color) -> mLightBarController.setScrimState(state, alpha, color),
                 scrimsVisible -> {
-                    if (mStatusBarWindowManager != null) {
-                        mStatusBarWindowManager.setScrimsVisibility(scrimsVisible);
+                    if (mStatusBarWindowController != null) {
+                        mStatusBarWindowController.setScrimsVisibility(scrimsVisible);
                     }
                 }, DozeParameters.getInstance(mContext),
                 mContext.getSystemService(AlarmManager.class));
@@ -1702,7 +1702,7 @@
                     mBackdrop.animate().cancel();
                     mBackdrop.setAlpha(1f);
                 }
-                mStatusBarWindowManager.setBackdropShowing(true);
+                mStatusBarWindowController.setBackdropShowing(true);
                 metaDataChanged = true;
                 if (DEBUG_MEDIA) {
                     Log.v(TAG, "DEBUG_MEDIA: Fading in album artwork");
@@ -1762,9 +1762,9 @@
                     // We are unlocking directly - no animation!
                     mBackdrop.setVisibility(View.GONE);
                     mBackdropBack.setImageDrawable(null);
-                    mStatusBarWindowManager.setBackdropShowing(false);
+                    mStatusBarWindowController.setBackdropShowing(false);
                 } else {
-                    mStatusBarWindowManager.setBackdropShowing(false);
+                    mStatusBarWindowController.setBackdropShowing(false);
                     mBackdrop.animate()
                             .alpha(SRC_MIN_ALPHA)
                             .setInterpolator(Interpolators.ACCELERATE_DECELERATE)
@@ -1918,7 +1918,7 @@
     }
 
     public void setQsExpanded(boolean expanded) {
-        mStatusBarWindowManager.setQsExpanded(expanded);
+        mStatusBarWindowController.setQsExpanded(expanded);
         mNotificationPanel.setStatusAccessibilityImportance(expanded
                 ? View.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS
                 : View.IMPORTANT_FOR_ACCESSIBILITY_AUTO);
@@ -2001,31 +2001,31 @@
     @Override
     public void onHeadsUpPinnedModeChanged(boolean inPinnedMode) {
         if (inPinnedMode) {
-            mStatusBarWindowManager.setHeadsUpShowing(true);
-            mStatusBarWindowManager.setForceStatusBarVisible(true);
+            mStatusBarWindowController.setHeadsUpShowing(true);
+            mStatusBarWindowController.setForceStatusBarVisible(true);
             if (mNotificationPanel.isFullyCollapsed()) {
                 // We need to ensure that the touchable region is updated before the window will be
                 // resized, in order to not catch any touches. A layout will ensure that
                 // onComputeInternalInsets will be called and after that we can resize the layout. Let's
                 // make sure that the window stays small for one frame until the touchableRegion is set.
                 mNotificationPanel.requestLayout();
-                mStatusBarWindowManager.setForceWindowCollapsed(true);
+                mStatusBarWindowController.setForceWindowCollapsed(true);
                 mNotificationPanel.post(() -> {
-                    mStatusBarWindowManager.setForceWindowCollapsed(false);
+                    mStatusBarWindowController.setForceWindowCollapsed(false);
                 });
             }
         } else {
             if (!mNotificationPanel.isFullyCollapsed() || mNotificationPanel.isTracking()) {
                 // We are currently tracking or is open and the shade doesn't need to be kept
                 // open artificially.
-                mStatusBarWindowManager.setHeadsUpShowing(false);
+                mStatusBarWindowController.setHeadsUpShowing(false);
             } else {
                 // we need to keep the panel open artificially, let's wait until the animation
                 // is finished.
                 mHeadsUpManager.setHeadsUpGoingAway(true);
                 mStackScroller.runAfterAnimationFinished(() -> {
                     if (!mHeadsUpManager.hasPinnedHeadsUp()) {
-                        mStatusBarWindowManager.setHeadsUpShowing(false);
+                        mStatusBarWindowController.setHeadsUpShowing(false);
                         mHeadsUpManager.setHeadsUpGoingAway(false);
                     }
                     mRemoteInputManager.removeRemoteInputEntriesKeptUntilCollapsed();
@@ -2065,7 +2065,7 @@
     public void setPanelExpanded(boolean isExpanded) {
         mPanelExpanded = isExpanded;
         updateHideIconsForBouncer(false /* animate */);
-        mStatusBarWindowManager.setPanelExpanded(isExpanded);
+        mStatusBarWindowController.setPanelExpanded(isExpanded);
         mVisualStabilityManager.setPanelExpanded(isExpanded);
         if (isExpanded && getBarState() != StatusBarState.KEYGUARD) {
             if (DEBUG) {
@@ -2274,7 +2274,7 @@
 
         // Expand the window to encompass the full screen in anticipation of the drag.
         // This is only possible to do atomically because the status bar is at the top of the screen!
-        mStatusBarWindowManager.setPanelVisible(true);
+        mStatusBarWindowController.setPanelVisible(true);
 
         visibilityChanged(true);
         recomputeDisableFlags(!force /* animate */);
@@ -2348,7 +2348,7 @@
                 + mNotificationPanel.canPanelBeCollapsed());
         if (mStatusBarWindow != null && mNotificationPanel.canPanelBeCollapsed()) {
             // release focus immediately to kick off focus change transition
-            mStatusBarWindowManager.setStatusBarFocusable(false);
+            mStatusBarWindowController.setStatusBarFocusable(false);
 
             mStatusBarWindow.cancelExpandHelper();
             mStatusBarView.collapsePanel(true /* animate */, delayed, speedUpFactor);
@@ -2420,8 +2420,8 @@
         visibilityChanged(false);
 
         // Shrink the window to the size of the status bar only
-        mStatusBarWindowManager.setPanelVisible(false);
-        mStatusBarWindowManager.setForceStatusBarVisible(false);
+        mStatusBarWindowController.setPanelVisible(false);
+        mStatusBarWindowController.setForceStatusBarVisible(false);
 
         // Close any guts that might be visible
         mGutsManager.closeAndSaveGuts(true /* removeLeavebehind */, true /* force */,
@@ -2894,7 +2894,7 @@
 
     private void addStatusBarWindow() {
         makeStatusBarView();
-        mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class);
+        mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
         mRemoteInputManager.setUpWithPresenter(this, mEntryManager, this,
                 new RemoteInputController.Delegate() {
                     public void setRemoteInputActive(NotificationData.Entry entry,
@@ -2911,8 +2911,8 @@
                         mStackScroller.requestDisallowDismiss();
                     }
                 });
-        mRemoteInputManager.getController().addCallback(mStatusBarWindowManager);
-        mStatusBarWindowManager.add(mStatusBarWindow, getStatusBarHeight());
+        mRemoteInputManager.getController().addCallback(mStatusBarWindowController);
+        mStatusBarWindowController.add(mStatusBarWindow, getStatusBarHeight());
     }
 
     // called by makeStatusbar and also by PhoneStatusBarView
@@ -3222,8 +3222,8 @@
         int oldBarHeight = mNaturalBarHeight;
         mNaturalBarHeight = res.getDimensionPixelSize(
                 com.android.internal.R.dimen.status_bar_height);
-        if (mStatusBarWindowManager != null && mNaturalBarHeight != oldBarHeight) {
-            mStatusBarWindowManager.setBarHeight(mNaturalBarHeight);
+        if (mStatusBarWindowController != null && mNaturalBarHeight != oldBarHeight) {
+            mStatusBarWindowController.setBarHeight(mNaturalBarHeight);
         }
         mMaxAllowedKeyguardNotifications = res.getInteger(
                 R.integer.keyguard_max_notification_count);
@@ -3881,7 +3881,7 @@
      * Switches theme from light to dark and vice-versa.
      */
     protected void updateTheme() {
-        final boolean inflated = mStackScroller != null && mStatusBarWindowManager != null;
+        final boolean inflated = mStackScroller != null && mStatusBarWindowController != null;
 
         // Lock wallpaper defines the color of the majority of the views, hence we'll use it
         // to set our default theme.
@@ -3907,7 +3907,7 @@
             mStackScroller.updateDecorViews(useDarkText);
 
             // Make sure we have the correct navbar/statusbar colors.
-            mStatusBarWindowManager.setKeyguardDark(useDarkText);
+            mStatusBarWindowController.setKeyguardDark(useDarkText);
         }
     }
 
@@ -4071,7 +4071,7 @@
         mGroupManager.setStatusBarState(state);
         mHeadsUpManager.setStatusBarState(state);
         mFalsingManager.setStatusBarState(state);
-        mStatusBarWindowManager.setStatusBarState(state);
+        mStatusBarWindowController.setStatusBarState(state);
         mStackScroller.setStatusBarState(state);
         updateReportRejectedTouchVisibility();
         updateDozing();
@@ -4101,7 +4101,7 @@
         if (!isPresenterFullyCollapsed()) {
             // if we set it not to be focusable when collapsing, we have to undo it when we aborted
             // the closing
-            mStatusBarWindowManager.setStatusBarFocusable(true);
+            mStatusBarWindowController.setStatusBarFocusable(true);
         }
     }
 
@@ -4718,7 +4718,7 @@
         if (mDozing != dozing) {
             mDozing = dozing;
             mKeyguardViewMediator.setAodShowing(mDozing);
-            mStatusBarWindowManager.setDozing(mDozing);
+            mStatusBarWindowController.setDozing(mDozing);
             mStatusBarKeyguardViewManager.setDozing(mDozing);
             if (mAmbientIndicationContainer instanceof DozeReceiver) {
                 ((DozeReceiver) mAmbientIndicationContainer).setDozing(mDozing);
@@ -4948,7 +4948,7 @@
 
         @Override
         public void setDozeScreenBrightness(int value) {
-            mStatusBarWindowManager.setDozeScreenBrightness(value);
+            mStatusBarWindowController.setDozeScreenBrightness(value);
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index c4424d8..9bc0252 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -74,7 +74,7 @@
     private static String TAG = "StatusBarKeyguardViewManager";
 
     protected final Context mContext;
-    private final StatusBarWindowManager mStatusBarWindowManager;
+    private final StatusBarWindowController mStatusBarWindowController;
     private final BouncerExpansionCallback mExpansionCallback = new BouncerExpansionCallback() {
         @Override
         public void onFullyShown() {
@@ -135,7 +135,7 @@
         mContext = context;
         mViewMediatorCallback = callback;
         mLockPatternUtils = lockPatternUtils;
-        mStatusBarWindowManager = Dependency.get(StatusBarWindowManager.class);
+        mStatusBarWindowController = Dependency.get(StatusBarWindowController.class);
         KeyguardUpdateMonitor.getInstance(context).registerCallback(mUpdateMonitorCallback);
     }
 
@@ -190,7 +190,7 @@
      */
     public void show(Bundle options) {
         mShowing = true;
-        mStatusBarWindowManager.setKeyguardShowing(true);
+        mStatusBarWindowController.setKeyguardShowing(true);
         reset(true /* hideBouncerWhenShowing */);
         StatsLog.write(StatsLog.KEYGUARD_STATE_CHANGED,
             StatsLog.KEYGUARD_STATE_CHANGED__STATE__SHOWN);
@@ -342,11 +342,11 @@
     }
 
     public void setNeedsInput(boolean needsInput) {
-        mStatusBarWindowManager.setKeyguardNeedsInput(needsInput);
+        mStatusBarWindowController.setKeyguardNeedsInput(needsInput);
     }
 
     public boolean isUnlockWithWallpaper() {
-        return mStatusBarWindowManager.isShowingWallpaper();
+        return mStatusBarWindowController.isShowingWallpaper();
     }
 
     public void setOccluded(boolean occluded, boolean animate) {
@@ -360,7 +360,7 @@
                         new Runnable() {
                             @Override
                             public void run() {
-                                mStatusBarWindowManager.setKeyguardOccluded(mOccluded);
+                                mStatusBarWindowController.setKeyguardOccluded(mOccluded);
                                 reset(true /* hideBouncerWhenShowing */);
                             }
                         });
@@ -375,7 +375,7 @@
         if (mShowing) {
             mStatusBar.updateMediaMetaData(false, animate && !occluded);
         }
-        mStatusBarWindowManager.setKeyguardOccluded(occluded);
+        mStatusBarWindowController.setKeyguardOccluded(occluded);
 
         // setDozing(false) will call reset once we stop dozing.
         if (!mDozing) {
@@ -425,8 +425,8 @@
             mStatusBar.fadeKeyguardAfterLaunchTransition(new Runnable() {
                 @Override
                 public void run() {
-                    mStatusBarWindowManager.setKeyguardShowing(false);
-                    mStatusBarWindowManager.setKeyguardFadingAway(true);
+                    mStatusBarWindowController.setKeyguardShowing(false);
+                    mStatusBarWindowController.setKeyguardFadingAway(true);
                     hideBouncer(true /* destroyView */);
                     updateStates();
                 }
@@ -434,7 +434,7 @@
                 @Override
                 public void run() {
                     mStatusBar.hideKeyguard();
-                    mStatusBarWindowManager.setKeyguardFadingAway(false);
+                    mStatusBarWindowController.setKeyguardFadingAway(false);
                     mViewMediatorCallback.keyguardGone();
                     executeAfterKeyguardGoneAction();
                 }
@@ -456,7 +456,7 @@
             } else {
                 boolean staying = mStatusBar.hideKeyguard();
                 if (!staying) {
-                    mStatusBarWindowManager.setKeyguardFadingAway(true);
+                    mStatusBarWindowController.setKeyguardFadingAway(true);
                     wakeAndUnlockDejank();
                 } else {
                     mStatusBar.finishKeyguardFadingAway();
@@ -464,7 +464,7 @@
                 }
             }
             updateStates();
-            mStatusBarWindowManager.setKeyguardShowing(false);
+            mStatusBarWindowController.setKeyguardShowing(false);
             mViewMediatorCallback.keyguardGone();
         }
         StatsLog.write(StatsLog.KEYGUARD_STATE_CHANGED,
@@ -481,7 +481,7 @@
     }
 
     public void onKeyguardFadedAway() {
-        mContainer.postDelayed(() -> mStatusBarWindowManager.setKeyguardFadingAway(false),
+        mContainer.postDelayed(() -> mStatusBarWindowController.setKeyguardFadingAway(false),
                 100);
         mStatusBar.finishKeyguardFadingAway();
         mBiometricUnlockController.finishKeyguardFadingAway();
@@ -599,7 +599,7 @@
         }
 
         if (bouncerShowing != mLastBouncerShowing || mFirstUpdate) {
-            mStatusBarWindowManager.setBouncerShowing(bouncerShowing);
+            mStatusBarWindowController.setBouncerShowing(bouncerShowing);
             mStatusBar.setBouncerShowing(bouncerShowing);
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
similarity index 94%
rename from packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
rename to packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index a5716f2..4d60121 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -36,6 +36,7 @@
 import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.keyguard.R;
 import com.android.systemui.Dumpable;
 import com.android.systemui.keyguard.KeyguardViewMediator;
@@ -49,9 +50,9 @@
 /**
  * Encapsulates all logic for the status bar window state management.
  */
-public class StatusBarWindowManager implements RemoteInputController.Callback, Dumpable {
+public class StatusBarWindowController implements RemoteInputController.Callback, Dumpable {
 
-    private static final String TAG = "StatusBarWindowManager";
+    private static final String TAG = "StatusBarWindowController";
 
     private final Context mContext;
     private final WindowManager mWindowManager;
@@ -68,12 +69,19 @@
     private final State mCurrentState = new State();
     private OtherwisedCollapsedListener mListener;
 
-    public StatusBarWindowManager(Context context) {
+    public StatusBarWindowController(Context context) {
+        this(context, context.getSystemService(WindowManager.class), ActivityManager.getService(),
+                DozeParameters.getInstance(context));
+    }
+
+    @VisibleForTesting
+    StatusBarWindowController(Context context, WindowManager windowManager,
+            IActivityManager activityManager, DozeParameters dozeParameters) {
         mContext = context;
-        mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
-        mActivityManager = ActivityManager.getService();
+        mWindowManager = windowManager;
+        mActivityManager = activityManager;
         mKeyguardScreenRotation = shouldEnableKeyguardScreenRotation();
-        mDozeParameters = DozeParameters.getInstance(mContext);
+        mDozeParameters = dozeParameters;
         mScreenBrightnessDoze = mDozeParameters.getScreenBrightnessDoze();
     }
 
@@ -149,6 +157,12 @@
         } else {
             mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
         }
+
+        if (state.dozing) {
+            mLpChanged.privateFlags |= LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+        } else {
+            mLpChanged.privateFlags &= ~LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+        }
     }
 
     private void adjustScreenOrientation(State state) {
@@ -433,7 +447,7 @@
     }
 
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        pw.println("StatusBarWindowManager state:");
+        pw.println("StatusBarWindowController state:");
         pw.println(mCurrentState);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
index 2bf62bb..533bd86 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
@@ -30,6 +30,7 @@
 import android.util.ArraySet;
 import android.util.Log;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.systemui.R;
 
 import java.io.FileDescriptor;
@@ -41,12 +42,16 @@
 
 import static android.media.MediaRouter.ROUTE_TYPE_REMOTE_DISPLAY;
 
+import androidx.annotation.VisibleForTesting;
+
+
 /** Platform implementation of the cast controller. **/
 public class CastControllerImpl implements CastController {
     private static final String TAG = "CastController";
     private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
 
     private final Context mContext;
+    @GuardedBy("mCallbacks")
     private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>();
     private final MediaRouter mMediaRouter;
     private final ArrayMap<String, RouteInfo> mRoutes = new ArrayMap<>();
@@ -72,7 +77,7 @@
         pw.println("CastController state:");
         pw.print("  mDiscovering="); pw.println(mDiscovering);
         pw.print("  mCallbackRegistered="); pw.println(mCallbackRegistered);
-        pw.print("  mCallbacks.size="); pw.println(mCallbacks.size());
+        pw.print("  mCallbacks.size="); synchronized (mCallbacks) {pw.println(mCallbacks.size());}
         pw.print("  mRoutes.size="); pw.println(mRoutes.size());
         for (int i = 0; i < mRoutes.size(); i++) {
             final RouteInfo route = mRoutes.valueAt(i);
@@ -83,7 +88,9 @@
 
     @Override
     public void addCallback(Callback callback) {
-        mCallbacks.add(callback);
+        synchronized (mCallbacks) {
+            mCallbacks.add(callback);
+        }
         fireOnCastDevicesChanged(callback);
         synchronized (mDiscoveringLock) {
             handleDiscoveryChangeLocked();
@@ -92,7 +99,9 @@
 
     @Override
     public void removeCallback(Callback callback) {
-        mCallbacks.remove(callback);
+        synchronized (mCallbacks) {
+            mCallbacks.remove(callback);
+        }
         synchronized (mDiscoveringLock) {
             handleDiscoveryChangeLocked();
         }
@@ -117,10 +126,16 @@
             mMediaRouter.addCallback(ROUTE_TYPE_REMOTE_DISPLAY, mMediaCallback,
                     MediaRouter.CALLBACK_FLAG_REQUEST_DISCOVERY);
             mCallbackRegistered = true;
-        } else if (mCallbacks.size() != 0) {
-            mMediaRouter.addCallback(ROUTE_TYPE_REMOTE_DISPLAY, mMediaCallback,
-                    MediaRouter.CALLBACK_FLAG_PASSIVE_DISCOVERY);
-            mCallbackRegistered = true;
+        } else {
+            boolean hasCallbacks = false;
+            synchronized (mCallbacks) {
+                hasCallbacks = mCallbacks.isEmpty();
+            }
+            if (!hasCallbacks) {
+                mMediaRouter.addCallback(ROUTE_TYPE_REMOTE_DISPLAY, mMediaCallback,
+                        MediaRouter.CALLBACK_FLAG_PASSIVE_DISCOVERY);
+                mCallbackRegistered = true;
+            }
         }
     }
 
@@ -248,12 +263,17 @@
         }
     }
 
-    private void fireOnCastDevicesChanged() {
-        for (Callback callback : mCallbacks) {
-            fireOnCastDevicesChanged(callback);
+    @VisibleForTesting
+    void fireOnCastDevicesChanged() {
+        synchronized (mCallbacks) {
+            for (Callback callback : mCallbacks) {
+                fireOnCastDevicesChanged(callback);
+            }
+
         }
     }
 
+
     private void fireOnCastDevicesChanged(Callback callback) {
         callback.onCastDevicesChanged();
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
index 644c0b3..cc96917 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/ScreenDecorationsTest.java
@@ -21,6 +21,7 @@
 
 import static org.hamcrest.Matchers.is;
 import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertEquals;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.anyString;
@@ -226,4 +227,17 @@
         verify(padding).destroy();
     }
 
+    @Test
+    public void testUpdateRoundedCorners() {
+        mContext.getOrCreateTestableResources().addOverride(
+                com.android.internal.R.bool.config_fillMainBuiltInDisplayCutout, false);
+        mContext.getOrCreateTestableResources().addOverride(dimen.rounded_corner_radius, 20);
+
+        mScreenDecorations.start();
+        assertEquals(mScreenDecorations.mRoundedDefault, 20);
+
+        mContext.getOrCreateTestableResources().addOverride(dimen.rounded_corner_radius, 5);
+        mScreenDecorations.onConfigurationChanged(null);
+        assertEquals(mScreenDecorations.mRoundedDefault, 5);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
index 9121473..8129b01 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NonPhoneDependencyTest.java
@@ -33,7 +33,7 @@
 import com.android.systemui.statusbar.notification.row.NotificationInfo;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 import com.android.systemui.statusbar.phone.NotificationGroupManager;
-import com.android.systemui.statusbar.phone.StatusBarWindowManager;
+import com.android.systemui.statusbar.phone.StatusBarWindowController;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 
 import org.junit.Before;
@@ -96,6 +96,6 @@
         viewHierarchyManager.setUpWithPresenter(mPresenter, entryManager, mListContainer);
         notificationListener.setUpWithPresenter(mPresenter, entryManager);
 
-        assertFalse(mDependency.hasInstantiatedDependency(StatusBarWindowManager.class));
+        assertFalse(mDependency.hasInstantiatedDependency(StatusBarWindowController.class));
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 6933328..be4560b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -68,7 +68,7 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
-        mDependency.injectMockDependency(StatusBarWindowManager.class);
+        mDependency.injectMockDependency(StatusBarWindowController.class);
         mStatusBarKeyguardViewManager = new TestableStatusBarKeyguardViewManager(getContext(),
                 mViewMediatorCallback, mLockPatternUtils);
         mStatusBarKeyguardViewManager.registerStatusBar(mStatusBar, mContainer,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index e39238d..a90346b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -204,7 +204,7 @@
                 mEntryManager, mScrimController, mBiometricUnlockController,
                 mock(ActivityLaunchAnimator.class), mKeyguardViewMediator,
                 mRemoteInputManager, mock(NotificationGroupManager.class),
-                mock(FalsingManager.class), mock(StatusBarWindowManager.class),
+                mock(FalsingManager.class), mock(StatusBarWindowController.class),
                 mock(NotificationIconAreaController.class), mock(DozeScrimController.class),
                 mock(NotificationShelf.class), mLockscreenUserManager,
                 mock(CommandQueue.class));
@@ -716,7 +716,7 @@
                 NotificationRemoteInputManager notificationRemoteInputManager,
                 NotificationGroupManager notificationGroupManager,
                 FalsingManager falsingManager,
-                StatusBarWindowManager statusBarWindowManager,
+                StatusBarWindowController statusBarWindowController,
                 NotificationIconAreaController notificationIconAreaController,
                 DozeScrimController dozeScrimController,
                 NotificationShelf notificationShelf,
@@ -744,7 +744,7 @@
             mRemoteInputManager = notificationRemoteInputManager;
             mGroupManager = notificationGroupManager;
             mFalsingManager = falsingManager;
-            mStatusBarWindowManager = statusBarWindowManager;
+            mStatusBarWindowController = statusBarWindowController;
             mNotificationIconAreaController = notificationIconAreaController;
             mDozeScrimController = dozeScrimController;
             mNotificationShelf = notificationShelf;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
new file mode 100644
index 0000000..f8223f6
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarWindowControllerTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.phone;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.IActivityManager;
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+import android.testing.TestableLooper.RunWithLooper;
+import android.view.View;
+import android.view.WindowManager;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidTestingRunner.class)
+@RunWithLooper
+@SmallTest
+public class StatusBarWindowControllerTest extends SysuiTestCase {
+
+    @Mock
+    private WindowManager mWindowManager;
+    @Mock
+    private DozeParameters mDozeParameters;
+    @Mock
+    private View mStatusBarView;
+    @Mock
+    private IActivityManager mActivityManager;
+
+    private StatusBarWindowController mStatusBarWindowController;
+
+    @Before
+    public void setUp() {
+        MockitoAnnotations.initMocks(this);
+        when(mDozeParameters.getAlwaysOn()).thenReturn(true);
+
+        mStatusBarWindowController = new StatusBarWindowController(mContext, mWindowManager,
+                mActivityManager, mDozeParameters);
+        mStatusBarWindowController.add(mStatusBarView, 100 /* height */);
+    }
+
+    @Test
+    public void testSetDozing_hidesSystemOverlays() {
+        mStatusBarWindowController.setDozing(true);
+        ArgumentCaptor<WindowManager.LayoutParams> captor =
+                ArgumentCaptor.forClass(WindowManager.LayoutParams.class);
+        verify(mWindowManager).updateViewLayout(any(), captor.capture());
+        int flag = captor.getValue().privateFlags
+                & WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+        assertThat(flag).isNotEqualTo(0);
+
+        reset(mWindowManager);
+        mStatusBarWindowController.setDozing(false);
+        verify(mWindowManager).updateViewLayout(any(), captor.capture());
+        flag = captor.getValue().privateFlags
+                & WindowManager.LayoutParams.PRIVATE_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS;
+        assertThat(flag).isEqualTo(0);
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CastControllerImplTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CastControllerImplTest.java
index 1b22f09..1ee7094 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CastControllerImplTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/CastControllerImplTest.java
@@ -6,8 +6,8 @@
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
+import static org.junit.Assert.fail;
 
-import android.content.Context;
 import android.media.MediaRouter;
 import android.media.projection.MediaProjectionInfo;
 import android.media.projection.MediaProjectionManager;
@@ -24,6 +24,11 @@
 import org.mockito.MockitoAnnotations;
 import org.junit.Test;
 
+import java.util.ConcurrentModificationException;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 @TestableLooper.RunWithLooper
@@ -49,15 +54,15 @@
     }
 
     @Test
-    public void testAddCallback(){
+    public void testAddCallback() {
         Callback mockCallback = mock(Callback.class);
 
         mController.addCallback(mockCallback);
-        verify(mockCallback,times(1)).onCastDevicesChanged();
+        verify(mockCallback, times(1)).onCastDevicesChanged();
     }
 
     @Test
-    public void testRemoveCallback(){
+    public void testRemoveCallback() {
         Callback mockCallback = mock(Callback.class);
 
         mController.addCallback(mockCallback);
@@ -68,10 +73,54 @@
     }
 
     @Test
-    public void testRemoveCallbackFromEmptyList(){
+    public void testRemoveCallbackFromEmptyList() {
         Callback mockCallback = mock(Callback.class);
 
         mController.removeCallback(mockCallback);
         verify(mockCallback, never()).onCastDevicesChanged();
     }
+
+    @Test
+    public void testAddCallbackRemoveCallback_concurrently() throws InterruptedException {
+        int callbackCount = 20;
+        int numThreads = 2 * callbackCount;
+        CountDownLatch startThreadsLatch = new CountDownLatch(1);
+        CountDownLatch threadsDone = new CountDownLatch(numThreads);
+        Callback[] callbackList = new Callback[callbackCount];
+        mController.setDiscovering(true);
+        AtomicBoolean error = new AtomicBoolean(false);
+        for (int cbIndex = 0; cbIndex < callbackCount; cbIndex++) {
+            callbackList[cbIndex] = mock(Callback.class);
+        }
+        for (int i = 0; i < numThreads; i++) {
+            final Callback mCallback = callbackList[i / 2];
+            final boolean shouldAdd = (i % 2 == 0);
+            new Thread() {
+                public void run() {
+                    try {
+                        startThreadsLatch.await(10, TimeUnit.SECONDS);
+                    } catch (InterruptedException e) {
+                        throw new RuntimeException(e);
+                    }
+                    try {
+                        if (shouldAdd) {
+                            mController.addCallback(mCallback);
+                        } else {
+                            mController.removeCallback(mCallback);
+                        }
+                        mController.fireOnCastDevicesChanged();
+                    } catch (ConcurrentModificationException exc) {
+                        error.compareAndSet(false, true);
+                    } finally {
+                        threadsDone.countDown();
+                    }
+                }
+            }.start();
+        }
+        startThreadsLatch.countDown();
+        threadsDone.await(10, TimeUnit.SECONDS);
+        if (error.get()) {
+            fail("Concurrent modification exception");
+        }
+    }
 }
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/strings.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/strings.xml
index 754ba72..b08924b 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/strings.xml
@@ -16,7 +16,7 @@
   -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
 
-    <string name="display_cutout_emulation_overlay">Corner display cutout</string>
+    <string name="display_cutout_emulation_overlay">Corner cutout</string>
 
 </resources>
 
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/strings.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/strings.xml
index 68c2dcb..0a106fa 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/strings.xml
@@ -16,7 +16,7 @@
   -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
 
-    <string name="display_cutout_emulation_overlay">Double display cutout</string>
+    <string name="display_cutout_emulation_overlay">Double cutout</string>
 
 </resources>
 
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/strings.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/strings.xml
index 4989677..0bf8330 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/strings.xml
@@ -18,7 +18,7 @@
 -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
 
-    <string name="display_cutout_emulation_overlay">Narrow display cutout</string>
+    <string name="display_cutout_emulation_overlay">Narrow cutout</string>
 
 </resources>
 
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/strings.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/strings.xml
index 6dcbbd9..bcc7c97 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/strings.xml
@@ -16,7 +16,7 @@
   -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
 
-    <string name="display_cutout_emulation_overlay">Tall display cutout</string>
+    <string name="display_cutout_emulation_overlay">Tall cutout</string>
 
 </resources>
 
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/strings.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/strings.xml
index f4b9f7e..0fcbdebb 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/strings.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/strings.xml
@@ -16,7 +16,7 @@
   -->
 <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
 
-    <string name="display_cutout_emulation_overlay">Wide display cutout</string>
+    <string name="display_cutout_emulation_overlay">Wide cutout</string>
 
 </resources>
 
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index acbb67c..6be9550 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -1567,8 +1567,9 @@
         }
         final long identity = Binder.clearCallingIdentity();
         try {
+            final String settingValue = builder.toString();
             Settings.Secure.putStringForUser(mContext.getContentResolver(),
-                    settingName, builder.toString(), userId);
+                    settingName, TextUtils.isEmpty(settingValue) ? null : settingValue, userId);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
diff --git a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
index 6f03b76..5771748 100644
--- a/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
+++ b/services/autofill/java/com/android/server/autofill/AutofillManagerService.java
@@ -438,8 +438,13 @@
         Slog.i(TAG, "setLogLevel(): " + level);
         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
 
-        Settings.Global.putInt(mContext.getContentResolver(),
-                Settings.Global.AUTOFILL_LOGGING_LEVEL, level);
+        final long token = Binder.clearCallingIdentity();
+        try {
+            Settings.Global.putInt(mContext.getContentResolver(),
+                    Settings.Global.AUTOFILL_LOGGING_LEVEL, level);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     private void setLogLevelFromSettings() {
@@ -492,8 +497,13 @@
         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
         Slog.i(TAG, "setMaxPartitions(): " + max);
 
-        Settings.Global.putInt(mContext.getContentResolver(),
-                Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE, max);
+        final long token = Binder.clearCallingIdentity();
+        try {
+            Settings.Global.putInt(mContext.getContentResolver(),
+                    Settings.Global.AUTOFILL_MAX_PARTITIONS_SIZE, max);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     private void setMaxPartitionsFromSettings() {
@@ -521,8 +531,13 @@
         mContext.enforceCallingPermission(MANAGE_AUTO_FILL, TAG);
         Slog.i(TAG, "setMaxVisibleDatasets(): " + max);
 
-        Settings.Global.putInt(mContext.getContentResolver(),
-                Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS, max);
+        final long token = Binder.clearCallingIdentity();
+        try {
+            Settings.Global.putInt(mContext.getContentResolver(),
+                    Settings.Global.AUTOFILL_MAX_VISIBLE_DATASETS, max);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
     }
 
     private void setMaxVisibleDatasetsFromSettings() {
diff --git a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
index 760e85e..9d3d3cb 100644
--- a/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
+++ b/services/autofill/java/com/android/server/autofill/ui/SaveUi.java
@@ -84,18 +84,19 @@
     }
 
     /**
-     * Wrapper that guarantees that only one callback is triggered by ignoring further calls after
+     * Wrapper that guarantees that only one callback action (either {@link #onSave()} or
+     * {@link #onCancel(IntentSender)}) is triggered by ignoring further calls after
      * it's destroyed.
      *
      * <p>It's needed becase {@link #onCancel(IntentSender)} is always called when the Save UI
      * dialog is dismissed.
      */
-    private class OneTimeListener implements OnSaveListener {
+    private class OneActionThenDestroyListener implements OnSaveListener {
 
         private final OnSaveListener mRealListener;
         private boolean mDone;
 
-        OneTimeListener(OnSaveListener realListener) {
+        OneActionThenDestroyListener(OnSaveListener realListener) {
             mRealListener = realListener;
         }
 
@@ -133,7 +134,7 @@
 
     private final @NonNull Dialog mDialog;
 
-    private final @NonNull OneTimeListener mListener;
+    private final @NonNull OneActionThenDestroyListener mListener;
 
     private final @NonNull OverlayControl mOverlayControl;
 
@@ -153,7 +154,7 @@
            @NonNull OverlayControl overlayControl, @NonNull OnSaveListener listener,
            boolean isUpdate, boolean compatMode) {
         mPendingUi= pendingUi;
-        mListener = new OneTimeListener(listener);
+        mListener = new OneActionThenDestroyListener(listener);
         mOverlayControl = overlayControl;
         mServicePackageName = servicePackageName;
         mComponentName = componentName;
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 784dfb4..02a62ff 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -1714,10 +1714,9 @@
     }
 
     @Override
-    public void addClient(IInputMethodClient client,
-            IInputContext inputContext, int uid, int pid) {
-        if (!calledFromValidUser()) {
-            return;
+    public void addClient(IInputMethodClient client, IInputContext inputContext, int uid, int pid) {
+        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+            throw new SecurityException("Only system process can call this method.");
         }
         synchronized (mMethodMap) {
             mClients.put(client.asBinder(), new ClientState(client,
@@ -1727,8 +1726,8 @@
 
     @Override
     public void removeClient(IInputMethodClient client) {
-        if (!calledFromValidUser()) {
-            return;
+        if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+            throw new SecurityException("Only system process can call this method.");
         }
         synchronized (mMethodMap) {
             ClientState cs = mClients.remove(client.asBinder());
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index 4b0379e..d829602 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -1227,25 +1227,25 @@
     public boolean getIpForwardingEnabled() throws IllegalStateException{
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
 
-        final NativeDaemonEvent event;
         try {
-            event = mConnector.execute("ipfwd", "status");
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
+            final boolean isEnabled = mNetdService.ipfwdEnabled();
+            return isEnabled;
+        } catch (RemoteException | ServiceSpecificException e) {
+            throw new IllegalStateException(e);
         }
-
-        // 211 Forwarding enabled
-        event.checkCode(IpFwdStatusResult);
-        return event.getMessage().endsWith("enabled");
     }
 
     @Override
     public void setIpForwardingEnabled(boolean enable) {
         mContext.enforceCallingOrSelfPermission(CONNECTIVITY_INTERNAL, TAG);
         try {
-            mConnector.execute("ipfwd", enable ? "enable" : "disable", "tethering");
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
+            if (enable) {
+                mNetdService.ipfwdEnableForwarding("tethering");
+            } else {
+                mNetdService.ipfwdDisableForwarding("tethering");
+            }
+        } catch (RemoteException | ServiceSpecificException e) {
+            throw new IllegalStateException(e);
         }
     }
 
@@ -1371,11 +1371,14 @@
     }
 
     private void modifyInterfaceForward(boolean add, String fromIface, String toIface) {
-        final Command cmd = new Command("ipfwd", add ? "add" : "remove", fromIface, toIface);
         try {
-            mConnector.execute(cmd);
-        } catch (NativeDaemonConnectorException e) {
-            throw e.rethrowAsParcelableException();
+            if (add) {
+                mNetdService.ipfwdAddInterfaceForward(fromIface, toIface);
+            } else {
+                mNetdService.ipfwdRemoveInterfaceForward(fromIface, toIface);
+            }
+        } catch (RemoteException | ServiceSpecificException e) {
+            throw new IllegalStateException(e);
         }
     }
 
diff --git a/services/core/java/com/android/server/display/DisplayDeviceInfo.java b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
index 349e1c8..512e851 100644
--- a/services/core/java/com/android/server/display/DisplayDeviceInfo.java
+++ b/services/core/java/com/android/server/display/DisplayDeviceInfo.java
@@ -104,6 +104,12 @@
     public static final int FLAG_DESTROY_CONTENT_ON_REMOVAL = 1 << 10;
 
     /**
+     * Flag: The display cutout of this display is masked.
+     * @hide
+     */
+    public static final int FLAG_MASK_DISPLAY_CUTOUT = 1 << 11;
+
+    /**
      * Touch attachment: Display does not receive touch.
      */
     public static final int TOUCH_NONE = 0;
@@ -453,6 +459,9 @@
         if ((flags & FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) {
             msg.append(", FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD");
         }
+        if ((flags & FLAG_MASK_DISPLAY_CUTOUT) != 0) {
+            msg.append(", FLAG_MASK_DISPLAY_CUTOUT");
+        }
         return msg.toString();
     }
 }
diff --git a/services/core/java/com/android/server/display/LocalDisplayAdapter.java b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
index 21ae048..16d82df 100644
--- a/services/core/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/core/java/com/android/server/display/LocalDisplayAdapter.java
@@ -402,6 +402,10 @@
                             && SystemProperties.getBoolean(PROPERTY_EMULATOR_CIRCULAR, false))) {
                         mInfo.flags |= DisplayDeviceInfo.FLAG_ROUND;
                     }
+                    if (res.getBoolean(
+                            com.android.internal.R.bool.config_maskMainBuiltInDisplayCutout)) {
+                        mInfo.flags |= DisplayDeviceInfo.FLAG_MASK_DISPLAY_CUTOUT;
+                    }
                     mInfo.displayCutout = DisplayCutout.fromResourcesRectApproximation(res,
                             mInfo.width, mInfo.height);
                     mInfo.type = Display.TYPE_BUILT_IN;
diff --git a/services/core/java/com/android/server/display/LogicalDisplay.java b/services/core/java/com/android/server/display/LogicalDisplay.java
index 23ee56b..373de63 100644
--- a/services/core/java/com/android/server/display/LogicalDisplay.java
+++ b/services/core/java/com/android/server/display/LogicalDisplay.java
@@ -23,6 +23,8 @@
 import android.view.Surface;
 import android.view.SurfaceControl;
 
+import com.android.server.wm.utils.InsetUtils;
+
 import java.io.PrintWriter;
 import java.util.Arrays;
 import java.util.List;
@@ -251,14 +253,18 @@
             if ((deviceInfo.flags & DisplayDeviceInfo.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD) != 0) {
                 mBaseDisplayInfo.flags |= Display.FLAG_CAN_SHOW_WITH_INSECURE_KEYGUARD;
             }
+            Rect maskingInsets = getMaskingInsets(deviceInfo);
+            int maskedWidth = deviceInfo.width - maskingInsets.left - maskingInsets.right;
+            int maskedHeight = deviceInfo.height - maskingInsets.top - maskingInsets.bottom;
+
             mBaseDisplayInfo.type = deviceInfo.type;
             mBaseDisplayInfo.address = deviceInfo.address;
             mBaseDisplayInfo.name = deviceInfo.name;
             mBaseDisplayInfo.uniqueId = deviceInfo.uniqueId;
-            mBaseDisplayInfo.appWidth = deviceInfo.width;
-            mBaseDisplayInfo.appHeight = deviceInfo.height;
-            mBaseDisplayInfo.logicalWidth = deviceInfo.width;
-            mBaseDisplayInfo.logicalHeight = deviceInfo.height;
+            mBaseDisplayInfo.appWidth = maskedWidth;
+            mBaseDisplayInfo.appHeight = maskedHeight;
+            mBaseDisplayInfo.logicalWidth = maskedWidth;
+            mBaseDisplayInfo.logicalHeight = maskedHeight;
             mBaseDisplayInfo.rotation = Surface.ROTATION_0;
             mBaseDisplayInfo.modeId = deviceInfo.modeId;
             mBaseDisplayInfo.defaultModeId = deviceInfo.defaultModeId;
@@ -275,13 +281,15 @@
             mBaseDisplayInfo.appVsyncOffsetNanos = deviceInfo.appVsyncOffsetNanos;
             mBaseDisplayInfo.presentationDeadlineNanos = deviceInfo.presentationDeadlineNanos;
             mBaseDisplayInfo.state = deviceInfo.state;
-            mBaseDisplayInfo.smallestNominalAppWidth = deviceInfo.width;
-            mBaseDisplayInfo.smallestNominalAppHeight = deviceInfo.height;
-            mBaseDisplayInfo.largestNominalAppWidth = deviceInfo.width;
-            mBaseDisplayInfo.largestNominalAppHeight = deviceInfo.height;
+            mBaseDisplayInfo.smallestNominalAppWidth = maskedWidth;
+            mBaseDisplayInfo.smallestNominalAppHeight = maskedHeight;
+            mBaseDisplayInfo.largestNominalAppWidth = maskedWidth;
+            mBaseDisplayInfo.largestNominalAppHeight = maskedHeight;
             mBaseDisplayInfo.ownerUid = deviceInfo.ownerUid;
             mBaseDisplayInfo.ownerPackageName = deviceInfo.ownerPackageName;
-            mBaseDisplayInfo.displayCutout = deviceInfo.displayCutout;
+            boolean maskCutout =
+                    (deviceInfo.flags & DisplayDeviceInfo.FLAG_MASK_DISPLAY_CUTOUT) != 0;
+            mBaseDisplayInfo.displayCutout = maskCutout ? null : deviceInfo.displayCutout;
 
             mPrimaryDisplayDeviceInfo = deviceInfo;
             mInfo = null;
@@ -289,6 +297,18 @@
     }
 
     /**
+     * Returns insets in ROTATION_0 for areas that are masked.
+     */
+    private static Rect getMaskingInsets(DisplayDeviceInfo deviceInfo) {
+        boolean maskCutout = (deviceInfo.flags & DisplayDeviceInfo.FLAG_MASK_DISPLAY_CUTOUT) != 0;
+        if (maskCutout && deviceInfo.displayCutout != null) {
+            return deviceInfo.displayCutout.getSafeInsets();
+        } else {
+            return new Rect();
+        }
+    }
+
+    /**
      * Applies the layer stack and transformation to the given display device
      * so that it shows the contents of this logical display.
      *
@@ -349,6 +369,12 @@
         int physWidth = rotated ? displayDeviceInfo.height : displayDeviceInfo.width;
         int physHeight = rotated ? displayDeviceInfo.width : displayDeviceInfo.height;
 
+        Rect maskingInsets = getMaskingInsets(displayDeviceInfo);
+        InsetUtils.rotateInsets(maskingInsets, orientation);
+        // Don't consider the masked area as available when calculating the scaling below.
+        physWidth -= maskingInsets.left + maskingInsets.right;
+        physHeight -= maskingInsets.top + maskingInsets.bottom;
+
         // Determine whether the width or height is more constrained to be scaled.
         //    physWidth / displayInfo.logicalWidth    => letter box
         // or physHeight / displayInfo.logicalHeight  => pillar box
@@ -375,6 +401,9 @@
         mTempDisplayRect.set(displayRectLeft, displayRectTop,
                 displayRectLeft + displayRectWidth, displayRectTop + displayRectHeight);
 
+        // Now add back the offset for the masked area.
+        mTempDisplayRect.offset(maskingInsets.left, maskingInsets.top);
+
         mTempDisplayRect.left += mDisplayOffsetX;
         mTempDisplayRect.right += mDisplayOffsetX;
         mTempDisplayRect.top += mDisplayOffsetY;
diff --git a/services/core/java/com/android/server/hdmi/HdmiControlService.java b/services/core/java/com/android/server/hdmi/HdmiControlService.java
index a2eb1c1..c16d3cd 100644
--- a/services/core/java/com/android/server/hdmi/HdmiControlService.java
+++ b/services/core/java/com/android/server/hdmi/HdmiControlService.java
@@ -402,6 +402,8 @@
         if (mCecController != null) {
             if (mHdmiControlEnabled) {
                 initializeCec(INITIATED_BY_BOOT_UP);
+            } else {
+                mCecController.setOption(OptionKey.ENABLE_CEC, false);
             }
         } else {
             Slog.i(TAG, "Device does not support HDMI-CEC.");
@@ -2384,6 +2386,7 @@
 
     @ServiceThreadOnly
     private void enableHdmiControlService() {
+        mCecController.setOption(OptionKey.ENABLE_CEC, true);
         mCecController.setOption(OptionKey.SYSTEM_CEC_CONTROL, true);
         mMhlController.setOption(OPTION_MHL_ENABLE, ENABLED);
 
@@ -2400,6 +2403,7 @@
                     @Override
                     public void run() {
                         mCecController.setOption(OptionKey.ENABLE_CEC, false);
+                        mCecController.setOption(OptionKey.SYSTEM_CEC_CONTROL, false);
                         mMhlController.setOption(OPTION_MHL_ENABLE, DISABLED);
                         clearLocalDevices();
                     }
diff --git a/services/core/java/com/android/server/notification/NotificationDelegate.java b/services/core/java/com/android/server/notification/NotificationDelegate.java
index 8be8450..decdac6 100644
--- a/services/core/java/com/android/server/notification/NotificationDelegate.java
+++ b/services/core/java/com/android/server/notification/NotificationDelegate.java
@@ -30,6 +30,7 @@
     void onNotificationClear(int callingUid, int callingPid,
             String pkg, String tag, int id, int userId, String key,
             @NotificationStats.DismissalSurface int dismissalSurface,
+            @NotificationStats.DismissalSentiment int dismissalSentiment,
             NotificationVisibility nv);
     void onNotificationError(int callingUid, int callingPid,
             String pkg, String tag, int id,
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index dd3e2d4..ce71dd2 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -700,7 +700,8 @@
         }
 
         @Override
-        public void onNotificationClick(int callingUid, int callingPid, String key, NotificationVisibility nv) {
+        public void onNotificationClick(int callingUid, int callingPid, String key,
+                NotificationVisibility nv) {
             exitIdle();
             synchronized (mNotificationLock) {
                 NotificationRecord r = mNotificationsByKey.get(key);
@@ -757,11 +758,13 @@
         public void onNotificationClear(int callingUid, int callingPid,
                 String pkg, String tag, int id, int userId, String key,
                 @NotificationStats.DismissalSurface int dismissalSurface,
+                @NotificationStats.DismissalSentiment int dismissalSentiment,
                 NotificationVisibility nv) {
             synchronized (mNotificationLock) {
                 NotificationRecord r = mNotificationsByKey.get(key);
                 if (r != null) {
                     r.recordDismissalSurface(dismissalSurface);
+                    r.recordDismissalSentiment(dismissalSentiment);
                 }
             }
             cancelNotification(callingUid, callingPid, pkg, tag, id, 0,
@@ -797,8 +800,8 @@
         }
 
         @Override
-        public void onNotificationError(int callingUid, int callingPid, String pkg, String tag, int id,
-                int uid, int initialPid, String message, int userId) {
+        public void onNotificationError(int callingUid, int callingPid, String pkg, String tag,
+                int id, int uid, int initialPid, String message, int userId) {
             cancelNotification(callingUid, callingPid, pkg, tag, id, 0, 0, false, userId,
                     REASON_ERROR, null);
         }
@@ -1040,10 +1043,12 @@
                     uidList = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
                 } else if (action.equals(Intent.ACTION_PACKAGES_SUSPENDED)) {
                     pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+                    uidList = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
                     cancelNotifications = false;
                     hideNotifications = true;
                 } else if (action.equals(Intent.ACTION_PACKAGES_UNSUSPENDED)) {
                     pkgList = intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
+                    uidList = intent.getIntArrayExtra(Intent.EXTRA_CHANGED_UID_LIST);
                     cancelNotifications = false;
                     unhideNotifications = true;
                 } else if (queryRestart) {
@@ -5964,6 +5969,7 @@
             }
             notificationList.remove(i);
             mNotificationsByKey.remove(r.getKey());
+            r.recordDismissalSentiment(NotificationStats.DISMISS_SENTIMENT_NEUTRAL);
             canceledNotifications.add(r);
             cancelNotificationLocked(r, sendDelete, reason, wasPosted, listenerName);
         }
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index a6d8615..fbb42ea 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -1065,6 +1065,10 @@
         mStats.setDismissalSurface(surface);
     }
 
+    public void recordDismissalSentiment(@NotificationStats.DismissalSentiment int sentiment) {
+        mStats.setDismissalSentiment(sentiment);
+    }
+
     public void recordSnoozed() {
         mStats.setSnoozed();
     }
diff --git a/services/core/java/com/android/server/pm/ComponentResolver.java b/services/core/java/com/android/server/pm/ComponentResolver.java
new file mode 100644
index 0000000..2b2db62
--- /dev/null
+++ b/services/core/java/com/android/server/pm/ComponentResolver.java
@@ -0,0 +1,1847 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import static android.content.pm.PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
+import static android.content.pm.PackageManagerInternal.PACKAGE_SETUP_WIZARD;
+
+import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING;
+import static com.android.server.pm.PackageManagerService.DEBUG_REMOVE;
+import static com.android.server.pm.PackageManagerService.fixProcessName;
+
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.pm.ActivityInfo;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.AuxiliaryResolveInfo;
+import android.content.pm.InstantAppResolveInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
+import android.content.pm.PackageParser;
+import android.content.pm.PackageParser.ActivityIntentInfo;
+import android.content.pm.PackageParser.ServiceIntentInfo;
+import android.content.pm.PackageUserState;
+import android.content.pm.ProviderInfo;
+import android.content.pm.ResolveInfo;
+import android.content.pm.ServiceInfo;
+import android.os.UserHandle;
+import android.util.ArrayMap;
+import android.util.ArraySet;
+import android.util.Log;
+import android.util.LogPrinter;
+import android.util.Pair;
+import android.util.Slog;
+
+import com.android.internal.annotations.GuardedBy;
+import com.android.server.IntentResolver;
+
+import java.io.PrintWriter;
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/** Resolves all Android component types [activities, services, providers and receivers]. */
+public class ComponentResolver {
+    private static final String TAG = "PackageManager";
+    private static final boolean DEBUG_FILTERS = false;
+    private static final boolean DEBUG_SHOW_INFO = false;
+
+    /**
+     * The set of all protected actions [i.e. those actions for which a high priority
+     * intent filter is disallowed].
+     */
+    private static final Set<String> PROTECTED_ACTIONS = new ArraySet<>();
+    static {
+        PROTECTED_ACTIONS.add(Intent.ACTION_SEND);
+        PROTECTED_ACTIONS.add(Intent.ACTION_SENDTO);
+        PROTECTED_ACTIONS.add(Intent.ACTION_SEND_MULTIPLE);
+        PROTECTED_ACTIONS.add(Intent.ACTION_VIEW);
+    }
+
+    static final Comparator<ResolveInfo> RESOLVE_PRIORITY_SORTER = (r1, r2) -> {
+        int v1 = r1.priority;
+        int v2 = r2.priority;
+        //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
+        if (v1 != v2) {
+            return (v1 > v2) ? -1 : 1;
+        }
+        v1 = r1.preferredOrder;
+        v2 = r2.preferredOrder;
+        if (v1 != v2) {
+            return (v1 > v2) ? -1 : 1;
+        }
+        if (r1.isDefault != r2.isDefault) {
+            return r1.isDefault ? -1 : 1;
+        }
+        v1 = r1.match;
+        v2 = r2.match;
+        //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
+        if (v1 != v2) {
+            return (v1 > v2) ? -1 : 1;
+        }
+        if (r1.system != r2.system) {
+            return r1.system ? -1 : 1;
+        }
+        if (r1.activityInfo != null) {
+            return r1.activityInfo.packageName.compareTo(r2.activityInfo.packageName);
+        }
+        if (r1.serviceInfo != null) {
+            return r1.serviceInfo.packageName.compareTo(r2.serviceInfo.packageName);
+        }
+        if (r1.providerInfo != null) {
+            return r1.providerInfo.packageName.compareTo(r2.providerInfo.packageName);
+        }
+        return 0;
+    };
+
+    private static UserManagerService sUserManager;
+    private static PackageManagerInternal sPackageManagerInternal;
+
+    private final Object mLock = new Object();
+
+    /** All available activities, for your resolving pleasure. */
+    @GuardedBy("mLock")
+    private final ActivityIntentResolver mActivities = new ActivityIntentResolver();
+
+    /** All available providers, for your resolving pleasure. */
+    @GuardedBy("mLock")
+    private final ProviderIntentResolver mProviders = new ProviderIntentResolver();
+
+    /** All available receivers, for your resolving pleasure. */
+    @GuardedBy("mLock")
+    private final ActivityIntentResolver mReceivers = new ActivityIntentResolver();
+
+    /** All available services, for your resolving pleasure. */
+    @GuardedBy("mLock")
+    private final ServiceIntentResolver mServices = new ServiceIntentResolver();
+
+    /** Mapping from provider authority [first directory in content URI codePath) to provider. */
+    @GuardedBy("mLock")
+    private final ArrayMap<String, PackageParser.Provider> mProvidersByAuthority = new ArrayMap<>();
+
+    /** Whether or not processing protected filters should be deferred. */
+    private boolean mDeferProtectedFilters = true;
+
+    /**
+     * Tracks high priority intent filters for protected actions. During boot, certain
+     * filter actions are protected and should never be allowed to have a high priority
+     * intent filter for them. However, there is one, and only one exception -- the
+     * setup wizard. It must be able to define a high priority intent filter for these
+     * actions to ensure there are no escapes from the wizard. We need to delay processing
+     * of these during boot as we need to inspect at all of the intent filters on the
+     * /system partition in order to know which component is the setup wizard. This can
+     * only ever be non-empty if {@link #mDeferProtectedFilters} is {@code true}.
+     */
+    private List<PackageParser.ActivityIntentInfo> mProtectedFilters;
+
+    ComponentResolver(UserManagerService userManager,
+            PackageManagerInternal packageManagerInternal) {
+        sPackageManagerInternal = packageManagerInternal;
+        sUserManager = userManager;
+    }
+
+    /** Returns the given activity */
+    PackageParser.Activity getActivity(ComponentName component) {
+        synchronized (mLock) {
+            return mActivities.mActivities.get(component);
+        }
+    }
+
+    /** Returns the given provider */
+    PackageParser.Provider getProvider(ComponentName component) {
+        synchronized (mLock) {
+            return mProviders.mProviders.get(component);
+        }
+    }
+
+    /** Returns the given receiver */
+    PackageParser.Activity getReceiver(ComponentName component) {
+        synchronized (mLock) {
+            return mReceivers.mActivities.get(component);
+        }
+    }
+
+    /** Returns the given service */
+    PackageParser.Service getService(ComponentName component) {
+        synchronized (mLock) {
+            return mServices.mServices.get(component);
+        }
+    }
+
+    List<ResolveInfo> queryActivities(Intent intent, String resolvedType, int flags, int userId) {
+        synchronized (mLock) {
+            return mActivities.queryIntent(intent, resolvedType, flags, userId);
+        }
+    }
+
+    List<ResolveInfo> queryActivities(Intent intent, String resolvedType, int flags,
+            List<PackageParser.Activity> activities, int userId) {
+        synchronized (mLock) {
+            return mActivities.queryIntentForPackage(
+                    intent, resolvedType, flags, activities, userId);
+        }
+    }
+
+    List<ResolveInfo> queryProviders(Intent intent, String resolvedType, int flags, int userId) {
+        synchronized (mLock) {
+            return mProviders.queryIntent(intent, resolvedType, flags, userId);
+        }
+    }
+
+    List<ResolveInfo> queryProviders(Intent intent, String resolvedType, int flags,
+            List<PackageParser.Provider> providers, int userId) {
+        synchronized (mLock) {
+            return mProviders.queryIntentForPackage(intent, resolvedType, flags, providers, userId);
+        }
+    }
+
+    List<ProviderInfo> queryProviders(String processName, String metaDataKey, int uid, int flags,
+            int userId) {
+        if (!sUserManager.exists(userId)) {
+            return null;
+        }
+        List<ProviderInfo> providerList = null;
+        synchronized (mLock) {
+            for (int i = mProviders.mProviders.size() - 1; i >= 0; --i) {
+                final PackageParser.Provider p = mProviders.mProviders.valueAt(i);
+                final PackageSetting ps = (PackageSetting) p.owner.mExtras;
+                if (ps == null) {
+                    continue;
+                }
+                if (p.info.authority == null) {
+                    continue;
+                }
+                if (processName != null && (!p.info.processName.equals(processName)
+                        || !UserHandle.isSameApp(p.info.applicationInfo.uid, uid))) {
+                    continue;
+                }
+                // See PM.queryContentProviders()'s javadoc for why we have the metaData parameter.
+                if (metaDataKey != null
+                        && (p.metaData == null || !p.metaData.containsKey(metaDataKey))) {
+                    continue;
+                }
+                final ProviderInfo info = PackageParser.generateProviderInfo(
+                        p, flags, ps.readUserState(userId), userId);
+                if (info == null) {
+                    continue;
+                }
+                if (providerList == null) {
+                    providerList = new ArrayList<>(i + 1);
+                }
+                providerList.add(info);
+            }
+        }
+        return providerList;
+    }
+
+    ProviderInfo queryProvider(String authority, int flags, int userId) {
+        synchronized (mLock) {
+            final PackageParser.Provider p = mProvidersByAuthority.get(authority);
+            if (p == null) {
+                return null;
+            }
+            final PackageSetting ps = (PackageSetting) p.owner.mExtras;
+            if (ps == null) {
+                return null;
+            }
+            return PackageParser.generateProviderInfo(p, flags, ps.readUserState(userId), userId);
+        }
+    }
+
+    void querySyncProviders(List<String> outNames, List<ProviderInfo> outInfo, boolean safeMode,
+            int userId) {
+        synchronized (mLock) {
+            for (int i = mProvidersByAuthority.size() - 1; i >= 0; --i) {
+                final PackageParser.Provider p = mProvidersByAuthority.valueAt(i);
+                final PackageSetting ps = (PackageSetting) p.owner.mExtras;
+                if (ps == null) {
+                    continue;
+                }
+                if (!p.syncable) {
+                    continue;
+                }
+                if (safeMode
+                        && (p.info.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+                    continue;
+                }
+                final ProviderInfo info =
+                        PackageParser.generateProviderInfo(p, 0, ps.readUserState(userId), userId);
+                if (info == null) {
+                    continue;
+                }
+                outNames.add(mProvidersByAuthority.keyAt(i));
+                outInfo.add(info);
+            }
+        }
+    }
+
+    List<ResolveInfo> queryReceivers(Intent intent, String resolvedType, int flags, int userId) {
+        synchronized (mLock) {
+            return mReceivers.queryIntent(intent, resolvedType, flags, userId);
+        }
+    }
+
+    List<ResolveInfo> queryReceivers(Intent intent, String resolvedType, int flags,
+            List<PackageParser.Activity> receivers, int userId) {
+        synchronized (mLock) {
+            return mReceivers.queryIntentForPackage(intent, resolvedType, flags, receivers, userId);
+        }
+    }
+
+    List<ResolveInfo> queryServices(Intent intent, String resolvedType, int flags, int userId) {
+        synchronized (mLock) {
+            return mServices.queryIntent(intent, resolvedType, flags, userId);
+        }
+    }
+
+    List<ResolveInfo> queryServices(Intent intent, String resolvedType, int flags,
+            List<PackageParser.Service> services, int userId) {
+        synchronized (mLock) {
+            return mServices.queryIntentForPackage(intent, resolvedType, flags, services, userId);
+        }
+    }
+
+    /** Returns {@code true} if the given activity is defined by some package */
+    boolean isActivityDefined(ComponentName component) {
+        synchronized (mLock) {
+            return mActivities.mActivities.get(component) != null;
+        }
+    }
+
+    /** Asserts none of the providers defined in the given package haven't already been defined. */
+    void assertProvidersNotDefined(PackageParser.Package pkg) throws PackageManagerException {
+        synchronized (mLock) {
+            assertProvidersNotDefinedLocked(pkg);
+        }
+    }
+
+    /** Add all components defined in the given package to the internal structures. */
+    void addAllComponents(PackageParser.Package pkg, boolean chatty) {
+        final ArrayList<PackageParser.ActivityIntentInfo> newIntents = new ArrayList<>();
+        synchronized (mLock) {
+            addActivitiesLocked(pkg, newIntents, chatty);
+            addReceiversLocked(pkg, chatty);
+            addProvidersLocked(pkg, chatty);
+            addServicesLocked(pkg, chatty);
+        }
+        final String setupWizardPackage = sPackageManagerInternal.getKnownPackageName(
+                PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM);
+        for (int i = newIntents.size() - 1; i >= 0; --i) {
+            final PackageParser.ActivityIntentInfo intentInfo = newIntents.get(i);
+            final PackageParser.Package disabledPkg = sPackageManagerInternal
+                    .getDisabledPackage(intentInfo.activity.info.packageName);
+            final List<PackageParser.Activity> systemActivities =
+                    disabledPkg != null ? disabledPkg.activities : null;
+            adjustPriority(systemActivities, intentInfo, setupWizardPackage);
+        }
+    }
+
+    /** Removes all components defined in the given package from the internal structures. */
+    void removeAllComponents(PackageParser.Package pkg, boolean chatty) {
+        synchronized (mLock) {
+            removeAllComponentsLocked(pkg, chatty);
+        }
+    }
+
+    /**
+     * Reprocess any protected filters that have been deferred. At this point, we've scanned
+     * all of the filters defined on the /system partition and know the special components.
+     */
+    void fixProtectedFilterPriorities() {
+        if (!mDeferProtectedFilters) {
+            return;
+        }
+        mDeferProtectedFilters = false;
+
+        if (mProtectedFilters == null || mProtectedFilters.size() == 0) {
+            return;
+        }
+        final List<ActivityIntentInfo> protectedFilters = mProtectedFilters;
+        mProtectedFilters = null;
+
+        final String setupWizardPackage = sPackageManagerInternal.getKnownPackageName(
+                PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM);
+        if (DEBUG_FILTERS && setupWizardPackage == null) {
+            Slog.i(TAG, "No setup wizard;"
+                    + " All protected intents capped to priority 0");
+        }
+        for (int i = protectedFilters.size() - 1; i >= 0; --i) {
+            final ActivityIntentInfo filter = protectedFilters.get(i);
+            if (filter.activity.info.packageName.equals(setupWizardPackage)) {
+                if (DEBUG_FILTERS) {
+                    Slog.i(TAG, "Found setup wizard;"
+                            + " allow priority " + filter.getPriority() + ";"
+                            + " package: " + filter.activity.info.packageName
+                            + " activity: " + filter.activity.className
+                            + " priority: " + filter.getPriority());
+                }
+                // skip setup wizard; allow it to keep the high priority filter
+                continue;
+            }
+            if (DEBUG_FILTERS) {
+                Slog.i(TAG, "Protected action; cap priority to 0;"
+                        + " package: " + filter.activity.info.packageName
+                        + " activity: " + filter.activity.className
+                        + " origPrio: " + filter.getPriority());
+            }
+            filter.setPriority(0);
+        }
+    }
+
+    void dumpActivityResolvers(PrintWriter pw, DumpState dumpState, String packageName) {
+        if (mActivities.dump(pw, dumpState.getTitlePrinted() ? "\nActivity Resolver Table:"
+                : "Activity Resolver Table:", "  ", packageName,
+                dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
+            dumpState.setTitlePrinted(true);
+        }
+    }
+
+    void dumpProviderResolvers(PrintWriter pw, DumpState dumpState, String packageName) {
+        if (mProviders.dump(pw, dumpState.getTitlePrinted() ? "\nProvider Resolver Table:"
+                : "Provider Resolver Table:", "  ", packageName,
+                dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
+            dumpState.setTitlePrinted(true);
+        }
+    }
+
+    void dumpReceiverResolvers(PrintWriter pw, DumpState dumpState, String packageName) {
+        if (mReceivers.dump(pw, dumpState.getTitlePrinted() ? "\nReceiver Resolver Table:"
+                : "Receiver Resolver Table:", "  ", packageName,
+                dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
+            dumpState.setTitlePrinted(true);
+        }
+    }
+
+    void dumpServiceResolvers(PrintWriter pw, DumpState dumpState, String packageName) {
+        if (mServices.dump(pw, dumpState.getTitlePrinted() ? "\nService Resolver Table:"
+                : "Service Resolver Table:", "  ", packageName,
+                dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
+            dumpState.setTitlePrinted(true);
+        }
+    }
+
+    void dumpContentProviders(PrintWriter pw, DumpState dumpState, String packageName) {
+        boolean printedSomething = false;
+        for (PackageParser.Provider p : mProviders.mProviders.values()) {
+            if (packageName != null && !packageName.equals(p.info.packageName)) {
+                continue;
+            }
+            if (!printedSomething) {
+                if (dumpState.onTitlePrinted()) {
+                    pw.println();
+                }
+                pw.println("Registered ContentProviders:");
+                printedSomething = true;
+            }
+            pw.print("  "); p.printComponentShortName(pw); pw.println(":");
+            pw.print("    "); pw.println(p.toString());
+        }
+        printedSomething = false;
+        for (Map.Entry<String, PackageParser.Provider> entry :
+                mProvidersByAuthority.entrySet()) {
+            PackageParser.Provider p = entry.getValue();
+            if (packageName != null && !packageName.equals(p.info.packageName)) {
+                continue;
+            }
+            if (!printedSomething) {
+                if (dumpState.onTitlePrinted()) {
+                    pw.println();
+                }
+                pw.println("ContentProvider Authorities:");
+                printedSomething = true;
+            }
+            pw.print("  ["); pw.print(entry.getKey()); pw.println("]:");
+            pw.print("    "); pw.println(p.toString());
+            if (p.info != null && p.info.applicationInfo != null) {
+                final String appInfo = p.info.applicationInfo.toString();
+                pw.print("      applicationInfo="); pw.println(appInfo);
+            }
+        }
+    }
+
+    void dumpServicePermissions(PrintWriter pw, DumpState dumpState, String packageName) {
+        if (dumpState.onTitlePrinted()) pw.println();
+        pw.println("Service permissions:");
+
+        final Iterator<ServiceIntentInfo> filterIterator = mServices.filterIterator();
+        while (filterIterator.hasNext()) {
+            final ServiceIntentInfo info = filterIterator.next();
+            final ServiceInfo serviceInfo = info.service.info;
+            final String permission = serviceInfo.permission;
+            if (permission != null) {
+                pw.print("    ");
+                pw.print(serviceInfo.getComponentName().flattenToShortString());
+                pw.print(": ");
+                pw.println(permission);
+            }
+        }
+    }
+
+    @GuardedBy("mLock")
+    private void addActivitiesLocked(PackageParser.Package pkg,
+            List<PackageParser.ActivityIntentInfo> newIntents, boolean chatty) {
+        final int activitiesSize = pkg.activities.size();
+        StringBuilder r = null;
+        for (int i = 0; i < activitiesSize; i++) {
+            PackageParser.Activity a = pkg.activities.get(i);
+            a.info.processName =
+                    fixProcessName(pkg.applicationInfo.processName, a.info.processName);
+            mActivities.addActivity(a, "activity", newIntents);
+            if (DEBUG_PACKAGE_SCANNING && chatty) {
+                if (r == null) {
+                    r = new StringBuilder(256);
+                } else {
+                    r.append(' ');
+                }
+                r.append(a.info.name);
+            }
+        }
+        if (DEBUG_PACKAGE_SCANNING && chatty) {
+            Log.d(TAG, "  Activities: " + (r == null ? "<NONE>" : r));
+        }
+    }
+
+    @GuardedBy("mLock")
+    private void addProvidersLocked(PackageParser.Package pkg, boolean chatty) {
+        final int providersSize = pkg.providers.size();
+        StringBuilder r = null;
+        for (int i = 0; i < providersSize; i++) {
+            PackageParser.Provider p = pkg.providers.get(i);
+            p.info.processName = fixProcessName(pkg.applicationInfo.processName,
+                    p.info.processName);
+            mProviders.addProvider(p);
+            p.syncable = p.info.isSyncable;
+            if (p.info.authority != null) {
+                String[] names = p.info.authority.split(";");
+                p.info.authority = null;
+                for (int j = 0; j < names.length; j++) {
+                    if (j == 1 && p.syncable) {
+                        // We only want the first authority for a provider to possibly be
+                        // syncable, so if we already added this provider using a different
+                        // authority clear the syncable flag. We copy the provider before
+                        // changing it because the mProviders object contains a reference
+                        // to a provider that we don't want to change.
+                        // Only do this for the second authority since the resulting provider
+                        // object can be the same for all future authorities for this provider.
+                        p = new PackageParser.Provider(p);
+                        p.syncable = false;
+                    }
+                    if (!mProvidersByAuthority.containsKey(names[j])) {
+                        mProvidersByAuthority.put(names[j], p);
+                        if (p.info.authority == null) {
+                            p.info.authority = names[j];
+                        } else {
+                            p.info.authority = p.info.authority + ";" + names[j];
+                        }
+                        if (DEBUG_PACKAGE_SCANNING && chatty) {
+                            Log.d(TAG, "Registered content provider: " + names[j]
+                                    + ", className = " + p.info.name
+                                    + ", isSyncable = " + p.info.isSyncable);
+                        }
+                    } else {
+                        final PackageParser.Provider other =
+                                mProvidersByAuthority.get(names[j]);
+                        final ComponentName component =
+                                (other != null && other.getComponentName() != null)
+                                        ? other.getComponentName() : null;
+                        final String packageName =
+                                component != null ? component.getPackageName() : "?";
+                        Slog.w(TAG, "Skipping provider name " + names[j]
+                                + " (in package " + pkg.applicationInfo.packageName + ")"
+                                + ": name already used by " + packageName);
+                    }
+                }
+            }
+            if (DEBUG_PACKAGE_SCANNING && chatty) {
+                if (r == null) {
+                    r = new StringBuilder(256);
+                } else {
+                    r.append(' ');
+                }
+                r.append(p.info.name);
+            }
+        }
+        if (DEBUG_PACKAGE_SCANNING && chatty) {
+            Log.d(TAG, "  Providers: " + (r == null ? "<NONE>" : r));
+        }
+    }
+
+    @GuardedBy("mLock")
+    private void addReceiversLocked(PackageParser.Package pkg, boolean chatty) {
+        final int receiversSize = pkg.receivers.size();
+        StringBuilder r = null;
+        for (int i = 0; i < receiversSize; i++) {
+            PackageParser.Activity a = pkg.receivers.get(i);
+            a.info.processName = fixProcessName(pkg.applicationInfo.processName,
+                    a.info.processName);
+            mReceivers.addActivity(a, "receiver", null);
+            if (DEBUG_PACKAGE_SCANNING && chatty) {
+                if (r == null) {
+                    r = new StringBuilder(256);
+                } else {
+                    r.append(' ');
+                }
+                r.append(a.info.name);
+            }
+        }
+        if (DEBUG_PACKAGE_SCANNING && chatty) {
+            Log.d(TAG, "  Receivers: " + (r == null ? "<NONE>" : r));
+        }
+    }
+
+    @GuardedBy("mLock")
+    private void addServicesLocked(PackageParser.Package pkg, boolean chatty) {
+        final int servicesSize = pkg.services.size();
+        StringBuilder r = null;
+        for (int i = 0; i < servicesSize; i++) {
+            PackageParser.Service s = pkg.services.get(i);
+            s.info.processName = fixProcessName(pkg.applicationInfo.processName,
+                    s.info.processName);
+            mServices.addService(s);
+            if (DEBUG_PACKAGE_SCANNING && chatty) {
+                if (r == null) {
+                    r = new StringBuilder(256);
+                } else {
+                    r.append(' ');
+                }
+                r.append(s.info.name);
+            }
+        }
+        if (DEBUG_PACKAGE_SCANNING && chatty) {
+            Log.d(TAG, "  Services: " + (r == null ? "<NONE>" : r));
+        }
+    }
+
+
+    /**
+     * <em>WARNING</em> for performance reasons, the passed in intentList WILL BE
+     * MODIFIED. Do not pass in a list that should not be changed.
+     */
+    private static <T> void getIntentListSubset(List<ActivityIntentInfo> intentList,
+            IterGenerator<T> generator, Iterator<T> searchIterator) {
+        // loop through the set of actions; every one must be found in the intent filter
+        while (searchIterator.hasNext()) {
+            // we must have at least one filter in the list to consider a match
+            if (intentList.size() == 0) {
+                break;
+            }
+
+            final T searchAction = searchIterator.next();
+
+            // loop through the set of intent filters
+            final Iterator<ActivityIntentInfo> intentIter = intentList.iterator();
+            while (intentIter.hasNext()) {
+                final ActivityIntentInfo intentInfo = intentIter.next();
+                boolean selectionFound = false;
+
+                // loop through the intent filter's selection criteria; at least one
+                // of them must match the searched criteria
+                final Iterator<T> intentSelectionIter = generator.generate(intentInfo);
+                while (intentSelectionIter != null && intentSelectionIter.hasNext()) {
+                    final T intentSelection = intentSelectionIter.next();
+                    if (intentSelection != null && intentSelection.equals(searchAction)) {
+                        selectionFound = true;
+                        break;
+                    }
+                }
+
+                // the selection criteria wasn't found in this filter's set; this filter
+                // is not a potential match
+                if (!selectionFound) {
+                    intentIter.remove();
+                }
+            }
+        }
+    }
+
+    private static boolean isProtectedAction(ActivityIntentInfo filter) {
+        final Iterator<String> actionsIter = filter.actionsIterator();
+        while (actionsIter != null && actionsIter.hasNext()) {
+            final String filterAction = actionsIter.next();
+            if (PROTECTED_ACTIONS.contains(filterAction)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Finds a privileged activity that matches the specified activity names.
+     */
+    private static PackageParser.Activity findMatchingActivity(
+            List<PackageParser.Activity> activityList, ActivityInfo activityInfo) {
+        for (PackageParser.Activity sysActivity : activityList) {
+            if (sysActivity.info.name.equals(activityInfo.name)) {
+                return sysActivity;
+            }
+            if (sysActivity.info.name.equals(activityInfo.targetActivity)) {
+                return sysActivity;
+            }
+            if (sysActivity.info.targetActivity != null) {
+                if (sysActivity.info.targetActivity.equals(activityInfo.name)) {
+                    return sysActivity;
+                }
+                if (sysActivity.info.targetActivity.equals(activityInfo.targetActivity)) {
+                    return sysActivity;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Adjusts the priority of the given intent filter according to policy.
+     * <p>
+     * <ul>
+     * <li>The priority for non privileged applications is capped to '0'</li>
+     * <li>The priority for protected actions on privileged applications is capped to '0'</li>
+     * <li>The priority for unbundled updates to privileged applications is capped to the
+     *      priority defined on the system partition</li>
+     * </ul>
+     * <p>
+     * <em>NOTE:</em> There is one exception. For security reasons, the setup wizard is
+     * allowed to obtain any priority on any action.
+     */
+    private void adjustPriority(List<PackageParser.Activity> systemActivities,
+            ActivityIntentInfo intent, String setupWizardPackage) {
+        // nothing to do; priority is fine as-is
+        if (intent.getPriority() <= 0) {
+            return;
+        }
+
+        final ActivityInfo activityInfo = intent.activity.info;
+        final ApplicationInfo applicationInfo = activityInfo.applicationInfo;
+
+        final boolean privilegedApp =
+                ((applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0);
+        if (!privilegedApp) {
+            // non-privileged applications can never define a priority >0
+            if (DEBUG_FILTERS) {
+                Slog.i(TAG, "Non-privileged app; cap priority to 0;"
+                        + " package: " + applicationInfo.packageName
+                        + " activity: " + intent.activity.className
+                        + " origPrio: " + intent.getPriority());
+            }
+            intent.setPriority(0);
+            return;
+        }
+
+        if (systemActivities == null) {
+            // the system package is not disabled; we're parsing the system partition
+            if (isProtectedAction(intent)) {
+                if (mDeferProtectedFilters) {
+                    // We can't deal with these just yet. No component should ever obtain a
+                    // >0 priority for a protected actions, with ONE exception -- the setup
+                    // wizard. The setup wizard, however, cannot be known until we're able to
+                    // query it for the category CATEGORY_SETUP_WIZARD. Which we can't do
+                    // until all intent filters have been processed. Chicken, meet egg.
+                    // Let the filter temporarily have a high priority and rectify the
+                    // priorities after all system packages have been scanned.
+                    if (mProtectedFilters == null) {
+                        mProtectedFilters = new ArrayList<>();
+                    }
+                    mProtectedFilters.add(intent);
+                    if (DEBUG_FILTERS) {
+                        Slog.i(TAG, "Protected action; save for later;"
+                                + " package: " + applicationInfo.packageName
+                                + " activity: " + intent.activity.className
+                                + " origPrio: " + intent.getPriority());
+                    }
+                    return;
+                } else {
+                    if (DEBUG_FILTERS && setupWizardPackage == null) {
+                        Slog.i(TAG, "No setup wizard;"
+                                + " All protected intents capped to priority 0");
+                    }
+                    if (intent.activity.info.packageName.equals(setupWizardPackage)) {
+                        if (DEBUG_FILTERS) {
+                            Slog.i(TAG, "Found setup wizard;"
+                                    + " allow priority " + intent.getPriority() + ";"
+                                    + " package: " + intent.activity.info.packageName
+                                    + " activity: " + intent.activity.className
+                                    + " priority: " + intent.getPriority());
+                        }
+                        // setup wizard gets whatever it wants
+                        return;
+                    }
+                    if (DEBUG_FILTERS) {
+                        Slog.i(TAG, "Protected action; cap priority to 0;"
+                                + " package: " + intent.activity.info.packageName
+                                + " activity: " + intent.activity.className
+                                + " origPrio: " + intent.getPriority());
+                    }
+                    intent.setPriority(0);
+                    return;
+                }
+            }
+            // privileged apps on the system image get whatever priority they request
+            return;
+        }
+
+        // privileged app unbundled update ... try to find the same activity
+        final PackageParser.Activity foundActivity =
+                findMatchingActivity(systemActivities, activityInfo);
+        if (foundActivity == null) {
+            // this is a new activity; it cannot obtain >0 priority
+            if (DEBUG_FILTERS) {
+                Slog.i(TAG, "New activity; cap priority to 0;"
+                        + " package: " + applicationInfo.packageName
+                        + " activity: " + intent.activity.className
+                        + " origPrio: " + intent.getPriority());
+            }
+            intent.setPriority(0);
+            return;
+        }
+
+        // found activity, now check for filter equivalence
+
+        // a shallow copy is enough; we modify the list, not its contents
+        final List<ActivityIntentInfo> intentListCopy = new ArrayList<>(foundActivity.intents);
+        final List<ActivityIntentInfo> foundFilters = mActivities.findFilters(intent);
+
+        // find matching action subsets
+        final Iterator<String> actionsIterator = intent.actionsIterator();
+        if (actionsIterator != null) {
+            getIntentListSubset(intentListCopy, new ActionIterGenerator(), actionsIterator);
+            if (intentListCopy.size() == 0) {
+                // no more intents to match; we're not equivalent
+                if (DEBUG_FILTERS) {
+                    Slog.i(TAG, "Mismatched action; cap priority to 0;"
+                            + " package: " + applicationInfo.packageName
+                            + " activity: " + intent.activity.className
+                            + " origPrio: " + intent.getPriority());
+                }
+                intent.setPriority(0);
+                return;
+            }
+        }
+
+        // find matching category subsets
+        final Iterator<String> categoriesIterator = intent.categoriesIterator();
+        if (categoriesIterator != null) {
+            getIntentListSubset(intentListCopy, new CategoriesIterGenerator(), categoriesIterator);
+            if (intentListCopy.size() == 0) {
+                // no more intents to match; we're not equivalent
+                if (DEBUG_FILTERS) {
+                    Slog.i(TAG, "Mismatched category; cap priority to 0;"
+                            + " package: " + applicationInfo.packageName
+                            + " activity: " + intent.activity.className
+                            + " origPrio: " + intent.getPriority());
+                }
+                intent.setPriority(0);
+                return;
+            }
+        }
+
+        // find matching schemes subsets
+        final Iterator<String> schemesIterator = intent.schemesIterator();
+        if (schemesIterator != null) {
+            getIntentListSubset(intentListCopy, new SchemesIterGenerator(), schemesIterator);
+            if (intentListCopy.size() == 0) {
+                // no more intents to match; we're not equivalent
+                if (DEBUG_FILTERS) {
+                    Slog.i(TAG, "Mismatched scheme; cap priority to 0;"
+                            + " package: " + applicationInfo.packageName
+                            + " activity: " + intent.activity.className
+                            + " origPrio: " + intent.getPriority());
+                }
+                intent.setPriority(0);
+                return;
+            }
+        }
+
+        // find matching authorities subsets
+        final Iterator<IntentFilter.AuthorityEntry> authoritiesIterator =
+                intent.authoritiesIterator();
+        if (authoritiesIterator != null) {
+            getIntentListSubset(intentListCopy, new AuthoritiesIterGenerator(),
+                    authoritiesIterator);
+            if (intentListCopy.size() == 0) {
+                // no more intents to match; we're not equivalent
+                if (DEBUG_FILTERS) {
+                    Slog.i(TAG, "Mismatched authority; cap priority to 0;"
+                            + " package: " + applicationInfo.packageName
+                            + " activity: " + intent.activity.className
+                            + " origPrio: " + intent.getPriority());
+                }
+                intent.setPriority(0);
+                return;
+            }
+        }
+
+        // we found matching filter(s); app gets the max priority of all intents
+        int cappedPriority = 0;
+        for (int i = intentListCopy.size() - 1; i >= 0; --i) {
+            cappedPriority = Math.max(cappedPriority, intentListCopy.get(i).getPriority());
+        }
+        if (intent.getPriority() > cappedPriority) {
+            if (DEBUG_FILTERS) {
+                Slog.i(TAG, "Found matching filter(s);"
+                        + " cap priority to " + cappedPriority + ";"
+                        + " package: " + applicationInfo.packageName
+                        + " activity: " + intent.activity.className
+                        + " origPrio: " + intent.getPriority());
+            }
+            intent.setPriority(cappedPriority);
+            return;
+        }
+        // all this for nothing; the requested priority was <= what was on the system
+    }
+
+    @GuardedBy("mLock")
+    private void removeAllComponentsLocked(PackageParser.Package pkg, boolean chatty) {
+        int componentSize;
+        StringBuilder r;
+        int i;
+
+        componentSize = pkg.activities.size();
+        r = null;
+        for (i = 0; i < componentSize; i++) {
+            PackageParser.Activity a = pkg.activities.get(i);
+            mActivities.removeActivity(a, "activity");
+            if (DEBUG_REMOVE && chatty) {
+                if (r == null) {
+                    r = new StringBuilder(256);
+                } else {
+                    r.append(' ');
+                }
+                r.append(a.info.name);
+            }
+        }
+        if (DEBUG_REMOVE && chatty) {
+            Log.d(TAG, "  Activities: " + (r == null ? "<NONE>" : r));
+        }
+
+        componentSize = pkg.providers.size();
+        r = null;
+        for (i = 0; i < componentSize; i++) {
+            PackageParser.Provider p = pkg.providers.get(i);
+            mProviders.removeProvider(p);
+            if (p.info.authority == null) {
+                // Another content provider with this authority existed when this app was
+                // installed, so this authority is null. Ignore it as we don't have to
+                // unregister the provider.
+                continue;
+            }
+            String[] names = p.info.authority.split(";");
+            for (int j = 0; j < names.length; j++) {
+                if (mProvidersByAuthority.get(names[j]) == p) {
+                    mProvidersByAuthority.remove(names[j]);
+                    if (DEBUG_REMOVE && chatty) {
+                        Log.d(TAG, "Unregistered content provider: " + names[j]
+                                + ", className = " + p.info.name + ", isSyncable = "
+                                + p.info.isSyncable);
+                    }
+                }
+            }
+            if (DEBUG_REMOVE && chatty) {
+                if (r == null) {
+                    r = new StringBuilder(256);
+                } else {
+                    r.append(' ');
+                }
+                r.append(p.info.name);
+            }
+        }
+        if (DEBUG_REMOVE && chatty) {
+            Log.d(TAG, "  Providers: " + (r == null ? "<NONE>" : r));
+        }
+
+        componentSize = pkg.receivers.size();
+        r = null;
+        for (i = 0; i < componentSize; i++) {
+            PackageParser.Activity a = pkg.receivers.get(i);
+            mReceivers.removeActivity(a, "receiver");
+            if (DEBUG_REMOVE && chatty) {
+                if (r == null) {
+                    r = new StringBuilder(256);
+                } else {
+                    r.append(' ');
+                }
+                r.append(a.info.name);
+            }
+        }
+        if (DEBUG_REMOVE && chatty) {
+            Log.d(TAG, "  Receivers: " + (r == null ? "<NONE>" : r));
+        }
+
+        componentSize = pkg.services.size();
+        r = null;
+        for (i = 0; i < componentSize; i++) {
+            PackageParser.Service s = pkg.services.get(i);
+            mServices.removeService(s);
+            if (DEBUG_REMOVE && chatty) {
+                if (r == null) {
+                    r = new StringBuilder(256);
+                } else {
+                    r.append(' ');
+                }
+                r.append(s.info.name);
+            }
+        }
+        if (DEBUG_REMOVE && chatty) {
+            Log.d(TAG, "  Services: " + (r == null ? "<NONE>" : r));
+        }
+    }
+
+    @GuardedBy("mLock")
+    private void assertProvidersNotDefinedLocked(PackageParser.Package pkg)
+            throws PackageManagerException {
+        final int providersSize = pkg.providers.size();
+        int i;
+        for (i = 0; i < providersSize; i++) {
+            PackageParser.Provider p = pkg.providers.get(i);
+            if (p.info.authority != null) {
+                final String[] names = p.info.authority.split(";");
+                for (int j = 0; j < names.length; j++) {
+                    if (mProvidersByAuthority.containsKey(names[j])) {
+                        final PackageParser.Provider other = mProvidersByAuthority.get(names[j]);
+                        final String otherPackageName =
+                                (other != null && other.getComponentName() != null)
+                                        ? other.getComponentName().getPackageName() : "?";
+                        throw new PackageManagerException(
+                                INSTALL_FAILED_CONFLICTING_PROVIDER,
+                                "Can't install because provider name " + names[j]
+                                        + " (in package " + pkg.applicationInfo.packageName
+                                        + ") is already used by " + otherPackageName);
+                    }
+                }
+            }
+        }
+    }
+
+    private static final class ActivityIntentResolver
+            extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
+        @Override
+        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
+                boolean defaultOnly, int userId) {
+            if (!sUserManager.exists(userId)) return null;
+            mFlags = (defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0);
+            return super.queryIntent(intent, resolvedType, defaultOnly, userId);
+        }
+
+        List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
+                int userId) {
+            if (!sUserManager.exists(userId)) {
+                return null;
+            }
+            mFlags = flags;
+            return super.queryIntent(intent, resolvedType,
+                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
+                    userId);
+        }
+
+        List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
+                int flags, List<PackageParser.Activity> packageActivities, int userId) {
+            if (!sUserManager.exists(userId)) {
+                return null;
+            }
+            if (packageActivities == null) {
+                return null;
+            }
+            mFlags = flags;
+            final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
+            final int activitiesSize = packageActivities.size();
+            ArrayList<PackageParser.ActivityIntentInfo[]> listCut = new ArrayList<>(activitiesSize);
+
+            ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
+            for (int i = 0; i < activitiesSize; ++i) {
+                intentFilters = packageActivities.get(i).intents;
+                if (intentFilters != null && intentFilters.size() > 0) {
+                    PackageParser.ActivityIntentInfo[] array =
+                            new PackageParser.ActivityIntentInfo[intentFilters.size()];
+                    intentFilters.toArray(array);
+                    listCut.add(array);
+                }
+            }
+            return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
+        }
+
+        private void addActivity(PackageParser.Activity a, String type,
+                List<PackageParser.ActivityIntentInfo> newIntents) {
+            mActivities.put(a.getComponentName(), a);
+            if (DEBUG_SHOW_INFO) {
+                final CharSequence label = a.info.nonLocalizedLabel != null
+                        ? a.info.nonLocalizedLabel
+                        : a.info.name;
+                Log.v(TAG, "  " + type + " " + label + ":");
+            }
+            if (DEBUG_SHOW_INFO) {
+                Log.v(TAG, "    Class=" + a.info.name);
+            }
+            final int intentsSize = a.intents.size();
+            for (int j = 0; j < intentsSize; j++) {
+                PackageParser.ActivityIntentInfo intent = a.intents.get(j);
+                if (newIntents != null && "activity".equals(type)) {
+                    newIntents.add(intent);
+                }
+                if (DEBUG_SHOW_INFO) {
+                    Log.v(TAG, "    IntentFilter:");
+                    intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
+                }
+                if (!intent.debugCheck()) {
+                    Log.w(TAG, "==> For Activity " + a.info.name);
+                }
+                addFilter(intent);
+            }
+        }
+
+        private void removeActivity(PackageParser.Activity a, String type) {
+            mActivities.remove(a.getComponentName());
+            if (DEBUG_SHOW_INFO) {
+                Log.v(TAG, "  " + type + " "
+                        + (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel
+                                : a.info.name) + ":");
+                Log.v(TAG, "    Class=" + a.info.name);
+            }
+            final int intentsSize = a.intents.size();
+            for (int j = 0; j < intentsSize; j++) {
+                PackageParser.ActivityIntentInfo intent = a.intents.get(j);
+                if (DEBUG_SHOW_INFO) {
+                    Log.v(TAG, "    IntentFilter:");
+                    intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
+                }
+                removeFilter(intent);
+            }
+        }
+
+        @Override
+        protected boolean allowFilterResult(
+                PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
+            ActivityInfo filterAi = filter.activity.info;
+            for (int i = dest.size() - 1; i >= 0; --i) {
+                ActivityInfo destAi = dest.get(i).activityInfo;
+                if (destAi.name == filterAi.name && destAi.packageName == filterAi.packageName) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        @Override
+        protected ActivityIntentInfo[] newArray(int size) {
+            return new ActivityIntentInfo[size];
+        }
+
+        @Override
+        protected boolean isFilterStopped(PackageParser.ActivityIntentInfo filter, int userId) {
+            if (!sUserManager.exists(userId)) return true;
+            PackageParser.Package p = filter.activity.owner;
+            if (p != null) {
+                PackageSetting ps = (PackageSetting) p.mExtras;
+                if (ps != null) {
+                    // System apps are never considered stopped for purposes of
+                    // filtering, because there may be no way for the user to
+                    // actually re-launch them.
+                    return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0
+                            && ps.getStopped(userId);
+                }
+            }
+            return false;
+        }
+
+        @Override
+        protected boolean isPackageForFilter(String packageName,
+                PackageParser.ActivityIntentInfo info) {
+            return packageName.equals(info.activity.owner.packageName);
+        }
+
+        @Override
+        protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
+                int match, int userId) {
+            if (!sUserManager.exists(userId)) return null;
+            if (!sPackageManagerInternal.isEnabledAndMatches(info.activity.info, mFlags, userId)) {
+                return null;
+            }
+            final PackageParser.Activity activity = info.activity;
+            PackageSetting ps = (PackageSetting) activity.owner.mExtras;
+            if (ps == null) {
+                return null;
+            }
+            final PackageUserState userState = ps.readUserState(userId);
+            ActivityInfo ai =
+                    PackageParser.generateActivityInfo(activity, mFlags, userState, userId);
+            if (ai == null) {
+                return null;
+            }
+            final boolean matchExplicitlyVisibleOnly =
+                    (mFlags & PackageManager.MATCH_EXPLICITLY_VISIBLE_ONLY) != 0;
+            final boolean matchVisibleToInstantApp =
+                    (mFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
+            final boolean componentVisible =
+                    matchVisibleToInstantApp
+                    && info.isVisibleToInstantApp()
+                    && (!matchExplicitlyVisibleOnly || info.isExplicitlyVisibleToInstantApp());
+            final boolean matchInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0;
+            // throw out filters that aren't visible to ephemeral apps
+            if (matchVisibleToInstantApp && !(componentVisible || userState.instantApp)) {
+                return null;
+            }
+            // throw out instant app filters if we're not explicitly requesting them
+            if (!matchInstantApp && userState.instantApp) {
+                return null;
+            }
+            // throw out instant app filters if updates are available; will trigger
+            // instant app resolution
+            if (userState.instantApp && ps.isUpdateAvailable()) {
+                return null;
+            }
+            final ResolveInfo res = new ResolveInfo();
+            res.activityInfo = ai;
+            if ((mFlags & PackageManager.GET_RESOLVED_FILTER) != 0) {
+                res.filter = info;
+            }
+            res.handleAllWebDataURI = info.handleAllWebDataURI();
+            res.priority = info.getPriority();
+            res.preferredOrder = activity.owner.mPreferredOrder;
+            //System.out.println("Result: " + res.activityInfo.className +
+            //                   " = " + res.priority);
+            res.match = match;
+            res.isDefault = info.hasDefault;
+            res.labelRes = info.labelRes;
+            res.nonLocalizedLabel = info.nonLocalizedLabel;
+            if (sPackageManagerInternal.userNeedsBadging(userId)) {
+                res.noResourceId = true;
+            } else {
+                res.icon = info.icon;
+            }
+            res.iconResourceId = info.icon;
+            res.system = res.activityInfo.applicationInfo.isSystemApp();
+            res.isInstantAppAvailable = userState.instantApp;
+            return res;
+        }
+
+        @Override
+        protected void sortResults(List<ResolveInfo> results) {
+            results.sort(RESOLVE_PRIORITY_SORTER);
+        }
+
+        @Override
+        protected void dumpFilter(PrintWriter out, String prefix,
+                PackageParser.ActivityIntentInfo filter) {
+            out.print(prefix);
+            out.print(Integer.toHexString(System.identityHashCode(filter.activity)));
+            out.print(' ');
+            filter.activity.printComponentShortName(out);
+            out.print(" filter ");
+            out.println(Integer.toHexString(System.identityHashCode(filter)));
+        }
+
+        @Override
+        protected Object filterToLabel(PackageParser.ActivityIntentInfo filter) {
+            return filter.activity;
+        }
+
+        protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int count) {
+            PackageParser.Activity activity = (PackageParser.Activity) label;
+            out.print(prefix);
+            out.print(Integer.toHexString(System.identityHashCode(activity)));
+            out.print(' ');
+            activity.printComponentShortName(out);
+            if (count > 1) {
+                out.print(" ("); out.print(count); out.print(" filters)");
+            }
+            out.println();
+        }
+
+        // Keys are String (activity class name), values are Activity.
+        private final ArrayMap<ComponentName, PackageParser.Activity> mActivities =
+                new ArrayMap<>();
+        private int mFlags;
+    }
+
+    private static final class ProviderIntentResolver
+            extends IntentResolver<PackageParser.ProviderIntentInfo, ResolveInfo> {
+        @Override
+        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
+                boolean defaultOnly, int userId) {
+            mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
+            return super.queryIntent(intent, resolvedType, defaultOnly, userId);
+        }
+
+        List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
+                int userId) {
+            if (!sUserManager.exists(userId)) {
+                return null;
+            }
+            mFlags = flags;
+            return super.queryIntent(intent, resolvedType,
+                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
+                    userId);
+        }
+
+        List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
+                int flags, List<PackageParser.Provider> packageProviders, int userId) {
+            if (!sUserManager.exists(userId)) {
+                return null;
+            }
+            if (packageProviders == null) {
+                return null;
+            }
+            mFlags = flags;
+            final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
+            final int providersSize = packageProviders.size();
+            ArrayList<PackageParser.ProviderIntentInfo[]> listCut = new ArrayList<>(providersSize);
+
+            ArrayList<PackageParser.ProviderIntentInfo> intentFilters;
+            for (int i = 0; i < providersSize; ++i) {
+                intentFilters = packageProviders.get(i).intents;
+                if (intentFilters != null && intentFilters.size() > 0) {
+                    PackageParser.ProviderIntentInfo[] array =
+                            new PackageParser.ProviderIntentInfo[intentFilters.size()];
+                    intentFilters.toArray(array);
+                    listCut.add(array);
+                }
+            }
+            return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
+        }
+
+        void addProvider(PackageParser.Provider p) {
+            if (mProviders.containsKey(p.getComponentName())) {
+                Slog.w(TAG, "Provider " + p.getComponentName() + " already defined; ignoring");
+                return;
+            }
+
+            mProviders.put(p.getComponentName(), p);
+            if (DEBUG_SHOW_INFO) {
+                Log.v(TAG, "  "
+                        + (p.info.nonLocalizedLabel != null
+                                ? p.info.nonLocalizedLabel
+                                : p.info.name)
+                        + ":");
+                Log.v(TAG, "    Class=" + p.info.name);
+            }
+            final int intentsSize = p.intents.size();
+            int j;
+            for (j = 0; j < intentsSize; j++) {
+                PackageParser.ProviderIntentInfo intent = p.intents.get(j);
+                if (DEBUG_SHOW_INFO) {
+                    Log.v(TAG, "    IntentFilter:");
+                    intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
+                }
+                if (!intent.debugCheck()) {
+                    Log.w(TAG, "==> For Provider " + p.info.name);
+                }
+                addFilter(intent);
+            }
+        }
+
+        void removeProvider(PackageParser.Provider p) {
+            mProviders.remove(p.getComponentName());
+            if (DEBUG_SHOW_INFO) {
+                Log.v(TAG, "  " + (p.info.nonLocalizedLabel != null
+                        ? p.info.nonLocalizedLabel
+                        : p.info.name) + ":");
+                Log.v(TAG, "    Class=" + p.info.name);
+            }
+            final int intentsSize = p.intents.size();
+            int j;
+            for (j = 0; j < intentsSize; j++) {
+                PackageParser.ProviderIntentInfo intent = p.intents.get(j);
+                if (DEBUG_SHOW_INFO) {
+                    Log.v(TAG, "    IntentFilter:");
+                    intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
+                }
+                removeFilter(intent);
+            }
+        }
+
+        @Override
+        protected boolean allowFilterResult(
+                PackageParser.ProviderIntentInfo filter, List<ResolveInfo> dest) {
+            ProviderInfo filterPi = filter.provider.info;
+            for (int i = dest.size() - 1; i >= 0; i--) {
+                ProviderInfo destPi = dest.get(i).providerInfo;
+                if (destPi.name == filterPi.name
+                        && destPi.packageName == filterPi.packageName) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        @Override
+        protected PackageParser.ProviderIntentInfo[] newArray(int size) {
+            return new PackageParser.ProviderIntentInfo[size];
+        }
+
+        @Override
+        protected boolean isFilterStopped(PackageParser.ProviderIntentInfo filter, int userId) {
+            if (!sUserManager.exists(userId)) {
+                return true;
+            }
+            PackageParser.Package p = filter.provider.owner;
+            if (p != null) {
+                PackageSetting ps = (PackageSetting) p.mExtras;
+                if (ps != null) {
+                    // System apps are never considered stopped for purposes of
+                    // filtering, because there may be no way for the user to
+                    // actually re-launch them.
+                    return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0
+                            && ps.getStopped(userId);
+                }
+            }
+            return false;
+        }
+
+        @Override
+        protected boolean isPackageForFilter(String packageName,
+                PackageParser.ProviderIntentInfo info) {
+            return packageName.equals(info.provider.owner.packageName);
+        }
+
+        @Override
+        protected ResolveInfo newResult(PackageParser.ProviderIntentInfo filter,
+                int match, int userId) {
+            if (!sUserManager.exists(userId)) {
+                return null;
+            }
+            final PackageParser.ProviderIntentInfo info = filter;
+            if (!sPackageManagerInternal.isEnabledAndMatches(info.provider.info, mFlags, userId)) {
+                return null;
+            }
+            final PackageParser.Provider provider = info.provider;
+            PackageSetting ps = (PackageSetting) provider.owner.mExtras;
+            if (ps == null) {
+                return null;
+            }
+            final PackageUserState userState = ps.readUserState(userId);
+            final boolean matchVisibleToInstantApp = (mFlags
+                    & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
+            final boolean isInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0;
+            // throw out filters that aren't visible to instant applications
+            if (matchVisibleToInstantApp
+                    && !(info.isVisibleToInstantApp() || userState.instantApp)) {
+                return null;
+            }
+            // throw out instant application filters if we're not explicitly requesting them
+            if (!isInstantApp && userState.instantApp) {
+                return null;
+            }
+            // throw out instant application filters if updates are available; will trigger
+            // instant application resolution
+            if (userState.instantApp && ps.isUpdateAvailable()) {
+                return null;
+            }
+            ProviderInfo pi = PackageParser.generateProviderInfo(provider, mFlags,
+                    userState, userId);
+            if (pi == null) {
+                return null;
+            }
+            final ResolveInfo res = new ResolveInfo();
+            res.providerInfo = pi;
+            if ((mFlags & PackageManager.GET_RESOLVED_FILTER) != 0) {
+                res.filter = filter;
+            }
+            res.priority = info.getPriority();
+            res.preferredOrder = provider.owner.mPreferredOrder;
+            res.match = match;
+            res.isDefault = info.hasDefault;
+            res.labelRes = info.labelRes;
+            res.nonLocalizedLabel = info.nonLocalizedLabel;
+            res.icon = info.icon;
+            res.system = res.providerInfo.applicationInfo.isSystemApp();
+            return res;
+        }
+
+        @Override
+        protected void sortResults(List<ResolveInfo> results) {
+            results.sort(RESOLVE_PRIORITY_SORTER);
+        }
+
+        @Override
+        protected void dumpFilter(PrintWriter out, String prefix,
+                PackageParser.ProviderIntentInfo filter) {
+            out.print(prefix);
+            out.print(Integer.toHexString(System.identityHashCode(filter.provider)));
+            out.print(' ');
+            filter.provider.printComponentShortName(out);
+            out.print(" filter ");
+            out.println(Integer.toHexString(System.identityHashCode(filter)));
+        }
+
+        @Override
+        protected Object filterToLabel(PackageParser.ProviderIntentInfo filter) {
+            return filter.provider;
+        }
+
+        protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int count) {
+            final PackageParser.Provider provider = (PackageParser.Provider) label;
+            out.print(prefix);
+            out.print(Integer.toHexString(System.identityHashCode(provider)));
+            out.print(' ');
+            provider.printComponentShortName(out);
+            if (count > 1) {
+                out.print(" (");
+                out.print(count);
+                out.print(" filters)");
+            }
+            out.println();
+        }
+
+        private final ArrayMap<ComponentName, PackageParser.Provider> mProviders = new ArrayMap<>();
+        private int mFlags;
+    }
+
+    private static final class ServiceIntentResolver
+            extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
+        @Override
+        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
+                boolean defaultOnly, int userId) {
+            mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
+            return super.queryIntent(intent, resolvedType, defaultOnly, userId);
+        }
+
+        List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
+                int userId) {
+            if (!sUserManager.exists(userId)) return null;
+            mFlags = flags;
+            return super.queryIntent(intent, resolvedType,
+                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
+                    userId);
+        }
+
+        List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
+                int flags, List<PackageParser.Service> packageServices, int userId) {
+            if (!sUserManager.exists(userId)) return null;
+            if (packageServices == null) {
+                return null;
+            }
+            mFlags = flags;
+            final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
+            final int servicesSize = packageServices.size();
+            ArrayList<PackageParser.ServiceIntentInfo[]> listCut = new ArrayList<>(servicesSize);
+
+            ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
+            for (int i = 0; i < servicesSize; ++i) {
+                intentFilters = packageServices.get(i).intents;
+                if (intentFilters != null && intentFilters.size() > 0) {
+                    PackageParser.ServiceIntentInfo[] array =
+                            new PackageParser.ServiceIntentInfo[intentFilters.size()];
+                    intentFilters.toArray(array);
+                    listCut.add(array);
+                }
+            }
+            return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
+        }
+
+        void addService(PackageParser.Service s) {
+            mServices.put(s.getComponentName(), s);
+            if (DEBUG_SHOW_INFO) {
+                Log.v(TAG, "  "
+                        + (s.info.nonLocalizedLabel != null
+                        ? s.info.nonLocalizedLabel : s.info.name) + ":");
+                Log.v(TAG, "    Class=" + s.info.name);
+            }
+            final int intentsSize = s.intents.size();
+            int j;
+            for (j = 0; j < intentsSize; j++) {
+                PackageParser.ServiceIntentInfo intent = s.intents.get(j);
+                if (DEBUG_SHOW_INFO) {
+                    Log.v(TAG, "    IntentFilter:");
+                    intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
+                }
+                if (!intent.debugCheck()) {
+                    Log.w(TAG, "==> For Service " + s.info.name);
+                }
+                addFilter(intent);
+            }
+        }
+
+        void removeService(PackageParser.Service s) {
+            mServices.remove(s.getComponentName());
+            if (DEBUG_SHOW_INFO) {
+                Log.v(TAG, "  " + (s.info.nonLocalizedLabel != null
+                        ? s.info.nonLocalizedLabel : s.info.name) + ":");
+                Log.v(TAG, "    Class=" + s.info.name);
+            }
+            final int intentsSize = s.intents.size();
+            int j;
+            for (j = 0; j < intentsSize; j++) {
+                PackageParser.ServiceIntentInfo intent = s.intents.get(j);
+                if (DEBUG_SHOW_INFO) {
+                    Log.v(TAG, "    IntentFilter:");
+                    intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
+                }
+                removeFilter(intent);
+            }
+        }
+
+        @Override
+        protected boolean allowFilterResult(
+                PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
+            ServiceInfo filterSi = filter.service.info;
+            for (int i = dest.size() - 1; i >= 0; --i) {
+                ServiceInfo destAi = dest.get(i).serviceInfo;
+                if (destAi.name == filterSi.name
+                        && destAi.packageName == filterSi.packageName) {
+                    return false;
+                }
+            }
+            return true;
+        }
+
+        @Override
+        protected PackageParser.ServiceIntentInfo[] newArray(int size) {
+            return new PackageParser.ServiceIntentInfo[size];
+        }
+
+        @Override
+        protected boolean isFilterStopped(PackageParser.ServiceIntentInfo filter, int userId) {
+            if (!sUserManager.exists(userId)) return true;
+            PackageParser.Package p = filter.service.owner;
+            if (p != null) {
+                PackageSetting ps = (PackageSetting) p.mExtras;
+                if (ps != null) {
+                    // System apps are never considered stopped for purposes of
+                    // filtering, because there may be no way for the user to
+                    // actually re-launch them.
+                    return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0
+                            && ps.getStopped(userId);
+                }
+            }
+            return false;
+        }
+
+        @Override
+        protected boolean isPackageForFilter(String packageName,
+                PackageParser.ServiceIntentInfo info) {
+            return packageName.equals(info.service.owner.packageName);
+        }
+
+        @Override
+        protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
+                int match, int userId) {
+            if (!sUserManager.exists(userId)) return null;
+            final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo) filter;
+            if (!sPackageManagerInternal.isEnabledAndMatches(info.service.info, mFlags, userId)) {
+                return null;
+            }
+            final PackageParser.Service service = info.service;
+            PackageSetting ps = (PackageSetting) service.owner.mExtras;
+            if (ps == null) {
+                return null;
+            }
+            final PackageUserState userState = ps.readUserState(userId);
+            ServiceInfo si = PackageParser.generateServiceInfo(service, mFlags,
+                    userState, userId);
+            if (si == null) {
+                return null;
+            }
+            final boolean matchVisibleToInstantApp =
+                    (mFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
+            final boolean isInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0;
+            // throw out filters that aren't visible to ephemeral apps
+            if (matchVisibleToInstantApp
+                    && !(info.isVisibleToInstantApp() || userState.instantApp)) {
+                return null;
+            }
+            // throw out ephemeral filters if we're not explicitly requesting them
+            if (!isInstantApp && userState.instantApp) {
+                return null;
+            }
+            // throw out instant app filters if updates are available; will trigger
+            // instant app resolution
+            if (userState.instantApp && ps.isUpdateAvailable()) {
+                return null;
+            }
+            final ResolveInfo res = new ResolveInfo();
+            res.serviceInfo = si;
+            if ((mFlags & PackageManager.GET_RESOLVED_FILTER) != 0) {
+                res.filter = filter;
+            }
+            res.priority = info.getPriority();
+            res.preferredOrder = service.owner.mPreferredOrder;
+            res.match = match;
+            res.isDefault = info.hasDefault;
+            res.labelRes = info.labelRes;
+            res.nonLocalizedLabel = info.nonLocalizedLabel;
+            res.icon = info.icon;
+            res.system = res.serviceInfo.applicationInfo.isSystemApp();
+            return res;
+        }
+
+        @Override
+        protected void sortResults(List<ResolveInfo> results) {
+            results.sort(RESOLVE_PRIORITY_SORTER);
+        }
+
+        @Override
+        protected void dumpFilter(PrintWriter out, String prefix,
+                PackageParser.ServiceIntentInfo filter) {
+            out.print(prefix);
+            out.print(Integer.toHexString(System.identityHashCode(filter.service)));
+            out.print(' ');
+            filter.service.printComponentShortName(out);
+            out.print(" filter ");
+            out.print(Integer.toHexString(System.identityHashCode(filter)));
+            if (filter.service.info.permission != null) {
+                out.print(" permission "); out.println(filter.service.info.permission);
+            } else {
+                out.println();
+            }
+        }
+
+        @Override
+        protected Object filterToLabel(PackageParser.ServiceIntentInfo filter) {
+            return filter.service;
+        }
+
+        protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int count) {
+            final PackageParser.Service service = (PackageParser.Service) label;
+            out.print(prefix);
+            out.print(Integer.toHexString(System.identityHashCode(service)));
+            out.print(' ');
+            service.printComponentShortName(out);
+            if (count > 1) {
+                out.print(" ("); out.print(count); out.print(" filters)");
+            }
+            out.println();
+        }
+
+        // Keys are String (activity class name), values are Activity.
+        private final ArrayMap<ComponentName, PackageParser.Service> mServices = new ArrayMap<>();
+        private int mFlags;
+    }
+
+    static final class InstantAppIntentResolver
+            extends IntentResolver<AuxiliaryResolveInfo.AuxiliaryFilter,
+            AuxiliaryResolveInfo.AuxiliaryFilter> {
+        /**
+         * The result that has the highest defined order. Ordering applies on a
+         * per-package basis. Mapping is from package name to Pair of order and
+         * EphemeralResolveInfo.
+         * <p>
+         * NOTE: This is implemented as a field variable for convenience and efficiency.
+         * By having a field variable, we're able to track filter ordering as soon as
+         * a non-zero order is defined. Otherwise, multiple loops across the result set
+         * would be needed to apply ordering. If the intent resolver becomes re-entrant,
+         * this needs to be contained entirely within {@link #filterResults}.
+         */
+        final ArrayMap<String, Pair<Integer, InstantAppResolveInfo>> mOrderResult =
+                new ArrayMap<>();
+
+        @Override
+        protected AuxiliaryResolveInfo.AuxiliaryFilter[] newArray(int size) {
+            return new AuxiliaryResolveInfo.AuxiliaryFilter[size];
+        }
+
+        @Override
+        protected boolean isPackageForFilter(String packageName,
+                AuxiliaryResolveInfo.AuxiliaryFilter responseObj) {
+            return true;
+        }
+
+        @Override
+        protected AuxiliaryResolveInfo.AuxiliaryFilter newResult(
+                AuxiliaryResolveInfo.AuxiliaryFilter responseObj, int match, int userId) {
+            if (!sUserManager.exists(userId)) {
+                return null;
+            }
+            final String packageName = responseObj.resolveInfo.getPackageName();
+            final Integer order = responseObj.getOrder();
+            final Pair<Integer, InstantAppResolveInfo> lastOrderResult =
+                    mOrderResult.get(packageName);
+            // ordering is enabled and this item's order isn't high enough
+            if (lastOrderResult != null && lastOrderResult.first >= order) {
+                return null;
+            }
+            final InstantAppResolveInfo res = responseObj.resolveInfo;
+            if (order > 0) {
+                // non-zero order, enable ordering
+                mOrderResult.put(packageName, new Pair<>(order, res));
+            }
+            return responseObj;
+        }
+
+        @Override
+        protected void filterResults(List<AuxiliaryResolveInfo.AuxiliaryFilter> results) {
+            // only do work if ordering is enabled [most of the time it won't be]
+            if (mOrderResult.size() == 0) {
+                return;
+            }
+            int resultSize = results.size();
+            for (int i = 0; i < resultSize; i++) {
+                final InstantAppResolveInfo info = results.get(i).resolveInfo;
+                final String packageName = info.getPackageName();
+                final Pair<Integer, InstantAppResolveInfo> savedInfo =
+                        mOrderResult.get(packageName);
+                if (savedInfo == null) {
+                    // package doesn't having ordering
+                    continue;
+                }
+                if (savedInfo.second == info) {
+                    // circled back to the highest ordered item; remove from order list
+                    mOrderResult.remove(packageName);
+                    if (mOrderResult.size() == 0) {
+                        // no more ordered items
+                        break;
+                    }
+                    continue;
+                }
+                // item has a worse order, remove it from the result list
+                results.remove(i);
+                resultSize--;
+                i--;
+            }
+        }
+    }
+
+    /** Generic to create an {@link Iterator} for a data type */
+    static class IterGenerator<E> {
+        public Iterator<E> generate(ActivityIntentInfo info) {
+            return null;
+        }
+    }
+
+    /** Create an {@link Iterator} for intent actions */
+    static class ActionIterGenerator extends IterGenerator<String> {
+        @Override
+        public Iterator<String> generate(ActivityIntentInfo info) {
+            return info.actionsIterator();
+        }
+    }
+
+    /** Create an {@link Iterator} for intent categories */
+    static class CategoriesIterGenerator extends IterGenerator<String> {
+        @Override
+        public Iterator<String> generate(ActivityIntentInfo info) {
+            return info.categoriesIterator();
+        }
+    }
+
+    /** Create an {@link Iterator} for intent schemes */
+    static class SchemesIterGenerator extends IterGenerator<String> {
+        @Override
+        public Iterator<String> generate(ActivityIntentInfo info) {
+            return info.schemesIterator();
+        }
+    }
+
+    /** Create an {@link Iterator} for intent authorities */
+    static class AuthoritiesIterGenerator extends IterGenerator<IntentFilter.AuthorityEntry> {
+        @Override
+        public Iterator<IntentFilter.AuthorityEntry> generate(ActivityIntentInfo info) {
+            return info.authoritiesIterator();
+        }
+    }
+
+}
diff --git a/services/core/java/com/android/server/pm/InstantAppResolver.java b/services/core/java/com/android/server/pm/InstantAppResolver.java
index 19cefb8..9bd3924 100644
--- a/services/core/java/com/android/server/pm/InstantAppResolver.java
+++ b/services/core/java/com/android/server/pm/InstantAppResolver.java
@@ -36,9 +36,9 @@
 import android.content.IntentFilter;
 import android.content.IntentSender;
 import android.content.pm.ActivityInfo;
-import android.content.pm.InstantAppRequest;
 import android.content.pm.AuxiliaryResolveInfo;
 import android.content.pm.InstantAppIntentFilter;
+import android.content.pm.InstantAppRequest;
 import android.content.pm.InstantAppResolveInfo;
 import android.content.pm.InstantAppResolveInfo.InstantAppDigest;
 import android.metrics.LogMaker;
@@ -458,8 +458,8 @@
             }
             return Collections.emptyList();
         }
-        final PackageManagerService.InstantAppIntentResolver instantAppResolver =
-                new PackageManagerService.InstantAppIntentResolver();
+        final ComponentResolver.InstantAppIntentResolver instantAppResolver =
+                new ComponentResolver.InstantAppIntentResolver();
         for (int j = instantAppFilters.size() - 1; j >= 0; --j) {
             final InstantAppIntentFilter instantAppFilter = instantAppFilters.get(j);
             final List<IntentFilter> splitFilters = instantAppFilter.getFilters();
diff --git a/services/core/java/com/android/server/pm/OtaDexoptService.java b/services/core/java/com/android/server/pm/OtaDexoptService.java
index 320affb..cf47d4e 100644
--- a/services/core/java/com/android/server/pm/OtaDexoptService.java
+++ b/services/core/java/com/android/server/pm/OtaDexoptService.java
@@ -365,10 +365,12 @@
                 continue;
             }
 
-            // If the path is in /system, /vendor or /product, ignore. It will have been
-            // ota-dexopted into /data/ota and moved into the dalvik-cache already.
-            if (pkg.codePath.startsWith("/system") || pkg.codePath.startsWith("/vendor")
-                    || pkg.codePath.startsWith("/product")) {
+            // If the path is in /system, /vendor, /product or /product_services, ignore. It will
+            // have been ota-dexopted into /data/ota and moved into the dalvik-cache already.
+            if (pkg.codePath.startsWith("/system")
+                    || pkg.codePath.startsWith("/vendor")
+                    || pkg.codePath.startsWith("/product")
+                    || pkg.codePath.startsWith("/product_services")) {
                 continue;
             }
 
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index f3d333b..fc2813b 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -44,7 +44,6 @@
 import static android.content.pm.PackageManager.FLAG_PERMISSION_USER_SET;
 import static android.content.pm.PackageManager.INSTALL_EXTERNAL;
 import static android.content.pm.PackageManager.INSTALL_FAILED_ALREADY_EXISTS;
-import static android.content.pm.PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
 import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE;
 import static android.content.pm.PackageManager.INSTALL_FAILED_DUPLICATE_PERMISSION;
 import static android.content.pm.PackageManager.INSTALL_FAILED_INSTANT_APP_INVALID;
@@ -95,6 +94,7 @@
 import static com.android.internal.app.IntentForwarderActivity.FORWARD_INTENT_TO_PARENT;
 import static com.android.internal.content.NativeLibraryHelper.LIB64_DIR_NAME;
 import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME;
+import static com.android.server.pm.ComponentResolver.RESOLVE_PRIORITY_SORTER;
 import static com.android.server.pm.InstructionSets.getAppDexInstructionSets;
 import static com.android.server.pm.InstructionSets.getDexCodeInstructionSet;
 import static com.android.server.pm.InstructionSets.getDexCodeInstructionSets;
@@ -158,7 +158,6 @@
 import android.content.pm.IPackageStatsObserver;
 import android.content.pm.InstantAppInfo;
 import android.content.pm.InstantAppRequest;
-import android.content.pm.InstantAppResolveInfo;
 import android.content.pm.InstrumentationInfo;
 import android.content.pm.IntentFilterVerificationInfo;
 import android.content.pm.KeySet;
@@ -177,7 +176,6 @@
 import android.content.pm.PackageParser.PackageLite;
 import android.content.pm.PackageParser.PackageParserException;
 import android.content.pm.PackageParser.ParseFlags;
-import android.content.pm.PackageParser.ServiceIntentInfo;
 import android.content.pm.PackageParser.SigningDetails;
 import android.content.pm.PackageParser.SigningDetails.SignatureSchemeVersion;
 import android.content.pm.PackageStats;
@@ -254,6 +252,7 @@
 import android.util.DisplayMetrics;
 import android.util.EventLog;
 import android.util.ExceptionUtils;
+import android.util.IntArray;
 import android.util.Log;
 import android.util.LogPrinter;
 import android.util.LongSparseArray;
@@ -294,7 +293,6 @@
 import com.android.server.DeviceIdleController;
 import com.android.server.EventLogTags;
 import com.android.server.FgThread;
-import com.android.server.IntentResolver;
 import com.android.server.LocalServices;
 import com.android.server.LockGuard;
 import com.android.server.ServiceThread;
@@ -415,12 +413,10 @@
     public static final boolean DEBUG_INSTALL = false;
     public static final boolean DEBUG_REMOVE = false;
     private static final boolean DEBUG_BROADCASTS = false;
-    private static final boolean DEBUG_SHOW_INFO = false;
     private static final boolean DEBUG_PACKAGE_INFO = false;
     private static final boolean DEBUG_INTENT_MATCHING = false;
     public static final boolean DEBUG_PACKAGE_SCANNING = false;
     private static final boolean DEBUG_VERIFY = false;
-    private static final boolean DEBUG_FILTERS = false;
     public static final boolean DEBUG_PERMISSIONS = false;
     private static final boolean DEBUG_SHARED_LIBRARIES = false;
     public static final boolean DEBUG_COMPRESSION = Build.IS_DEBUGGABLE;
@@ -449,26 +445,27 @@
     private static final int SHELL_UID = Process.SHELL_UID;
     private static final int SE_UID = Process.SE_UID;
 
-    static final int SCAN_NO_DEX = 1<<0;
-    static final int SCAN_UPDATE_SIGNATURE = 1<<1;
-    static final int SCAN_NEW_INSTALL = 1<<2;
-    static final int SCAN_UPDATE_TIME = 1<<3;
-    static final int SCAN_BOOTING = 1<<4;
-    static final int SCAN_REQUIRE_KNOWN = 1<<7;
-    static final int SCAN_MOVE = 1<<8;
-    static final int SCAN_INITIAL = 1<<9;
-    static final int SCAN_CHECK_ONLY = 1<<10;
-    static final int SCAN_DONT_KILL_APP = 1<<11;
-    static final int SCAN_IGNORE_FROZEN = 1<<12;
-    static final int SCAN_FIRST_BOOT_OR_UPGRADE = 1<<13;
-    static final int SCAN_AS_INSTANT_APP = 1<<14;
-    static final int SCAN_AS_FULL_APP = 1<<15;
-    static final int SCAN_AS_VIRTUAL_PRELOAD = 1<<16;
-    static final int SCAN_AS_SYSTEM = 1<<17;
-    static final int SCAN_AS_PRIVILEGED = 1<<18;
-    static final int SCAN_AS_OEM = 1<<19;
-    static final int SCAN_AS_VENDOR = 1<<20;
-    static final int SCAN_AS_PRODUCT = 1<<21;
+    static final int SCAN_NO_DEX = 1 << 0;
+    static final int SCAN_UPDATE_SIGNATURE = 1 << 1;
+    static final int SCAN_NEW_INSTALL = 1 << 2;
+    static final int SCAN_UPDATE_TIME = 1 << 3;
+    static final int SCAN_BOOTING = 1 << 4;
+    static final int SCAN_REQUIRE_KNOWN = 1 << 7;
+    static final int SCAN_MOVE = 1 << 8;
+    static final int SCAN_INITIAL = 1 << 9;
+    static final int SCAN_CHECK_ONLY = 1 << 10;
+    static final int SCAN_DONT_KILL_APP = 1 << 11;
+    static final int SCAN_IGNORE_FROZEN = 1 << 12;
+    static final int SCAN_FIRST_BOOT_OR_UPGRADE = 1 << 13;
+    static final int SCAN_AS_INSTANT_APP = 1 << 14;
+    static final int SCAN_AS_FULL_APP = 1 << 15;
+    static final int SCAN_AS_VIRTUAL_PRELOAD = 1 << 16;
+    static final int SCAN_AS_SYSTEM = 1 << 17;
+    static final int SCAN_AS_PRIVILEGED = 1 << 18;
+    static final int SCAN_AS_OEM = 1 << 19;
+    static final int SCAN_AS_VENDOR = 1 << 20;
+    static final int SCAN_AS_PRODUCT = 1 << 21;
+    static final int SCAN_AS_PRODUCT_SERVICES = 1 << 22;
 
     @IntDef(flag = true, prefix = { "SCAN_" }, value = {
             SCAN_NO_DEX,
@@ -574,6 +571,8 @@
 
     private static final String PRODUCT_OVERLAY_DIR = "/product/overlay";
 
+    private static final String PRODUCT_SERVICES_OVERLAY_DIR = "/product_services/overlay";
+
     /** Canonical intent used to identify what counts as a "web browser" app */
     private static final Intent sBrowserIntent;
     static {
@@ -584,18 +583,6 @@
         sBrowserIntent.addFlags(Intent.FLAG_IGNORE_EPHEMERAL);
     }
 
-    /**
-     * The set of all protected actions [i.e. those actions for which a high priority
-     * intent filter is disallowed].
-     */
-    private static final Set<String> PROTECTED_ACTIONS = new ArraySet<>();
-    static {
-        PROTECTED_ACTIONS.add(Intent.ACTION_SEND);
-        PROTECTED_ACTIONS.add(Intent.ACTION_SENDTO);
-        PROTECTED_ACTIONS.add(Intent.ACTION_SEND_MULTIPLE);
-        PROTECTED_ACTIONS.add(Intent.ACTION_VIEW);
-    }
-
     // Compilation reasons.
     public static final int REASON_UNKNOWN = -1;
     public static final int REASON_FIRST_BOOT = 0;
@@ -697,20 +684,6 @@
      * are package location.
      */
     final private ArrayMap<String, File> mExpectingBetter = new ArrayMap<>();
-    /**
-     * Tracks high priority intent filters for protected actions. During boot, certain
-     * filter actions are protected and should never be allowed to have a high priority
-     * intent filter for them. However, there is one, and only one exception -- the
-     * setup wizard. It must be able to define a high priority intent filter for these
-     * actions to ensure there are no escapes from the wizard. We need to delay processing
-     * of these during boot as we need to look at all of the system packages in order
-     * to know which component is the setup wizard.
-     */
-    private final List<PackageParser.ActivityIntentInfo> mProtectedFilters = new ArrayList<>();
-    /**
-     * Whether or not processing protected filters should be deferred.
-     */
-    private boolean mDeferProtectedFilters = true;
 
     /**
      * Tracks existing system packages prior to receiving an OTA. Keys are package name.
@@ -908,24 +881,6 @@
     final ArrayMap<String, LongSparseArray<SharedLibraryEntry>> mStaticLibsByDeclaringPackage =
             new ArrayMap<>();
 
-    // All available activities, for your resolving pleasure.
-    final ActivityIntentResolver mActivities =
-            new ActivityIntentResolver();
-
-    // All available receivers, for your resolving pleasure.
-    final ActivityIntentResolver mReceivers =
-            new ActivityIntentResolver();
-
-    // All available services, for your resolving pleasure.
-    final ServiceIntentResolver mServices = new ServiceIntentResolver();
-
-    // All available providers, for your resolving pleasure.
-    final ProviderIntentResolver mProviders = new ProviderIntentResolver();
-
-    // Mapping from provider base names (first directory in content URI codePath)
-    // to the provider information.
-    final ArrayMap<String, PackageParser.Provider> mProvidersByAuthority = new ArrayMap<>();
-
     // Mapping from instrumentation class names to info about them.
     final ArrayMap<ComponentName, PackageParser.Instrumentation> mInstrumentation =
             new ArrayMap<>();
@@ -956,7 +911,7 @@
     private final OnPermissionChangeListeners mOnPermissionChangeListeners;
 
     // Cache of users who need badging.
-    SparseBooleanArray mUserNeedsBadging = new SparseBooleanArray();
+    private final SparseBooleanArray mUserNeedsBadging = new SparseBooleanArray();
 
     /** Token for keys in mPendingVerification. */
     private int mPendingVerificationToken = 0;
@@ -996,6 +951,7 @@
     final DefaultPermissionGrantPolicy mDefaultPermissionPolicy;
     private final PermissionManagerInternal mPermissionManager;
 
+    private final ComponentResolver mComponentResolver;
     // List of packages names to keep cached, even if they are uninstalled for all users
     private List<String> mKeepUninstalledPackages;
 
@@ -2411,6 +2367,8 @@
                     PackageManagerInternal.class, new PackageManagerInternalImpl());
             sUserManager = new UserManagerService(context, this,
                     new UserDataPreparer(mInstaller, mInstallLock, mContext, mOnlyCore), mPackages);
+            mComponentResolver = new ComponentResolver(sUserManager,
+                    LocalServices.getService(PackageManagerInternal.class));
             mPermissionManager = PermissionManagerService.create(context,
                     new DefaultPermissionGrantedCallback() {
                         @Override
@@ -2421,7 +2379,8 @@
                         }
                     }, mPackages /*externalLock*/);
             mDefaultPermissionPolicy = mPermissionManager.getDefaultPermissionGrantPolicy();
-            mSettings = new Settings(mPermissionManager.getPermissionSettings(), mPackages);
+            mSettings = new Settings(Environment.getDataDirectory(),
+                    mPermissionManager.getPermissionSettings(), mPackages);
         }
         }
         mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
@@ -2589,9 +2548,10 @@
                 scanFlags = scanFlags | SCAN_FIRST_BOOT_OR_UPGRADE;
             }
 
-            // Collect vendor/product overlay packages. (Do this before scanning any apps.)
-            // For security and version matching reason, only consider
-            // overlay packages if they reside in the right directory.
+            // Collect vendor/product/product_services overlay packages. (Do this before scanning
+            // any apps.)
+            // For security and version matching reason, only consider overlay packages if they
+            // reside in the right directory.
             scanDirTracedLI(new File(VENDOR_OVERLAY_DIR),
                     mDefParseFlags
                     | PackageParser.PARSE_IS_SYSTEM_DIR,
@@ -2606,6 +2566,13 @@
                     | SCAN_AS_SYSTEM
                     | SCAN_AS_PRODUCT,
                     0);
+            scanDirTracedLI(new File(PRODUCT_SERVICES_OVERLAY_DIR),
+                    mDefParseFlags
+                    | PackageParser.PARSE_IS_SYSTEM_DIR,
+                    scanFlags
+                    | SCAN_AS_SYSTEM
+                    | SCAN_AS_PRODUCT_SERVICES,
+                    0);
 
             mParallelPackageParserCallback.findStaticOverlayPackages();
 
@@ -2717,7 +2684,7 @@
                     | SCAN_AS_OEM,
                     0);
 
-            // Collected privileged product packages.
+            // Collected privileged /product packages.
             File privilegedProductAppDir = new File(Environment.getProductDirectory(), "priv-app");
             try {
                 privilegedProductAppDir = privilegedProductAppDir.getCanonicalFile();
@@ -2733,7 +2700,7 @@
                     | SCAN_AS_PRIVILEGED,
                     0);
 
-            // Collect ordinary product packages.
+            // Collect ordinary /product packages.
             File productAppDir = new File(Environment.getProductDirectory(), "app");
             try {
                 productAppDir = productAppDir.getCanonicalFile();
@@ -2748,6 +2715,39 @@
                     | SCAN_AS_PRODUCT,
                     0);
 
+            // Collected privileged /product_services packages.
+            File privilegedProductServicesAppDir =
+                    new File(Environment.getProductServicesDirectory(), "priv-app");
+            try {
+                privilegedProductServicesAppDir =
+                        privilegedProductServicesAppDir.getCanonicalFile();
+            } catch (IOException e) {
+                // failed to look up canonical path, continue with original one
+            }
+            scanDirTracedLI(privilegedProductServicesAppDir,
+                    mDefParseFlags
+                    | PackageParser.PARSE_IS_SYSTEM_DIR,
+                    scanFlags
+                    | SCAN_AS_SYSTEM
+                    | SCAN_AS_PRODUCT_SERVICES
+                    | SCAN_AS_PRIVILEGED,
+                    0);
+
+            // Collect ordinary /product_services packages.
+            File productServicesAppDir = new File(Environment.getProductServicesDirectory(), "app");
+            try {
+                productServicesAppDir = productServicesAppDir.getCanonicalFile();
+            } catch (IOException e) {
+                // failed to look up canonical path, continue with original one
+            }
+            scanDirTracedLI(productServicesAppDir,
+                    mDefParseFlags
+                    | PackageParser.PARSE_IS_SYSTEM_DIR,
+                    scanFlags
+                    | SCAN_AS_SYSTEM
+                    | SCAN_AS_PRODUCT_SERVICES,
+                    0);
+
             // Prune any system packages that no longer exist.
             final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<>();
             // Stub packages must either be replaced with full versions in the /data
@@ -2952,6 +2952,23 @@
                                     scanFlags
                                     | SCAN_AS_SYSTEM
                                     | SCAN_AS_PRODUCT;
+                        } else if (FileUtils.contains(privilegedProductServicesAppDir, scanFile)) {
+                            reparseFlags =
+                                    mDefParseFlags |
+                                    PackageParser.PARSE_IS_SYSTEM_DIR;
+                            rescanFlags =
+                                    scanFlags
+                                    | SCAN_AS_SYSTEM
+                                    | SCAN_AS_PRODUCT_SERVICES
+                                    | SCAN_AS_PRIVILEGED;
+                        } else if (FileUtils.contains(productServicesAppDir, scanFile)) {
+                            reparseFlags =
+                                    mDefParseFlags |
+                                    PackageParser.PARSE_IS_SYSTEM_DIR;
+                            rescanFlags =
+                                    scanFlags
+                                    | SCAN_AS_SYSTEM
+                                    | SCAN_AS_PRODUCT_SERVICES;
                         } else {
                             Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile);
                             continue;
@@ -2995,38 +3012,10 @@
             // Resolve protected action filters. Only the setup wizard is allowed to
             // have a high priority filter for these actions.
             mSetupWizardPackage = getSetupWizardPackageName();
-            if (mProtectedFilters.size() > 0) {
-                if (DEBUG_FILTERS && mSetupWizardPackage == null) {
-                    Slog.i(TAG, "No setup wizard;"
-                        + " All protected intents capped to priority 0");
-                }
-                for (ActivityIntentInfo filter : mProtectedFilters) {
-                    if (filter.activity.info.packageName.equals(mSetupWizardPackage)) {
-                        if (DEBUG_FILTERS) {
-                            Slog.i(TAG, "Found setup wizard;"
-                                + " allow priority " + filter.getPriority() + ";"
-                                + " package: " + filter.activity.info.packageName
-                                + " activity: " + filter.activity.className
-                                + " priority: " + filter.getPriority());
-                        }
-                        // skip setup wizard; allow it to keep the high priority filter
-                        continue;
-                    }
-                    if (DEBUG_FILTERS) {
-                        Slog.i(TAG, "Protected action; cap priority to 0;"
-                                + " package: " + filter.activity.info.packageName
-                                + " activity: " + filter.activity.className
-                                + " origPrio: " + filter.getPriority());
-                    }
-                    filter.setPriority(0);
-                }
-            }
+            mComponentResolver.fixProtectedFilterPriorities();
 
             mSystemTextClassifierPackage = getSystemTextClassifierPackageName();
 
-            mDeferProtectedFilters = false;
-            mProtectedFilters.clear();
-
             // Now that we know all of the shared libraries, update all clients to have
             // the correct library paths.
             updateAllSharedLibrariesLPw(null);
@@ -3084,7 +3073,7 @@
             // all defined users.
             if (!onlyCore && (mPromoteSystemApps || mFirstBoot)) {
                 for (UserInfo user : sUserManager.getUsers(true)) {
-                    mSettings.applyDefaultPreferredAppsLPw(this, user.id);
+                    mSettings.applyDefaultPreferredAppsLPw(user.id);
                     applyFactoryDefaultBrowserLPw(user.id);
                     primeDomainVerificationsLPw(user.id);
                 }
@@ -4180,7 +4169,7 @@
     private boolean isComponentVisibleToInstantApp(
             @Nullable ComponentName component, @ComponentType int type) {
         if (type == TYPE_ACTIVITY) {
-            final PackageParser.Activity activity = mActivities.mActivities.get(component);
+            final PackageParser.Activity activity = mComponentResolver.getActivity(component);
             if (activity == null) {
                 return false;
             }
@@ -4190,7 +4179,7 @@
                     (activity.info.flags & ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP) == 0;
             return visibleToInstantApp && explicitlyVisibleToInstantApp;
         } else if (type == TYPE_RECEIVER) {
-            final PackageParser.Activity activity = mReceivers.mActivities.get(component);
+            final PackageParser.Activity activity = mComponentResolver.getReceiver(component);
             if (activity == null) {
                 return false;
             }
@@ -4200,12 +4189,12 @@
                     (activity.info.flags & ActivityInfo.FLAG_IMPLICITLY_VISIBLE_TO_INSTANT_APP) == 0;
             return visibleToInstantApp && !explicitlyVisibleToInstantApp;
         } else if (type == TYPE_SERVICE) {
-            final PackageParser.Service service = mServices.mServices.get(component);
+            final PackageParser.Service service = mComponentResolver.getService(component);
             return service != null
                     ? (service.info.flags & ServiceInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0
                     : false;
         } else if (type == TYPE_PROVIDER) {
-            final PackageParser.Provider provider = mProviders.mProviders.get(component);
+            final PackageParser.Provider provider = mComponentResolver.getProvider(component);
             return provider != null
                     ? (provider.info.flags & ProviderInfo.FLAG_VISIBLE_TO_INSTANT_APP) != 0
                     : false;
@@ -4953,7 +4942,7 @@
         }
 
         synchronized (mPackages) {
-            PackageParser.Activity a = mActivities.mActivities.get(component);
+            PackageParser.Activity a = mComponentResolver.getActivity(component);
 
             if (DEBUG_PACKAGE_INFO) Log.v(TAG, "getActivityInfo " + component + ": " + a);
             if (a != null && mSettings.isEnabledAndMatchLPr(a.info, flags, userId)) {
@@ -4999,7 +4988,7 @@
             }
             final int callingUid = Binder.getCallingUid();
             final int callingUserId = UserHandle.getUserId(callingUid);
-            PackageParser.Activity a = mActivities.mActivities.get(component);
+            PackageParser.Activity a = mComponentResolver.getActivity(component);
             if (a == null) {
                 return false;
             }
@@ -5028,7 +5017,7 @@
         mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                 false /* requireFullPermission */, false /* checkShell */, "get receiver info");
         synchronized (mPackages) {
-            PackageParser.Activity a = mReceivers.mActivities.get(component);
+            PackageParser.Activity a = mComponentResolver.getReceiver(component);
             if (DEBUG_PACKAGE_INFO) Log.v(
                 TAG, "getReceiverInfo " + component + ": " + a);
             if (a != null && mSettings.isEnabledAndMatchLPr(a.info, flags, userId)) {
@@ -5166,7 +5155,7 @@
         mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                 false /* requireFullPermission */, false /* checkShell */, "get service info");
         synchronized (mPackages) {
-            PackageParser.Service s = mServices.mServices.get(component);
+            PackageParser.Service s = mComponentResolver.getService(component);
             if (DEBUG_PACKAGE_INFO) Log.v(
                 TAG, "getServiceInfo " + component + ": " + s);
             if (s != null && mSettings.isEnabledAndMatchLPr(s.info, flags, userId)) {
@@ -5190,7 +5179,7 @@
         mPermissionManager.enforceCrossUserPermission(callingUid, userId,
                 false /* requireFullPermission */, false /* checkShell */, "get provider info");
         synchronized (mPackages) {
-            PackageParser.Provider p = mProviders.mProviders.get(component);
+            PackageParser.Provider p = mComponentResolver.getProvider(component);
             if (DEBUG_PACKAGE_INFO) Log.v(
                 TAG, "getProviderInfo " + component + ": " + p);
             if (p != null && mSettings.isEnabledAndMatchLPr(p.info, flags, userId)) {
@@ -6744,7 +6733,7 @@
                 }
 
                 // Check for results in the current profile.
-                result = filterIfNotSystemUser(mActivities.queryIntent(
+                result = filterIfNotSystemUser(mComponentResolver.queryActivities(
                         intent, resolvedType, flags, userId), userId);
                 addInstant = isInstantAppResolutionAllowed(intent, result, userId,
                         false /*skipPackageCheck*/);
@@ -6801,10 +6790,8 @@
                 final PackageParser.Package pkg = mPackages.get(pkgName);
                 result = null;
                 if (pkg != null) {
-                    result = filterIfNotSystemUser(
-                            mActivities.queryIntentForPackage(
-                                    intent, resolvedType, flags, pkg.activities, userId),
-                            userId);
+                    result = filterIfNotSystemUser(mComponentResolver.queryActivities(
+                            intent, resolvedType, flags, pkg.activities, userId), userId);
                 }
                 if (result == null || result.size() == 0) {
                     // the caller wants to resolve for a particular package; however, there
@@ -6822,7 +6809,7 @@
                     result, intent, resolvedType, flags, userId, resolveForStart);
         }
         if (sortResult) {
-            Collections.sort(result, mResolvePrioritySorter);
+            Collections.sort(result, RESOLVE_PRIORITY_SORTER);
         }
         return applyPostResolutionFilter(
                 result, instantAppPkgName, allowDynamicSplits, filterCallingUid, resolveForStart,
@@ -6836,7 +6823,9 @@
         ResolveInfo localInstantApp = null;
         boolean blockResolution = false;
         if (!alreadyResolvedLocally) {
-            final List<ResolveInfo> instantApps = mActivities.queryIntent(intent, resolvedType,
+            final List<ResolveInfo> instantApps = mComponentResolver.queryActivities(
+                    intent,
+                    resolvedType,
                     flags
                         | PackageManager.GET_RESOLVED_FILTER
                         | PackageManager.MATCH_INSTANT
@@ -6942,7 +6931,7 @@
                 sourceUserId)) {
             return null;
         }
-        List<ResolveInfo> resultTargetUser = mActivities.queryIntent(intent,
+        List<ResolveInfo> resultTargetUser = mComponentResolver.queryActivities(intent,
                 resolvedType, flags, parentUserId);
 
         if (resultTargetUser == null || resultTargetUser.isEmpty()) {
@@ -7382,7 +7371,7 @@
     private ResolveInfo createForwardingResolveInfo(CrossProfileIntentFilter filter, Intent intent,
             String resolvedType, int flags, int sourceUserId) {
         int targetUserId = filter.getTargetUserId();
-        List<ResolveInfo> resultTargetUser = mActivities.queryIntent(intent,
+        List<ResolveInfo> resultTargetUser = mComponentResolver.queryActivities(intent,
                 resolvedType, flags, targetUserId);
         if (resultTargetUser != null && isUserEnabled(targetUserId)) {
             // If all the matches in the target profile are suspended, return null.
@@ -7690,14 +7679,14 @@
             String pkgName = intent.getPackage();
             if (pkgName == null) {
                 final List<ResolveInfo> result =
-                        mReceivers.queryIntent(intent, resolvedType, flags, userId);
+                        mComponentResolver.queryReceivers(intent, resolvedType, flags, userId);
                 return applyPostResolutionFilter(
                         result, instantAppPkgName, allowDynamicSplits, callingUid, false, userId,
                         intent);
             }
             final PackageParser.Package pkg = mPackages.get(pkgName);
             if (pkg != null) {
-                final List<ResolveInfo> result = mReceivers.queryIntentForPackage(
+                final List<ResolveInfo> result = mComponentResolver.queryReceivers(
                         intent, resolvedType, flags, pkg.receivers, userId);
                 return applyPostResolutionFilter(
                         result, instantAppPkgName, allowDynamicSplits, callingUid, false, userId,
@@ -7794,13 +7783,13 @@
             String pkgName = intent.getPackage();
             if (pkgName == null) {
                 return applyPostServiceResolutionFilter(
-                        mServices.queryIntent(intent, resolvedType, flags, userId),
+                        mComponentResolver.queryServices(intent, resolvedType, flags, userId),
                         instantAppPkgName);
             }
             final PackageParser.Package pkg = mPackages.get(pkgName);
             if (pkg != null) {
                 return applyPostServiceResolutionFilter(
-                        mServices.queryIntentForPackage(intent, resolvedType, flags, pkg.services,
+                        mComponentResolver.queryServices(intent, resolvedType, flags, pkg.services,
                                 userId),
                         instantAppPkgName);
             }
@@ -7912,14 +7901,14 @@
             String pkgName = intent.getPackage();
             if (pkgName == null) {
                 return applyPostContentProviderResolutionFilter(
-                        mProviders.queryIntent(intent, resolvedType, flags, userId),
+                        mComponentResolver.queryProviders(intent, resolvedType, flags, userId),
                         instantAppPkgName);
             }
             final PackageParser.Package pkg = mPackages.get(pkgName);
             if (pkg != null) {
                 return applyPostContentProviderResolutionFilter(
-                        mProviders.queryIntentForPackage(
-                        intent, resolvedType, flags, pkg.providers, userId),
+                        mComponentResolver.queryProviders(intent, resolvedType, flags,
+                                pkg.providers, userId),
                         instantAppPkgName);
             }
             return Collections.emptyList();
@@ -8332,26 +8321,22 @@
         if (!sUserManager.exists(userId)) return null;
         flags = updateFlagsForComponent(flags, userId, name);
         final int callingUid = Binder.getCallingUid();
-        synchronized (mPackages) {
-            final PackageParser.Provider provider = mProvidersByAuthority.get(name);
-            PackageSetting ps = provider != null
-                    ? mSettings.mPackages.get(provider.owner.packageName)
-                    : null;
-            if (ps != null) {
-                // provider not enabled
-                if (!mSettings.isEnabledAndMatchLPr(provider.info, flags, userId)) {
-                    return null;
-                }
-                final ComponentName component =
-                        new ComponentName(provider.info.packageName, provider.info.name);
-                if (filterAppAccessLPr(ps, callingUid, component, TYPE_PROVIDER, userId)) {
-                    return null;
-                }
-                return PackageParser.generateProviderInfo(
-                        provider, flags, ps.readUserState(userId), userId);
-            }
+        final ProviderInfo providerInfo = mComponentResolver.queryProvider(name, flags, userId);
+        if (providerInfo == null) {
             return null;
         }
+        if (!mSettings.isEnabledAndMatchLPr(providerInfo, flags, userId)) {
+            return null;
+        }
+        synchronized (mPackages) {
+            final PackageSetting ps = mSettings.mPackages.get(providerInfo.packageName);
+            final ComponentName component =
+                    new ComponentName(providerInfo.packageName, providerInfo.name);
+            if (filterAppAccessLPr(ps, callingUid, component, TYPE_PROVIDER, userId)) {
+                return null;
+            }
+            return providerInfo;
+        }
     }
 
     /**
@@ -8362,28 +8347,8 @@
         if (getInstantAppPackageName(Binder.getCallingUid()) != null) {
             return;
         }
-        // reader
-        synchronized (mPackages) {
-            final Iterator<Map.Entry<String, PackageParser.Provider>> i = mProvidersByAuthority
-                    .entrySet().iterator();
-            final int userId = UserHandle.getCallingUserId();
-            while (i.hasNext()) {
-                Map.Entry<String, PackageParser.Provider> entry = i.next();
-                PackageParser.Provider p = entry.getValue();
-                PackageSetting ps = mSettings.mPackages.get(p.owner.packageName);
-
-                if (ps != null && p.syncable
-                        && (!mSafeMode || (p.info.applicationInfo.flags
-                                &ApplicationInfo.FLAG_SYSTEM) != 0)) {
-                    ProviderInfo info = PackageParser.generateProviderInfo(p, 0,
-                            ps.readUserState(userId), userId);
-                    if (info != null) {
-                        outNames.add(entry.getKey());
-                        outInfo.add(info);
-                    }
-                }
-            }
-        }
+        mComponentResolver.querySyncProviders(
+                outNames, outInfo, mSafeMode, UserHandle.getCallingUserId());
     }
 
     @Override
@@ -8395,43 +8360,30 @@
         if (!sUserManager.exists(userId)) return ParceledListSlice.emptyList();
         flags = updateFlagsForComponent(flags, userId, processName);
         ArrayList<ProviderInfo> finalList = null;
-        // reader
+        final List<ProviderInfo> matchList =
+                mComponentResolver.queryProviders(processName, metaDataKey, uid, flags, userId);
+        final int listSize = (matchList == null ? 0 : matchList.size());
         synchronized (mPackages) {
-            final Iterator<PackageParser.Provider> i = mProviders.mProviders.values().iterator();
-            while (i.hasNext()) {
-                final PackageParser.Provider p = i.next();
-                PackageSetting ps = mSettings.mPackages.get(p.owner.packageName);
-                if (ps != null && p.info.authority != null
-                        && (processName == null
-                                || (p.info.processName.equals(processName)
-                                        && UserHandle.isSameApp(p.info.applicationInfo.uid, uid)))
-                        && mSettings.isEnabledAndMatchLPr(p.info, flags, userId)) {
-
-                    // See PM.queryContentProviders()'s javadoc for why we have the metaData
-                    // parameter.
-                    if (metaDataKey != null
-                            && (p.metaData == null || !p.metaData.containsKey(metaDataKey))) {
-                        continue;
-                    }
-                    final ComponentName component =
-                            new ComponentName(p.info.packageName, p.info.name);
-                    if (filterAppAccessLPr(ps, callingUid, component, TYPE_PROVIDER, userId)) {
-                        continue;
-                    }
-                    if (finalList == null) {
-                        finalList = new ArrayList<>(3);
-                    }
-                    ProviderInfo info = PackageParser.generateProviderInfo(p, flags,
-                            ps.readUserState(userId), userId);
-                    if (info != null) {
-                        finalList.add(info);
-                    }
+            for (int i = 0; i < listSize; i++) {
+                final ProviderInfo providerInfo = matchList.get(i);
+                if (!mSettings.isEnabledAndMatchLPr(providerInfo, flags, userId)) {
+                    continue;
                 }
+                final PackageSetting ps = mSettings.mPackages.get(providerInfo.packageName);
+                final ComponentName component =
+                        new ComponentName(providerInfo.packageName, providerInfo.name);
+                if (filterAppAccessLPr(ps, callingUid, component, TYPE_PROVIDER, userId)) {
+                    continue;
+                }
+                if (finalList == null) {
+                    finalList = new ArrayList<>(listSize - i);
+                }
+                finalList.add(providerInfo);
             }
         }
 
         if (finalList != null) {
-            finalList.sort(mProviderInitOrderSorter);
+            finalList.sort(sProviderInitOrderSorter);
             return new ParceledListSlice<>(finalList);
         }
 
@@ -9001,8 +8953,7 @@
                 + pkg.staticSharedLibVersion);
     }
 
-    private static String fixProcessName(String defProcessName,
-            String processName) {
+    static String fixProcessName(String defProcessName, String processName) {
         if (processName == null) {
             return defProcessName;
         }
@@ -10166,6 +10117,7 @@
      * <li>{@link #SCAN_AS_OEM}</li>
      * <li>{@link #SCAN_AS_VENDOR}</li>
      * <li>{@link #SCAN_AS_PRODUCT}</li>
+     * <li>{@link #SCAN_AS_PRODUCT_SERVICES}</li>
      * <li>{@link #SCAN_AS_INSTANT_APP}</li>
      * <li>{@link #SCAN_AS_VIRTUAL_PRELOAD}</li>
      * </ul>
@@ -10192,6 +10144,10 @@
                     & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0) {
                 scanFlags |= SCAN_AS_PRODUCT;
             }
+            if ((disabledPkgSetting.pkgPrivateFlags
+                    & ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES) != 0) {
+                scanFlags |= SCAN_AS_PRODUCT_SERVICES;
+            }
         }
         if (pkgSetting != null) {
             final int userId = ((user == null) ? 0 : user.getIdentifier());
@@ -11034,6 +10990,10 @@
             pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRODUCT;
         }
 
+        if ((scanFlags & SCAN_AS_PRODUCT_SERVICES) != 0) {
+            pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES;
+        }
+
         // Check if the package is signed with the same key as the platform package.
         if (PLATFORM_PACKAGE_NAME.equals(pkg.packageName) ||
                 (platformPkg != null && compareSignatures(
@@ -11287,27 +11247,7 @@
             // package isn't already installed, since we don't want to break
             // things that are installed.
             if ((scanFlags & SCAN_NEW_INSTALL) != 0) {
-                final int N = pkg.providers.size();
-                int i;
-                for (i=0; i<N; i++) {
-                    PackageParser.Provider p = pkg.providers.get(i);
-                    if (p.info.authority != null) {
-                        String names[] = p.info.authority.split(";");
-                        for (int j = 0; j < names.length; j++) {
-                            if (mProvidersByAuthority.containsKey(names[j])) {
-                                PackageParser.Provider other = mProvidersByAuthority.get(names[j]);
-                                final String otherPackageName =
-                                        ((other != null && other.getComponentName() != null) ?
-                                                other.getComponentName().getPackageName() : "?");
-                                throw new PackageManagerException(
-                                        INSTALL_FAILED_CONFLICTING_PROVIDER,
-                                        "Can't install because provider name " + names[j]
-                                                + " (in package " + pkg.applicationInfo.packageName
-                                                + ") is already used by " + otherPackageName);
-                            }
-                        }
-                    }
-                }
+                mComponentResolver.assertProvidersNotDefined(pkg);
             }
 
             // Verify that packages sharing a user with a privileged app are marked as privileged.
@@ -11605,125 +11545,7 @@
             KeySetManagerService ksms = mSettings.mKeySetManagerService;
             ksms.addScannedPackageLPw(pkg);
 
-            int N = pkg.providers.size();
-            StringBuilder r = null;
-            int i;
-            for (i=0; i<N; i++) {
-                PackageParser.Provider p = pkg.providers.get(i);
-                p.info.processName = fixProcessName(pkg.applicationInfo.processName,
-                        p.info.processName);
-                mProviders.addProvider(p);
-                p.syncable = p.info.isSyncable;
-                if (p.info.authority != null) {
-                    String names[] = p.info.authority.split(";");
-                    p.info.authority = null;
-                    for (int j = 0; j < names.length; j++) {
-                        if (j == 1 && p.syncable) {
-                            // We only want the first authority for a provider to possibly be
-                            // syncable, so if we already added this provider using a different
-                            // authority clear the syncable flag. We copy the provider before
-                            // changing it because the mProviders object contains a reference
-                            // to a provider that we don't want to change.
-                            // Only do this for the second authority since the resulting provider
-                            // object can be the same for all future authorities for this provider.
-                            p = new PackageParser.Provider(p);
-                            p.syncable = false;
-                        }
-                        if (!mProvidersByAuthority.containsKey(names[j])) {
-                            mProvidersByAuthority.put(names[j], p);
-                            if (p.info.authority == null) {
-                                p.info.authority = names[j];
-                            } else {
-                                p.info.authority = p.info.authority + ";" + names[j];
-                            }
-                            if (DEBUG_PACKAGE_SCANNING) {
-                                if (chatty)
-                                    Log.d(TAG, "Registered content provider: " + names[j]
-                                            + ", className = " + p.info.name + ", isSyncable = "
-                                            + p.info.isSyncable);
-                            }
-                        } else {
-                            PackageParser.Provider other = mProvidersByAuthority.get(names[j]);
-                            Slog.w(TAG, "Skipping provider name " + names[j] +
-                                    " (in package " + pkg.applicationInfo.packageName +
-                                    "): name already used by "
-                                    + ((other != null && other.getComponentName() != null)
-                                            ? other.getComponentName().getPackageName() : "?"));
-                        }
-                    }
-                }
-                if (chatty) {
-                    if (r == null) {
-                        r = new StringBuilder(256);
-                    } else {
-                        r.append(' ');
-                    }
-                    r.append(p.info.name);
-                }
-            }
-            if (r != null) {
-                if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Providers: " + r);
-            }
-
-            N = pkg.services.size();
-            r = null;
-            for (i=0; i<N; i++) {
-                PackageParser.Service s = pkg.services.get(i);
-                s.info.processName = fixProcessName(pkg.applicationInfo.processName,
-                        s.info.processName);
-                mServices.addService(s);
-                if (chatty) {
-                    if (r == null) {
-                        r = new StringBuilder(256);
-                    } else {
-                        r.append(' ');
-                    }
-                    r.append(s.info.name);
-                }
-            }
-            if (r != null) {
-                if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Services: " + r);
-            }
-
-            N = pkg.receivers.size();
-            r = null;
-            for (i=0; i<N; i++) {
-                PackageParser.Activity a = pkg.receivers.get(i);
-                a.info.processName = fixProcessName(pkg.applicationInfo.processName,
-                        a.info.processName);
-                mReceivers.addActivity(a, "receiver");
-                if (chatty) {
-                    if (r == null) {
-                        r = new StringBuilder(256);
-                    } else {
-                        r.append(' ');
-                    }
-                    r.append(a.info.name);
-                }
-            }
-            if (r != null) {
-                if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Receivers: " + r);
-            }
-
-            N = pkg.activities.size();
-            r = null;
-            for (i=0; i<N; i++) {
-                PackageParser.Activity a = pkg.activities.get(i);
-                a.info.processName = fixProcessName(pkg.applicationInfo.processName,
-                        a.info.processName);
-                mActivities.addActivity(a, "activity");
-                if (chatty) {
-                    if (r == null) {
-                        r = new StringBuilder(256);
-                    } else {
-                        r.append(' ');
-                    }
-                    r.append(a.info.name);
-                }
-            }
-            if (r != null) {
-                if (DEBUG_PACKAGE_SCANNING) Log.d(TAG, "  Activities: " + r);
-            }
+            mComponentResolver.addAllComponents(pkg, chatty);
 
             // Don't allow ephemeral applications to define new permissions groups.
             if ((scanFlags & SCAN_AS_INSTANT_APP) != 0) {
@@ -11741,9 +11563,10 @@
                 mPermissionManager.addAllPermissions(pkg, chatty);
             }
 
-            N = pkg.instrumentation.size();
-            r = null;
-            for (i=0; i<N; i++) {
+            int collectionSize = pkg.instrumentation.size();
+            StringBuilder r = null;
+            int i;
+            for (i = 0; i < collectionSize; i++) {
                 PackageParser.Instrumentation a = pkg.instrumentation.get(i);
                 a.info.packageName = pkg.applicationInfo.packageName;
                 a.info.sourceDir = pkg.applicationInfo.sourceDir;
@@ -11774,9 +11597,9 @@
             }
 
             if (pkg.protectedBroadcasts != null) {
-                N = pkg.protectedBroadcasts.size();
+                collectionSize = pkg.protectedBroadcasts.size();
                 synchronized (mProtectedBroadcasts) {
-                    for (i = 0; i < N; i++) {
+                    for (i = 0; i < collectionSize; i++) {
                         mProtectedBroadcasts.add(pkg.protectedBroadcasts.get(i));
                     }
                 }
@@ -12127,6 +11950,8 @@
             codeRoot = Environment.getOdmDirectory();
         } else if (FileUtils.contains(Environment.getProductDirectory(), codePath)) {
             codeRoot = Environment.getProductDirectory();
+        } else if (FileUtils.contains(Environment.getProductServicesDirectory(), codePath)) {
+            codeRoot = Environment.getProductServicesDirectory();
         } else {
             // Unrecognized code path; take its top real segment as the apk root:
             // e.g. /something/app/blah.apk => /something
@@ -12393,105 +12218,15 @@
     }
 
     void cleanPackageDataStructuresLILPw(PackageParser.Package pkg, boolean chatty) {
-        int N = pkg.providers.size();
-        StringBuilder r = null;
-        int i;
-        for (i=0; i<N; i++) {
-            PackageParser.Provider p = pkg.providers.get(i);
-            mProviders.removeProvider(p);
-            if (p.info.authority == null) {
-
-                /* There was another ContentProvider with this authority when
-                 * this app was installed so this authority is null,
-                 * Ignore it as we don't have to unregister the provider.
-                 */
-                continue;
-            }
-            String names[] = p.info.authority.split(";");
-            for (int j = 0; j < names.length; j++) {
-                if (mProvidersByAuthority.get(names[j]) == p) {
-                    mProvidersByAuthority.remove(names[j]);
-                    if (DEBUG_REMOVE) {
-                        if (chatty)
-                            Log.d(TAG, "Unregistered content provider: " + names[j]
-                                    + ", className = " + p.info.name + ", isSyncable = "
-                                    + p.info.isSyncable);
-                    }
-                }
-            }
-            if (DEBUG_REMOVE && chatty) {
-                if (r == null) {
-                    r = new StringBuilder(256);
-                } else {
-                    r.append(' ');
-                }
-                r.append(p.info.name);
-            }
-        }
-        if (r != null) {
-            if (DEBUG_REMOVE) Log.d(TAG, "  Providers: " + r);
-        }
-
-        N = pkg.services.size();
-        r = null;
-        for (i=0; i<N; i++) {
-            PackageParser.Service s = pkg.services.get(i);
-            mServices.removeService(s);
-            if (chatty) {
-                if (r == null) {
-                    r = new StringBuilder(256);
-                } else {
-                    r.append(' ');
-                }
-                r.append(s.info.name);
-            }
-        }
-        if (r != null) {
-            if (DEBUG_REMOVE) Log.d(TAG, "  Services: " + r);
-        }
-
-        N = pkg.receivers.size();
-        r = null;
-        for (i=0; i<N; i++) {
-            PackageParser.Activity a = pkg.receivers.get(i);
-            mReceivers.removeActivity(a, "receiver");
-            if (DEBUG_REMOVE && chatty) {
-                if (r == null) {
-                    r = new StringBuilder(256);
-                } else {
-                    r.append(' ');
-                }
-                r.append(a.info.name);
-            }
-        }
-        if (r != null) {
-            if (DEBUG_REMOVE) Log.d(TAG, "  Receivers: " + r);
-        }
-
-        N = pkg.activities.size();
-        r = null;
-        for (i=0; i<N; i++) {
-            PackageParser.Activity a = pkg.activities.get(i);
-            mActivities.removeActivity(a, "activity");
-            if (DEBUG_REMOVE && chatty) {
-                if (r == null) {
-                    r = new StringBuilder(256);
-                } else {
-                    r.append(' ');
-                }
-                r.append(a.info.name);
-            }
-        }
-        if (r != null) {
-            if (DEBUG_REMOVE) Log.d(TAG, "  Activities: " + r);
-        }
+        mComponentResolver.removeAllComponents(pkg, chatty);
 
         final ArrayList<String> allPackageNames = new ArrayList<>(mPackages.keySet());
         mPermissionManager.removeAllPermissions(pkg, allPackageNames, mPermissionCallback, chatty);
 
-        N = pkg.instrumentation.size();
-        r = null;
-        for (i=0; i<N; i++) {
+        final int instrumentationSize = pkg.instrumentation.size();
+        StringBuilder r = null;
+        int i;
+        for (i = 0; i < instrumentationSize; i++) {
             PackageParser.Instrumentation a = pkg.instrumentation.get(i);
             mInstrumentation.remove(a.getComponentName());
             if (DEBUG_REMOVE && chatty) {
@@ -12511,7 +12246,8 @@
         if ((pkg.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) != 0) {
             // Only system apps can hold shared libraries.
             if (pkg.libraryNames != null) {
-                for (i = 0; i < pkg.libraryNames.size(); i++) {
+                final int libraryNamesSize = pkg.libraryNames.size();
+                for (i = 0; i < libraryNamesSize; i++) {
                     String name = pkg.libraryNames.get(i);
                     if (removeSharedLibraryLPw(name, 0)) {
                         if (DEBUG_REMOVE && chatty) {
@@ -12548,1135 +12284,6 @@
         }
     }
 
-
-    final class ActivityIntentResolver
-            extends IntentResolver<PackageParser.ActivityIntentInfo, ResolveInfo> {
-        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
-                boolean defaultOnly, int userId) {
-            if (!sUserManager.exists(userId)) return null;
-            mFlags = (defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0);
-            return super.queryIntent(intent, resolvedType, defaultOnly, userId);
-        }
-
-        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
-                int userId) {
-            if (!sUserManager.exists(userId)) return null;
-            mFlags = flags;
-            return super.queryIntent(intent, resolvedType,
-                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
-                    userId);
-        }
-
-        public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
-                int flags, ArrayList<PackageParser.Activity> packageActivities, int userId) {
-            if (!sUserManager.exists(userId)) return null;
-            if (packageActivities == null) {
-                return null;
-            }
-            mFlags = flags;
-            final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
-            final int N = packageActivities.size();
-            ArrayList<PackageParser.ActivityIntentInfo[]> listCut =
-                new ArrayList<PackageParser.ActivityIntentInfo[]>(N);
-
-            ArrayList<PackageParser.ActivityIntentInfo> intentFilters;
-            for (int i = 0; i < N; ++i) {
-                intentFilters = packageActivities.get(i).intents;
-                if (intentFilters != null && intentFilters.size() > 0) {
-                    PackageParser.ActivityIntentInfo[] array =
-                            new PackageParser.ActivityIntentInfo[intentFilters.size()];
-                    intentFilters.toArray(array);
-                    listCut.add(array);
-                }
-            }
-            return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
-        }
-
-        /**
-         * Finds a privileged activity that matches the specified activity names.
-         */
-        private PackageParser.Activity findMatchingActivity(
-                List<PackageParser.Activity> activityList, ActivityInfo activityInfo) {
-            for (PackageParser.Activity sysActivity : activityList) {
-                if (sysActivity.info.name.equals(activityInfo.name)) {
-                    return sysActivity;
-                }
-                if (sysActivity.info.name.equals(activityInfo.targetActivity)) {
-                    return sysActivity;
-                }
-                if (sysActivity.info.targetActivity != null) {
-                    if (sysActivity.info.targetActivity.equals(activityInfo.name)) {
-                        return sysActivity;
-                    }
-                    if (sysActivity.info.targetActivity.equals(activityInfo.targetActivity)) {
-                        return sysActivity;
-                    }
-                }
-            }
-            return null;
-        }
-
-        public class IterGenerator<E> {
-            public Iterator<E> generate(ActivityIntentInfo info) {
-                return null;
-            }
-        }
-
-        public class ActionIterGenerator extends IterGenerator<String> {
-            @Override
-            public Iterator<String> generate(ActivityIntentInfo info) {
-                return info.actionsIterator();
-            }
-        }
-
-        public class CategoriesIterGenerator extends IterGenerator<String> {
-            @Override
-            public Iterator<String> generate(ActivityIntentInfo info) {
-                return info.categoriesIterator();
-            }
-        }
-
-        public class SchemesIterGenerator extends IterGenerator<String> {
-            @Override
-            public Iterator<String> generate(ActivityIntentInfo info) {
-                return info.schemesIterator();
-            }
-        }
-
-        public class AuthoritiesIterGenerator extends IterGenerator<IntentFilter.AuthorityEntry> {
-            @Override
-            public Iterator<IntentFilter.AuthorityEntry> generate(ActivityIntentInfo info) {
-                return info.authoritiesIterator();
-            }
-        }
-
-        /**
-         * <em>WARNING</em> for performance reasons, the passed in intentList WILL BE
-         * MODIFIED. Do not pass in a list that should not be changed.
-         */
-        private <T> void getIntentListSubset(List<ActivityIntentInfo> intentList,
-                IterGenerator<T> generator, Iterator<T> searchIterator) {
-            // loop through the set of actions; every one must be found in the intent filter
-            while (searchIterator.hasNext()) {
-                // we must have at least one filter in the list to consider a match
-                if (intentList.size() == 0) {
-                    break;
-                }
-
-                final T searchAction = searchIterator.next();
-
-                // loop through the set of intent filters
-                final Iterator<ActivityIntentInfo> intentIter = intentList.iterator();
-                while (intentIter.hasNext()) {
-                    final ActivityIntentInfo intentInfo = intentIter.next();
-                    boolean selectionFound = false;
-
-                    // loop through the intent filter's selection criteria; at least one
-                    // of them must match the searched criteria
-                    final Iterator<T> intentSelectionIter = generator.generate(intentInfo);
-                    while (intentSelectionIter != null && intentSelectionIter.hasNext()) {
-                        final T intentSelection = intentSelectionIter.next();
-                        if (intentSelection != null && intentSelection.equals(searchAction)) {
-                            selectionFound = true;
-                            break;
-                        }
-                    }
-
-                    // the selection criteria wasn't found in this filter's set; this filter
-                    // is not a potential match
-                    if (!selectionFound) {
-                        intentIter.remove();
-                    }
-                }
-            }
-        }
-
-        private boolean isProtectedAction(ActivityIntentInfo filter) {
-            final Iterator<String> actionsIter = filter.actionsIterator();
-            while (actionsIter != null && actionsIter.hasNext()) {
-                final String filterAction = actionsIter.next();
-                if (PROTECTED_ACTIONS.contains(filterAction)) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        /**
-         * Adjusts the priority of the given intent filter according to policy.
-         * <p>
-         * <ul>
-         * <li>The priority for non privileged applications is capped to '0'</li>
-         * <li>The priority for protected actions on privileged applications is capped to '0'</li>
-         * <li>The priority for unbundled updates to privileged applications is capped to the
-         *      priority defined on the system partition</li>
-         * </ul>
-         * <p>
-         * <em>NOTE:</em> There is one exception. For security reasons, the setup wizard is
-         * allowed to obtain any priority on any action.
-         */
-        private void adjustPriority(
-                List<PackageParser.Activity> systemActivities, ActivityIntentInfo intent) {
-            // nothing to do; priority is fine as-is
-            if (intent.getPriority() <= 0) {
-                return;
-            }
-
-            final ActivityInfo activityInfo = intent.activity.info;
-            final ApplicationInfo applicationInfo = activityInfo.applicationInfo;
-
-            final boolean privilegedApp =
-                    ((applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0);
-            if (!privilegedApp) {
-                // non-privileged applications can never define a priority >0
-                if (DEBUG_FILTERS) {
-                    Slog.i(TAG, "Non-privileged app; cap priority to 0;"
-                            + " package: " + applicationInfo.packageName
-                            + " activity: " + intent.activity.className
-                            + " origPrio: " + intent.getPriority());
-                }
-                intent.setPriority(0);
-                return;
-            }
-
-            if (systemActivities == null) {
-                // the system package is not disabled; we're parsing the system partition
-                if (isProtectedAction(intent)) {
-                    if (mDeferProtectedFilters) {
-                        // We can't deal with these just yet. No component should ever obtain a
-                        // >0 priority for a protected actions, with ONE exception -- the setup
-                        // wizard. The setup wizard, however, cannot be known until we're able to
-                        // query it for the category CATEGORY_SETUP_WIZARD. Which we can't do
-                        // until all intent filters have been processed. Chicken, meet egg.
-                        // Let the filter temporarily have a high priority and rectify the
-                        // priorities after all system packages have been scanned.
-                        mProtectedFilters.add(intent);
-                        if (DEBUG_FILTERS) {
-                            Slog.i(TAG, "Protected action; save for later;"
-                                    + " package: " + applicationInfo.packageName
-                                    + " activity: " + intent.activity.className
-                                    + " origPrio: " + intent.getPriority());
-                        }
-                        return;
-                    } else {
-                        if (DEBUG_FILTERS && mSetupWizardPackage == null) {
-                            Slog.i(TAG, "No setup wizard;"
-                                + " All protected intents capped to priority 0");
-                        }
-                        if (intent.activity.info.packageName.equals(mSetupWizardPackage)) {
-                            if (DEBUG_FILTERS) {
-                                Slog.i(TAG, "Found setup wizard;"
-                                    + " allow priority " + intent.getPriority() + ";"
-                                    + " package: " + intent.activity.info.packageName
-                                    + " activity: " + intent.activity.className
-                                    + " priority: " + intent.getPriority());
-                            }
-                            // setup wizard gets whatever it wants
-                            return;
-                        }
-                        if (DEBUG_FILTERS) {
-                            Slog.i(TAG, "Protected action; cap priority to 0;"
-                                    + " package: " + intent.activity.info.packageName
-                                    + " activity: " + intent.activity.className
-                                    + " origPrio: " + intent.getPriority());
-                        }
-                        intent.setPriority(0);
-                        return;
-                    }
-                }
-                // privileged apps on the system image get whatever priority they request
-                return;
-            }
-
-            // privileged app unbundled update ... try to find the same activity
-            final PackageParser.Activity foundActivity =
-                    findMatchingActivity(systemActivities, activityInfo);
-            if (foundActivity == null) {
-                // this is a new activity; it cannot obtain >0 priority
-                if (DEBUG_FILTERS) {
-                    Slog.i(TAG, "New activity; cap priority to 0;"
-                            + " package: " + applicationInfo.packageName
-                            + " activity: " + intent.activity.className
-                            + " origPrio: " + intent.getPriority());
-                }
-                intent.setPriority(0);
-                return;
-            }
-
-            // found activity, now check for filter equivalence
-
-            // a shallow copy is enough; we modify the list, not its contents
-            final List<ActivityIntentInfo> intentListCopy =
-                    new ArrayList<>(foundActivity.intents);
-            final List<ActivityIntentInfo> foundFilters = findFilters(intent);
-
-            // find matching action subsets
-            final Iterator<String> actionsIterator = intent.actionsIterator();
-            if (actionsIterator != null) {
-                getIntentListSubset(
-                        intentListCopy, new ActionIterGenerator(), actionsIterator);
-                if (intentListCopy.size() == 0) {
-                    // no more intents to match; we're not equivalent
-                    if (DEBUG_FILTERS) {
-                        Slog.i(TAG, "Mismatched action; cap priority to 0;"
-                                + " package: " + applicationInfo.packageName
-                                + " activity: " + intent.activity.className
-                                + " origPrio: " + intent.getPriority());
-                    }
-                    intent.setPriority(0);
-                    return;
-                }
-            }
-
-            // find matching category subsets
-            final Iterator<String> categoriesIterator = intent.categoriesIterator();
-            if (categoriesIterator != null) {
-                getIntentListSubset(intentListCopy, new CategoriesIterGenerator(),
-                        categoriesIterator);
-                if (intentListCopy.size() == 0) {
-                    // no more intents to match; we're not equivalent
-                    if (DEBUG_FILTERS) {
-                        Slog.i(TAG, "Mismatched category; cap priority to 0;"
-                                + " package: " + applicationInfo.packageName
-                                + " activity: " + intent.activity.className
-                                + " origPrio: " + intent.getPriority());
-                    }
-                    intent.setPriority(0);
-                    return;
-                }
-            }
-
-            // find matching schemes subsets
-            final Iterator<String> schemesIterator = intent.schemesIterator();
-            if (schemesIterator != null) {
-                getIntentListSubset(intentListCopy, new SchemesIterGenerator(),
-                        schemesIterator);
-                if (intentListCopy.size() == 0) {
-                    // no more intents to match; we're not equivalent
-                    if (DEBUG_FILTERS) {
-                        Slog.i(TAG, "Mismatched scheme; cap priority to 0;"
-                                + " package: " + applicationInfo.packageName
-                                + " activity: " + intent.activity.className
-                                + " origPrio: " + intent.getPriority());
-                    }
-                    intent.setPriority(0);
-                    return;
-                }
-            }
-
-            // find matching authorities subsets
-            final Iterator<IntentFilter.AuthorityEntry>
-                    authoritiesIterator = intent.authoritiesIterator();
-            if (authoritiesIterator != null) {
-                getIntentListSubset(intentListCopy,
-                        new AuthoritiesIterGenerator(),
-                        authoritiesIterator);
-                if (intentListCopy.size() == 0) {
-                    // no more intents to match; we're not equivalent
-                    if (DEBUG_FILTERS) {
-                        Slog.i(TAG, "Mismatched authority; cap priority to 0;"
-                                + " package: " + applicationInfo.packageName
-                                + " activity: " + intent.activity.className
-                                + " origPrio: " + intent.getPriority());
-                    }
-                    intent.setPriority(0);
-                    return;
-                }
-            }
-
-            // we found matching filter(s); app gets the max priority of all intents
-            int cappedPriority = 0;
-            for (int i = intentListCopy.size() - 1; i >= 0; --i) {
-                cappedPriority = Math.max(cappedPriority, intentListCopy.get(i).getPriority());
-            }
-            if (intent.getPriority() > cappedPriority) {
-                if (DEBUG_FILTERS) {
-                    Slog.i(TAG, "Found matching filter(s);"
-                            + " cap priority to " + cappedPriority + ";"
-                            + " package: " + applicationInfo.packageName
-                            + " activity: " + intent.activity.className
-                            + " origPrio: " + intent.getPriority());
-                }
-                intent.setPriority(cappedPriority);
-                return;
-            }
-            // all this for nothing; the requested priority was <= what was on the system
-        }
-
-        public final void addActivity(PackageParser.Activity a, String type) {
-            mActivities.put(a.getComponentName(), a);
-            if (DEBUG_SHOW_INFO)
-                Log.v(
-                TAG, "  " + type + " " +
-                (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel : a.info.name) + ":");
-            if (DEBUG_SHOW_INFO)
-                Log.v(TAG, "    Class=" + a.info.name);
-            final int NI = a.intents.size();
-            for (int j=0; j<NI; j++) {
-                PackageParser.ActivityIntentInfo intent = a.intents.get(j);
-                if ("activity".equals(type)) {
-                    final PackageSetting ps =
-                            mSettings.getDisabledSystemPkgLPr(intent.activity.info.packageName);
-                    final List<PackageParser.Activity> systemActivities =
-                            ps != null && ps.pkg != null ? ps.pkg.activities : null;
-                    adjustPriority(systemActivities, intent);
-                }
-                if (DEBUG_SHOW_INFO) {
-                    Log.v(TAG, "    IntentFilter:");
-                    intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
-                }
-                if (!intent.debugCheck()) {
-                    Log.w(TAG, "==> For Activity " + a.info.name);
-                }
-                addFilter(intent);
-            }
-        }
-
-        public final void removeActivity(PackageParser.Activity a, String type) {
-            mActivities.remove(a.getComponentName());
-            if (DEBUG_SHOW_INFO) {
-                Log.v(TAG, "  " + type + " "
-                        + (a.info.nonLocalizedLabel != null ? a.info.nonLocalizedLabel
-                                : a.info.name) + ":");
-                Log.v(TAG, "    Class=" + a.info.name);
-            }
-            final int NI = a.intents.size();
-            for (int j=0; j<NI; j++) {
-                PackageParser.ActivityIntentInfo intent = a.intents.get(j);
-                if (DEBUG_SHOW_INFO) {
-                    Log.v(TAG, "    IntentFilter:");
-                    intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
-                }
-                removeFilter(intent);
-            }
-        }
-
-        @Override
-        protected boolean allowFilterResult(
-                PackageParser.ActivityIntentInfo filter, List<ResolveInfo> dest) {
-            ActivityInfo filterAi = filter.activity.info;
-            for (int i=dest.size()-1; i>=0; i--) {
-                ActivityInfo destAi = dest.get(i).activityInfo;
-                if (destAi.name == filterAi.name
-                        && destAi.packageName == filterAi.packageName) {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        @Override
-        protected ActivityIntentInfo[] newArray(int size) {
-            return new ActivityIntentInfo[size];
-        }
-
-        @Override
-        protected boolean isFilterStopped(PackageParser.ActivityIntentInfo filter, int userId) {
-            if (!sUserManager.exists(userId)) return true;
-            PackageParser.Package p = filter.activity.owner;
-            if (p != null) {
-                PackageSetting ps = (PackageSetting)p.mExtras;
-                if (ps != null) {
-                    // System apps are never considered stopped for purposes of
-                    // filtering, because there may be no way for the user to
-                    // actually re-launch them.
-                    return (ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) == 0
-                            && ps.getStopped(userId);
-                }
-            }
-            return false;
-        }
-
-        @Override
-        protected boolean isPackageForFilter(String packageName,
-                PackageParser.ActivityIntentInfo info) {
-            return packageName.equals(info.activity.owner.packageName);
-        }
-
-        @Override
-        protected ResolveInfo newResult(PackageParser.ActivityIntentInfo info,
-                int match, int userId) {
-            if (!sUserManager.exists(userId)) return null;
-            if (!mSettings.isEnabledAndMatchLPr(info.activity.info, mFlags, userId)) {
-                return null;
-            }
-            final PackageParser.Activity activity = info.activity;
-            PackageSetting ps = (PackageSetting) activity.owner.mExtras;
-            if (ps == null) {
-                return null;
-            }
-            final PackageUserState userState = ps.readUserState(userId);
-            ActivityInfo ai =
-                    PackageParser.generateActivityInfo(activity, mFlags, userState, userId);
-            if (ai == null) {
-                return null;
-            }
-            final boolean matchExplicitlyVisibleOnly =
-                    (mFlags & PackageManager.MATCH_EXPLICITLY_VISIBLE_ONLY) != 0;
-            final boolean matchVisibleToInstantApp =
-                    (mFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
-            final boolean componentVisible =
-                    matchVisibleToInstantApp
-                    && info.isVisibleToInstantApp()
-                    && (!matchExplicitlyVisibleOnly || info.isExplicitlyVisibleToInstantApp());
-            final boolean matchInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0;
-            // throw out filters that aren't visible to ephemeral apps
-            if (matchVisibleToInstantApp && !(componentVisible || userState.instantApp)) {
-                return null;
-            }
-            // throw out instant app filters if we're not explicitly requesting them
-            if (!matchInstantApp && userState.instantApp) {
-                return null;
-            }
-            // throw out instant app filters if updates are available; will trigger
-            // instant app resolution
-            if (userState.instantApp && ps.isUpdateAvailable()) {
-                return null;
-            }
-            final ResolveInfo res = new ResolveInfo();
-            res.activityInfo = ai;
-            if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
-                res.filter = info;
-            }
-            res.handleAllWebDataURI = info.handleAllWebDataURI();
-            res.priority = info.getPriority();
-            res.preferredOrder = activity.owner.mPreferredOrder;
-            //System.out.println("Result: " + res.activityInfo.className +
-            //                   " = " + res.priority);
-            res.match = match;
-            res.isDefault = info.hasDefault;
-            res.labelRes = info.labelRes;
-            res.nonLocalizedLabel = info.nonLocalizedLabel;
-            if (userNeedsBadging(userId)) {
-                res.noResourceId = true;
-            } else {
-                res.icon = info.icon;
-            }
-            res.iconResourceId = info.icon;
-            res.system = res.activityInfo.applicationInfo.isSystemApp();
-            res.isInstantAppAvailable = userState.instantApp;
-            return res;
-        }
-
-        @Override
-        protected void sortResults(List<ResolveInfo> results) {
-            results.sort(mResolvePrioritySorter);
-        }
-
-        @Override
-        protected void dumpFilter(PrintWriter out, String prefix,
-                PackageParser.ActivityIntentInfo filter) {
-            out.print(prefix); out.print(
-                    Integer.toHexString(System.identityHashCode(filter.activity)));
-                    out.print(' ');
-                    filter.activity.printComponentShortName(out);
-                    out.print(" filter ");
-                    out.println(Integer.toHexString(System.identityHashCode(filter)));
-        }
-
-        @Override
-        protected Object filterToLabel(PackageParser.ActivityIntentInfo filter) {
-            return filter.activity;
-        }
-
-        protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int count) {
-            PackageParser.Activity activity = (PackageParser.Activity)label;
-            out.print(prefix); out.print(
-                    Integer.toHexString(System.identityHashCode(activity)));
-                    out.print(' ');
-                    activity.printComponentShortName(out);
-            if (count > 1) {
-                out.print(" ("); out.print(count); out.print(" filters)");
-            }
-            out.println();
-        }
-
-        // Keys are String (activity class name), values are Activity.
-        private final ArrayMap<ComponentName, PackageParser.Activity> mActivities
-                = new ArrayMap<>();
-        private int mFlags;
-    }
-
-    private final class ServiceIntentResolver
-            extends IntentResolver<PackageParser.ServiceIntentInfo, ResolveInfo> {
-        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
-                boolean defaultOnly, int userId) {
-            mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
-            return super.queryIntent(intent, resolvedType, defaultOnly, userId);
-        }
-
-        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
-                int userId) {
-            if (!sUserManager.exists(userId)) return null;
-            mFlags = flags;
-            return super.queryIntent(intent, resolvedType,
-                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
-                    userId);
-        }
-
-        public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
-                int flags, ArrayList<PackageParser.Service> packageServices, int userId) {
-            if (!sUserManager.exists(userId)) return null;
-            if (packageServices == null) {
-                return null;
-            }
-            mFlags = flags;
-            final boolean defaultOnly = (flags&PackageManager.MATCH_DEFAULT_ONLY) != 0;
-            final int N = packageServices.size();
-            ArrayList<PackageParser.ServiceIntentInfo[]> listCut = new ArrayList<>(N);
-
-            ArrayList<PackageParser.ServiceIntentInfo> intentFilters;
-            for (int i = 0; i < N; ++i) {
-                intentFilters = packageServices.get(i).intents;
-                if (intentFilters != null && intentFilters.size() > 0) {
-                    PackageParser.ServiceIntentInfo[] array =
-                            new PackageParser.ServiceIntentInfo[intentFilters.size()];
-                    intentFilters.toArray(array);
-                    listCut.add(array);
-                }
-            }
-            return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
-        }
-
-        public final void addService(PackageParser.Service s) {
-            mServices.put(s.getComponentName(), s);
-            if (DEBUG_SHOW_INFO) {
-                Log.v(TAG, "  "
-                        + (s.info.nonLocalizedLabel != null
-                        ? s.info.nonLocalizedLabel : s.info.name) + ":");
-                Log.v(TAG, "    Class=" + s.info.name);
-            }
-            final int NI = s.intents.size();
-            int j;
-            for (j=0; j<NI; j++) {
-                PackageParser.ServiceIntentInfo intent = s.intents.get(j);
-                if (DEBUG_SHOW_INFO) {
-                    Log.v(TAG, "    IntentFilter:");
-                    intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
-                }
-                if (!intent.debugCheck()) {
-                    Log.w(TAG, "==> For Service " + s.info.name);
-                }
-                addFilter(intent);
-            }
-        }
-
-        public final void removeService(PackageParser.Service s) {
-            mServices.remove(s.getComponentName());
-            if (DEBUG_SHOW_INFO) {
-                Log.v(TAG, "  " + (s.info.nonLocalizedLabel != null
-                        ? s.info.nonLocalizedLabel : s.info.name) + ":");
-                Log.v(TAG, "    Class=" + s.info.name);
-            }
-            final int NI = s.intents.size();
-            int j;
-            for (j=0; j<NI; j++) {
-                PackageParser.ServiceIntentInfo intent = s.intents.get(j);
-                if (DEBUG_SHOW_INFO) {
-                    Log.v(TAG, "    IntentFilter:");
-                    intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
-                }
-                removeFilter(intent);
-            }
-        }
-
-        @Override
-        protected boolean allowFilterResult(
-                PackageParser.ServiceIntentInfo filter, List<ResolveInfo> dest) {
-            ServiceInfo filterSi = filter.service.info;
-            for (int i=dest.size()-1; i>=0; i--) {
-                ServiceInfo destAi = dest.get(i).serviceInfo;
-                if (destAi.name == filterSi.name
-                        && destAi.packageName == filterSi.packageName) {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        @Override
-        protected PackageParser.ServiceIntentInfo[] newArray(int size) {
-            return new PackageParser.ServiceIntentInfo[size];
-        }
-
-        @Override
-        protected boolean isFilterStopped(PackageParser.ServiceIntentInfo filter, int userId) {
-            if (!sUserManager.exists(userId)) return true;
-            PackageParser.Package p = filter.service.owner;
-            if (p != null) {
-                PackageSetting ps = (PackageSetting)p.mExtras;
-                if (ps != null) {
-                    // System apps are never considered stopped for purposes of
-                    // filtering, because there may be no way for the user to
-                    // actually re-launch them.
-                    return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0
-                            && ps.getStopped(userId);
-                }
-            }
-            return false;
-        }
-
-        @Override
-        protected boolean isPackageForFilter(String packageName,
-                PackageParser.ServiceIntentInfo info) {
-            return packageName.equals(info.service.owner.packageName);
-        }
-
-        @Override
-        protected ResolveInfo newResult(PackageParser.ServiceIntentInfo filter,
-                int match, int userId) {
-            if (!sUserManager.exists(userId)) return null;
-            final PackageParser.ServiceIntentInfo info = (PackageParser.ServiceIntentInfo)filter;
-            if (!mSettings.isEnabledAndMatchLPr(info.service.info, mFlags, userId)) {
-                return null;
-            }
-            final PackageParser.Service service = info.service;
-            PackageSetting ps = (PackageSetting) service.owner.mExtras;
-            if (ps == null) {
-                return null;
-            }
-            final PackageUserState userState = ps.readUserState(userId);
-            ServiceInfo si = PackageParser.generateServiceInfo(service, mFlags,
-                    userState, userId);
-            if (si == null) {
-                return null;
-            }
-            final boolean matchVisibleToInstantApp =
-                    (mFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
-            final boolean isInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0;
-            // throw out filters that aren't visible to ephemeral apps
-            if (matchVisibleToInstantApp
-                    && !(info.isVisibleToInstantApp() || userState.instantApp)) {
-                return null;
-            }
-            // throw out ephemeral filters if we're not explicitly requesting them
-            if (!isInstantApp && userState.instantApp) {
-                return null;
-            }
-            // throw out instant app filters if updates are available; will trigger
-            // instant app resolution
-            if (userState.instantApp && ps.isUpdateAvailable()) {
-                return null;
-            }
-            final ResolveInfo res = new ResolveInfo();
-            res.serviceInfo = si;
-            if ((mFlags&PackageManager.GET_RESOLVED_FILTER) != 0) {
-                res.filter = filter;
-            }
-            res.priority = info.getPriority();
-            res.preferredOrder = service.owner.mPreferredOrder;
-            res.match = match;
-            res.isDefault = info.hasDefault;
-            res.labelRes = info.labelRes;
-            res.nonLocalizedLabel = info.nonLocalizedLabel;
-            res.icon = info.icon;
-            res.system = res.serviceInfo.applicationInfo.isSystemApp();
-            return res;
-        }
-
-        @Override
-        protected void sortResults(List<ResolveInfo> results) {
-            results.sort(mResolvePrioritySorter);
-        }
-
-        @Override
-        protected void dumpFilter(PrintWriter out, String prefix,
-                PackageParser.ServiceIntentInfo filter) {
-            out.print(prefix); out.print(
-                    Integer.toHexString(System.identityHashCode(filter.service)));
-                    out.print(' ');
-                    filter.service.printComponentShortName(out);
-                    out.print(" filter ");
-                    out.print(Integer.toHexString(System.identityHashCode(filter)));
-                    if (filter.service.info.permission != null) {
-                        out.print(" permission "); out.println(filter.service.info.permission);
-                    } else {
-                        out.println();
-                    }
-        }
-
-        @Override
-        protected Object filterToLabel(PackageParser.ServiceIntentInfo filter) {
-            return filter.service;
-        }
-
-        protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int count) {
-            PackageParser.Service service = (PackageParser.Service)label;
-            out.print(prefix); out.print(
-                    Integer.toHexString(System.identityHashCode(service)));
-                    out.print(' ');
-                    service.printComponentShortName(out);
-            if (count > 1) {
-                out.print(" ("); out.print(count); out.print(" filters)");
-            }
-            out.println();
-        }
-
-//        List<ResolveInfo> filterEnabled(List<ResolveInfo> resolveInfoList) {
-//            final Iterator<ResolveInfo> i = resolveInfoList.iterator();
-//            final List<ResolveInfo> retList = Lists.newArrayList();
-//            while (i.hasNext()) {
-//                final ResolveInfo resolveInfo = (ResolveInfo) i;
-//                if (isEnabledLP(resolveInfo.serviceInfo)) {
-//                    retList.add(resolveInfo);
-//                }
-//            }
-//            return retList;
-//        }
-
-        // Keys are String (activity class name), values are Activity.
-        private final ArrayMap<ComponentName, PackageParser.Service> mServices = new ArrayMap<>();
-        private int mFlags;
-    }
-
-    private final class ProviderIntentResolver
-            extends IntentResolver<PackageParser.ProviderIntentInfo, ResolveInfo> {
-        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType,
-                boolean defaultOnly, int userId) {
-            mFlags = defaultOnly ? PackageManager.MATCH_DEFAULT_ONLY : 0;
-            return super.queryIntent(intent, resolvedType, defaultOnly, userId);
-        }
-
-        public List<ResolveInfo> queryIntent(Intent intent, String resolvedType, int flags,
-                int userId) {
-            if (!sUserManager.exists(userId))
-                return null;
-            mFlags = flags;
-            return super.queryIntent(intent, resolvedType,
-                    (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0,
-                    userId);
-        }
-
-        public List<ResolveInfo> queryIntentForPackage(Intent intent, String resolvedType,
-                int flags, ArrayList<PackageParser.Provider> packageProviders, int userId) {
-            if (!sUserManager.exists(userId))
-                return null;
-            if (packageProviders == null) {
-                return null;
-            }
-            mFlags = flags;
-            final boolean defaultOnly = (flags & PackageManager.MATCH_DEFAULT_ONLY) != 0;
-            final int N = packageProviders.size();
-            ArrayList<PackageParser.ProviderIntentInfo[]> listCut = new ArrayList<>(N);
-
-            ArrayList<PackageParser.ProviderIntentInfo> intentFilters;
-            for (int i = 0; i < N; ++i) {
-                intentFilters = packageProviders.get(i).intents;
-                if (intentFilters != null && intentFilters.size() > 0) {
-                    PackageParser.ProviderIntentInfo[] array =
-                            new PackageParser.ProviderIntentInfo[intentFilters.size()];
-                    intentFilters.toArray(array);
-                    listCut.add(array);
-                }
-            }
-            return super.queryIntentFromList(intent, resolvedType, defaultOnly, listCut, userId);
-        }
-
-        public final void addProvider(PackageParser.Provider p) {
-            if (mProviders.containsKey(p.getComponentName())) {
-                Slog.w(TAG, "Provider " + p.getComponentName() + " already defined; ignoring");
-                return;
-            }
-
-            mProviders.put(p.getComponentName(), p);
-            if (DEBUG_SHOW_INFO) {
-                Log.v(TAG, "  "
-                        + (p.info.nonLocalizedLabel != null
-                                ? p.info.nonLocalizedLabel : p.info.name) + ":");
-                Log.v(TAG, "    Class=" + p.info.name);
-            }
-            final int NI = p.intents.size();
-            int j;
-            for (j = 0; j < NI; j++) {
-                PackageParser.ProviderIntentInfo intent = p.intents.get(j);
-                if (DEBUG_SHOW_INFO) {
-                    Log.v(TAG, "    IntentFilter:");
-                    intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
-                }
-                if (!intent.debugCheck()) {
-                    Log.w(TAG, "==> For Provider " + p.info.name);
-                }
-                addFilter(intent);
-            }
-        }
-
-        public final void removeProvider(PackageParser.Provider p) {
-            mProviders.remove(p.getComponentName());
-            if (DEBUG_SHOW_INFO) {
-                Log.v(TAG, "  " + (p.info.nonLocalizedLabel != null
-                        ? p.info.nonLocalizedLabel : p.info.name) + ":");
-                Log.v(TAG, "    Class=" + p.info.name);
-            }
-            final int NI = p.intents.size();
-            int j;
-            for (j = 0; j < NI; j++) {
-                PackageParser.ProviderIntentInfo intent = p.intents.get(j);
-                if (DEBUG_SHOW_INFO) {
-                    Log.v(TAG, "    IntentFilter:");
-                    intent.dump(new LogPrinter(Log.VERBOSE, TAG), "      ");
-                }
-                removeFilter(intent);
-            }
-        }
-
-        @Override
-        protected boolean allowFilterResult(
-                PackageParser.ProviderIntentInfo filter, List<ResolveInfo> dest) {
-            ProviderInfo filterPi = filter.provider.info;
-            for (int i = dest.size() - 1; i >= 0; i--) {
-                ProviderInfo destPi = dest.get(i).providerInfo;
-                if (destPi.name == filterPi.name
-                        && destPi.packageName == filterPi.packageName) {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        @Override
-        protected PackageParser.ProviderIntentInfo[] newArray(int size) {
-            return new PackageParser.ProviderIntentInfo[size];
-        }
-
-        @Override
-        protected boolean isFilterStopped(PackageParser.ProviderIntentInfo filter, int userId) {
-            if (!sUserManager.exists(userId))
-                return true;
-            PackageParser.Package p = filter.provider.owner;
-            if (p != null) {
-                PackageSetting ps = (PackageSetting) p.mExtras;
-                if (ps != null) {
-                    // System apps are never considered stopped for purposes of
-                    // filtering, because there may be no way for the user to
-                    // actually re-launch them.
-                    return (ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0
-                            && ps.getStopped(userId);
-                }
-            }
-            return false;
-        }
-
-        @Override
-        protected boolean isPackageForFilter(String packageName,
-                PackageParser.ProviderIntentInfo info) {
-            return packageName.equals(info.provider.owner.packageName);
-        }
-
-        @Override
-        protected ResolveInfo newResult(PackageParser.ProviderIntentInfo filter,
-                int match, int userId) {
-            if (!sUserManager.exists(userId))
-                return null;
-            final PackageParser.ProviderIntentInfo info = filter;
-            if (!mSettings.isEnabledAndMatchLPr(info.provider.info, mFlags, userId)) {
-                return null;
-            }
-            final PackageParser.Provider provider = info.provider;
-            PackageSetting ps = (PackageSetting) provider.owner.mExtras;
-            if (ps == null) {
-                return null;
-            }
-            final PackageUserState userState = ps.readUserState(userId);
-            final boolean matchVisibleToInstantApp =
-                    (mFlags & PackageManager.MATCH_VISIBLE_TO_INSTANT_APP_ONLY) != 0;
-            final boolean isInstantApp = (mFlags & PackageManager.MATCH_INSTANT) != 0;
-            // throw out filters that aren't visible to instant applications
-            if (matchVisibleToInstantApp
-                    && !(info.isVisibleToInstantApp() || userState.instantApp)) {
-                return null;
-            }
-            // throw out instant application filters if we're not explicitly requesting them
-            if (!isInstantApp && userState.instantApp) {
-                return null;
-            }
-            // throw out instant application filters if updates are available; will trigger
-            // instant application resolution
-            if (userState.instantApp && ps.isUpdateAvailable()) {
-                return null;
-            }
-            ProviderInfo pi = PackageParser.generateProviderInfo(provider, mFlags,
-                    userState, userId);
-            if (pi == null) {
-                return null;
-            }
-            final ResolveInfo res = new ResolveInfo();
-            res.providerInfo = pi;
-            if ((mFlags & PackageManager.GET_RESOLVED_FILTER) != 0) {
-                res.filter = filter;
-            }
-            res.priority = info.getPriority();
-            res.preferredOrder = provider.owner.mPreferredOrder;
-            res.match = match;
-            res.isDefault = info.hasDefault;
-            res.labelRes = info.labelRes;
-            res.nonLocalizedLabel = info.nonLocalizedLabel;
-            res.icon = info.icon;
-            res.system = res.providerInfo.applicationInfo.isSystemApp();
-            return res;
-        }
-
-        @Override
-        protected void sortResults(List<ResolveInfo> results) {
-            results.sort(mResolvePrioritySorter);
-        }
-
-        @Override
-        protected void dumpFilter(PrintWriter out, String prefix,
-                PackageParser.ProviderIntentInfo filter) {
-            out.print(prefix);
-            out.print(
-                    Integer.toHexString(System.identityHashCode(filter.provider)));
-            out.print(' ');
-            filter.provider.printComponentShortName(out);
-            out.print(" filter ");
-            out.println(Integer.toHexString(System.identityHashCode(filter)));
-        }
-
-        @Override
-        protected Object filterToLabel(PackageParser.ProviderIntentInfo filter) {
-            return filter.provider;
-        }
-
-        protected void dumpFilterLabel(PrintWriter out, String prefix, Object label, int count) {
-            PackageParser.Provider provider = (PackageParser.Provider)label;
-            out.print(prefix); out.print(
-                    Integer.toHexString(System.identityHashCode(provider)));
-                    out.print(' ');
-                    provider.printComponentShortName(out);
-            if (count > 1) {
-                out.print(" ("); out.print(count); out.print(" filters)");
-            }
-            out.println();
-        }
-
-        private final ArrayMap<ComponentName, PackageParser.Provider> mProviders
-                = new ArrayMap<>();
-        private int mFlags;
-    }
-
-    static final class InstantAppIntentResolver
-            extends IntentResolver<AuxiliaryResolveInfo.AuxiliaryFilter,
-            AuxiliaryResolveInfo.AuxiliaryFilter> {
-        /**
-         * The result that has the highest defined order. Ordering applies on a
-         * per-package basis. Mapping is from package name to Pair of order and
-         * EphemeralResolveInfo.
-         * <p>
-         * NOTE: This is implemented as a field variable for convenience and efficiency.
-         * By having a field variable, we're able to track filter ordering as soon as
-         * a non-zero order is defined. Otherwise, multiple loops across the result set
-         * would be needed to apply ordering. If the intent resolver becomes re-entrant,
-         * this needs to be contained entirely within {@link #filterResults}.
-         */
-        final ArrayMap<String, Pair<Integer, InstantAppResolveInfo>> mOrderResult = new ArrayMap<>();
-
-        @Override
-        protected AuxiliaryResolveInfo.AuxiliaryFilter[] newArray(int size) {
-            return new AuxiliaryResolveInfo.AuxiliaryFilter[size];
-        }
-
-        @Override
-        protected boolean isPackageForFilter(String packageName,
-                AuxiliaryResolveInfo.AuxiliaryFilter responseObj) {
-            return true;
-        }
-
-        @Override
-        protected AuxiliaryResolveInfo.AuxiliaryFilter newResult(
-                AuxiliaryResolveInfo.AuxiliaryFilter responseObj, int match, int userId) {
-            if (!sUserManager.exists(userId)) {
-                return null;
-            }
-            final String packageName = responseObj.resolveInfo.getPackageName();
-            final Integer order = responseObj.getOrder();
-            final Pair<Integer, InstantAppResolveInfo> lastOrderResult =
-                    mOrderResult.get(packageName);
-            // ordering is enabled and this item's order isn't high enough
-            if (lastOrderResult != null && lastOrderResult.first >= order) {
-                return null;
-            }
-            final InstantAppResolveInfo res = responseObj.resolveInfo;
-            if (order > 0) {
-                // non-zero order, enable ordering
-                mOrderResult.put(packageName, new Pair<>(order, res));
-            }
-            return responseObj;
-        }
-
-        @Override
-        protected void filterResults(List<AuxiliaryResolveInfo.AuxiliaryFilter> results) {
-            // only do work if ordering is enabled [most of the time it won't be]
-            if (mOrderResult.size() == 0) {
-                return;
-            }
-            int resultSize = results.size();
-            for (int i = 0; i < resultSize; i++) {
-                final InstantAppResolveInfo info = results.get(i).resolveInfo;
-                final String packageName = info.getPackageName();
-                final Pair<Integer, InstantAppResolveInfo> savedInfo = mOrderResult.get(packageName);
-                if (savedInfo == null) {
-                    // package doesn't having ordering
-                    continue;
-                }
-                if (savedInfo.second == info) {
-                    // circled back to the highest ordered item; remove from order list
-                    mOrderResult.remove(packageName);
-                    if (mOrderResult.size() == 0) {
-                        // no more ordered items
-                        break;
-                    }
-                    continue;
-                }
-                // item has a worse order, remove it from the result list
-                results.remove(i);
-                resultSize--;
-                i--;
-            }
-        }
-    }
-
-    private static final Comparator<ResolveInfo> mResolvePrioritySorter = (r1, r2) -> {
-        int v1 = r1.priority;
-        int v2 = r2.priority;
-        //System.out.println("Comparing: q1=" + q1 + " q2=" + q2);
-        if (v1 != v2) {
-            return (v1 > v2) ? -1 : 1;
-        }
-        v1 = r1.preferredOrder;
-        v2 = r2.preferredOrder;
-        if (v1 != v2) {
-            return (v1 > v2) ? -1 : 1;
-        }
-        if (r1.isDefault != r2.isDefault) {
-            return r1.isDefault ? -1 : 1;
-        }
-        v1 = r1.match;
-        v2 = r2.match;
-        //System.out.println("Comparing: m1=" + m1 + " m2=" + m2);
-        if (v1 != v2) {
-            return (v1 > v2) ? -1 : 1;
-        }
-        if (r1.system != r2.system) {
-            return r1.system ? -1 : 1;
-        }
-        if (r1.activityInfo != null) {
-            return r1.activityInfo.packageName.compareTo(r2.activityInfo.packageName);
-        }
-        if (r1.serviceInfo != null) {
-            return r1.serviceInfo.packageName.compareTo(r2.serviceInfo.packageName);
-        }
-        if (r1.providerInfo != null) {
-            return r1.providerInfo.packageName.compareTo(r2.providerInfo.packageName);
-        }
-        return 0;
-    };
-
-    private static final Comparator<ProviderInfo> mProviderInitOrderSorter = (p1, p2) -> {
-        final int v1 = p1.initOrder;
-        final int v2 = p2.initOrder;
-        return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
-    };
-
     @Override
     public void sendPackageBroadcast(final String action, final String pkg, final Bundle extras,
             final int flags, final String targetPkg, final IIntentReceiver finishedReceiver,
@@ -13716,6 +12323,12 @@
         }
     }
 
+    private static final Comparator<ProviderInfo> sProviderInitOrderSorter = (p1, p2) -> {
+        final int v1 = p1.initOrder;
+        final int v2 = p2.initOrder;
+        return (v1 > v2) ? -1 : ((v1 < v2) ? 1 : 0);
+    };
+
     @Override
     public void notifyPackageRemoved(String packageName) {
         final PackageListObserver[] observers;
@@ -14169,11 +12782,12 @@
         info.sendPackageRemovedBroadcasts(true /*killApp*/);
     }
 
-    private void sendPackagesSuspendedForUser(String[] pkgList, int userId, boolean suspended,
-            PersistableBundle launcherExtras) {
+    private void sendPackagesSuspendedForUser(String[] pkgList, int[] uidList, int userId,
+            boolean suspended, PersistableBundle launcherExtras) {
         if (pkgList.length > 0) {
             Bundle extras = new Bundle(1);
             extras.putStringArray(Intent.EXTRA_CHANGED_PACKAGE_LIST, pkgList);
+            extras.putIntArray(Intent.EXTRA_CHANGED_UID_LIST, uidList);
             if (launcherExtras != null) {
                 extras.putBundle(Intent.EXTRA_LAUNCHER_EXTRAS,
                         new Bundle(launcherExtras.deepCopy()));
@@ -14355,6 +12969,7 @@
         }
 
         final List<String> changedPackagesList = new ArrayList<>(packageNames.length);
+        final IntArray changedUids = new IntArray(packageNames.length);
         final List<String> unactionedPackages = new ArrayList<>(packageNames.length);
         final long callingId = Binder.clearCallingIdentity();
         try {
@@ -14382,6 +12997,7 @@
                     pkgSetting.setSuspended(suspended, callingPackage, dialogMessage, appExtras,
                             launcherExtras, userId);
                     changedPackagesList.add(packageName);
+                    changedUids.add(UserHandle.getUid(userId, pkgSetting.appId));
                 }
             }
         } finally {
@@ -14390,7 +13006,8 @@
         if (!changedPackagesList.isEmpty()) {
             final String[] changedPackages = changedPackagesList.toArray(
                     new String[changedPackagesList.size()]);
-            sendPackagesSuspendedForUser(changedPackages, userId, suspended, launcherExtras);
+            sendPackagesSuspendedForUser(
+                    changedPackages, changedUids.toArray(), userId, suspended, launcherExtras);
             sendMyPackageSuspendedOrUnsuspended(changedPackages, suspended, appExtras, userId);
             synchronized (mPackages) {
                 scheduleWritePackageRestrictionsLocked(userId);
@@ -14505,12 +13122,14 @@
 
     private void unsuspendForSuspendingPackages(Predicate<String> packagePredicate, int userId) {
         final List<String> affectedPackages = new ArrayList<>();
+        final IntArray affectedUids = new IntArray();
         synchronized (mPackages) {
             for (PackageSetting ps : mSettings.mPackages.values()) {
                 final PackageUserState pus = ps.readUserState(userId);
                 if (pus.suspended && packagePredicate.test(pus.suspendingPackage)) {
                     ps.setSuspended(false, null, null, null, null, userId);
                     affectedPackages.add(ps.name);
+                    affectedUids.add(UserHandle.getUid(userId, ps.getAppId()));
                 }
             }
         }
@@ -14518,7 +13137,8 @@
             final String[] packageArray = affectedPackages.toArray(
                     new String[affectedPackages.size()]);
             sendMyPackageSuspendedOrUnsuspended(packageArray, false, null, userId);
-            sendPackagesSuspendedForUser(packageArray, userId, false, null);
+            sendPackagesSuspendedForUser(
+                    packageArray, affectedUids.toArray(), userId, false, null);
             // Write package restrictions immediately to avoid an inconsistent state.
             mSettings.writePackageRestrictionsLPr(userId);
         }
@@ -16667,13 +15287,16 @@
             final boolean oem = isOemApp(oldPackage);
             final boolean vendor = isVendorApp(oldPackage);
             final boolean product = isProductApp(oldPackage);
+            final boolean productServices = isProductServicesApp(oldPackage);
+
             final @ParseFlags int systemParseFlags = parseFlags;
             final @ScanFlags int systemScanFlags = scanFlags
                     | SCAN_AS_SYSTEM
                     | (privileged ? SCAN_AS_PRIVILEGED : 0)
                     | (oem ? SCAN_AS_OEM : 0)
                     | (vendor ? SCAN_AS_VENDOR : 0)
-                    | (product ? SCAN_AS_PRODUCT : 0);
+                    | (product ? SCAN_AS_PRODUCT : 0)
+                    | (productServices ? SCAN_AS_PRODUCT_SERVICES : 0);
 
             replaceSystemPackageLIF(oldPackage, pkg, systemParseFlags, systemScanFlags,
                     user, allUsers, installerPackageName, res, installReason);
@@ -17982,6 +16605,11 @@
         return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
     }
 
+    private static boolean isProductServicesApp(PackageParser.Package pkg) {
+        return (pkg.applicationInfo.privateFlags
+                & ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES) != 0;
+    }
+
     private static boolean hasDomainURLs(PackageParser.Package pkg) {
         return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) != 0;
     }
@@ -18721,10 +17349,13 @@
             final File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app");
             final File privilegedOdmAppDir = new File(Environment.getOdmDirectory(), "priv-app");
             final File privilegedProductAppDir = new File(Environment.getProductDirectory(), "priv-app");
+            final File privilegedProductServicesAppDir =
+                    new File(Environment.getProductServicesDirectory(), "priv-app");
             return path.startsWith(privilegedAppDir.getCanonicalPath())
                     || path.startsWith(privilegedVendorAppDir.getCanonicalPath())
                     || path.startsWith(privilegedOdmAppDir.getCanonicalPath())
-                    || path.startsWith(privilegedProductAppDir.getCanonicalPath());
+                    || path.startsWith(privilegedProductAppDir.getCanonicalPath())
+                    || path.startsWith(privilegedProductServicesAppDir.getCanonicalPath());
         } catch (IOException e) {
             Slog.e(TAG, "Unable to access code path " + path);
         }
@@ -18759,6 +17390,15 @@
         return false;
     }
 
+    static boolean locationIsProductServices(String path) {
+        try {
+            return path.startsWith(Environment.getProductServicesDirectory().getCanonicalPath());
+        } catch (IOException e) {
+            Slog.e(TAG, "Unable to access code path " + path);
+        }
+        return false;
+    }
+
     /*
      * Tries to delete system package.
      */
@@ -18886,6 +17526,9 @@
         if (locationIsProduct(codePathString)) {
             scanFlags |= SCAN_AS_PRODUCT;
         }
+        if (locationIsProductServices(codePathString)) {
+            scanFlags |= SCAN_AS_PRODUCT_SERVICES;
+        }
 
         final File codePath = new File(codePathString);
         final PackageParser.Package pkg =
@@ -20078,7 +18721,7 @@
         try {
             synchronized (mPackages) {
                 clearPackagePreferredActivitiesLPw(null, userId);
-                mSettings.applyDefaultPreferredAppsLPw(this, userId);
+                mSettings.applyDefaultPreferredAppsLPw(userId);
                 // TODO: We have to reset the default SMS and Phone. This requires
                 // significant refactoring to keep all default apps in the package
                 // manager (cleaner but more work) or have the services provide
@@ -21319,7 +19962,7 @@
                 PreferredIntentResolver pir = mSettings.mPreferredActivities.valueAt(i);
                 removed.clear();
                 for (PreferredActivity pa : pir.filterSet()) {
-                    if (mActivities.mActivities.get(pa.mPref.mComponent) == null) {
+                    if (!mComponentResolver.isActivityDefined(pa.mPref.mComponent)) {
                         removed.add(pa);
                     }
                 }
@@ -21462,6 +20105,7 @@
                 this, in, out, err, args, callback, resultReceiver);
     }
 
+    @SuppressWarnings("resource")
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         if (!DumpUtils.checkDumpAndUsageStatsPermission(mContext, TAG, pw)) return;
@@ -21792,32 +20436,16 @@
             }
 
             if (!checkin && dumpState.isDumping(DumpState.DUMP_ACTIVITY_RESOLVERS)) {
-                if (mActivities.dump(pw, dumpState.getTitlePrinted() ? "\nActivity Resolver Table:"
-                        : "Activity Resolver Table:", "  ", packageName,
-                        dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
-                    dumpState.setTitlePrinted(true);
-                }
+                mComponentResolver.dumpActivityResolvers(pw, dumpState, packageName);
             }
             if (!checkin && dumpState.isDumping(DumpState.DUMP_RECEIVER_RESOLVERS)) {
-                if (mReceivers.dump(pw, dumpState.getTitlePrinted() ? "\nReceiver Resolver Table:"
-                        : "Receiver Resolver Table:", "  ", packageName,
-                        dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
-                    dumpState.setTitlePrinted(true);
-                }
+                mComponentResolver.dumpReceiverResolvers(pw, dumpState, packageName);
             }
             if (!checkin && dumpState.isDumping(DumpState.DUMP_SERVICE_RESOLVERS)) {
-                if (mServices.dump(pw, dumpState.getTitlePrinted() ? "\nService Resolver Table:"
-                        : "Service Resolver Table:", "  ", packageName,
-                        dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
-                    dumpState.setTitlePrinted(true);
-                }
+                mComponentResolver.dumpServiceResolvers(pw, dumpState, packageName);
             }
             if (!checkin && dumpState.isDumping(DumpState.DUMP_CONTENT_RESOLVERS)) {
-                if (mProviders.dump(pw, dumpState.getTitlePrinted() ? "\nProvider Resolver Table:"
-                        : "Provider Resolver Table:", "  ", packageName,
-                        dumpState.isOptionEnabled(DumpState.OPTION_SHOW_FILTERS), true)) {
-                    dumpState.setTitlePrinted(true);
-                }
+                mComponentResolver.dumpProviderResolvers(pw, dumpState, packageName);
             }
 
             if (!checkin && dumpState.isDumping(DumpState.DUMP_PREFERRED)) {
@@ -21919,40 +20547,7 @@
             }
 
             if (!checkin && dumpState.isDumping(DumpState.DUMP_PROVIDERS)) {
-                boolean printedSomething = false;
-                for (PackageParser.Provider p : mProviders.mProviders.values()) {
-                    if (packageName != null && !packageName.equals(p.info.packageName)) {
-                        continue;
-                    }
-                    if (!printedSomething) {
-                        if (dumpState.onTitlePrinted())
-                            pw.println();
-                        pw.println("Registered ContentProviders:");
-                        printedSomething = true;
-                    }
-                    pw.print("  "); p.printComponentShortName(pw); pw.println(":");
-                    pw.print("    "); pw.println(p.toString());
-                }
-                printedSomething = false;
-                for (Map.Entry<String, PackageParser.Provider> entry :
-                        mProvidersByAuthority.entrySet()) {
-                    PackageParser.Provider p = entry.getValue();
-                    if (packageName != null && !packageName.equals(p.info.packageName)) {
-                        continue;
-                    }
-                    if (!printedSomething) {
-                        if (dumpState.onTitlePrinted())
-                            pw.println();
-                        pw.println("ContentProvider Authorities:");
-                        printedSomething = true;
-                    }
-                    pw.print("  ["); pw.print(entry.getKey()); pw.println("]:");
-                    pw.print("    "); pw.println(p.toString());
-                    if (p.info != null && p.info.applicationInfo != null) {
-                        final String appInfo = p.info.applicationInfo.toString();
-                        pw.print("      applicationInfo="); pw.println(appInfo);
-                    }
-                }
+                mComponentResolver.dumpContentProviders(pw, dumpState, packageName);
             }
 
             if (!checkin && dumpState.isDumping(DumpState.DUMP_KEYSETS)) {
@@ -22034,21 +20629,7 @@
 
             if (!checkin && dumpState.isDumping(DumpState.DUMP_SERVICE_PERMISSIONS)
                     && packageName == null) {
-                if (dumpState.onTitlePrinted()) pw.println();
-                pw.println("Service permissions:");
-
-                final Iterator<ServiceIntentInfo> filterIterator = mServices.filterIterator();
-                while (filterIterator.hasNext()) {
-                    final ServiceIntentInfo info = filterIterator.next();
-                    final ServiceInfo serviceInfo = info.service.info;
-                    final String permission = serviceInfo.permission;
-                    if (permission != null) {
-                        pw.print("    ");
-                        pw.print(serviceInfo.getComponentName().flattenToShortString());
-                        pw.print(": ");
-                        pw.println(permission);
-                    }
-                }
+                mComponentResolver.dumpServicePermissions(pw, dumpState, packageName);
             }
 
             if (!checkin && dumpState.isDumping(DumpState.DUMP_DEXOPT)) {
@@ -22179,6 +20760,7 @@
     }
 
     @GuardedBy("mPackages")
+    @SuppressWarnings("resource")
     private void dumpDexoptStateLPr(PrintWriter pw, String packageName) {
         final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
         ipw.println();
@@ -22207,6 +20789,7 @@
     }
 
     @GuardedBy("mPackages")
+    @SuppressWarnings("resource")
     private void dumpCompilerStatsLPr(PrintWriter pw, String packageName) {
         final IndentingPrintWriter ipw = new IndentingPrintWriter(pw, "  ");
         ipw.println();
@@ -24234,6 +22817,20 @@
         }
 
         @Override
+        public boolean isEnabledAndMatches(ComponentInfo info, int flags, int userId) {
+            synchronized (mPackages) {
+                return mSettings.isEnabledAndMatchLPr(info, flags, userId);
+            }
+        }
+
+        @Override
+        public boolean userNeedsBadging(int userId) {
+            synchronized (mPackages) {
+                return PackageManagerService.this.userNeedsBadging(userId);
+            }
+        }
+
+        @Override
         public void grantRuntimePermission(String packageName, String permName, int userId,
                 boolean overridePolicy) {
             PackageManagerService.this.mPermissionManager.grantRuntimePermission(
@@ -24432,7 +23029,7 @@
         public boolean canAccessComponent(int callingUid, ComponentName component, int userId) {
             synchronized (mPackages) {
                 final PackageSetting ps = mSettings.mPackages.get(component.getPackageName());
-                return !PackageManagerService.this.filterAppAccessLPr(
+                return ps != null && !PackageManagerService.this.filterAppAccessLPr(
                         ps, callingUid, component, TYPE_UNKNOWN, userId);
             }
         }
diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
index 3834a88..f2c0395 100644
--- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
+++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java
@@ -25,7 +25,6 @@
 import android.accounts.IAccountManager;
 import android.app.ActivityManager;
 import android.app.ActivityManagerInternal;
-import android.app.Application;
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.IIntentReceiver;
@@ -67,7 +66,6 @@
 import android.os.IUserManager;
 import android.os.ParcelFileDescriptor;
 import android.os.ParcelFileDescriptor.AutoCloseInputStream;
-import android.os.ParcelFileDescriptor.AutoCloseOutputStream;
 import android.os.PersistableBundle;
 import android.os.Process;
 import android.os.RemoteException;
@@ -84,11 +82,17 @@
 import android.text.format.DateUtils;
 import android.util.ArraySet;
 import android.util.PrintWriterPrinter;
+
 import com.android.internal.content.PackageHelper;
 import com.android.internal.util.ArrayUtils;
 import com.android.server.LocalServices;
 import com.android.server.SystemConfig;
+
 import dalvik.system.DexFile;
+
+import libcore.io.IoUtils;
+import libcore.io.Streams;
+
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
@@ -96,10 +100,6 @@
 import java.io.OutputStream;
 import java.io.PrintWriter;
 import java.net.URISyntaxException;
-import java.nio.file.Files;
-import java.nio.file.Paths;
-import java.nio.file.StandardCopyOption;
-import java.nio.file.attribute.FileAttribute;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
@@ -110,10 +110,7 @@
 import java.util.WeakHashMap;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.SynchronousQueue;
 import java.util.concurrent.TimeUnit;
-import libcore.io.IoUtils;
-import libcore.io.Streams;
 
 class PackageManagerShellCommand extends ShellCommand {
     /** Path for streaming APK content */
@@ -1777,6 +1774,15 @@
         }
     }
 
+    private boolean isProductServicesApp(String pkg) {
+        try {
+            final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM);
+            return info != null && info.applicationInfo.isProductServices();
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
     private int runGetPrivappPermissions() {
         final String pkg = getNextArg();
         if (pkg == null) {
@@ -1789,6 +1795,9 @@
             privAppPermissions = SystemConfig.getInstance().getVendorPrivAppPermissions(pkg);
         } else if (isProductApp(pkg)) {
             privAppPermissions = SystemConfig.getInstance().getProductPrivAppPermissions(pkg);
+        } else if (isProductServicesApp(pkg)) {
+            privAppPermissions = SystemConfig.getInstance()
+                    .getProductServicesPrivAppPermissions(pkg);
         } else {
             privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg);
         }
@@ -1810,6 +1819,9 @@
             privAppPermissions = SystemConfig.getInstance().getVendorPrivAppDenyPermissions(pkg);
         } else if (isProductApp(pkg)) {
             privAppPermissions = SystemConfig.getInstance().getProductPrivAppDenyPermissions(pkg);
+        } else if (isProductServicesApp(pkg)) {
+            privAppPermissions = SystemConfig.getInstance()
+                    .getProductServicesPrivAppDenyPermissions(pkg);
         } else {
             privAppPermissions = SystemConfig.getInstance().getPrivAppDenyPermissions(pkg);
         }
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index ea05b74..727fb15 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -148,6 +148,10 @@
         return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT) != 0;
     }
 
+    public boolean isProductServices() {
+        return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES) != 0;
+    }
+
     public boolean isForwardLocked() {
         return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0;
     }
diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java
index 7c92045..239dc99 100644
--- a/services/core/java/com/android/server/pm/SettingBase.java
+++ b/services/core/java/com/android/server/pm/SettingBase.java
@@ -63,6 +63,7 @@
                 | ApplicationInfo.PRIVATE_FLAG_OEM
                 | ApplicationInfo.PRIVATE_FLAG_VENDOR
                 | ApplicationInfo.PRIVATE_FLAG_PRODUCT
+                | ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES
                 | ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK
                 | ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER);
     }
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index e9cd707..8dd1a0f 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -44,6 +44,7 @@
 import android.content.pm.IntentFilterVerificationInfo;
 import android.content.pm.PackageCleanItem;
 import android.content.pm.PackageManager;
+import android.content.pm.PackageManagerInternal;
 import android.content.pm.PackageParser;
 import android.content.pm.PackageUserState;
 import android.content.pm.PermissionInfo;
@@ -88,6 +89,7 @@
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.JournaledFile;
 import com.android.internal.util.XmlUtils;
+import com.android.server.LocalServices;
 import com.android.server.pm.Installer.InstallerException;
 import com.android.server.pm.permission.BasePermission;
 import com.android.server.pm.permission.PermissionSettings;
@@ -422,11 +424,8 @@
     /** Settings and other information about permissions */
     final PermissionSettings mPermissions;
 
-    Settings(PermissionSettings permissions, Object lock) {
-        this(Environment.getDataDirectory(), permissions, lock);
-    }
-
-    Settings(File dataDir, PermissionSettings permission, Object lock) {
+    Settings(File dataDir, PermissionSettings permission,
+            Object lock) {
         mLock = lock;
         mPermissions = permission;
         mRuntimePermissionsPersistence = new RuntimePermissionPersistence(mLock);
@@ -850,7 +849,8 @@
         pkgSetting.pkgPrivateFlags &= ~(ApplicationInfo.PRIVATE_FLAG_PRIVILEGED
                 | ApplicationInfo.PRIVATE_FLAG_OEM
                 | ApplicationInfo.PRIVATE_FLAG_VENDOR
-                | ApplicationInfo.PRIVATE_FLAG_PRODUCT);
+                | ApplicationInfo.PRIVATE_FLAG_PRODUCT
+                | ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES);
         pkgSetting.pkgFlags |= pkgFlags & ApplicationInfo.FLAG_SYSTEM;
         pkgSetting.pkgPrivateFlags |=
                 pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
@@ -860,6 +860,8 @@
                 pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR;
         pkgSetting.pkgPrivateFlags |=
                 pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT;
+        pkgSetting.pkgPrivateFlags |=
+                pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES;
         pkgSetting.primaryCpuAbiString = primaryCpuAbi;
         pkgSetting.secondaryCpuAbiString = secondaryCpuAbi;
         if (childPkgNames != null) {
@@ -3232,8 +3234,10 @@
         return true;
     }
 
-    void applyDefaultPreferredAppsLPw(PackageManagerService service, int userId) {
+    void applyDefaultPreferredAppsLPw(int userId) {
         // First pull data from any pre-installed apps.
+        final PackageManagerInternal pmInternal =
+                LocalServices.getService(PackageManagerInternal.class);
         for (PackageSetting ps : mPackages.values()) {
             if ((ps.pkgFlags&ApplicationInfo.FLAG_SYSTEM) != 0 && ps.pkg != null
                     && ps.pkg.preferredActivityFilters != null) {
@@ -3241,8 +3245,8 @@
                         = ps.pkg.preferredActivityFilters;
                 for (int i=0; i<intents.size(); i++) {
                     PackageParser.ActivityIntentInfo aii = intents.get(i);
-                    applyDefaultPreferredActivityLPw(service, aii, new ComponentName(
-                            ps.name, aii.activity.className), userId);
+                    applyDefaultPreferredActivityLPw(pmInternal, aii, new ComponentName(
+                                    ps.name, aii.activity.className), userId);
                 }
             }
         }
@@ -3290,7 +3294,7 @@
                             + " does not start with 'preferred-activities'");
                     continue;
                 }
-                readDefaultPreferredActivitiesLPw(service, parser, userId);
+                readDefaultPreferredActivitiesLPw(parser, userId);
             } catch (XmlPullParserException e) {
                 Slog.w(TAG, "Error reading apps file " + f, e);
             } catch (IOException e) {
@@ -3306,8 +3310,8 @@
         }
     }
 
-    private void applyDefaultPreferredActivityLPw(PackageManagerService service,
-            IntentFilter tmpPa, ComponentName cn, int userId) {
+    private void applyDefaultPreferredActivityLPw(
+            PackageManagerInternal pmInternal, IntentFilter tmpPa, ComponentName cn, int userId) {
         // The initial preferences only specify the target activity
         // component and intent-filter, not the set of matches.  So we
         // now need to query for the matches to build the correct
@@ -3332,27 +3336,31 @@
         boolean doNonData = true;
         boolean hasSchemes = false;
 
-        for (int ischeme=0; ischeme<tmpPa.countDataSchemes(); ischeme++) {
+        final int dataSchemesCount = tmpPa.countDataSchemes();
+        for (int ischeme = 0; ischeme < dataSchemesCount; ischeme++) {
             boolean doScheme = true;
-            String scheme = tmpPa.getDataScheme(ischeme);
+            final String scheme = tmpPa.getDataScheme(ischeme);
             if (scheme != null && !scheme.isEmpty()) {
                 hasSchemes = true;
             }
-            for (int issp=0; issp<tmpPa.countDataSchemeSpecificParts(); issp++) {
+            final int dataSchemeSpecificPartsCount = tmpPa.countDataSchemeSpecificParts();
+            for (int issp = 0; issp < dataSchemeSpecificPartsCount; issp++) {
                 Uri.Builder builder = new Uri.Builder();
                 builder.scheme(scheme);
                 PatternMatcher ssp = tmpPa.getDataSchemeSpecificPart(issp);
                 builder.opaquePart(ssp.getPath());
                 Intent finalIntent = new Intent(intent);
                 finalIntent.setData(builder.build());
-                applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
+                applyDefaultPreferredActivityLPw(pmInternal, finalIntent, flags, cn,
                         scheme, ssp, null, null, userId);
                 doScheme = false;
             }
-            for (int iauth=0; iauth<tmpPa.countDataAuthorities(); iauth++) {
+            final int dataAuthoritiesCount = tmpPa.countDataAuthorities();
+            for (int iauth = 0; iauth < dataAuthoritiesCount; iauth++) {
                 boolean doAuth = true;
-                IntentFilter.AuthorityEntry auth = tmpPa.getDataAuthority(iauth);
-                for (int ipath=0; ipath<tmpPa.countDataPaths(); ipath++) {
+                final IntentFilter.AuthorityEntry auth = tmpPa.getDataAuthority(iauth);
+                final int dataPathsCount = tmpPa.countDataPaths();
+                for (int ipath = 0; ipath < dataPathsCount; ipath++) {
                     Uri.Builder builder = new Uri.Builder();
                     builder.scheme(scheme);
                     if (auth.getHost() != null) {
@@ -3362,7 +3370,7 @@
                     builder.path(path.getPath());
                     Intent finalIntent = new Intent(intent);
                     finalIntent.setData(builder.build());
-                    applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
+                    applyDefaultPreferredActivityLPw(pmInternal, finalIntent, flags, cn,
                             scheme, null, auth, path, userId);
                     doAuth = doScheme = false;
                 }
@@ -3374,7 +3382,7 @@
                     }
                     Intent finalIntent = new Intent(intent);
                     finalIntent.setData(builder.build());
-                    applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
+                    applyDefaultPreferredActivityLPw(pmInternal, finalIntent, flags, cn,
                             scheme, null, auth, null, userId);
                     doScheme = false;
                 }
@@ -3384,7 +3392,7 @@
                 builder.scheme(scheme);
                 Intent finalIntent = new Intent(intent);
                 finalIntent.setData(builder.build());
-                applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
+                applyDefaultPreferredActivityLPw(pmInternal, finalIntent, flags, cn,
                         scheme, null, null, null, userId);
             }
             doNonData = false;
@@ -3400,129 +3408,134 @@
                         Intent finalIntent = new Intent(intent);
                         builder.scheme(scheme);
                         finalIntent.setDataAndType(builder.build(), mimeType);
-                        applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
+                        applyDefaultPreferredActivityLPw(pmInternal, finalIntent, flags, cn,
                                 scheme, null, null, null, userId);
                     }
                 }
             } else {
                 Intent finalIntent = new Intent(intent);
                 finalIntent.setType(mimeType);
-                applyDefaultPreferredActivityLPw(service, finalIntent, flags, cn,
+                applyDefaultPreferredActivityLPw(pmInternal, finalIntent, flags, cn,
                         null, null, null, null, userId);
             }
             doNonData = false;
         }
 
         if (doNonData) {
-            applyDefaultPreferredActivityLPw(service, intent, flags, cn,
+            applyDefaultPreferredActivityLPw(pmInternal, intent, flags, cn,
                     null, null, null, null, userId);
         }
     }
 
-    private void applyDefaultPreferredActivityLPw(PackageManagerService service,
-            Intent intent, int flags, ComponentName cn, String scheme, PatternMatcher ssp,
+    private void applyDefaultPreferredActivityLPw(PackageManagerInternal pmInternal, Intent intent,
+            int flags, ComponentName cn, String scheme, PatternMatcher ssp,
             IntentFilter.AuthorityEntry auth, PatternMatcher path, int userId) {
-        flags = service.updateFlagsForResolve(flags, userId, intent, Binder.getCallingUid(), false);
-        List<ResolveInfo> ri = service.mActivities.queryIntent(intent,
-                intent.getType(), flags, 0);
-        if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Queried " + intent
-                + " results: " + ri);
+        final List<ResolveInfo> ri =
+                pmInternal.queryIntentActivities(intent, flags, Binder.getCallingUid(), 0);
+        if (PackageManagerService.DEBUG_PREFERRED) {
+            Log.d(TAG, "Queried " + intent + " results: " + ri);
+        }
         int systemMatch = 0;
         int thirdPartyMatch = 0;
-        if (ri != null && ri.size() > 1) {
-            boolean haveAct = false;
-            ComponentName haveNonSys = null;
-            ComponentName[] set = new ComponentName[ri.size()];
-            for (int i=0; i<ri.size(); i++) {
-                ActivityInfo ai = ri.get(i).activityInfo;
-                set[i] = new ComponentName(ai.packageName, ai.name);
-                if ((ai.applicationInfo.flags&ApplicationInfo.FLAG_SYSTEM) == 0) {
-                    if (ri.get(i).match >= thirdPartyMatch) {
-                        // Keep track of the best match we find of all third
-                        // party apps, for use later to determine if we actually
-                        // want to set a preferred app for this intent.
-                        if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Result "
-                                + ai.packageName + "/" + ai.name + ": non-system!");
-                        haveNonSys = set[i];
-                        break;
+        final int numMatches = (ri == null ? 0 : ri.size());
+        if (numMatches <= 1) {
+            Slog.w(TAG, "No potential matches found for " + intent
+                    + " while setting preferred " + cn.flattenToShortString());
+            return;
+        }
+        boolean haveAct = false;
+        ComponentName haveNonSys = null;
+        ComponentName[] set = new ComponentName[ri.size()];
+        for (int i = 0; i < numMatches; i++) {
+            final ActivityInfo ai = ri.get(i).activityInfo;
+            set[i] = new ComponentName(ai.packageName, ai.name);
+            if ((ai.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 0) {
+                if (ri.get(i).match >= thirdPartyMatch) {
+                    // Keep track of the best match we find of all third
+                    // party apps, for use later to determine if we actually
+                    // want to set a preferred app for this intent.
+                    if (PackageManagerService.DEBUG_PREFERRED) {
+                        Log.d(TAG, "Result " + ai.packageName + "/" + ai.name + ": non-system!");
                     }
-                } else if (cn.getPackageName().equals(ai.packageName)
-                        && cn.getClassName().equals(ai.name)) {
-                    if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Result "
-                            + ai.packageName + "/" + ai.name + ": default!");
-                    haveAct = true;
-                    systemMatch = ri.get(i).match;
-                } else {
-                    if (PackageManagerService.DEBUG_PREFERRED) Log.d(TAG, "Result "
-                            + ai.packageName + "/" + ai.name + ": skipped");
+                    haveNonSys = set[i];
+                    break;
                 }
-            }
-            if (haveNonSys != null && thirdPartyMatch < systemMatch) {
-                // If we have a matching third party app, but its match is not as
-                // good as the built-in system app, then we don't want to actually
-                // consider it a match because presumably the built-in app is still
-                // the thing we want users to see by default.
-                haveNonSys = null;
-            }
-            if (haveAct && haveNonSys == null) {
-                IntentFilter filter = new IntentFilter();
-                if (intent.getAction() != null) {
-                    filter.addAction(intent.getAction());
+            } else if (cn.getPackageName().equals(ai.packageName)
+                    && cn.getClassName().equals(ai.name)) {
+                if (PackageManagerService.DEBUG_PREFERRED) {
+                    Log.d(TAG, "Result " + ai.packageName + "/" + ai.name + ": default!");
                 }
-                if (intent.getCategories() != null) {
-                    for (String cat : intent.getCategories()) {
-                        filter.addCategory(cat);
-                    }
-                }
-                if ((flags & MATCH_DEFAULT_ONLY) != 0) {
-                    filter.addCategory(Intent.CATEGORY_DEFAULT);
-                }
-                if (scheme != null) {
-                    filter.addDataScheme(scheme);
-                }
-                if (ssp != null) {
-                    filter.addDataSchemeSpecificPart(ssp.getPath(), ssp.getType());
-                }
-                if (auth != null) {
-                    filter.addDataAuthority(auth);
-                }
-                if (path != null) {
-                    filter.addDataPath(path);
-                }
-                if (intent.getType() != null) {
-                    try {
-                        filter.addDataType(intent.getType());
-                    } catch (IntentFilter.MalformedMimeTypeException ex) {
-                        Slog.w(TAG, "Malformed mimetype " + intent.getType() + " for " + cn);
-                    }
-                }
-                PreferredActivity pa = new PreferredActivity(filter, systemMatch, set, cn, true);
-                editPreferredActivitiesLPw(userId).addFilter(pa);
-            } else if (haveNonSys == null) {
-                StringBuilder sb = new StringBuilder();
-                sb.append("No component ");
-                sb.append(cn.flattenToShortString());
-                sb.append(" found setting preferred ");
-                sb.append(intent);
-                sb.append("; possible matches are ");
-                for (int i=0; i<set.length; i++) {
-                    if (i > 0) sb.append(", ");
-                    sb.append(set[i].flattenToShortString());
-                }
-                Slog.w(TAG, sb.toString());
+                haveAct = true;
+                systemMatch = ri.get(i).match;
             } else {
-                Slog.i(TAG, "Not setting preferred " + intent + "; found third party match "
-                        + haveNonSys.flattenToShortString());
+                if (PackageManagerService.DEBUG_PREFERRED) {
+                    Log.d(TAG, "Result " + ai.packageName + "/" + ai.name + ": skipped");
+                }
             }
+        }
+        if (haveNonSys != null && thirdPartyMatch < systemMatch) {
+            // If we have a matching third party app, but its match is not as
+            // good as the built-in system app, then we don't want to actually
+            // consider it a match because presumably the built-in app is still
+            // the thing we want users to see by default.
+            haveNonSys = null;
+        }
+        if (haveAct && haveNonSys == null) {
+            IntentFilter filter = new IntentFilter();
+            if (intent.getAction() != null) {
+                filter.addAction(intent.getAction());
+            }
+            if (intent.getCategories() != null) {
+                for (String cat : intent.getCategories()) {
+                    filter.addCategory(cat);
+                }
+            }
+            if ((flags & MATCH_DEFAULT_ONLY) != 0) {
+                filter.addCategory(Intent.CATEGORY_DEFAULT);
+            }
+            if (scheme != null) {
+                filter.addDataScheme(scheme);
+            }
+            if (ssp != null) {
+                filter.addDataSchemeSpecificPart(ssp.getPath(), ssp.getType());
+            }
+            if (auth != null) {
+                filter.addDataAuthority(auth);
+            }
+            if (path != null) {
+                filter.addDataPath(path);
+            }
+            if (intent.getType() != null) {
+                try {
+                    filter.addDataType(intent.getType());
+                } catch (IntentFilter.MalformedMimeTypeException ex) {
+                    Slog.w(TAG, "Malformed mimetype " + intent.getType() + " for " + cn);
+                }
+            }
+            PreferredActivity pa = new PreferredActivity(filter, systemMatch, set, cn, true);
+            editPreferredActivitiesLPw(userId).addFilter(pa);
+        } else if (haveNonSys == null) {
+            StringBuilder sb = new StringBuilder();
+            sb.append("No component ");
+            sb.append(cn.flattenToShortString());
+            sb.append(" found setting preferred ");
+            sb.append(intent);
+            sb.append("; possible matches are ");
+            for (int i = 0; i < set.length; i++) {
+                if (i > 0) sb.append(", ");
+                sb.append(set[i].flattenToShortString());
+            }
+            Slog.w(TAG, sb.toString());
         } else {
-            Slog.w(TAG, "No potential matches found for " + intent + " while setting preferred "
-                    + cn.flattenToShortString());
+            Slog.i(TAG, "Not setting preferred " + intent + "; found third party match "
+                    + haveNonSys.flattenToShortString());
         }
     }
 
-    private void readDefaultPreferredActivitiesLPw(PackageManagerService service,
-            XmlPullParser parser, int userId)
+    private void readDefaultPreferredActivitiesLPw(XmlPullParser parser, int userId)
             throws XmlPullParserException, IOException {
+        final PackageManagerInternal pmInternal =
+                LocalServices.getService(PackageManagerInternal.class);
         int outerDepth = parser.getDepth();
         int type;
         while ((type = parser.next()) != XmlPullParser.END_DOCUMENT
@@ -3535,8 +3548,8 @@
             if (tagName.equals(TAG_ITEM)) {
                 PreferredActivity tmpPa = new PreferredActivity(parser);
                 if (tmpPa.mPref.getParseError() == null) {
-                    applyDefaultPreferredActivityLPw(service, tmpPa, tmpPa.mPref.mComponent,
-                            userId);
+                    applyDefaultPreferredActivityLPw(
+                            pmInternal, tmpPa, tmpPa.mPref.mComponent, userId);
                 } else {
                     PackageManagerService.reportSettingsProblem(Log.WARN,
                             "Error in package manager settings: <preferred-activity> "
@@ -4151,7 +4164,7 @@
             }
         }
         synchronized (mPackages) {
-            applyDefaultPreferredAppsLPw(service, userHandle);
+            applyDefaultPreferredAppsLPw(userHandle);
         }
     }
 
@@ -4445,6 +4458,7 @@
             ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY, "STATIC_SHARED_LIBRARY",
             ApplicationInfo.PRIVATE_FLAG_VENDOR, "VENDOR",
             ApplicationInfo.PRIVATE_FLAG_PRODUCT, "PRODUCT",
+            ApplicationInfo.PRIVATE_FLAG_PRODUCT_SERVICES, "PRODUCT_SERVICES",
             ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD, "VIRTUAL_PRELOAD",
     };
 
diff --git a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
index 843cd8a..a78cb33 100644
--- a/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
+++ b/services/core/java/com/android/server/pm/permission/DefaultPermissionGrantPolicy.java
@@ -25,7 +25,6 @@
 import android.app.DownloadManager;
 import android.app.admin.DevicePolicyManager;
 import android.companion.CompanionDeviceManager;
-import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.pm.ApplicationInfo;
@@ -54,7 +53,6 @@
 import android.provider.MediaStore;
 import android.provider.Telephony.Sms.Intents;
 import android.security.Credentials;
-import android.service.textclassifier.TextClassifierService;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 import android.util.ArrayMap;
@@ -1399,6 +1397,11 @@
         if (dir.isDirectory() && dir.canRead()) {
             Collections.addAll(ret, dir.listFiles());
         }
+        dir = new File(Environment.getProductServicesDirectory(),
+                "etc/default-permissions");
+        if (dir.isDirectory() && dir.canRead()) {
+            Collections.addAll(ret, dir.listFiles());
+        }
         // For IoT devices, we check the oem partition for default permissions for each app.
         if (mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_EMBEDDED, 0)) {
             dir = new File(Environment.getOemDirectory(), "etc/default-permissions");
diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
index 9dc0b29..c4f90a12 100644
--- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
+++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java
@@ -1097,6 +1097,10 @@
         } else if (pkg.isProduct()) {
             wlPermissions =
                     SystemConfig.getInstance().getProductPrivAppPermissions(pkg.packageName);
+        } else if (pkg.isProductServices()) {
+            wlPermissions =
+                    SystemConfig.getInstance().getProductServicesPrivAppPermissions(
+                            pkg.packageName);
         } else {
             wlPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg.packageName);
         }
@@ -1129,6 +1133,9 @@
                     } else if (pkg.isProduct()) {
                         deniedPermissions = SystemConfig.getInstance()
                                 .getProductPrivAppDenyPermissions(pkg.packageName);
+                    } else if (pkg.isProductServices()) {
+                        deniedPermissions = SystemConfig.getInstance()
+                                .getProductServicesPrivAppDenyPermissions(pkg.packageName);
                     } else {
                         deniedPermissions = SystemConfig.getInstance()
                                 .getPrivAppDenyPermissions(pkg.packageName);
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index f418ad4..b8c9be7 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -1053,14 +1053,16 @@
 
     @Override
     public void onNotificationClear(String pkg, String tag, int id, int userId, String key,
-            @NotificationStats.DismissalSurface int dismissalSurface, NotificationVisibility nv) {
+            @NotificationStats.DismissalSurface int dismissalSurface,
+            @NotificationStats.DismissalSentiment int dismissalSentiment,
+            NotificationVisibility nv) {
         enforceStatusBarService();
         final int callingUid = Binder.getCallingUid();
         final int callingPid = Binder.getCallingPid();
         long identity = Binder.clearCallingIdentity();
         try {
             mNotificationDelegate.onNotificationClear(callingUid, callingPid, pkg, tag, id, userId,
-                    key, dismissalSurface, nv);
+                    key, dismissalSurface, dismissalSentiment, nv);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index a6bda37..d8cbb26 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -16,9 +16,46 @@
 
 package com.android.server.wm;
 
+import static android.view.Display.DEFAULT_DISPLAY;
+import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
+import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
+import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
+
+import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
+import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
+import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
+import static com.android.server.wm.RootWindowContainerProto.DISPLAYS;
+import static com.android.server.wm.RootWindowContainerProto.WINDOWS;
+import static com.android.server.wm.RootWindowContainerProto.WINDOW_CONTAINER;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
+import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
+import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
+import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
+import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
+import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
+import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS;
+import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
+import static com.android.server.wm.WindowManagerService.H.WINDOW_FREEZE_TIMEOUT;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
+import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
+import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_NONE;
+import static com.android.server.wm.WindowManagerService.logSurface;
+import static com.android.server.wm.WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED;
+import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
+import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
+import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING;
+import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
+
 import android.annotation.CallSuper;
 import android.content.res.Configuration;
-import android.graphics.Rect;
 import android.hardware.power.V1_0.PowerHint;
 import android.os.Binder;
 import android.os.Debug;
@@ -26,7 +63,6 @@
 import android.os.IBinder;
 import android.os.Looper;
 import android.os.Message;
-import android.os.ParcelFileDescriptor;
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -43,51 +79,11 @@
 import com.android.internal.util.ArrayUtils;
 import com.android.server.EventLogTags;
 
-import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.function.Consumer;
 
-import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.Display.INVALID_DISPLAY;
-import static android.view.WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_SUSTAINED_PERFORMANCE_MODE;
-import static android.view.WindowManager.LayoutParams.TYPE_DREAM;
-import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
-
-import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
-import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
-import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_DISPLAY;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_KEEP_SCREEN_ON;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_LAYOUT_REPEATS;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ORIENTATION;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WALLPAPER_LIGHT;
-import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_WINDOW_TRACE;
-import static com.android.server.wm.WindowManagerDebugConfig.SHOW_LIGHT_TRANSACTIONS;
-import static com.android.server.wm.WindowManagerDebugConfig.SHOW_SURFACE_ALLOC;
-import static com.android.server.wm.WindowManagerDebugConfig.SHOW_TRANSACTIONS;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_KEEP_SCREEN_ON;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME;
-import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM;
-import static com.android.server.wm.WindowManagerService.H.REPORT_LOSING_FOCUS;
-import static com.android.server.wm.WindowManagerService.H.SEND_NEW_CONFIGURATION;
-import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_PLACING_SURFACES;
-import static com.android.server.wm.WindowManagerService.UPDATE_FOCUS_WILL_PLACE_SURFACES;
-import static com.android.server.wm.WindowManagerService.WINDOWS_FREEZING_SCREENS_NONE;
-import static com.android.server.wm.WindowManagerService.H.WINDOW_FREEZE_TIMEOUT;
-import static com.android.server.wm.WindowManagerService.logSurface;
-import static com.android.server.wm.WindowSurfacePlacer.SET_FORCE_HIDING_CHANGED;
-import static com.android.server.wm.WindowSurfacePlacer.SET_ORIENTATION_CHANGE_COMPLETE;
-import static com.android.server.wm.WindowSurfacePlacer.SET_UPDATE_ROTATION;
-import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_ACTION_PENDING;
-import static com.android.server.wm.WindowSurfacePlacer.SET_WALLPAPER_MAY_CHANGE;
-import static com.android.server.wm.RootWindowContainerProto.DISPLAYS;
-import static com.android.server.wm.RootWindowContainerProto.WINDOWS;
-import static com.android.server.wm.RootWindowContainerProto.WINDOW_CONTAINER;
-
 /** Root {@link WindowContainer} for the device. */
 class RootWindowContainer extends WindowContainer<DisplayContent> {
     private static final String TAG = TAG_WITH_CLASS_NAME ? "RootWindowContainer" : TAG_WM;
@@ -301,6 +297,18 @@
         return null;
     }
 
+    /** Returns the window token for the input binder if it exist in the system. */
+    WindowToken getWindowToken(IBinder binder) {
+        for (int i = mChildren.size() - 1; i >= 0; --i) {
+            final DisplayContent dc = mChildren.get(i);
+            final WindowToken wtoken = dc.getWindowToken(binder);
+            if (wtoken != null) {
+                return wtoken;
+            }
+        }
+        return null;
+    }
+
     /** Returns the display object the input window token is currently mapped on. */
     DisplayContent getWindowTokenDisplay(WindowToken token) {
         if (token == null) {
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 8a57143..158d09a 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -1151,7 +1151,7 @@
                 throw new IllegalStateException("Display has not been initialialized");
             }
 
-            final DisplayContent displayContent = getDisplayContentOrCreate(displayId);
+            final DisplayContent displayContent = getDisplayContentOrCreate(displayId, attrs.token);
 
             if (displayContent == null) {
                 Slog.w(TAG_WM, "Attempted to add window to a display that does not exist: "
@@ -1540,9 +1540,20 @@
      * that corresponds to a display just added to DisplayManager has not yet been created. This
      * usually means that the call of this method was initiated from outside of Activity or Window
      * Manager. In most cases the regular getter should be used.
+     * @param displayId The preferred display Id.
+     * @param token The window token associated with the window we are trying to get display for.
+     *              if not null then the display of the window token will be returned. Set to null
+     *              is there isn't an a token associated with the request.
      * @see RootWindowContainer#getDisplayContent(int)
      */
-    private DisplayContent getDisplayContentOrCreate(int displayId) {
+    private DisplayContent getDisplayContentOrCreate(int displayId, IBinder token) {
+        if (token != null) {
+            final WindowToken wToken = mRoot.getWindowToken(token);
+            if (wToken != null) {
+                return wToken.getDisplayContent();
+            }
+        }
+
         DisplayContent displayContent = mRoot.getDisplayContent(displayId);
 
         // Create an instance if possible instead of waiting for the ActivityManagerService to drive
@@ -2092,12 +2103,9 @@
             }
 
             if (focusMayChange) {
-                //System.out.println("Focus may change: " + win.mAttrs.getTitle());
-                if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
-                        false /*updateInputWindows*/)) {
+                if (updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/)) {
                     imMayMove = false;
                 }
-                //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
             }
 
             // updateFocusedWindowLocked() already assigned layers so we only need to
@@ -7070,7 +7078,7 @@
         final long token = Binder.clearCallingIdentity();
         try {
             synchronized (mWindowMap) {
-                final DisplayContent dc = getDisplayContentOrCreate(displayId);
+                final DisplayContent dc = getDisplayContentOrCreate(displayId, null);
                 if (dc == null) {
                     throw new IllegalArgumentException(
                             "Trying to register a non existent display.");
diff --git a/services/core/java/com/android/server/wm/utils/InsetUtils.java b/services/core/java/com/android/server/wm/utils/InsetUtils.java
index c5b103f..f5cc0d5 100644
--- a/services/core/java/com/android/server/wm/utils/InsetUtils.java
+++ b/services/core/java/com/android/server/wm/utils/InsetUtils.java
@@ -19,6 +19,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.graphics.Rect;
+import android.view.Surface;
 
 
 /**
@@ -30,6 +31,32 @@
     }
 
     /**
+     * Transforms insets given in one rotation into insets in a different rotation.
+     *
+     * @param inOutInsets the insets to transform, is set to the transformed insets
+     * @param rotationDelta the delta between the new and old rotation.
+     *                      Must be one of Surface.ROTATION_0/90/180/270.
+     */
+    public static void rotateInsets(Rect inOutInsets, int rotationDelta) {
+        final Rect r = inOutInsets;
+        switch (rotationDelta) {
+            case Surface.ROTATION_0:
+                return;
+            case Surface.ROTATION_90:
+                r.set(r.top, r.right, r.bottom, r.left);
+                break;
+            case Surface.ROTATION_180:
+                r.set(r.right, r.bottom, r.left, r.top);
+                break;
+            case Surface.ROTATION_270:
+                r.set(r.bottom, r.left, r.top, r.right);
+                break;
+            default:
+                throw new IllegalArgumentException("Unknown rotation: " + rotationDelta);
+        }
+    }
+
+    /**
      * Adds {@code insetsToAdd} to {@code inOutInsets}.
      */
     public static void addInsets(Rect inOutInsets, Rect insetsToAdd) {
diff --git a/services/tests/servicestests/src/com/android/server/wm/utils/InsetUtilsTest.java b/services/tests/servicestests/src/com/android/server/wm/utils/InsetUtilsTest.java
index 75b4d2f..3364aef 100644
--- a/services/tests/servicestests/src/com/android/server/wm/utils/InsetUtilsTest.java
+++ b/services/tests/servicestests/src/com/android/server/wm/utils/InsetUtilsTest.java
@@ -16,6 +16,11 @@
 
 package com.android.server.wm.utils;
 
+import static android.hardware.camera2.params.OutputConfiguration.ROTATION_90;
+import static android.view.Surface.ROTATION_0;
+import static android.view.Surface.ROTATION_180;
+import static android.view.Surface.ROTATION_270;
+
 import static junit.framework.Assert.assertEquals;
 
 import android.graphics.Rect;
@@ -39,5 +44,29 @@
         InsetUtils.addInsets(rect1, rect2);
         assertEquals(new Rect(60, 80, 100, 120), rect1);
     }
+
+    @Test
+    public void rotate() {
+        final Rect original = new Rect(1, 2, 3, 4);
+
+        assertEquals("rot0", original, rotateCopy(original, ROTATION_0));
+
+        final Rect rot90 = rotateCopy(original, ROTATION_90);
+        assertEquals("rot90", new Rect(2, 3, 4, 1), rot90);
+
+        final Rect rot180 = rotateCopy(original, ROTATION_180);
+        assertEquals("rot180", new Rect(3, 4, 1, 2), rot180);
+        assertEquals("rot90(rot90)=rot180", rotateCopy(rot90, ROTATION_90), rot180);
+
+        final Rect rot270 = rotateCopy(original, ROTATION_270);
+        assertEquals("rot270", new Rect(4, 1, 2, 3), rot270);
+        assertEquals("rot90(rot180)=rot270", rotateCopy(rot180, ROTATION_90), rot270);
+    }
+
+    private static Rect rotateCopy(Rect insets, int rotationDelta) {
+        final Rect copy = new Rect(insets);
+        InsetUtils.rotateInsets(copy, rotationDelta);
+        return copy;
+    }
 }
 
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 4dcb8cf..0ff124e 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -2483,13 +2483,29 @@
 
         final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
         mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.sbn.getTag(),
-                r.sbn.getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD, nv);
+                r.sbn.getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
+                NotificationStats.DISMISS_SENTIMENT_POSITIVE, nv);
         waitForIdle();
 
         assertEquals(NotificationStats.DISMISSAL_AOD, r.getStats().getDismissalSurface());
     }
 
     @Test
+    public void testStats_dismissalSentiment() throws Exception {
+        final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
+        mService.addNotification(r);
+
+        final NotificationVisibility nv = NotificationVisibility.obtain(r.getKey(), 0, 1, true);
+        mService.mNotificationDelegate.onNotificationClear(mUid, 0, PKG, r.sbn.getTag(),
+                r.sbn.getId(), r.getUserId(), r.getKey(), NotificationStats.DISMISSAL_AOD,
+                NotificationStats.DISMISS_SENTIMENT_NEGATIVE, nv);
+        waitForIdle();
+
+        assertEquals(NotificationStats.DISMISS_SENTIMENT_NEGATIVE,
+                r.getStats().getDismissalSentiment());
+    }
+
+    @Test
     public void testApplyAdjustmentMultiUser() throws Exception {
         final NotificationRecord r = generateNotificationRecord(mTestNotificationChannel);
         mService.addNotification(r);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationStatsTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationStatsTest.java
index 0a630f4..bae8564 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationStatsTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationStatsTest.java
@@ -16,6 +16,8 @@
 package com.android.server.notification;
 
 import static android.service.notification.NotificationStats.DISMISSAL_PEEK;
+import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_NEGATIVE;
+import static android.service.notification.NotificationStats.DISMISS_SENTIMENT_POSITIVE;
 
 import static junit.framework.Assert.assertEquals;
 import static junit.framework.Assert.assertFalse;
@@ -46,6 +48,7 @@
         assertFalse(stats.hasViewedSettings());
         assertFalse(stats.hasSnoozed());
         assertEquals(NotificationStats.DISMISSAL_NOT_DISMISSED, stats.getDismissalSurface());
+        assertEquals(NotificationStats.DISMISS_SENTIMENT_UNKNOWN, stats.getDismissalSentiment());
     }
 
     @Test
@@ -97,10 +100,19 @@
     }
 
     @Test
+    public void testDismissalSentiment() {
+        NotificationStats stats = new NotificationStats();
+        stats.setDismissalSentiment(DISMISS_SENTIMENT_NEGATIVE);
+        assertEquals(DISMISS_SENTIMENT_NEGATIVE, stats.getDismissalSentiment());
+        assertFalse(stats.hasInteracted());
+    }
+
+    @Test
     public void testWriteToParcel() {
         NotificationStats stats = new NotificationStats();
         stats.setViewedSettings();
         stats.setDismissalSurface(NotificationStats.DISMISSAL_AOD);
+        stats.setDismissalSentiment(NotificationStats.DISMISS_SENTIMENT_POSITIVE);
         Parcel parcel = Parcel.obtain();
         stats.writeToParcel(parcel, 0);
         parcel.setDataPosition(0);
diff --git a/telephony/java/android/telephony/SmsManager.java b/telephony/java/android/telephony/SmsManager.java
index 9565507..ea408bf 100644
--- a/telephony/java/android/telephony/SmsManager.java
+++ b/telephony/java/android/telephony/SmsManager.java
@@ -274,6 +274,17 @@
     private static final int SMS_PICK = 2;
 
     /**
+     * 3gpp2 SMS priority is not specified
+     * @hide
+     */
+    public static final int SMS_MESSAGE_PRIORITY_NOT_SPECIFIED = -1;
+    /**
+     * 3gpp SMS period is not specified
+     * @hide
+     */
+    public static final int SMS_MESSAGE_PERIOD_NOT_SPECIFIED = -1;
+
+    /**
      * Send a text based SMS.
      *
      * <p class="note"><strong>Note:</strong> Using this method requires that your app has the
@@ -464,11 +475,11 @@
         }
 
         if (priority < 0x00 || priority > 0x03) {
-            throw new IllegalArgumentException("Invalid priority");
+            priority = SMS_MESSAGE_PRIORITY_NOT_SPECIFIED;
         }
 
         if (validityPeriod < 0x05 || validityPeriod > 0x09b0a0) {
-            throw new IllegalArgumentException("Invalid validity period");
+            validityPeriod = SMS_MESSAGE_PERIOD_NOT_SPECIFIED;
         }
 
         try {
@@ -728,7 +739,8 @@
             ArrayList<PendingIntent> sentIntents, ArrayList<PendingIntent> deliveryIntents,
             int priority, boolean expectMore, int validityPeriod) {
         sendMultipartTextMessageInternal(destinationAddress, scAddress, parts, sentIntents,
-                deliveryIntents, true /* persistMessage*/);
+                deliveryIntents, true /* persistMessage*/, priority, expectMore,
+                validityPeriod);
     }
 
     private void sendMultipartTextMessageInternal(
@@ -743,11 +755,11 @@
         }
 
         if (priority < 0x00 || priority > 0x03) {
-            throw new IllegalArgumentException("Invalid priority");
+           priority = SMS_MESSAGE_PRIORITY_NOT_SPECIFIED;
         }
 
         if (validityPeriod < 0x05 || validityPeriod > 0x09b0a0) {
-            throw new IllegalArgumentException("Invalid validity period");
+           validityPeriod = SMS_MESSAGE_PERIOD_NOT_SPECIFIED;
         }
 
         if (parts.size() > 1) {
diff --git a/tests/libs-permissions/Android.mk b/tests/libs-permissions/Android.mk
index eb38623..f4250c8 100644
--- a/tests/libs-permissions/Android.mk
+++ b/tests/libs-permissions/Android.mk
@@ -13,3 +13,17 @@
 LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_ETC)/permissions
 LOCAL_SRC_FILES:= product/com.android.test.libs.product.xml
 include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := com.android.test.libs.product_services
+LOCAL_PRODUCT_SERVICES_MODULE := true
+LOCAL_SRC_FILES := $(call all-java-files-under, product_services/java)
+LOCAL_REQUIRED_MODULES := com.android.test.libs.product_services.xml
+include $(BUILD_JAVA_LIBRARY)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := com.android.test.libs.product_services.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_SERVICES_ETC)/permissions
+LOCAL_SRC_FILES:= product_services/com.android.test.libs.product_services.xml
+include $(BUILD_PREBUILT)
diff --git a/tests/libs-permissions/product_services/com.android.test.libs.product_services.xml b/tests/libs-permissions/product_services/com.android.test.libs.product_services.xml
new file mode 100644
index 0000000..082a9be
--- /dev/null
+++ b/tests/libs-permissions/product_services/com.android.test.libs.product_services.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2018 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<permissions>
+    <library name="com.android.test.libs.product_services"
+            file="/product_services/framework/com.android.test.libs.product_services.jar" />
+</permissions>
diff --git a/tests/libs-permissions/product_services/java/com/android/test/libs/product_services/LibsProductServicesTest.java b/tests/libs-permissions/product_services/java/com/android/test/libs/product_services/LibsProductServicesTest.java
new file mode 100644
index 0000000..dcbdae8
--- /dev/null
+++ b/tests/libs-permissions/product_services/java/com/android/test/libs/product_services/LibsProductServicesTest.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.test.libs.product_services;
+
+/**
+ * Test class for product_services libs.
+ */
+public class LibsProductServicesTest {
+
+    /**
+     * Dummy method for testing.
+     */
+    public static void test() {
+    }
+}
diff --git a/tests/privapp-permissions/Android.mk b/tests/privapp-permissions/Android.mk
index 9795188..1149b8a 100644
--- a/tests/privapp-permissions/Android.mk
+++ b/tests/privapp-permissions/Android.mk
@@ -46,3 +46,19 @@
 LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_ETC)/permissions
 LOCAL_SRC_FILES:= product/privapp-permissions-test.xml
 include $(BUILD_PREBUILT)
+
+include $(CLEAR_VARS)
+LOCAL_PACKAGE_NAME := ProductServicesPrivAppPermissionTest
+LOCAL_SDK_VERSION := current
+LOCAL_PRIVILEGED_MODULE := true
+LOCAL_MANIFEST_FILE := product_services/AndroidManifest.xml
+LOCAL_PRODUCT_SERVICES_MODULE := true
+LOCAL_REQUIRED_MODULES := product_servicesprivapp-permissions-test.xml
+include $(BUILD_PACKAGE)
+
+include $(CLEAR_VARS)
+LOCAL_MODULE := product_servicesprivapp-permissions-test.xml
+LOCAL_MODULE_CLASS := ETC
+LOCAL_MODULE_PATH := $(TARGET_OUT_PRODUCT_SERVICES_ETC)/permissions
+LOCAL_SRC_FILES:= product_services/privapp-permissions-test.xml
+include $(BUILD_PREBUILT)
diff --git a/tests/privapp-permissions/product_services/AndroidManifest.xml b/tests/privapp-permissions/product_services/AndroidManifest.xml
new file mode 100644
index 0000000..511ddee
--- /dev/null
+++ b/tests/privapp-permissions/product_services/AndroidManifest.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ * Copyright (C) 2018 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          package="com.android.framework.permission.privapp.tests.product_services">
+
+    <!-- MANAGE_USB is signature|privileged -->
+    <uses-permission android:name="android.permission.MANAGE_USB"/>
+</manifest>
diff --git a/tests/privapp-permissions/product_services/privapp-permissions-test.xml b/tests/privapp-permissions/product_services/privapp-permissions-test.xml
new file mode 100644
index 0000000..43baebb
--- /dev/null
+++ b/tests/privapp-permissions/product_services/privapp-permissions-test.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<permissions>
+    <privapp-permissions package="com.android.framework.permission.privapp.tests.product_services">
+        <permission name="android.permission.MANAGE_USB"/>
+    </privapp-permissions>
+</permissions>