Snap for 13040896 from af6f802c50ca8cd8afbdf2dfc5786dcfee8ad8f5 to udc-car-lts-release

Change-Id: I4df9f0222f07c277c6a25c71040186711548572f
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 3bc0b0b..cf00ee7 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1250,8 +1250,13 @@
         }
 
         private void updateCompatOverrideScale(CompatibilityInfo info) {
-            CompatibilityInfo.setOverrideInvertedScale(
-                    info.hasOverrideScaling() ? info.applicationInvertedScale : 1f);
+            if (info.hasOverrideScaling()) {
+                CompatibilityInfo.setOverrideInvertedScale(info.applicationInvertedScale,
+                        info.applicationDensityInvertedScale);
+            } else {
+                CompatibilityInfo.setOverrideInvertedScale(/* invertScale */ 1f,
+                        /* densityInvertScale */1f);
+            }
         }
 
         public final void runIsolatedEntryPoint(String entryPoint, String[] entryPointArgs) {
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index 27f6a26..8926ff7 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -20,7 +20,6 @@
 import android.annotation.Nullable;
 import android.app.Activity;
 import android.app.ActivityOptions;
-import android.app.LoadedApk;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
@@ -733,9 +732,6 @@
      */
     protected Context getRemoteContextEnsuringCorrectCachedApkPath() {
         try {
-            ApplicationInfo expectedAppInfo = mInfo.providerInfo.applicationInfo;
-            LoadedApk.checkAndUpdateApkPaths(expectedAppInfo);
-            // Return if cloned successfully, otherwise default
             Context newContext = mContext.createApplicationContext(
                     mInfo.providerInfo.applicationInfo,
                     Context.CONTEXT_RESTRICTED);
diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java
index 3487e0b..65c7446 100644
--- a/core/java/android/content/pm/ApplicationInfo.java
+++ b/core/java/android/content/pm/ApplicationInfo.java
@@ -833,6 +833,13 @@
      */
     public static final int PRIVATE_FLAG_EXT_CPU_OVERRIDE = 1 << 5;
 
+    /**
+     * Value for {@link #privateFlagsExt}: whether app requires display compatibility
+     * features
+     * @hide
+     */
+    public static final int PRIVATE_FLAG_EXT_DISPLAY_COMPAT = 1 << 6;
+
     /** @hide */
     @IntDef(flag = true, prefix = { "PRIVATE_FLAG_EXT_" }, value = {
             PRIVATE_FLAG_EXT_PROFILEABLE,
@@ -841,6 +848,7 @@
             PRIVATE_FLAG_EXT_ENABLE_ON_BACK_INVOKED_CALLBACK,
             PRIVATE_FLAG_EXT_ALLOWLISTED_FOR_HIDDEN_APIS,
             PRIVATE_FLAG_EXT_CPU_OVERRIDE,
+            PRIVATE_FLAG_EXT_DISPLAY_COMPAT,
     })
     @Retention(RetentionPolicy.SOURCE)
     public @interface ApplicationInfoPrivateFlagsExt {}
diff --git a/core/java/android/content/res/CompatibilityInfo.java b/core/java/android/content/res/CompatibilityInfo.java
index 08ba5b6c..5433017 100644
--- a/core/java/android/content/res/CompatibilityInfo.java
+++ b/core/java/android/content/res/CompatibilityInfo.java
@@ -100,7 +100,7 @@
      * The effective screen density we have selected for this application.
      */
     public final int applicationDensity;
-    
+
     /**
      * Application's scale.
      */
@@ -112,9 +112,27 @@
      */
     public final float applicationInvertedScale;
 
+    /**
+     * Application's density scale.
+     *
+     * <p>In most cases this is equal to {@link #applicationScale}, but in some cases e.g.
+     * Automotive the requirement is to just scale the density and keep the resolution the same.
+     * This is used for artificially making apps look zoomed in to compensate for the user distance
+     * from the screen.
+     */
+    public float applicationDensityScale;
+
+    /**
+     * Application's density inverted scale.
+     */
+    public float applicationDensityInvertedScale;
+
     /** The process level override inverted scale. See {@link #HAS_OVERRIDE_SCALING}. */
     private static float sOverrideInvertedScale = 1f;
 
+    /** The process level override inverted density scale. See {@link #HAS_OVERRIDE_SCALING}. */
+    private static float sOverrideDensityInvertScale = 1f;
+
     @UnsupportedAppUsage
     @Deprecated
     public CompatibilityInfo(ApplicationInfo appInfo, int screenLayout, int sw,
@@ -123,17 +141,24 @@
     }
 
     public CompatibilityInfo(ApplicationInfo appInfo, int screenLayout, int sw,
-            boolean forceCompat, float overrideScale) {
+            boolean forceCompat, float scaleFactor) {
+        this(appInfo, screenLayout, sw, forceCompat, 1f, scaleFactor, scaleFactor);
+    }
+
+    public CompatibilityInfo(ApplicationInfo appInfo, int screenLayout, int sw,
+            boolean forceCompat, float overrideScale, float scaleFactor, float densityScaleFactor) {
         int compatFlags = 0;
 
         if (appInfo.targetSdkVersion < VERSION_CODES.O) {
             compatFlags |= NEEDS_COMPAT_RES;
         }
-        if (overrideScale != 1.0f) {
-            applicationScale = overrideScale;
-            applicationInvertedScale = 1.0f / overrideScale;
+        if (scaleFactor != 1f || densityScaleFactor != 1f) {
+            applicationScale = scaleFactor;
+            applicationInvertedScale = 1f / scaleFactor;
+            applicationDensityScale = densityScaleFactor;
+            applicationDensityInvertedScale = 1f / densityScaleFactor;
             applicationDensity = (int) ((DisplayMetrics.DENSITY_DEVICE_STABLE
-                    * applicationInvertedScale) + .5f);
+                    * applicationDensityInvertedScale) + .5f);
             mCompatibilityFlags = NEVER_NEEDS_COMPAT | HAS_OVERRIDE_SCALING;
             // Override scale has the highest priority. So ignore other compatibility attributes.
             return;
@@ -181,7 +206,8 @@
             applicationDensity = DisplayMetrics.DENSITY_DEVICE;
             applicationScale = 1.0f;
             applicationInvertedScale = 1.0f;
-
+            applicationDensityScale = 1.0f;
+            applicationDensityInvertedScale = 1.0f;
         } else {
             /**
              * Has the application said that its UI is expandable?  Based on the
@@ -267,15 +293,26 @@
                 compatFlags |= NEVER_NEEDS_COMPAT;
             }
 
-            if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
+           if (overrideScale != 1.0f) {
+                applicationScale = overrideScale;
+                applicationInvertedScale = 1.0f / overrideScale;
+                applicationDensity = (int) ((DisplayMetrics.DENSITY_DEVICE_STABLE
+                        * applicationInvertedScale) + .5f);
+                compatFlags |= HAS_OVERRIDE_SCALING;
+            } else if ((appInfo.flags & ApplicationInfo.FLAG_SUPPORTS_SCREEN_DENSITIES) != 0) {
                 applicationDensity = DisplayMetrics.DENSITY_DEVICE;
                 applicationScale = 1.0f;
                 applicationInvertedScale = 1.0f;
+                applicationDensityScale = 1.0f;
+                applicationDensityInvertedScale = 1.0f;
             } else {
                 applicationDensity = DisplayMetrics.DENSITY_DEFAULT;
                 applicationScale = DisplayMetrics.DENSITY_DEVICE
                         / (float) DisplayMetrics.DENSITY_DEFAULT;
                 applicationInvertedScale = 1.0f / applicationScale;
+                applicationDensityScale = DisplayMetrics.DENSITY_DEVICE
+                        / (float) DisplayMetrics.DENSITY_DEFAULT;
+                applicationDensityInvertedScale = 1f / applicationDensityScale;
                 compatFlags |= SCALING_REQUIRED;
             }
         }
@@ -289,6 +326,8 @@
         applicationDensity = dens;
         applicationScale = scale;
         applicationInvertedScale = invertedScale;
+        applicationDensityScale = (float) DisplayMetrics.DENSITY_DEVICE_STABLE / dens;
+        applicationDensityInvertedScale = 1f / applicationDensityScale;
     }
 
     @UnsupportedAppUsage
@@ -528,7 +567,8 @@
     /** Applies the compatibility adjustment to the display metrics. */
     public void applyDisplayMetricsIfNeeded(DisplayMetrics inoutDm, boolean applyToSize) {
         if (hasOverrideScale()) {
-            scaleDisplayMetrics(sOverrideInvertedScale, inoutDm, applyToSize);
+            scaleDisplayMetrics(sOverrideInvertedScale, sOverrideDensityInvertScale, inoutDm,
+                    applyToSize);
             return;
         }
         if (!equals(DEFAULT_COMPATIBILITY_INFO)) {
@@ -548,15 +588,17 @@
         }
 
         if (isScalingRequired()) {
-            scaleDisplayMetrics(applicationInvertedScale, inoutDm, true /* applyToSize */);
+            scaleDisplayMetrics(applicationInvertedScale, applicationDensityInvertedScale, inoutDm,
+                    true /* applyToSize */);
         }
     }
 
     /** Scales the density of the given display metrics. */
-    private static void scaleDisplayMetrics(float invertedRatio, DisplayMetrics inoutDm,
-            boolean applyToSize) {
-        inoutDm.density = inoutDm.noncompatDensity * invertedRatio;
-        inoutDm.densityDpi = (int) ((inoutDm.noncompatDensityDpi * invertedRatio) + .5f);
+    private static void scaleDisplayMetrics(float invertScale, float densityInvertScale,
+            DisplayMetrics inoutDm, boolean applyToSize) {
+        inoutDm.density = inoutDm.noncompatDensity * densityInvertScale;
+        inoutDm.densityDpi = (int) ((inoutDm.noncompatDensityDpi
+                * densityInvertScale) + .5f);
         // Note: since this is changing the scaledDensity, you might think we also need to change
         // inoutDm.fontScaleConverter to accurately calculate non-linear font scaling. But we're not
         // going to do that, for a couple of reasons (see b/265695259 for details):
@@ -570,12 +612,12 @@
         //    b. Sometime later by WindowManager in onResume or other windowing events. In this case
         //       the DisplayMetrics object is never used by the app/resources, so it's ok if
         //       fontScaleConverter is null because it's not being used to scale fonts anyway.
-        inoutDm.scaledDensity = inoutDm.noncompatScaledDensity * invertedRatio;
-        inoutDm.xdpi = inoutDm.noncompatXdpi * invertedRatio;
-        inoutDm.ydpi = inoutDm.noncompatYdpi * invertedRatio;
+        inoutDm.scaledDensity = inoutDm.noncompatScaledDensity * densityInvertScale;
+        inoutDm.xdpi = inoutDm.noncompatXdpi * densityInvertScale;
+        inoutDm.ydpi = inoutDm.noncompatYdpi * densityInvertScale;
         if (applyToSize) {
-            inoutDm.widthPixels = (int) (inoutDm.widthPixels * invertedRatio + 0.5f);
-            inoutDm.heightPixels = (int) (inoutDm.heightPixels * invertedRatio + 0.5f);
+            inoutDm.widthPixels = (int) (inoutDm.widthPixels * invertScale + 0.5f);
+            inoutDm.heightPixels = (int) (inoutDm.heightPixels * invertScale + 0.5f);
         }
     }
 
@@ -594,38 +636,55 @@
         }
         inoutConfig.densityDpi = displayDensity;
         if (isScalingRequired()) {
-            scaleConfiguration(applicationInvertedScale, inoutConfig);
+            scaleConfiguration(applicationInvertedScale, applicationDensityInvertedScale,
+                    inoutConfig);
         }
     }
 
     /** Scales the density and bounds of the given configuration. */
-    public static void scaleConfiguration(float invertedRatio, Configuration inoutConfig) {
-        inoutConfig.densityDpi = (int) ((inoutConfig.densityDpi * invertedRatio) + .5f);
-        inoutConfig.windowConfiguration.scale(invertedRatio);
+    public static void scaleConfiguration(float invertScale, Configuration inoutConfig) {
+        scaleConfiguration(invertScale, invertScale, inoutConfig);
+    }
+
+    /** Scales the density and bounds of the given configuration. */
+    public static void scaleConfiguration(float invertScale, float densityInvertScale,
+            Configuration inoutConfig) {
+        inoutConfig.densityDpi = (int) ((inoutConfig.densityDpi
+                * densityInvertScale) + .5f);
+        inoutConfig.windowConfiguration.scale(invertScale);
     }
 
     /** @see #sOverrideInvertedScale */
     public static void applyOverrideScaleIfNeeded(Configuration config) {
         if (!hasOverrideScale()) return;
-        scaleConfiguration(sOverrideInvertedScale, config);
+        scaleConfiguration(sOverrideInvertedScale, sOverrideDensityInvertScale, config);
     }
 
     /** @see #sOverrideInvertedScale */
     public static void applyOverrideScaleIfNeeded(MergedConfiguration mergedConfig) {
         if (!hasOverrideScale()) return;
-        scaleConfiguration(sOverrideInvertedScale, mergedConfig.getGlobalConfiguration());
-        scaleConfiguration(sOverrideInvertedScale, mergedConfig.getOverrideConfiguration());
-        scaleConfiguration(sOverrideInvertedScale, mergedConfig.getMergedConfiguration());
+        scaleConfiguration(sOverrideInvertedScale, sOverrideDensityInvertScale,
+                mergedConfig.getGlobalConfiguration());
+        scaleConfiguration(sOverrideInvertedScale, sOverrideDensityInvertScale,
+                mergedConfig.getOverrideConfiguration());
+        scaleConfiguration(sOverrideInvertedScale, sOverrideDensityInvertScale,
+                mergedConfig.getMergedConfiguration());
     }
 
     /** Returns {@code true} if this process is in a environment with override scale. */
     private static boolean hasOverrideScale() {
-        return sOverrideInvertedScale != 1f;
+        return sOverrideInvertedScale != 1f || sOverrideDensityInvertScale != 1f;
     }
 
     /** @see #sOverrideInvertedScale */
-    public static void setOverrideInvertedScale(float invertedRatio) {
-        sOverrideInvertedScale = invertedRatio;
+    public static void setOverrideInvertedScale(float invertScale) {
+        setOverrideInvertedScale(invertScale, invertScale);
+    }
+
+    /** @see #sOverrideInvertedScale */
+    public static void setOverrideInvertedScale(float invertScale, float densityInvertScale) {
+        sOverrideInvertedScale = invertScale;
+        sOverrideDensityInvertScale = densityInvertScale;
     }
 
     /** @see #sOverrideInvertedScale */
@@ -633,6 +692,11 @@
         return sOverrideInvertedScale;
     }
 
+    /** @see #sOverrideDensityInvertScale */
+    public static float getOverrideDensityInvertedScale() {
+        return sOverrideDensityInvertScale;
+    }
+
     /**
      * Compute the frame Rect for applications runs under compatibility mode.
      *
@@ -693,6 +757,8 @@
             if (applicationDensity != oc.applicationDensity) return false;
             if (applicationScale != oc.applicationScale) return false;
             if (applicationInvertedScale != oc.applicationInvertedScale) return false;
+            if (applicationDensityScale != oc.applicationDensityScale) return false;
+            if (applicationDensityInvertedScale != oc.applicationDensityInvertedScale) return false;
             return true;
         } catch (ClassCastException e) {
             return false;
@@ -713,6 +779,8 @@
         if (hasOverrideScaling()) {
             sb.append(" overrideInvScale=");
             sb.append(applicationInvertedScale);
+            sb.append(" overrideDensityInvScale=");
+            sb.append(applicationDensityInvertedScale);
         }
         if (!supportsScreen()) {
             sb.append(" resizing");
@@ -734,6 +802,8 @@
         result = 31 * result + applicationDensity;
         result = 31 * result + Float.floatToIntBits(applicationScale);
         result = 31 * result + Float.floatToIntBits(applicationInvertedScale);
+        result = 31 * result + Float.floatToIntBits(applicationDensityScale);
+        result = 31 * result + Float.floatToIntBits(applicationDensityInvertedScale);
         return result;
     }
 
@@ -748,6 +818,8 @@
         dest.writeInt(applicationDensity);
         dest.writeFloat(applicationScale);
         dest.writeFloat(applicationInvertedScale);
+        dest.writeFloat(applicationDensityScale);
+        dest.writeFloat(applicationDensityInvertedScale);
     }
 
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
@@ -769,5 +841,61 @@
         applicationDensity = source.readInt();
         applicationScale = source.readFloat();
         applicationInvertedScale = source.readFloat();
+        applicationDensityScale = source.readFloat();
+        applicationDensityInvertedScale = source.readFloat();
+    }
+
+    /**
+     * A data class for holding scale factor for width, height, and density.
+     */
+    public static final class CompatScale {
+
+        public final float mScaleFactor;
+        public final float mDensityScaleFactor;
+
+        public CompatScale(float scaleFactor) {
+            this(scaleFactor, scaleFactor);
+        }
+
+        public CompatScale(float scaleFactor, float densityScaleFactor) {
+            mScaleFactor = scaleFactor;
+            mDensityScaleFactor = densityScaleFactor;
+        }
+
+        @Override
+        public boolean equals(@Nullable Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (!(o instanceof CompatScale)) {
+                return false;
+            }
+            try {
+                CompatScale oc = (CompatScale) o;
+                if (mScaleFactor != oc.mScaleFactor) return false;
+                if (mDensityScaleFactor != oc.mDensityScaleFactor) return false;
+                return true;
+            } catch (ClassCastException e) {
+                return false;
+            }
+        }
+
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder(128);
+            sb.append("mScaleFactor= ");
+            sb.append(mScaleFactor);
+            sb.append(" mDensityScaleFactor= ");
+            sb.append(mDensityScaleFactor);
+            return sb.toString();
+        }
+
+        @Override
+        public int hashCode() {
+            int result = 17;
+            result = 31 * result + Float.floatToIntBits(mScaleFactor);
+            result = 31 * result + Float.floatToIntBits(mDensityScaleFactor);
+            return result;
+        }
     }
 }
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index 912e8df..8d222a2 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -466,6 +466,20 @@
         // LINT.ThenChange(frameworks/base/core/java/android/hardware/biometrics/PromptInfo.java)
 
         /**
+         * Set the class name of ConfirmDeviceCredentialActivity.
+         *
+         * @return This builder.
+         * @hide
+         */
+        @NonNull
+        @RequiresPermission(anyOf = {TEST_BIOMETRIC, USE_BIOMETRIC_INTERNAL})
+        public Builder setClassNameIfItIsConfirmDeviceCredentialActivity() {
+            mPromptInfo.setClassNameIfItIsConfirmDeviceCredentialActivity(
+                    mContext.getClass().getName());
+            return this;
+        }
+
+        /**
          * Creates a {@link BiometricPrompt}.
          *
          * @return An instance of {@link BiometricPrompt}.
diff --git a/core/java/android/hardware/biometrics/PromptInfo.java b/core/java/android/hardware/biometrics/PromptInfo.java
index e275078..b9157c8 100644
--- a/core/java/android/hardware/biometrics/PromptInfo.java
+++ b/core/java/android/hardware/biometrics/PromptInfo.java
@@ -48,6 +48,7 @@
     private boolean mAllowBackgroundAuthentication;
     private boolean mIgnoreEnrollmentState;
     private boolean mIsForLegacyFingerprintManager = false;
+    private String mClassNameIfItIsConfirmDeviceCredentialActivity = null;
 
     public PromptInfo() {
 
@@ -72,6 +73,7 @@
         mAllowBackgroundAuthentication = in.readBoolean();
         mIgnoreEnrollmentState = in.readBoolean();
         mIsForLegacyFingerprintManager = in.readBoolean();
+        mClassNameIfItIsConfirmDeviceCredentialActivity = in.readString();
     }
 
     public static final Creator<PromptInfo> CREATOR = new Creator<PromptInfo>() {
@@ -111,6 +113,7 @@
         dest.writeBoolean(mAllowBackgroundAuthentication);
         dest.writeBoolean(mIgnoreEnrollmentState);
         dest.writeBoolean(mIsForLegacyFingerprintManager);
+        dest.writeString(mClassNameIfItIsConfirmDeviceCredentialActivity);
     }
 
     // LINT.IfChange
@@ -127,6 +130,8 @@
             return true;
         } else if (mIgnoreEnrollmentState) {
             return true;
+        } else if (mClassNameIfItIsConfirmDeviceCredentialActivity != null) {
+            return true;
         }
         return false;
     }
@@ -228,6 +233,13 @@
         mAllowedSensorIds.add(sensorId);
     }
 
+    /**
+     * Set the class name of ConfirmDeviceCredentialActivity.
+     */
+    void setClassNameIfItIsConfirmDeviceCredentialActivity(String className) {
+        mClassNameIfItIsConfirmDeviceCredentialActivity = className;
+    }
+
     // Getters
 
     public CharSequence getTitle() {
@@ -309,4 +321,12 @@
     public boolean isForLegacyFingerprintManager() {
         return mIsForLegacyFingerprintManager;
     }
+
+    /**
+     * Get the class name of ConfirmDeviceCredentialActivity. Returns null if the direct caller is
+     * not ConfirmDeviceCredentialActivity.
+     */
+    public String getClassNameIfItIsConfirmDeviceCredentialActivity() {
+        return mClassNameIfItIsConfirmDeviceCredentialActivity;
+    }
 }
diff --git a/core/java/android/os/BaseBundle.java b/core/java/android/os/BaseBundle.java
index 4e3adfb..9773134 100644
--- a/core/java/android/os/BaseBundle.java
+++ b/core/java/android/os/BaseBundle.java
@@ -471,10 +471,10 @@
             map.erase();
             map.ensureCapacity(count);
         }
-        int numLazyValues = 0;
+        int[] numLazyValues = new int[]{0};
         try {
-            numLazyValues = parcelledData.readArrayMap(map, count, !parcelledByNative,
-                    /* lazy */ ownsParcel, mClassLoader);
+            parcelledData.readArrayMap(map, count, !parcelledByNative,
+                    /* lazy */ ownsParcel, mClassLoader, numLazyValues);
         } catch (BadParcelableException e) {
             if (sShouldDefuse) {
                 Log.w(TAG, "Failed to parse Bundle, but defusing quietly", e);
@@ -485,14 +485,14 @@
         } finally {
             mWeakParcelledData = null;
             if (ownsParcel) {
-                if (numLazyValues == 0) {
+                if (numLazyValues[0] == 0) {
                     recycleParcel(parcelledData);
                 } else {
                     mWeakParcelledData = new WeakReference<>(parcelledData);
                 }
             }
 
-            mLazyValues = numLazyValues;
+            mLazyValues = numLazyValues[0];
             mParcelledByNative = false;
             mMap = map;
             // Set field last as it is volatile
diff --git a/core/java/android/os/Parcel.java b/core/java/android/os/Parcel.java
index 453aba3..11eb5cc 100644
--- a/core/java/android/os/Parcel.java
+++ b/core/java/android/os/Parcel.java
@@ -5335,7 +5335,7 @@
 
     private void readArrayMapInternal(@NonNull ArrayMap<? super String, Object> outVal,
             int size, @Nullable ClassLoader loader) {
-        readArrayMap(outVal, size, /* sorted */ true, /* lazy */ false, loader);
+        readArrayMap(outVal, size, /* sorted */ true, /* lazy */ false, loader, null);
     }
 
     /**
@@ -5345,17 +5345,16 @@
      * @param lazy   Whether to populate the map with lazy {@link Function} objects for
      *               length-prefixed values. See {@link Parcel#readLazyValue(ClassLoader)} for more
      *               details.
-     * @return a count of the lazy values in the map
+     * @param lazyValueCount number of lazy values added here
      * @hide
      */
-    int readArrayMap(ArrayMap<? super String, Object> map, int size, boolean sorted,
-            boolean lazy, @Nullable ClassLoader loader) {
-        int lazyValues = 0;
+    void readArrayMap(ArrayMap<? super String, Object> map, int size, boolean sorted,
+            boolean lazy, @Nullable ClassLoader loader, int[] lazyValueCount) {
         while (size > 0) {
             String key = readString();
             Object value = (lazy) ? readLazyValue(loader) : readValue(loader);
             if (value instanceof LazyValue) {
-                lazyValues++;
+                lazyValueCount[0]++;
             }
             if (sorted) {
                 map.append(key, value);
@@ -5367,7 +5366,6 @@
         if (sorted) {
             map.validate();
         }
-        return lazyValues;
     }
 
     /**
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 385dfc7..5bbc56e 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -35,7 +35,6 @@
 import android.app.ActivityThread;
 import android.app.AppGlobals;
 import android.app.Application;
-import android.app.LoadedApk;
 import android.app.PendingIntent;
 import android.app.RemoteInput;
 import android.appwidget.AppWidgetHostView;
@@ -6284,9 +6283,18 @@
                 return context;
             }
             try {
-                LoadedApk.checkAndUpdateApkPaths(mApplication);
-                return context.createApplicationContext(mApplication,
+                // Use PackageManager as the source of truth for application information, rather
+                // than the parceled ApplicationInfo provided by the app.
+                ApplicationInfo sanitizedApplication =
+                        context.getPackageManager().getApplicationInfoAsUser(
+                                mApplication.packageName, 0,
+                                UserHandle.getUserId(mApplication.uid));
+                Context applicationContext = context.createApplicationContext(
+                        sanitizedApplication,
                         Context.CONTEXT_RESTRICTED);
+                // Get the correct apk paths while maintaining the current context's configuration.
+                return applicationContext.createConfigurationContext(
+                        context.getResources().getConfiguration());
             } catch (NameNotFoundException e) {
                 Log.e(LOG_TAG, "Package name " + mApplication.packageName + " not found");
             }
diff --git a/core/java/com/android/internal/app/ChooserActivity.java b/core/java/com/android/internal/app/ChooserActivity.java
index 697633b..33a4192 100644
--- a/core/java/com/android/internal/app/ChooserActivity.java
+++ b/core/java/com/android/internal/app/ChooserActivity.java
@@ -21,6 +21,7 @@
 import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_SHARE_WITH_PERSONAL;
 import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CANT_SHARE_WITH_WORK;
 import static android.app.admin.DevicePolicyResources.Strings.Core.RESOLVER_CROSS_PROFILE_BLOCKED_TITLE;
+import static android.content.ContentProvider.getUriWithoutUserId;
 import static android.content.ContentProvider.getUserIdFromUri;
 import static android.stats.devicepolicy.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_PERSONAL;
 import static android.stats.devicepolicy.DevicePolicyEnums.RESOLVER_EMPTY_STATE_NO_SHARING_TO_WORK;
@@ -40,7 +41,9 @@
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
+import android.app.IUriGrantsManager;
 import android.app.SharedElementCallback;
+import android.app.UriGrantsManager;
 import android.app.prediction.AppPredictionContext;
 import android.app.prediction.AppPredictionManager;
 import android.app.prediction.AppPredictor;
@@ -77,6 +80,7 @@
 import android.graphics.Path;
 import android.graphics.drawable.AnimatedVectorDrawable;
 import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
 import android.metrics.LogMaker;
 import android.net.Uri;
 import android.os.AsyncTask;
@@ -86,6 +90,7 @@
 import android.os.Message;
 import android.os.Parcelable;
 import android.os.PatternMatcher;
+import android.os.RemoteException;
 import android.os.ResultReceiver;
 import android.os.UserHandle;
 import android.os.UserManager;
@@ -692,7 +697,11 @@
                     targets = null;
                     break;
                 }
-                targets[i] = (ChooserTarget) pa[i];
+                ChooserTarget chooserTarget = (ChooserTarget) pa[i];
+                if (!hasValidIcon(chooserTarget)) {
+                    chooserTarget = removeIcon(chooserTarget);
+                }
+                targets[i] = chooserTarget;
             }
             mCallerChooserTargets = targets;
         }
@@ -4312,4 +4321,43 @@
     private boolean shouldNearbyShareBeIncludedAsActionButton() {
         return !shouldNearbyShareBeFirstInRankedRow();
     }
+
+    private boolean hasValidIcon(ChooserTarget target) {
+        Icon icon = target.getIcon();
+        if (icon == null) {
+            return true;
+        }
+        if (icon.getType() == Icon.TYPE_URI || icon.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP) {
+            Uri uri = icon.getUri();
+            try {
+                getUriGrantsManager().checkGrantUriPermission_ignoreNonSystem(
+                        getLaunchedFromUid(),
+                        getPackageName(),
+                        getUriWithoutUserId(uri),
+                        Intent.FLAG_GRANT_READ_URI_PERMISSION,
+                        getUserIdFromUri(uri)
+                );
+            } catch (SecurityException | RemoteException e) {
+                Log.e(TAG, "Failed to get URI permission for: " + uri, e);
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private IUriGrantsManager getUriGrantsManager() {
+        return UriGrantsManager.getService();
+    }
+
+    private static ChooserTarget removeIcon(ChooserTarget target) {
+        if (target == null) {
+            return null;
+        }
+        return new ChooserTarget(
+                target.getTitle(),
+                null,
+                target.getScore(),
+                target.getComponentName(),
+                target.getIntentExtras());
+    }
 }
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index 65b5979..259e821 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -512,24 +512,35 @@
                 Intent.FLAG_ACTIVITY_FORWARD_RESULT | Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
         sanitizeIntent(forwardIntent);
 
-        Intent intentToCheck = forwardIntent;
-        if (Intent.ACTION_CHOOSER.equals(forwardIntent.getAction())) {
+        if (!canForwardInner(forwardIntent, sourceUserId, targetUserId, packageManager,
+                contentResolver)) {
             return null;
         }
         if (forwardIntent.getSelector() != null) {
-            intentToCheck = forwardIntent.getSelector();
+            sanitizeIntent(forwardIntent.getSelector());
+            if (!canForwardInner(forwardIntent.getSelector(), sourceUserId, targetUserId,
+                    packageManager, contentResolver)) {
+                return null;
+            }
         }
-        String resolvedType = intentToCheck.resolveTypeIfNeeded(contentResolver);
-        sanitizeIntent(intentToCheck);
+        return forwardIntent;
+    }
+
+    private static boolean canForwardInner(Intent intent, int sourceUserId, int targetUserId,
+            IPackageManager packageManager, ContentResolver contentResolver) {
+        if (Intent.ACTION_CHOOSER.equals(intent.getAction())) {
+            return false;
+        }
+        String resolvedType = intent.resolveTypeIfNeeded(contentResolver);
         try {
             if (packageManager.canForwardTo(
-                    intentToCheck, resolvedType, sourceUserId, targetUserId)) {
-                return forwardIntent;
+                    intent, resolvedType, sourceUserId, targetUserId)) {
+                return true;
             }
         } catch (RemoteException e) {
             Slog.e(TAG, "PackageManagerService is dead?");
         }
-        return null;
+        return false;
     }
 
     /**
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index e02b578..06df85c 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -17,7 +17,9 @@
 package com.android.internal.policy;
 
 import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
+import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_EXT_DISPLAY_COMPAT;
 import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static android.os.Build.IS_DEBUGGABLE;
 import static android.os.Build.VERSION_CODES.M;
 import static android.os.Build.VERSION_CODES.N;
 import static android.view.InsetsState.clearsCompatInsets;
@@ -47,11 +49,14 @@
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.TestApi;
 import android.app.WindowConfiguration;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
 import android.content.res.Configuration;
 import android.content.res.Resources;
 import android.graphics.Canvas;
@@ -67,6 +72,7 @@
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.InsetDrawable;
 import android.graphics.drawable.LayerDrawable;
+import android.os.UserHandle;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.util.Pair;
@@ -217,6 +223,7 @@
     private final int mBarEnterExitDuration;
     final boolean mForceWindowDrawsBarBackgrounds;
     private final int mSemiTransparentBarColor;
+    private final boolean mRequiresDisplayCompat;
 
     private final BackgroundFallback mBackgroundFallback = new BackgroundFallback();
 
@@ -308,6 +315,7 @@
                 && context.getApplicationInfo().targetSdkVersion >= N;
         mSemiTransparentBarColor = context.getResources().getColor(
                 R.color.system_bar_background_semi_transparent, null /* theme */);
+        mRequiresDisplayCompat = requiresDisplayCompat(context);
 
         setWindow(window);
 
@@ -316,6 +324,37 @@
         mLegacyNavigationBarBackgroundPaint.setColor(Color.BLACK);
     }
 
+    /**
+     * Apps not built specifically for a form factor may require display compat features
+     * including limiting of drawing behind system bars, e.g. apps from tablet or mobile
+     * that are installed on Automotive devices.
+     *
+     * NOTE: This does not use context.getApplicationInfo() as this data doesn't include user-
+     * specific settings like display compat, use getApplicationInfoAsUser instead.
+     * @return true if app requires display compat
+     */
+    private static boolean requiresDisplayCompat(@NonNull Context context) {
+        boolean requiresDisplayCompat = false;
+        final String packageName = context.getPackageName();
+        final int userId = UserHandle.myUserId();
+        UserHandle userHandle = UserHandle.of(userId);
+        try {
+            ApplicationInfo applicationInfo = context.getPackageManager()
+                .getApplicationInfoAsUser(packageName, 0 /** flags */, userHandle);
+            requiresDisplayCompat = (applicationInfo.privateFlagsExt
+                    & PRIVATE_FLAG_EXT_DISPLAY_COMPAT) != 0;
+        } catch (PackageManager.NameNotFoundException e) {
+            Log.e(TAG, "Self package not found: " + packageName);
+        } finally {
+            if (IS_DEBUGGABLE) {
+                Log.d(TAG, "package: " + packageName +
+                        " user: " + userId +
+                        " displayCompat: " + requiresDisplayCompat);
+            }
+            return requiresDisplayCompat;
+        }
+    }
+
     void setBackgroundFallback(@Nullable Drawable fallbackDrawable) {
         mBackgroundFallback.setDrawable(fallbackDrawable);
         setWillNotDraw(getBackground() == null && !mBackgroundFallback.hasFallback());
@@ -1211,7 +1250,7 @@
                         && decorFitsSystemWindows
                         && !hideNavigation)
                 || ((mLastForceConsumingTypes & WindowInsets.Type.navigationBars()) != 0
-                        && hideNavigation);
+                        && hideNavigation) || mRequiresDisplayCompat;
 
         boolean consumingNavBar =
                 ((attrs.flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0
@@ -1235,7 +1274,7 @@
                         && mForceWindowDrawsBarBackgrounds
                         && mLastTopInset != 0)
                 || ((mLastForceConsumingTypes & WindowInsets.Type.statusBars()) != 0
-                        && fullscreen);
+                        && fullscreen) || mRequiresDisplayCompat;
 
         int consumedTop = consumingStatusBar ? mLastTopInset : 0;
         int consumedRight = consumingNavBar ? mLastRightInset : 0;
diff --git a/core/proto/android/service/package.proto b/core/proto/android/service/package.proto
index 0fe2a6b..2bed45b 100644
--- a/core/proto/android/service/package.proto
+++ b/core/proto/android/service/package.proto
@@ -114,6 +114,7 @@
         optional int32 distraction_flags = 10;
         // UTC timestamp of first install for the user
         optional int32 first_install_time_ms = 11;
+        optional bool is_display_compat = 12;
     }
 
     message InstallSourceProto {
diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
index f9a7148..f0a8639 100644
--- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
+++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java
@@ -786,8 +786,10 @@
     }
 
     private static ClientTransaction newRelaunchResumeTransaction(Activity activity) {
+        final Configuration currentConfig = activity.getResources().getConfiguration();
         final ClientTransactionItem callbackItem = ActivityRelaunchItem.obtain(null,
-                null, 0, new MergedConfiguration(), false /* preserveWindow */);
+                null, 0, new MergedConfiguration(currentConfig, currentConfig),
+                false /* preserveWindow */);
         final ResumeActivityItem resumeStateRequest =
                 ResumeActivityItem.obtain(true /* isForward */,
                         false /* shouldSendCompatFakeFocus*/);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CarWindowDecorViewModel.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CarWindowDecorViewModel.java
new file mode 100644
index 0000000..4bdb229
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CarWindowDecorViewModel.java
@@ -0,0 +1,269 @@
+/*
+ * Copyright (C) 2025 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.wm.shell.windowdecor;
+
+import android.annotation.SuppressLint;
+import android.app.ActivityManager.RunningTaskInfo;
+import android.app.ActivityTaskManager;
+import android.content.Context;
+import android.hardware.input.InputManager;
+import android.os.SystemClock;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.InputDevice;
+import android.view.InsetsState;
+import android.view.KeyCharacterMap;
+import android.view.KeyEvent;
+import android.view.SurfaceControl;
+import android.view.View;
+import android.window.WindowContainerToken;
+import android.window.WindowContainerTransaction;
+
+import com.android.wm.shell.R;
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.DisplayInsetsController;
+import com.android.wm.shell.common.ShellExecutor;
+import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.common.annotations.ShellBackgroundThread;
+import com.android.wm.shell.common.annotations.ShellMainThread;
+import com.android.wm.shell.freeform.FreeformTaskTransitionStarter;
+import com.android.wm.shell.splitscreen.SplitScreenController;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * Works with decorations that extend {@link CarWindowDecoration}.
+ */
+public abstract class CarWindowDecorViewModel
+        implements WindowDecorViewModel, DisplayController.OnDisplaysChangedListener {
+    private static final String TAG = "CarWindowDecorViewModel";
+
+    private final ShellTaskOrganizer mTaskOrganizer;
+    private final Context mContext;
+    private final @ShellBackgroundThread ShellExecutor mBgExecutor;
+    private final @ShellMainThread ShellExecutor mMainExecutor;
+    private final DisplayController mDisplayController;
+    private final DisplayInsetsController mDisplayInsetsController;
+    private final SyncTransactionQueue mSyncQueue;
+    private final SparseArray<CarWindowDecoration> mWindowDecorByTaskId = new SparseArray<>();
+    private final Map<Integer, DisplayInsetsController.OnInsetsChangedListener>
+            mDisplayIdToInsetsChangedListenerMap = new HashMap<>();
+
+    public CarWindowDecorViewModel(
+            Context context,
+            @ShellMainThread ShellExecutor mainExecutor,
+            @ShellBackgroundThread ShellExecutor bgExecutor,
+            ShellTaskOrganizer taskOrganizer,
+            DisplayController displayController,
+            DisplayInsetsController displayInsetsController,
+            SyncTransactionQueue syncQueue) {
+        mContext = context;
+        mMainExecutor = mainExecutor;
+        mBgExecutor = bgExecutor;
+        mTaskOrganizer = taskOrganizer;
+        mDisplayController = displayController;
+        mDisplayInsetsController = displayInsetsController;
+        mSyncQueue = syncQueue;
+
+        mDisplayController.addDisplayWindowListener(this);
+    }
+
+    @Override
+    public void onDisplayAdded(int displayId) {
+        DisplayInsetsController.OnInsetsChangedListener listener =
+                mDisplayIdToInsetsChangedListenerMap.computeIfAbsent(displayId,
+                        key -> new InsetsChangedListener(key));
+        mDisplayInsetsController.addInsetsChangedListener(displayId, listener);
+    }
+
+    @Override
+    public void onDisplayRemoved(int displayId) {
+        DisplayInsetsController.OnInsetsChangedListener listener =
+                mDisplayIdToInsetsChangedListenerMap.remove(displayId);
+        if (listener == null) {
+            return;
+        }
+        mDisplayInsetsController.removeInsetsChangedListener(displayId, listener);
+    }
+
+    private class InsetsChangedListener implements DisplayInsetsController.OnInsetsChangedListener {
+        private final int mDisplayId;
+
+        private InsetsChangedListener(int displayId) {
+            mDisplayId = displayId;
+        }
+
+        @Override
+        public void insetsChanged(InsetsState insetsState) {
+            ActivityTaskManager.getInstance().getTasks(
+                            Integer.MAX_VALUE, /* filterOnlyVisibleRecents= */ false,
+                            /* keepIntentExtra= */ false, mDisplayId)
+                    .stream().filter(taskInfo -> taskInfo.isRunning && taskInfo.isVisible)
+                    .forEach(taskInfo -> {
+                        onTaskInfoChanged(taskInfo);
+                    });
+        }
+
+    }
+
+    @Override
+    public void setFreeformTaskTransitionStarter(FreeformTaskTransitionStarter transitionStarter) {
+        // no-op
+    }
+
+    @Override
+    public void setSplitScreenController(SplitScreenController splitScreenController) {
+        // no-op
+    }
+
+    @Override
+    public boolean onTaskOpening(
+            RunningTaskInfo taskInfo,
+            SurfaceControl taskSurface,
+            SurfaceControl.Transaction startT,
+            SurfaceControl.Transaction finishT) {
+        createWindowDecoration(taskInfo, taskSurface, startT, finishT);
+        return true;
+    }
+
+    @Override
+    public void onTaskInfoChanged(RunningTaskInfo taskInfo) {
+        final CarWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId);
+
+        if (decoration == null) {
+            return;
+        }
+
+        final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+        decoration.relayout(taskInfo, t, t,
+                /* isCaptionVisible= */ shouldShowWindowDecor(taskInfo));
+    }
+
+    @Override
+    public void onTaskChanging(
+            RunningTaskInfo taskInfo,
+            SurfaceControl taskSurface,
+            SurfaceControl.Transaction startT,
+            SurfaceControl.Transaction finishT) {
+        final CarWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId);
+
+        if (!shouldShowWindowDecor(taskInfo)) {
+            if (decoration != null) {
+                destroyWindowDecoration(taskInfo);
+            }
+            return;
+        }
+
+        if (decoration == null) {
+            createWindowDecoration(taskInfo, taskSurface, startT, finishT);
+        } else {
+            decoration.relayout(taskInfo, startT, finishT);
+        }
+    }
+
+    @Override
+    public void onTaskClosing(
+            RunningTaskInfo taskInfo,
+            SurfaceControl.Transaction startT,
+            SurfaceControl.Transaction finishT) {
+        final CarWindowDecoration decoration = mWindowDecorByTaskId.get(taskInfo.taskId);
+        if (decoration == null) {
+            return;
+        }
+        decoration.relayout(taskInfo, startT, finishT);
+    }
+
+    @Override
+    public void destroyWindowDecoration(RunningTaskInfo taskInfo) {
+        final CarWindowDecoration decoration =
+                mWindowDecorByTaskId.removeReturnOld(taskInfo.taskId);
+        if (decoration == null) {
+            return;
+        }
+
+        decoration.close();
+    }
+
+    /**
+     * @return {@code true} if the task/activity associated with {@code taskInfo} should show
+     * window decoration.
+     */
+    protected abstract boolean shouldShowWindowDecor(RunningTaskInfo taskInfo);
+
+    private void createWindowDecoration(
+            RunningTaskInfo taskInfo,
+            SurfaceControl taskSurface,
+            SurfaceControl.Transaction startT,
+            SurfaceControl.Transaction finishT) {
+        final CarWindowDecoration oldDecoration = mWindowDecorByTaskId.get(taskInfo.taskId);
+        if (oldDecoration != null) {
+            // close the old decoration if it exists to avoid two window decorations being added
+            oldDecoration.close();
+        }
+        final CarWindowDecoration windowDecoration =
+                new CarWindowDecoration(
+                        mContext,
+                        mDisplayController,
+                        mTaskOrganizer,
+                        taskInfo,
+                        taskSurface,
+                        mBgExecutor,
+                        new ButtonClickListener(taskInfo));
+        mWindowDecorByTaskId.put(taskInfo.taskId, windowDecoration);
+        windowDecoration.relayout(taskInfo, startT, finishT,
+                /* isCaptionVisible= */ shouldShowWindowDecor(taskInfo));
+    }
+
+    private class ButtonClickListener implements View.OnClickListener {
+        private final WindowContainerToken mTaskToken;
+        private final int mDisplayId;
+
+        private ButtonClickListener(RunningTaskInfo taskInfo) {
+            mTaskToken = taskInfo.token;
+            mDisplayId = taskInfo.displayId;
+        }
+
+        @Override
+        public void onClick(View v) {
+            final int id = v.getId();
+            if (id == R.id.close_window) {
+                WindowContainerTransaction wct = new WindowContainerTransaction();
+                wct.removeTask(mTaskToken);
+                mSyncQueue.queue(wct);
+            } else if (id == R.id.back_button) {
+                sendBackEvent(KeyEvent.ACTION_DOWN, mDisplayId);
+                sendBackEvent(KeyEvent.ACTION_UP, mDisplayId);
+            }
+        }
+
+        @SuppressLint("MissingPermission")
+        private void sendBackEvent(int action, int displayId) {
+            final long when = SystemClock.uptimeMillis();
+            final KeyEvent ev = new KeyEvent(when, when, action, KeyEvent.KEYCODE_BACK,
+                    0 /* repeat */, 0 /* metaState */, KeyCharacterMap.VIRTUAL_KEYBOARD,
+                    0 /* scancode */, KeyEvent.FLAG_FROM_SYSTEM | KeyEvent.FLAG_VIRTUAL_HARD_KEY,
+                    InputDevice.SOURCE_KEYBOARD);
+
+            ev.setDisplayId(displayId);
+            if (!mContext.getSystemService(InputManager.class)
+                    .injectInputEvent(ev, InputManager.INJECT_INPUT_EVENT_MODE_ASYNC)) {
+                Log.e(TAG, "Inject input event fail");
+            }
+        }
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CarWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CarWindowDecoration.java
new file mode 100644
index 0000000..93f8668
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/CarWindowDecoration.java
@@ -0,0 +1,140 @@
+/*
+ * Copyright (C) 2025 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.wm.shell.windowdecor;
+
+import android.annotation.SuppressLint;
+import android.app.ActivityManager;
+import android.content.Context;
+import android.graphics.Insets;
+import android.graphics.Rect;
+import android.view.InsetsState;
+import android.view.SurfaceControl;
+import android.view.View;
+import android.view.WindowInsets;
+import android.window.WindowContainerTransaction;
+
+import com.android.wm.shell.R;
+import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.common.DisplayController;
+import com.android.wm.shell.common.ShellExecutor;
+
+/**
+ * {@link WindowDecoration} to show app controls for windows on automotive.
+ */
+public class CarWindowDecoration extends WindowDecoration<WindowDecorLinearLayout> {
+    private WindowDecorLinearLayout mRootView;
+    private final ShellExecutor mBgExecutor;
+    private final View.OnClickListener mClickListener;
+    private final RelayoutParams mRelayoutParams = new RelayoutParams();
+
+    CarWindowDecoration(
+            Context context,
+            DisplayController displayController,
+            ShellTaskOrganizer taskOrganizer,
+            ActivityManager.RunningTaskInfo taskInfo,
+            SurfaceControl taskSurface,
+            ShellExecutor bgExecutor,
+            View.OnClickListener clickListener) {
+        super(context, displayController, taskOrganizer, taskInfo, taskSurface);
+        mBgExecutor = bgExecutor;
+        mClickListener = clickListener;
+    }
+
+    @Override
+    void relayout(ActivityManager.RunningTaskInfo taskInfo) {
+        final SurfaceControl.Transaction t = new SurfaceControl.Transaction();
+        relayout(taskInfo, t, t);
+    }
+
+    @SuppressLint("MissingPermission")
+    void relayout(ActivityManager.RunningTaskInfo taskInfo,
+            SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT) {
+        relayout(taskInfo, startT, finishT,
+                /* isCaptionVisible= */ mRelayoutParams.mIsCaptionVisible);
+    }
+
+    @SuppressLint("MissingPermission")
+    void relayout(ActivityManager.RunningTaskInfo taskInfo,
+            SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,
+            boolean isCaptionVisible) {
+        final WindowContainerTransaction wct = new WindowContainerTransaction();
+
+        RelayoutResult<WindowDecorLinearLayout> outResult = new RelayoutResult<>();
+
+        updateRelayoutParams(mRelayoutParams, taskInfo, isCaptionVisible);
+
+        relayout(mRelayoutParams, startT, finishT, wct, mRootView, outResult);
+        // After this line, mTaskInfo is up-to-date and should be used instead of taskInfo
+        mBgExecutor.execute(() -> mTaskOrganizer.applyTransaction(wct));
+
+        if (outResult.mRootView == null) {
+            // This means something blocks the window decor from showing, e.g. the task is hidden.
+            // Nothing is set up in this case including the decoration surface.
+            return;
+        }
+        if (mRootView != outResult.mRootView) {
+            mRootView = outResult.mRootView;
+            setupRootView(outResult.mRootView, mClickListener);
+        }
+    }
+
+    @Override
+    int getCaptionViewId() {
+        return R.id.caption;
+    }
+
+    private void updateRelayoutParams(
+            RelayoutParams relayoutParams,
+            ActivityManager.RunningTaskInfo taskInfo,
+            boolean isCaptionVisible) {
+        relayoutParams.reset();
+        relayoutParams.mRunningTaskInfo = taskInfo;
+        // todo(b/382071404): update to car specific UI
+        relayoutParams.mLayoutResId = R.layout.caption_window_decor;
+        relayoutParams.mCaptionHeightId = R.dimen.freeform_decor_caption_height;
+        relayoutParams.mIsCaptionVisible = isCaptionVisible;
+        relayoutParams.mCaptionTopPadding = getTopPadding(taskInfo, relayoutParams);
+        relayoutParams.mApplyStartTransactionOnDraw = true;
+    }
+
+    private int getTopPadding(ActivityManager.RunningTaskInfo taskInfo,
+            RelayoutParams relayoutParams) {
+        Rect taskBounds = taskInfo.getConfiguration().windowConfiguration.getBounds();
+        InsetsState insetsState = mDisplayController.getInsetsState(taskInfo.displayId);
+        if (insetsState == null) {
+            return relayoutParams.mCaptionTopPadding;
+        }
+        Insets systemDecor = insetsState.calculateInsets(taskBounds,
+                WindowInsets.Type.systemBars() & ~WindowInsets.Type.captionBar(),
+                false /* ignoreVisibility */);
+        return systemDecor.top;
+    }
+
+    /**
+     * Sets up listeners when a new root view is created.
+     */
+    private void setupRootView(View rootView, View.OnClickListener onClickListener) {
+        final View caption = rootView.findViewById(R.id.caption);
+        final View close = caption.findViewById(R.id.close_window);
+        if (close != null) {
+            close.setOnClickListener(onClickListener);
+        }
+        final View back = caption.findViewById(R.id.back_button);
+        if (back != null) {
+            back.setOnClickListener(onClickListener);
+        }
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index 0b0d9d5..c797e33 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -221,6 +221,9 @@
                     .inflate(params.mLayoutResId, null);
         }
 
+        boolean isCaptionVisible = params.mIsCaptionVisible;
+        setCaptionVisibility(outResult.mRootView, isCaptionVisible);
+
         final Resources resources = mDecorWindowContext.getResources();
         final Rect taskBounds = taskConfig.windowConfiguration.getBounds();
         outResult.mWidth = taskBounds.width();
@@ -253,7 +256,8 @@
                     .build();
         }
 
-        final int captionHeight = loadDimensionPixelSize(resources, params.mCaptionHeightId);
+        final int captionHeight = loadDimensionPixelSize(resources, params.mCaptionHeightId)
+                + params.mCaptionTopPadding;
         final int captionWidth = taskBounds.width();
 
         startT.setWindowCrop(mCaptionContainerSurface, captionWidth, captionHeight)
@@ -264,33 +268,41 @@
             outResult.mRootView.setTaskFocusState(mTaskInfo.isFocused);
 
             // Caption insets
-            mCaptionInsetsRect.set(taskBounds);
-            mCaptionInsetsRect.bottom = mCaptionInsetsRect.top + captionHeight + params.mCaptionY;
-            wct.addInsetsSource(mTaskInfo.token,
-                    mOwner, 0 /* index */, WindowInsets.Type.captionBar(), mCaptionInsetsRect);
-            wct.addInsetsSource(mTaskInfo.token,
-                    mOwner, 0 /* index */, WindowInsets.Type.mandatorySystemGestures(),
-                    mCaptionInsetsRect);
+            if (!isCaptionVisible) {
+                wct.removeInsetsSource(mTaskInfo.token,
+                        mOwner, 0 /* index */, WindowInsets.Type.captionBar());
+                wct.removeInsetsSource(mTaskInfo.token,
+                        mOwner, 0 /* index */, WindowInsets.Type.mandatorySystemGestures());
+            } else {
+                mCaptionInsetsRect.set(taskBounds);
+                mCaptionInsetsRect.bottom =
+                        mCaptionInsetsRect.top + captionHeight + params.mCaptionY;
+                wct.addInsetsSource(mTaskInfo.token,
+                        mOwner, 0 /* index */, WindowInsets.Type.captionBar(), mCaptionInsetsRect);
+                wct.addInsetsSource(mTaskInfo.token,
+                        mOwner, 0 /* index */, WindowInsets.Type.mandatorySystemGestures(),
+                        mCaptionInsetsRect);
+            }
         } else {
             startT.hide(mCaptionContainerSurface);
         }
 
         // Task surface itself
         float shadowRadius = loadDimension(resources, params.mShadowRadiusId);
-        int backgroundColorInt = mTaskInfo.taskDescription.getBackgroundColor();
-        mTmpColor[0] = (float) Color.red(backgroundColorInt) / 255.f;
-        mTmpColor[1] = (float) Color.green(backgroundColorInt) / 255.f;
-        mTmpColor[2] = (float) Color.blue(backgroundColorInt) / 255.f;
         final Point taskPosition = mTaskInfo.positionInParent;
         startT.setWindowCrop(mTaskSurface, outResult.mWidth, outResult.mHeight)
                 .setShadowRadius(mTaskSurface, shadowRadius)
-                .setColor(mTaskSurface, mTmpColor)
                 .show(mTaskSurface);
         finishT.setPosition(mTaskSurface, taskPosition.x, taskPosition.y)
                 .setShadowRadius(mTaskSurface, shadowRadius)
                 .setWindowCrop(mTaskSurface, outResult.mWidth, outResult.mHeight);
         if (mTaskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM) {
-            startT.setCornerRadius(mTaskSurface, params.mCornerRadius);
+            int backgroundColorInt = mTaskInfo.taskDescription.getBackgroundColor();
+            mTmpColor[0] = (float) Color.red(backgroundColorInt) / 255.f;
+            mTmpColor[1] = (float) Color.green(backgroundColorInt) / 255.f;
+            mTmpColor[2] = (float) Color.blue(backgroundColorInt) / 255.f;
+            startT.setCornerRadius(mTaskSurface, params.mCornerRadius)
+                    .setColor(mTaskSurface, mTmpColor);
             finishT.setCornerRadius(mTaskSurface, params.mCornerRadius);
         }
 
@@ -316,11 +328,21 @@
             if (params.mApplyStartTransactionOnDraw) {
                 mViewHost.getRootSurfaceControl().applyTransactionOnDraw(startT);
             }
+            outResult.mRootView.setPadding(
+                    outResult.mRootView.getPaddingLeft(),
+                    params.mCaptionTopPadding,
+                    outResult.mRootView.getPaddingRight(),
+                    outResult.mRootView.getPaddingBottom());
             mViewHost.setView(outResult.mRootView, lp);
         } else {
             if (params.mApplyStartTransactionOnDraw) {
                 mViewHost.getRootSurfaceControl().applyTransactionOnDraw(startT);
             }
+            outResult.mRootView.setPadding(
+                    outResult.mRootView.getPaddingLeft(),
+                    params.mCaptionTopPadding,
+                    outResult.mRootView.getPaddingRight(),
+                    outResult.mRootView.getPaddingBottom());
             mViewHost.relayout(lp);
         }
     }
@@ -469,7 +491,8 @@
 
         int mCaptionX;
         int mCaptionY;
-
+        int mCaptionTopPadding;
+        boolean mIsCaptionVisible;
         boolean mApplyStartTransactionOnDraw;
 
         void reset() {
@@ -482,6 +505,8 @@
 
             mCaptionX = 0;
             mCaptionY = 0;
+            mCaptionTopPadding = 0;
+            mIsCaptionVisible = false;
 
             mApplyStartTransactionOnDraw = false;
         }
@@ -505,6 +530,21 @@
         }
     }
 
+    private void setCaptionVisibility(View rootView, boolean visible) {
+        if (rootView == null) {
+            return;
+        }
+        final int v = visible ? View.VISIBLE : View.GONE;
+        final View captionView = rootView.findViewById(getCaptionViewId());
+        if (captionView != null) {
+            captionView.setVisibility(v);
+        }
+    }
+
+    int getCaptionViewId() {
+        return Resources.ID_NULL;
+    }
+
     /**
      * Subclass for additional windows associated with this WindowDecoration
      */
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
index 7fc1c99..50d976fc 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
@@ -257,8 +257,6 @@
         verify(mMockSurfaceControlFinishT).setCornerRadius(taskSurface, CORNER_RADIUS);
         verify(mMockSurfaceControlStartT)
                 .show(taskSurface);
-        verify(mMockSurfaceControlStartT)
-                .setColor(taskSurface, new float[] {1.f, 1.f, 0.f});
         verify(mMockSurfaceControlStartT).setShadowRadius(taskSurface, 10);
 
         assertEquals(300, mRelayoutResult.mWidth);
@@ -283,12 +281,8 @@
         final SurfaceControl.Transaction t = mock(SurfaceControl.Transaction.class);
         mMockSurfaceControlTransactions.add(t);
 
-        final ActivityManager.TaskDescription.Builder taskDescriptionBuilder =
-                new ActivityManager.TaskDescription.Builder()
-                        .setBackgroundColor(Color.YELLOW);
         final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder()
                 .setDisplayId(Display.DEFAULT_DISPLAY)
-                .setTaskDescriptionBuilder(taskDescriptionBuilder)
                 .setBounds(TASK_BOUNDS)
                 .setPositionInParent(TASK_POSITION_IN_PARENT.x, TASK_POSITION_IN_PARENT.y)
                 .setVisible(true)
@@ -513,6 +507,40 @@
         verify(mMockRootSurfaceControl).applyTransactionOnDraw(mMockSurfaceControlStartT);
     }
 
+    @Test
+    public void testRelayout_freeformTask_setTaskSurfaceColor() {
+        final Display defaultDisplay = mock(Display.class);
+        doReturn(defaultDisplay).when(mMockDisplayController)
+                .getDisplay(Display.DEFAULT_DISPLAY);
+
+        final SurfaceControl decorContainerSurface = mock(SurfaceControl.class);
+        final SurfaceControl.Builder decorContainerSurfaceBuilder =
+                createMockSurfaceControlBuilder(decorContainerSurface);
+        mMockSurfaceControlBuilders.add(decorContainerSurfaceBuilder);
+        final SurfaceControl captionContainerSurface = mock(SurfaceControl.class);
+        final SurfaceControl.Builder captionContainerSurfaceBuilder =
+                createMockSurfaceControlBuilder(captionContainerSurface);
+        mMockSurfaceControlBuilders.add(captionContainerSurfaceBuilder);
+
+        final ActivityManager.TaskDescription.Builder taskDescriptionBuilder =
+                new ActivityManager.TaskDescription.Builder()
+                        .setBackgroundColor(Color.YELLOW);
+
+        final ActivityManager.RunningTaskInfo taskInfo = new TestRunningTaskInfoBuilder()
+                .setDisplayId(Display.DEFAULT_DISPLAY)
+                .setTaskDescriptionBuilder(taskDescriptionBuilder)
+                .setVisible(true)
+                .setWindowingMode(WINDOWING_MODE_FREEFORM)
+                .build();
+        taskInfo.isFocused = true;
+        final SurfaceControl taskSurface = mock(SurfaceControl.class);
+        final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo, taskSurface);
+
+        windowDecor.relayout(taskInfo);
+
+        verify(mMockSurfaceControlStartT).setColor(taskSurface, new float[] {1.f, 1.f, 0.f});
+    }
+
     private TestWindowDecoration createWindowDecoration(
             ActivityManager.RunningTaskInfo taskInfo, SurfaceControl testSurface) {
         return new TestWindowDecoration(mContext, mMockDisplayController, mMockShellTaskOrganizer,
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
index 3790490..e7be4b6 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/InstallStart.java
@@ -66,7 +66,7 @@
         mUserManager = getSystemService(UserManager.class);
 
         Intent intent = getIntent();
-        String callingPackage = getCallingPackage();
+        String callingPackage = getLaunchedFromPackage();
         String callingAttributionTag = null;
 
         final boolean isSessionInstall =
diff --git a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java
index 9c67817..bf3bc8e 100644
--- a/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java
+++ b/packages/PackageInstaller/src/com/android/packageinstaller/UninstallerActivity.java
@@ -56,8 +56,6 @@
 import com.android.packageinstaller.television.UninstallAlertFragment;
 import com.android.packageinstaller.television.UninstallAppProgress;
 
-import java.util.List;
-
 /*
  * This activity presents UI to uninstall an application. Usually launched with intent
  * Intent.ACTION_UNINSTALL_PKG_COMMAND and attribute
@@ -162,12 +160,15 @@
         if (mDialogInfo.user == null) {
             mDialogInfo.user = Process.myUserHandle();
         } else {
-            List<UserHandle> profiles = userManager.getUserProfiles();
-            if (!profiles.contains(mDialogInfo.user)) {
-                Log.e(TAG, "User " + Process.myUserHandle() + " can't request uninstall "
-                        + "for user " + mDialogInfo.user);
-                showUserIsNotAllowed();
-                return;
+            if (!mDialogInfo.user.equals(Process.myUserHandle())) {
+                final boolean isCurrentUserProfileOwner = Process.myUserHandle().equals(
+                        userManager.getProfileParent(mDialogInfo.user));
+                if (!isCurrentUserProfileOwner) {
+                    Log.e(TAG, "User " + Process.myUserHandle() + " can't request uninstall "
+                            + "for user " + mDialogInfo.user);
+                    showUserIsNotAllowed();
+                    return;
+                }
             }
         }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
new file mode 100644
index 0000000..03c1f92
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/tiles/QuickAccessWalletTileTest.java
@@ -0,0 +1,545 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.qs.tiles;
+
+import static android.content.pm.PackageManager.FEATURE_NFC_HOST_CARD_EMULATION;
+import static android.provider.Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static junit.framework.TestCase.assertEquals;
+import static junit.framework.TestCase.assertFalse;
+import static junit.framework.TestCase.assertNotNull;
+import static junit.framework.TestCase.assertNull;
+import static junit.framework.TestCase.assertTrue;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+import android.app.PendingIntent;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.graphics.Bitmap;
+import android.graphics.drawable.Drawable;
+import android.graphics.drawable.Icon;
+import android.os.Handler;
+import android.os.UserHandle;
+import android.service.quickaccesswallet.GetWalletCardsError;
+import android.service.quickaccesswallet.GetWalletCardsResponse;
+import android.service.quickaccesswallet.QuickAccessWalletClient;
+import android.service.quickaccesswallet.QuickAccessWalletService;
+import android.service.quickaccesswallet.WalletCard;
+import android.service.quicksettings.Tile;
+import android.testing.TestableLooper;
+
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.SmallTest;
+
+import com.android.internal.logging.MetricsLogger;
+import com.android.systemui.SysuiTestCase;
+import com.android.systemui.classifier.FalsingManagerFake;
+import com.android.systemui.plugins.ActivityStarter;
+import com.android.systemui.plugins.qs.QSTile;
+import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.qs.QSHost;
+import com.android.systemui.qs.QsEventLogger;
+import com.android.systemui.qs.logging.QSLogger;
+import com.android.systemui.qs.tileimpl.QSTileImpl;
+import com.android.systemui.res.R;
+import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.util.settings.SecureSettings;
+import com.android.systemui.wallet.controller.QuickAccessWalletController;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Collections;
+
+@RunWith(AndroidJUnit4.class)
[email protected](setAsMainLooper = true)
+@SmallTest
+public class QuickAccessWalletTileTest extends SysuiTestCase {
+
+    private static final String CARD_ID = "card_id";
+    private static final String LABEL = "QAW";
+    private static final String CARD_DESCRIPTION = "•••• 1234";
+    private static final Icon CARD_IMAGE =
+            Icon.createWithBitmap(Bitmap.createBitmap(70, 50, Bitmap.Config.ARGB_8888));
+    private static final Icon INVALID_CARD_IMAGE =
+            Icon.createWithContentUri("content://media/external/images/media");
+    private static final int PRIMARY_USER_ID = 0;
+    private static final int SECONDARY_USER_ID = 10;
+
+    private final Drawable mTileIcon = mContext.getDrawable(R.drawable.ic_qs_wallet);
+    private final Intent mWalletIntent = new Intent(QuickAccessWalletService.ACTION_VIEW_WALLET)
+            .setComponent(new ComponentName(mContext.getPackageName(), "WalletActivity"));
+
+    @Mock
+    private QSHost mHost;
+    @Mock
+    private MetricsLogger mMetricsLogger;
+    @Mock
+    private StatusBarStateController mStatusBarStateController;
+    @Mock
+    private ActivityStarter mActivityStarter;
+    @Mock
+    private QSLogger mQSLogger;
+    @Mock
+    private QsEventLogger mUiEventLogger;
+    @Mock
+    private QuickAccessWalletClient mQuickAccessWalletClient;
+    @Mock
+    private KeyguardStateController mKeyguardStateController;
+    @Mock
+    private PackageManager mPackageManager;
+    @Mock
+    private SecureSettings mSecureSettings;
+    @Mock
+    private QuickAccessWalletController mController;
+    @Mock
+    private Icon mCardImage;
+    @Captor
+    ArgumentCaptor<QuickAccessWalletClient.OnWalletCardsRetrievedCallback> mCallbackCaptor;
+
+    private Context mSpiedContext;
+    private TestableLooper mTestableLooper;
+    private QuickAccessWalletTile mTile;
+
+    @Before
+    public void setUp() throws Exception {
+        MockitoAnnotations.initMocks(this);
+
+        mTestableLooper = TestableLooper.get(this);
+        mSpiedContext = spy(mContext);
+
+        doNothing().when(mSpiedContext).startActivity(any(Intent.class));
+        when(mHost.getContext()).thenReturn(mSpiedContext);
+        when(mQuickAccessWalletClient.getServiceLabel()).thenReturn(LABEL);
+        when(mQuickAccessWalletClient.getTileIcon()).thenReturn(mTileIcon);
+        when(mQuickAccessWalletClient.isWalletFeatureAvailable()).thenReturn(true);
+        when(mQuickAccessWalletClient.isWalletServiceAvailable()).thenReturn(true);
+        when(mQuickAccessWalletClient.isWalletFeatureAvailableWhenDeviceLocked()).thenReturn(true);
+        when(mController.getWalletClient()).thenReturn(mQuickAccessWalletClient);
+        when(mCardImage.getType()).thenReturn(Icon.TYPE_URI);
+        when(mCardImage.loadDrawableAsUser(any(), eq(SECONDARY_USER_ID))).thenReturn(null);
+
+        mTile = new QuickAccessWalletTile(
+                mHost,
+                mUiEventLogger,
+                mTestableLooper.getLooper(),
+                new Handler(mTestableLooper.getLooper()),
+                new FalsingManagerFake(),
+                mMetricsLogger,
+                mStatusBarStateController,
+                mActivityStarter,
+                mQSLogger,
+                mKeyguardStateController,
+                mPackageManager,
+                mSecureSettings,
+                mController);
+
+        mTile.initialize();
+        mTestableLooper.processAllMessages();
+    }
+
+    @After
+    public void tearDown() {
+        mTile.destroy();
+        mTestableLooper.processAllMessages();
+    }
+
+    @Test
+    public void testNewTile() {
+        assertFalse(mTile.newTileState().handlesLongClick);
+    }
+
+    @Test
+    public void testWalletServiceUnavailable_recreateWalletClient() {
+        when(mQuickAccessWalletClient.isWalletServiceAvailable()).thenReturn(false);
+
+        mTile.handleSetListening(true);
+
+        verify(mController, times(1)).reCreateWalletClient();
+    }
+
+    @Test
+    public void testWalletFeatureUnavailable_recreateWalletClient() {
+        when(mQuickAccessWalletClient.isWalletFeatureAvailable()).thenReturn(false);
+
+        mTile.handleSetListening(true);
+
+        verify(mController, times(1)).reCreateWalletClient();
+    }
+
+    @Test
+    public void testIsAvailable_qawFeatureAvailableWalletUnavailable() {
+        when(mController.isWalletRoleAvailable()).thenReturn(false);
+        when(mPackageManager.hasSystemFeature(FEATURE_NFC_HOST_CARD_EMULATION)).thenReturn(true);
+        when(mPackageManager.hasSystemFeature("org.chromium.arc")).thenReturn(false);
+        when(mSecureSettings.getStringForUser(NFC_PAYMENT_DEFAULT_COMPONENT,
+                UserHandle.USER_CURRENT)).thenReturn("Component");
+
+        assertTrue(mTile.isAvailable());
+    }
+
+    @Test
+    public void testIsAvailable_nfcUnavailableWalletAvailable() {
+        when(mController.isWalletRoleAvailable()).thenReturn(true);
+        when(mHost.getUserId()).thenReturn(PRIMARY_USER_ID);
+        when(mPackageManager.hasSystemFeature(FEATURE_NFC_HOST_CARD_EMULATION)).thenReturn(false);
+        when(mPackageManager.hasSystemFeature("org.chromium.arc")).thenReturn(false);
+
+        assertTrue(mTile.isAvailable());
+    }
+
+    @Test
+    public void testHandleClick_startQuickAccessUiIntent_noCard() {
+        setUpWalletCard(/* hasCard= */ false);
+
+        mTile.handleClick(/* view= */ null);
+        mTestableLooper.processAllMessages();
+
+        verify(mController).startQuickAccessUiIntent(
+                eq(mActivityStarter),
+                eq(null),
+                /* hasCard= */ eq(false));
+    }
+
+    @Test
+    public void testHandleClick_startQuickAccessUiIntent_hasCard() {
+        setUpWalletCard(/* hasCard= */ true);
+
+        mTile.handleClick(null /* view */);
+        mTestableLooper.processAllMessages();
+
+        verify(mController).startQuickAccessUiIntent(
+                eq(mActivityStarter),
+                eq(null),
+                /* hasCard= */ eq(true));
+    }
+
+    @Test
+    public void testHandleUpdateState_updateLabelAndIcon() {
+        QSTile.State state = new QSTile.State();
+
+        mTile.handleUpdateState(state, null);
+
+        assertEquals(LABEL, state.label.toString());
+        assertTrue(state.label.toString().contentEquals(state.contentDescription));
+        assertEquals(mTileIcon, state.icon.getDrawable(mContext));
+    }
+
+    @Test
+    public void testHandleUpdateState_updateLabelAndIcon_noIconFromApi() {
+        when(mQuickAccessWalletClient.getTileIcon()).thenReturn(null);
+        QSTile.State state = new QSTile.State();
+        QSTile.Icon icon = QSTileImpl.ResourceIcon.get(R.drawable.ic_wallet_lockscreen);
+
+        mTile.handleUpdateState(state, null);
+
+        assertEquals(LABEL, state.label.toString());
+        assertTrue(state.label.toString().contentEquals(state.contentDescription));
+        assertEquals(icon, state.icon);
+    }
+
+    @Test
+    public void testGetTileLabel_serviceLabelExists() {
+        assertEquals(LABEL, mTile.getTileLabel().toString());
+    }
+
+    @Test
+    public void testGetTileLabel_serviceLabelDoesNotExist() {
+        when(mQuickAccessWalletClient.getServiceLabel()).thenReturn(null);
+        assertEquals(mContext.getString(R.string.wallet_title), mTile.getTileLabel().toString());
+    }
+
+    @Test
+    public void testHandleUpdateState_walletIsUpdating() {
+        when(mKeyguardStateController.isUnlocked()).thenReturn(true);
+        QSTile.State state = new QSTile.State();
+        GetWalletCardsResponse response =
+                new GetWalletCardsResponse(
+                        Collections.singletonList(createWalletCard(mContext)), 0);
+
+        mTile.handleSetListening(true);
+
+        verify(mController).queryWalletCards(mCallbackCaptor.capture());
+
+        // Wallet cards fetching on its way; wallet updating.
+        mTile.handleUpdateState(state, null);
+
+        assertEquals(Tile.STATE_INACTIVE, state.state);
+        assertEquals(
+                mContext.getString(R.string.wallet_secondary_label_updating), state.secondaryLabel);
+        assertNotNull(state.stateDescription);
+        assertNull(state.sideViewCustomDrawable);
+
+        // Wallet cards fetching completed.
+        mCallbackCaptor.getValue().onWalletCardsRetrieved(response);
+        mTestableLooper.processAllMessages();
+
+        mTile.handleUpdateState(state, null);
+
+        assertEquals(Tile.STATE_ACTIVE, state.state);
+        assertEquals(CARD_DESCRIPTION, state.secondaryLabel);
+        assertNotNull(state.stateDescription);
+        assertNotNull(state.sideViewCustomDrawable);
+    }
+
+    @Test
+    public void testHandleUpdateState_hasCard_deviceLocked_tileInactive() {
+        when(mKeyguardStateController.isUnlocked()).thenReturn(false);
+        QSTile.State state = new QSTile.State();
+        setUpWalletCard(/* hasCard= */ true);
+
+        mTile.handleUpdateState(state, null);
+
+        assertEquals(Tile.STATE_INACTIVE, state.state);
+        assertEquals(CARD_DESCRIPTION, state.secondaryLabel);
+        assertNotNull(state.stateDescription);
+        assertNotNull(state.sideViewCustomDrawable);
+    }
+
+    @Test
+    public void testHandleUpdateState_hasCard_deviceUnlocked_tileActive() {
+        when(mKeyguardStateController.isUnlocked()).thenReturn(true);
+        QSTile.State state = new QSTile.State();
+        setUpWalletCard(/* hasCard= */ true);
+
+        mTile.handleUpdateState(state, null);
+
+        assertEquals(Tile.STATE_ACTIVE, state.state);
+        assertEquals(CARD_DESCRIPTION, state.secondaryLabel);
+        assertNotNull(state.stateDescription);
+        assertNotNull(state.sideViewCustomDrawable);
+    }
+
+
+    @Test
+    public void testHandleUpdateState_noCard_tileInactive() {
+        QSTile.State state = new QSTile.State();
+        setUpWalletCard(/* hasCard= */ false);
+
+        mTile.handleUpdateState(state, null);
+
+        assertEquals(Tile.STATE_INACTIVE, state.state);
+        assertEquals(
+                mContext.getString(R.string.wallet_secondary_label_no_card),
+                state.secondaryLabel);
+        assertNotNull(state.stateDescription);
+        assertNull(state.sideViewCustomDrawable);
+    }
+
+    @Test
+    public void testHandleUpdateState_qawServiceUnavailable_tileUnavailable() {
+        when(mQuickAccessWalletClient.isWalletServiceAvailable()).thenReturn(false);
+        QSTile.State state = new QSTile.State();
+
+        mTile.handleUpdateState(state, null);
+
+        assertEquals(Tile.STATE_UNAVAILABLE, state.state);
+        assertNull(state.stateDescription);
+        assertNull(state.sideViewCustomDrawable);
+    }
+
+    @Test
+    public void testHandleUpdateState_qawFeatureUnavailable_tileUnavailable() {
+        when(mQuickAccessWalletClient.isWalletFeatureAvailable()).thenReturn(false);
+        QSTile.State state = new QSTile.State();
+
+        mTile.handleUpdateState(state, null);
+
+        assertEquals(Tile.STATE_UNAVAILABLE, state.state);
+        assertNull(state.stateDescription);
+        assertNull(state.sideViewCustomDrawable);
+    }
+
+    @Test
+    public void testHandleSetListening_queryCards() {
+        mTile.handleSetListening(true);
+
+        verify(mController).queryWalletCards(mCallbackCaptor.capture());
+
+        assertThat(mCallbackCaptor.getValue()).isInstanceOf(
+                QuickAccessWalletClient.OnWalletCardsRetrievedCallback.class);
+    }
+
+    @Test
+    public void testQueryCards_hasCards_updateSideViewDrawable() {
+        when(mKeyguardStateController.isUnlocked()).thenReturn(true);
+        setUpWalletCard(/* hasCard= */ true);
+
+        assertNotNull(mTile.getState().sideViewCustomDrawable);
+    }
+
+    @Test
+    public void testQueryCards_notCurrentUser_hasCards_noSideViewDrawable() {
+        when(mKeyguardStateController.isUnlocked()).thenReturn(true);
+
+        PendingIntent pendingIntent =
+                PendingIntent.getActivity(mContext, 0, mWalletIntent, PendingIntent.FLAG_IMMUTABLE);
+        WalletCard walletCard =
+                new WalletCard.Builder(
+                        CARD_ID, mCardImage, CARD_DESCRIPTION, pendingIntent).build();
+        GetWalletCardsResponse response =
+                new GetWalletCardsResponse(Collections.singletonList(walletCard), 0);
+
+        mTile.handleSetListening(true);
+
+        verify(mController).queryWalletCards(mCallbackCaptor.capture());
+
+        mCallbackCaptor.getValue().onWalletCardsRetrieved(response);
+        mTestableLooper.processAllMessages();
+
+        assertNull(mTile.getState().sideViewCustomDrawable);
+    }
+
+    @Test
+    public void testQueryCards_cardDataPayment_updateSideViewDrawable() {
+        when(mKeyguardStateController.isUnlocked()).thenReturn(true);
+        setUpWalletCardWithType(/* hasCard =*/ true, WalletCard.CARD_TYPE_PAYMENT);
+
+        assertNotNull(mTile.getState().sideViewCustomDrawable);
+    }
+
+    @Test
+    public void testQueryCards_cardDataNonPayment_updateSideViewDrawable() {
+        when(mKeyguardStateController.isUnlocked()).thenReturn(true);
+        setUpWalletCardWithType(/* hasCard =*/ true, WalletCard.CARD_TYPE_NON_PAYMENT);
+
+        assertNull(mTile.getState().sideViewCustomDrawable);
+    }
+
+    @Test
+    public void testQueryCards_noCards_notUpdateSideViewDrawable() {
+        setUpWalletCard(/* hasCard= */ false);
+
+        assertNull(mTile.getState().sideViewCustomDrawable);
+    }
+
+    @Test
+    public void testQueryCards_invalidDrawable_noSideViewDrawable() {
+        when(mKeyguardStateController.isUnlocked()).thenReturn(true);
+        setUpInvalidWalletCard(/* hasCard= */ true);
+
+        assertNull(mTile.getState().sideViewCustomDrawable);
+    }
+
+    @Test
+    public void testQueryCards_error_notUpdateSideViewDrawable() {
+        String errorMessage = "getWalletCardsError";
+        GetWalletCardsError error = new GetWalletCardsError(CARD_IMAGE, errorMessage);
+
+        mTile.handleSetListening(true);
+
+        verify(mController).queryWalletCards(mCallbackCaptor.capture());
+
+        mCallbackCaptor.getValue().onWalletCardRetrievalError(error);
+        mTestableLooper.processAllMessages();
+
+        assertNull(mTile.getState().sideViewCustomDrawable);
+    }
+
+    @Test
+    public void testHandleSetListening_notListening_notQueryCards() {
+        mTile.handleSetListening(false);
+
+        verifyNoMoreInteractions(mQuickAccessWalletClient);
+    }
+
+    private WalletCard createWalletCardWithType(Context context, int cardType) {
+        PendingIntent pendingIntent =
+                PendingIntent.getActivity(context, 0, mWalletIntent, PendingIntent.FLAG_IMMUTABLE);
+        return new WalletCard.Builder(CARD_ID, cardType, CARD_IMAGE, CARD_DESCRIPTION,
+                pendingIntent).build();
+    }
+
+    private void setUpWalletCardWithType(boolean hasCard, int cardType) {
+        GetWalletCardsResponse response =
+                new GetWalletCardsResponse(
+                        hasCard
+                                ? Collections.singletonList(
+                                createWalletCardWithType(mContext, cardType))
+                                : Collections.EMPTY_LIST, 0);
+
+        mTile.handleSetListening(true);
+
+        verify(mController).queryWalletCards(mCallbackCaptor.capture());
+
+        mCallbackCaptor.getValue().onWalletCardsRetrieved(response);
+        mTestableLooper.processAllMessages();
+    }
+
+    private void setUpWalletCard(boolean hasCard) {
+        GetWalletCardsResponse response =
+                new GetWalletCardsResponse(
+                        hasCard
+                                ? Collections.singletonList(createWalletCard(mContext))
+                                : Collections.EMPTY_LIST, 0);
+
+        mTile.handleSetListening(true);
+
+        verify(mController).queryWalletCards(mCallbackCaptor.capture());
+
+        mCallbackCaptor.getValue().onWalletCardsRetrieved(response);
+        mTestableLooper.processAllMessages();
+    }
+
+    private void setUpInvalidWalletCard(boolean hasCard) {
+        GetWalletCardsResponse response =
+                new GetWalletCardsResponse(
+                        hasCard
+                                ? Collections.singletonList(createInvalidWalletCard(mContext))
+                                : Collections.EMPTY_LIST, 0);
+
+        mTile.handleSetListening(true);
+
+        verify(mController).queryWalletCards(mCallbackCaptor.capture());
+
+        mCallbackCaptor.getValue().onWalletCardsRetrieved(response);
+        mTestableLooper.processAllMessages();
+    }
+
+    private WalletCard createWalletCard(Context context) {
+        PendingIntent pendingIntent =
+                PendingIntent.getActivity(context, 0, mWalletIntent, PendingIntent.FLAG_IMMUTABLE);
+        return new WalletCard.Builder(CARD_ID, CARD_IMAGE, CARD_DESCRIPTION, pendingIntent).build();
+    }
+
+    private WalletCard createInvalidWalletCard(Context context) {
+        PendingIntent pendingIntent =
+                PendingIntent.getActivity(context, 0, mWalletIntent, PendingIntent.FLAG_IMMUTABLE);
+        return new WalletCard.Builder(
+                CARD_ID, INVALID_CARD_IMAGE, CARD_DESCRIPTION, pendingIntent).build();
+    }
+
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
index 7464c88..9518bb6 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthContainerView.java
@@ -809,6 +809,10 @@
     }
 
     @Override
+    public String getClassNameIfItIsConfirmDeviceCredentialActivity() {
+        return  mConfig.mPromptInfo.getClassNameIfItIsConfirmDeviceCredentialActivity();
+    }
+    @Override
     public long getRequestId() {
         return mConfig.mRequestId;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index d5289a4..2977363 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -22,7 +22,6 @@
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.ActivityManager;
 import android.app.ActivityTaskManager;
 import android.app.TaskStackListener;
 import android.content.BroadcastReceiver;
@@ -188,7 +187,7 @@
     final TaskStackListener mTaskStackListener = new TaskStackListener() {
         @Override
         public void onTaskStackChanged() {
-            if (!isOwnerInForeground()) {
+            if (isOwnerInBackground()) {
                 mHandler.post(AuthController.this::cancelIfOwnerIsNotInForeground);
             }
         }
@@ -228,21 +227,20 @@
         }
     }
 
-    private boolean isOwnerInForeground() {
+    private boolean isOwnerInBackground() {
         if (mCurrentDialog != null) {
             final String clientPackage = mCurrentDialog.getOpPackageName();
-            final List<ActivityManager.RunningTaskInfo> runningTasks =
-                    mActivityTaskManager.getTasks(1);
-            if (!runningTasks.isEmpty()) {
-                final String topPackage = runningTasks.get(0).topActivity.getPackageName();
-                if (!topPackage.contentEquals(clientPackage)
-                        && !Utils.isSystem(mContext, clientPackage)) {
-                    Log.w(TAG, "Evicting client due to: " + topPackage);
-                    return false;
-                }
+            final String clientClassNameIfItIsConfirmDeviceCredentialActivity =
+                    mCurrentDialog.getClassNameIfItIsConfirmDeviceCredentialActivity();
+            final boolean isInBackground = Utils.isSystemAppOrInBackground(mActivityTaskManager,
+                    mContext, clientPackage,
+                    clientClassNameIfItIsConfirmDeviceCredentialActivity);
+            if (isInBackground) {
+                Log.w(TAG, "Evicting client due to top activity is not : " + clientPackage);
             }
+            return isInBackground;
         }
-        return true;
+        return false;
     }
 
     private void cancelIfOwnerIsNotInForeground() {
@@ -1258,7 +1256,7 @@
         }
         mCurrentDialog = newDialog;
 
-        if (!promptInfo.isAllowBackgroundAuthentication() && !isOwnerInForeground()) {
+        if (!promptInfo.isAllowBackgroundAuthentication() && isOwnerInBackground()) {
             cancelIfOwnerIsNotInForeground();
         } else {
             mCurrentDialog.show(mWindowManager, savedState);
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java
index 3cfc6f2..9529692 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthDialog.java
@@ -156,6 +156,12 @@
      */
     String getOpPackageName();
 
+    /**
+     * Get the class name of ConfirmDeviceCredentialActivity. Returns null if the direct caller is
+     * not ConfirmDeviceCredentialActivity.
+     */
+    String getClassNameIfItIsConfirmDeviceCredentialActivity();
+
     /** The requestId of the underlying operation within the framework. */
     long getRequestId();
 
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt b/packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt
index 1ca57e7..0cb3e7c 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/Utils.kt
@@ -16,6 +16,7 @@
 package com.android.systemui.biometrics
 
 import android.Manifest
+import android.app.ActivityTaskManager
 import android.annotation.IntDef
 import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHABETIC
 import android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_ALPHANUMERIC
@@ -32,6 +33,7 @@
 import android.hardware.biometrics.SensorPropertiesInternal
 import android.os.UserManager
 import android.util.DisplayMetrics
+import android.util.Log
 import android.view.ViewGroup
 import android.view.WindowInsets
 import android.view.WindowManager
@@ -43,6 +45,8 @@
 import java.lang.annotation.RetentionPolicy
 
 object Utils {
+    private const val TAG = "SysUIBiometricUtils"
+
     const val CREDENTIAL_PIN = 1
     const val CREDENTIAL_PATTERN = 2
     const val CREDENTIAL_PASSWORD = 3
@@ -135,4 +139,37 @@
     @Retention(RetentionPolicy.SOURCE)
     @IntDef(CREDENTIAL_PIN, CREDENTIAL_PATTERN, CREDENTIAL_PASSWORD)
     internal annotation class CredentialType
+
+    @JvmStatic
+    /**
+    * Checks if a client package is running in the background or it's a system app.
+    *
+    * @param clientPackage The name of the package to be checked.
+    * @param clientClassNameIfItIsConfirmDeviceCredentialActivity The class name of
+    *   ConfirmDeviceCredentialActivity.
+    * @return Whether the client package is running in background
+    */
+    fun ActivityTaskManager.isSystemAppOrInBackground(
+        context: Context,
+        clientPackage: String,
+        clientClassNameIfItIsConfirmDeviceCredentialActivity: String?
+    ): Boolean {
+        Log.v(TAG, "Checking if the authenticating is in background, clientPackage:$clientPackage")
+        val tasks = getTasks(Int.MAX_VALUE)
+        if (tasks == null || tasks.isEmpty()) {
+            Log.w(TAG, "No running tasks reported")
+            return false
+        }
+
+        val topActivity = tasks[0].topActivity
+        val isSystemApp = isSystem(context, clientPackage)
+        val topPackageEqualsToClient = topActivity!!.packageName == clientPackage
+        val isClientConfirmDeviceCredentialActivity =
+            clientClassNameIfItIsConfirmDeviceCredentialActivity != null
+        // b/339532378: If it's ConfirmDeviceCredentialActivity, we need to check further on
+        // class name.
+        return !(isSystemApp || topPackageEqualsToClient) ||
+                (isClientConfirmDeviceCredentialActivity &&
+                   topActivity.className != clientClassNameIfItIsConfirmDeviceCredentialActivity)
+    }
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
index d403788..5dfd4a8 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaProjectionPermissionActivity.java
@@ -103,12 +103,11 @@
         final Intent launchingIntent = getIntent();
         mReviewGrantedConsentRequired = launchingIntent.getBooleanExtra(
                 EXTRA_USER_REVIEW_GRANTED_CONSENT, false);
-
-        mPackageName = getCallingPackage();
+        mPackageName = getLaunchedFromPackage();
 
         // This activity is launched directly by an app, or system server. System server provides
         // the package name through the intent if so.
-        if (mPackageName == null) {
+        if (getCallingPackage() == null)  {
             if (launchingIntent.hasExtra(EXTRA_PACKAGE_REUSING_GRANTED_CONSENT)) {
                 mPackageName = launchingIntent.getStringExtra(
                         EXTRA_PACKAGE_REUSING_GRANTED_CONSENT);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
index e382eca..7e686a2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/QuickAccessWalletTile.java
@@ -16,8 +16,13 @@
 
 package com.android.systemui.qs.tiles;
 
-import static android.graphics.drawable.Icon.TYPE_URI;
 import static android.provider.Settings.Secure.NFC_PAYMENT_DEFAULT_COMPONENT;
+import static android.graphics.drawable.Icon.TYPE_URI;
+import static android.graphics.drawable.Icon.TYPE_URI_ADAPTIVE_BITMAP;
+import static android.graphics.drawable.Icon.TYPE_RESOURCE;
+import static android.graphics.drawable.Icon.TYPE_BITMAP;
+import static android.graphics.drawable.Icon.TYPE_ADAPTIVE_BITMAP;
+import static android.graphics.drawable.Icon.TYPE_DATA;
 
 import static com.android.systemui.wallet.controller.QuickAccessWalletController.WalletChangeEvent.DEFAULT_PAYMENT_APP_CHANGE;
 import static com.android.systemui.wallet.util.WalletCardUtilsKt.getPaymentCards;
@@ -227,11 +232,21 @@
                 return;
             }
             mSelectedCard = cards.get(selectedIndex);
-            android.graphics.drawable.Icon cardImageIcon = mSelectedCard.getCardImage();
-            if (cardImageIcon.getType() == TYPE_URI) {
-                mCardViewDrawable = null;
-            } else {
-                mCardViewDrawable = mSelectedCard.getCardImage().loadDrawable(mContext);
+            switch (mSelectedCard.getCardImage().getType()) {
+                case TYPE_BITMAP:
+                case TYPE_ADAPTIVE_BITMAP:
+                    mCardViewDrawable = mSelectedCard.getCardImage().loadDrawable(mContext);
+                    break;
+                case TYPE_URI:
+                case TYPE_URI_ADAPTIVE_BITMAP:
+                case TYPE_RESOURCE:
+                case TYPE_DATA:
+                    mCardViewDrawable = null;
+                    break;
+                default:
+                    Log.e(TAG, "Unknown icon type: " + mSelectedCard.getCardImage().getType());
+                    mCardViewDrawable = null;
+                    break;
             }
             refreshState();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
index 895c25c..eda5c4f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarIconView.java
@@ -661,17 +661,7 @@
             }
         }
 
-        CharSequence title = n.extras.getCharSequence(Notification.EXTRA_TITLE);
-        CharSequence text = n.extras.getCharSequence(Notification.EXTRA_TEXT);
-        CharSequence ticker = n.tickerText;
-
-        // Some apps just put the app name into the title
-        CharSequence titleOrText = TextUtils.equals(title, appName) ? text : title;
-
-        CharSequence desc = !TextUtils.isEmpty(titleOrText) ? titleOrText
-                : !TextUtils.isEmpty(ticker) ? ticker : "";
-
-        return c.getString(R.string.accessibility_desc_notification_icon, appName, desc);
+        return c.getString(R.string.accessibility_desc_notification_icon, appName, "");
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java
index 6fd0a4d..bced661 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletScreenController.java
@@ -330,13 +330,19 @@
         QAWalletCardViewInfo(Context context, WalletCard walletCard) {
             mWalletCard = walletCard;
             Icon cardImageIcon = mWalletCard.getCardImage();
-            if (cardImageIcon.getType() == Icon.TYPE_URI) {
-                mCardDrawable = null;
-            } else {
+            if (cardImageIcon.getType() == Icon.TYPE_BITMAP
+                    || cardImageIcon.getType() == Icon.TYPE_ADAPTIVE_BITMAP) {
                 mCardDrawable = mWalletCard.getCardImage().loadDrawable(context);
+            } else {
+                mCardDrawable = null;
             }
             Icon icon = mWalletCard.getCardIcon();
-            mIconDrawable = icon == null ? null : icon.loadDrawable(context);
+            if (icon != null && (icon.getType() == Icon.TYPE_BITMAP
+                    || icon.getType() == Icon.TYPE_ADAPTIVE_BITMAP)) {
+                mIconDrawable = icon.loadDrawable(context);
+            } else {
+                mIconDrawable = null;
+            }
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java
index cab47a3..2bb4931 100644
--- a/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java
+++ b/packages/SystemUI/src/com/android/systemui/wallet/ui/WalletView.java
@@ -282,6 +282,11 @@
         return mCardLabel;
     }
 
+    @VisibleForTesting
+    ImageView getIcon() {
+        return mIcon;
+    }
+
     @Nullable
     private static Drawable getHeaderIcon(Context context, WalletCardViewInfo walletCard) {
         Drawable icon = walletCard.getIcon();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java
index c1d11aa..d55bedb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/wallet/ui/WalletScreenControllerTest.java
@@ -316,6 +316,31 @@
     }
 
     @Test
+    public void queryCards_hasCards_showCarousel_invalidIconSource_noIcon() {
+        GetWalletCardsResponse response =
+                new GetWalletCardsResponse(
+                        Collections.singletonList(createWalletCardWithInvalidIcon(mContext)), 0);
+
+        mController.queryWalletCards();
+        mTestableLooper.processAllMessages();
+
+        verify(mWalletClient).getWalletCards(any(), any(), mCallbackCaptor.capture());
+
+        QuickAccessWalletClient.OnWalletCardsRetrievedCallback callback =
+                mCallbackCaptor.getValue();
+
+        assertEquals(mController, callback);
+
+        callback.onWalletCardsRetrieved(response);
+        mTestableLooper.processAllMessages();
+
+        assertEquals(VISIBLE, mWalletView.getCardCarousel().getVisibility());
+        assertEquals(GONE, mWalletView.getEmptyStateView().getVisibility());
+        assertEquals(GONE, mWalletView.getErrorView().getVisibility());
+        assertEquals(null, mWalletView.getIcon().getDrawable());
+    }
+
+    @Test
     public void queryCards_noCards_showEmptyState() {
         GetWalletCardsResponse response = new GetWalletCardsResponse(Collections.EMPTY_LIST, 0);
 
@@ -507,6 +532,16 @@
                 .build();
     }
 
+    private WalletCard createWalletCardWithInvalidIcon(Context context) {
+        PendingIntent pendingIntent =
+                PendingIntent.getActivity(context, 0, mWalletIntent, PendingIntent.FLAG_IMMUTABLE);
+        return new WalletCard.Builder(
+                CARD_ID_1, createIconWithInvalidSource(), "•••• 1234", pendingIntent)
+                .setCardIcon(createIconWithInvalidSource())
+                .setCardLabel("Hold to reader")
+                .build();
+    }
+
     private WalletCard createCrazyWalletCard(Context context, boolean hasLabel) {
         PendingIntent pendingIntent =
                 PendingIntent.getActivity(context, 0, mWalletIntent, PendingIntent.FLAG_IMMUTABLE);
@@ -520,6 +555,10 @@
         return Icon.createWithBitmap(Bitmap.createBitmap(70, 44, Bitmap.Config.ARGB_8888));
     }
 
+    private static Icon createIconWithInvalidSource() {
+        return Icon.createWithContentUri("content://media/external/images/media");
+    }
+
     private WalletCardViewInfo createCardViewInfo(WalletCard walletCard) {
         return new WalletScreenController.QAWalletCardViewInfo(
                 mContext, walletCard);
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index a305ed3..c73b633 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -1364,4 +1364,11 @@
     @Deprecated
     public abstract void legacyReconcileSecondaryDexFiles(String packageName)
             throws LegacyDexoptDisabledException;
+    /**
+     * Sets the display compat mode for a package.
+     * @param packageName a specific package
+     * @param userId The user for whom the package is installed
+     * @param enabled Whether to enable or disable the display compat mode
+     */
+    public abstract void setDisplayCompat(String packageName, int userId, boolean enabled);
 }
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 0e93883..5d0fe1a 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -3137,6 +3137,12 @@
                                         "the type and name should not be empty");
                                 return;
                             }
+                            if (!type.equals(mAccountType)) {
+                                onError(AccountManager.ERROR_CODE_INVALID_RESPONSE,
+                                        "incorrect account type");
+                                return;
+                            }
+
                             Account resultAccount = new Account(name, type);
                             if (!customTokens) {
                                 saveAuthTokenToDatabase(
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 5402f54..bb2445e3 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -13954,8 +13954,7 @@
                 return null;
             }
             if (callerApp.info.uid != SYSTEM_UID
-                    && !callerApp.getPkgList().containsKey(callerPackage)
-                    && !"android".equals(callerPackage)) {
+                    && !callerApp.getPkgList().containsKey(callerPackage)) {
                 throw new SecurityException("Given caller package " + callerPackage
                         + " is not running in process " + callerApp);
             }
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index e2388e2..fe98aa0 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -589,7 +589,7 @@
         }
     }
 
-    /** Returned from {@link #verifyAndGetBypass(int, String, String, String, boolean)}. */
+    /** Returned from {@link #verifyAndGetBypass(int, String, String, int, String, boolean)}. */
     private static final class PackageVerificationResult {
 
         final RestrictionBypass bypass;
@@ -2503,10 +2503,10 @@
     public int checkPackage(int uid, String packageName) {
         Objects.requireNonNull(packageName);
         try {
-            verifyAndGetBypass(uid, packageName, null, null, true);
+            verifyAndGetBypass(uid, packageName, null, Process.INVALID_UID, null, true);
             // When the caller is the system, it's possible that the packageName is the special
             // one (e.g., "root") which isn't actually existed.
-            if (resolveUid(packageName) == uid
+            if (resolveNonAppUid(packageName) == uid
                     || (isPackageExisted(packageName)
                             && !filterAppAccessUnlocked(packageName, UserHandle.getUserId(uid)))) {
                 return AppOpsManager.MODE_ALLOWED;
@@ -2636,7 +2636,7 @@
             boolean shouldCollectMessage) {
         PackageVerificationResult pvr;
         try {
-            pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName);
+            pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName);
             boolean wasNull = attributionTag == null;
             if (!pvr.isAttributionTagValid) {
                 attributionTag = null;
@@ -3178,7 +3178,7 @@
             int attributionChainId, boolean dryRun) {
         PackageVerificationResult pvr;
         try {
-            pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName);
+            pvr = verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName);
             if (!pvr.isAttributionTagValid) {
                 attributionTag = null;
             }
@@ -3671,13 +3671,17 @@
     private boolean isSpecialPackage(int callingUid, @Nullable String packageName) {
         final String resolvedPackage = AppOpsManager.resolvePackageName(callingUid, packageName);
         return callingUid == Process.SYSTEM_UID
-                || resolveUid(resolvedPackage) != Process.INVALID_UID;
+                || resolveNonAppUid(resolvedPackage) != Process.INVALID_UID;
     }
 
     private boolean isCallerAndAttributionTrusted(@NonNull AttributionSource attributionSource) {
         if (attributionSource.getUid() != Binder.getCallingUid()
                 && attributionSource.isTrusted(mContext)) {
-            return true;
+            // if there is a next attribution source, it must be trusted, as well.
+            if (attributionSource.getNext() == null
+                    || attributionSource.getNext().isTrusted(mContext)) {
+                return true;
+            }
         }
         return mContext.checkPermission(android.Manifest.permission.UPDATE_APP_OPS_STATS,
                 Binder.getCallingPid(), Binder.getCallingUid(), null)
@@ -3760,19 +3764,20 @@
     }
 
     /**
-     * @see #verifyAndGetBypass(int, String, String, String, boolean)
+     * @see #verifyAndGetBypass(int, String, String, int, String, boolean)
      */
     private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName,
             @Nullable String attributionTag) {
-        return verifyAndGetBypass(uid, packageName, attributionTag, null);
+        return verifyAndGetBypass(uid, packageName, attributionTag, Process.INVALID_UID, null);
     }
 
     /**
-     * @see #verifyAndGetBypass(int, String, String, String, boolean)
+     * @see #verifyAndGetBypass(int, String, String, int, String, boolean)
      */
     private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName,
-            @Nullable String attributionTag, @Nullable String proxyPackageName) {
-        return verifyAndGetBypass(uid, packageName, attributionTag, proxyPackageName, false);
+            @Nullable String attributionTag, int proxyUid, @Nullable String proxyPackageName) {
+        return verifyAndGetBypass(uid, packageName, attributionTag, proxyUid, proxyPackageName,
+                false);
     }
 
     /**
@@ -3783,14 +3788,15 @@
      * @param uid The uid the package belongs to
      * @param packageName The package the might belong to the uid
      * @param attributionTag attribution tag or {@code null} if no need to verify
-     * @param proxyPackageName The proxy package, from which the attribution tag is to be pulled
+     * @param proxyUid The proxy uid, from which the attribution tag is to be pulled
+     * @param proxyPackageName The proxy package, from which the attribution tag may be pulled
      * @param suppressErrorLogs Whether to print to logcat about nonmatching parameters
      *
      * @return PackageVerificationResult containing {@link RestrictionBypass} and whether the
      *         attribution tag is valid
      */
     private @NonNull PackageVerificationResult verifyAndGetBypass(int uid, String packageName,
-            @Nullable String attributionTag, @Nullable String proxyPackageName,
+            @Nullable String attributionTag, int proxyUid, @Nullable String proxyPackageName,
             boolean suppressErrorLogs) {
         if (uid == Process.ROOT_UID) {
             // For backwards compatibility, don't check package name for root UID.
@@ -3834,34 +3840,47 @@
 
         int callingUid = Binder.getCallingUid();
 
-        // Allow any attribution tag for resolvable uids
-        int pkgUid;
+        // Allow any attribution tag for resolvable, non-app uids
+        int nonAppUid;
         if (Objects.equals(packageName, "com.android.shell")) {
             // Special case for the shell which is a package but should be able
             // to bypass app attribution tag restrictions.
-            pkgUid = Process.SHELL_UID;
+            nonAppUid = Process.SHELL_UID;
         } else {
-            pkgUid = resolveUid(packageName);
+            nonAppUid = resolveNonAppUid(packageName);
         }
-        if (pkgUid != Process.INVALID_UID) {
-            if (pkgUid != UserHandle.getAppId(uid)) {
+        if (nonAppUid != Process.INVALID_UID) {
+            if (nonAppUid != UserHandle.getAppId(uid)) {
                 if (!suppressErrorLogs) {
                     Slog.e(TAG, "Bad call made by uid " + callingUid + ". "
-                            + "Package \"" + packageName + "\" does not belong to uid " + uid
-                            + ".");
+                                + "Package \"" + packageName + "\" does not belong to uid " + uid
+                                + ".");
                 }
-                String otherUidMessage = DEBUG ? " but it is really " + pkgUid : " but it is not";
-                throw new SecurityException("Specified package \"" + packageName + "\" under uid "
-                        +  UserHandle.getAppId(uid) + otherUidMessage);
+                String otherUidMessage =
+                            DEBUG ? " but it is really " + nonAppUid : " but it is not";
+                throw new SecurityException("Specified package \"" + packageName
+                            + "\" under uid " +  UserHandle.getAppId(uid) + otherUidMessage);
+            }
+            // We only allow bypassing the attribution tag verification if the proxy is a
+            // system app (or is null), in order to prevent abusive apps clogging the appops
+            // system with unlimited attribution tags via proxy calls.
+            boolean proxyIsSystemAppOrNull = true;
+            if (proxyPackageName != null) {
+                int proxyAppId = UserHandle.getAppId(proxyUid);
+                if (proxyAppId >= Process.FIRST_APPLICATION_UID) {
+                    proxyIsSystemAppOrNull =
+                            mPackageManagerInternal.isSystemPackage(proxyPackageName);
+                }
             }
             return new PackageVerificationResult(RestrictionBypass.UNRESTRICTED,
-                    /* isAttributionTagValid */ true);
+                    /* isAttributionTagValid */ proxyIsSystemAppOrNull);
         }
 
         int userId = UserHandle.getUserId(uid);
         RestrictionBypass bypass = null;
         boolean isAttributionTagValid = false;
 
+        int pkgUid = nonAppUid;
         final long ident = Binder.clearCallingIdentity();
         try {
             PackageManagerInternal pmInt = LocalServices.getService(PackageManagerInternal.class);
@@ -4613,7 +4632,7 @@
             if (nonpackageUid != -1) {
                 packageName = null;
             } else {
-                packageUid = resolveUid(packageName);
+                packageUid = resolveNonAppUid(packageName);
                 if (packageUid < 0) {
                     packageUid = AppGlobals.getPackageManager().getPackageUid(packageName,
                             PackageManager.MATCH_UNINSTALLED_PACKAGES, userId);
@@ -5628,7 +5647,13 @@
                 if (restricted && attrOp.isRunning()) {
                     attrOp.pause();
                 } else if (attrOp.isPaused()) {
-                    attrOp.resume();
+                    RestrictionBypass bypass = verifyAndGetBypass(uid, ops.packageName, attrOp.tag)
+                            .bypass;
+                    if (!isOpRestrictedLocked(uid, code, ops.packageName, attrOp.tag,
+                            bypass, false)) {
+                        // Only resume if there are no other restrictions remaining on this op
+                        attrOp.resume();
+                    }
                 }
             }
         }
@@ -6077,7 +6102,7 @@
         }
     }
 
-    private static int resolveUid(String packageName)  {
+    private static int resolveNonAppUid(String packageName)  {
         if (packageName == null) {
             return Process.INVALID_UID;
         }
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index ad043aa..7856df3 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -7728,6 +7728,12 @@
         }
     }
 
+    private boolean shouldPreserveVolume(boolean userSwitch, VolumeGroupState vgs) {
+        // as for STREAM_MUSIC, preserve volume from one user to the next except
+        // Android Automotive platform
+        return (userSwitch && vgs.isMusic()) && !isPlatformAutomotive();
+    }
+
     private void readVolumeGroupsSettings(boolean userSwitch) {
         synchronized (mSettingsLock) {
             synchronized (VolumeStreamState.class) {
@@ -7736,8 +7742,7 @@
                 }
                 for (int i = 0; i < sVolumeGroupStates.size(); i++) {
                     VolumeGroupState vgs = sVolumeGroupStates.valueAt(i);
-                    // as for STREAM_MUSIC, preserve volume from one user to the next.
-                    if (!(userSwitch && vgs.isMusic())) {
+                    if (!shouldPreserveVolume(userSwitch, vgs)) {
                         vgs.clearIndexCache();
                         vgs.readSettings();
                     }
@@ -8132,6 +8137,11 @@
             mIndexMap.clear();
         }
 
+        private @UserIdInt int getVolumePersistenceUserId() {
+            return isMusic() && !isPlatformAutomotive()
+                    ? UserHandle.USER_SYSTEM : UserHandle.USER_CURRENT;
+        }
+
         private void persistVolumeGroup(int device) {
             // No need to persist the index if the volume group is backed up
             // by a public stream type as this is redundant
@@ -8149,7 +8159,7 @@
             boolean success = mSettings.putSystemIntForUser(mContentResolver,
                     getSettingNameForDevice(device),
                     getIndex(device),
-                    isMusic() ? UserHandle.USER_SYSTEM : UserHandle.USER_CURRENT);
+                    getVolumePersistenceUserId());
             if (!success) {
                 Log.e(TAG, "persistVolumeGroup failed for group " +  mAudioVolumeGroup.name());
             }
@@ -8172,7 +8182,7 @@
                     String name = getSettingNameForDevice(device);
                     index = mSettings.getSystemIntForUser(
                             mContentResolver, name, defaultIndex,
-                            isMusic() ? UserHandle.USER_SYSTEM : UserHandle.USER_CURRENT);
+                            getVolumePersistenceUserId());
                     if (index == -1) {
                         continue;
                     }
diff --git a/services/core/java/com/android/server/notification/ManagedServices.java b/services/core/java/com/android/server/notification/ManagedServices.java
index fa9886e..975f33f 100644
--- a/services/core/java/com/android/server/notification/ManagedServices.java
+++ b/services/core/java/com/android/server/notification/ManagedServices.java
@@ -945,7 +945,7 @@
                 || isPackageOrComponentAllowed(component.getPackageName(), userId))) {
             return false;
         }
-        return isValidService(component, userId);
+        return componentHasBindPermission(component, userId);
     }
 
     private boolean componentHasBindPermission(ComponentName component, int userId) {
@@ -1282,12 +1282,11 @@
                     if (TextUtils.equals(getPackageName(approvedPackageOrComponent), packageName)) {
                         final ComponentName component = ComponentName.unflattenFromString(
                                 approvedPackageOrComponent);
-                        if (component != null && !isValidService(component, userId)) {
+                        if (component != null && !componentHasBindPermission(component, userId)) {
                             approved.removeAt(j);
                             if (DEBUG) {
                                 Slog.v(TAG, "Removing " + approvedPackageOrComponent
-                                        + " from approved list; no bind permission or "
-                                        + "service interface filter found "
+                                        + " from approved list; no bind permission found "
                                         + mConfig.bindPermission);
                             }
                         }
@@ -1306,11 +1305,6 @@
         }
     }
 
-    protected boolean isValidService(ComponentName component, int userId) {
-        return componentHasBindPermission(component, userId) && queryPackageForServices(
-                component.getPackageName(), userId).contains(component);
-    }
-
     protected boolean isValidEntry(String packageOrComponent, int userId) {
         return hasMatchingServices(packageOrComponent, userId);
     }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index bb1de5e..04d7cd7 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2342,6 +2342,7 @@
                 mPermissionManager,
                 mNotificationChannelLogger,
                 mAppOps,
+                mUgmInternal,
                 new SysUiStatsEvent.BuilderFactory(),
                 mShowReviewPermissionsNotification);
         mRankingHelper = new RankingHelper(getContext(),
@@ -5881,13 +5882,7 @@
             final Uri originalSoundUri =
                     (originalChannel != null) ? originalChannel.getSound() : null;
             if (soundUri != null && !Objects.equals(originalSoundUri, soundUri)) {
-                Binder.withCleanCallingIdentity(() -> {
-                    mUgmInternal.checkGrantUriPermission(sourceUid, null,
-                            ContentProvider.getUriWithoutUserId(soundUri),
-                            Intent.FLAG_GRANT_READ_URI_PERMISSION,
-                            ContentProvider.getUserIdFromUri(soundUri,
-                            UserHandle.getUserId(sourceUid)));
-                });
+                PermissionHelper.grantUriPermission(mUgmInternal, soundUri, sourceUid);
             }
         }
 
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index 100c638..de6c36f 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -1417,20 +1417,13 @@
      * {@link SecurityException} depending on target SDK of enqueuing app.
      */
     private void visitGrantableUri(Uri uri, boolean userOverriddenUri, boolean isSound) {
-        if (uri == null || !ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) return;
-
         if (mGrantableUris != null && mGrantableUris.contains(uri)) {
             return; // already verified this URI
         }
 
         final int sourceUid = getSbn().getUid();
-        final long ident = Binder.clearCallingIdentity();
         try {
-            // This will throw a SecurityException if the caller can't grant.
-            mUgmInternal.checkGrantUriPermission(sourceUid, null,
-                    ContentProvider.getUriWithoutUserId(uri),
-                    Intent.FLAG_GRANT_READ_URI_PERMISSION,
-                    ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(sourceUid)));
+            PermissionHelper.grantUriPermission(mUgmInternal, uri, sourceUid);
 
             if (mGrantableUris == null) {
                 mGrantableUris = new ArraySet<>();
@@ -1450,8 +1443,6 @@
                     }
                 }
             }
-        } finally {
-            Binder.restoreCallingIdentity(ident);
         }
     }
 
diff --git a/services/core/java/com/android/server/notification/PermissionHelper.java b/services/core/java/com/android/server/notification/PermissionHelper.java
index 93c83e1..e62613f 100644
--- a/services/core/java/com/android/server/notification/PermissionHelper.java
+++ b/services/core/java/com/android/server/notification/PermissionHelper.java
@@ -25,19 +25,25 @@
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.UserIdInt;
+import android.content.ContentProvider;
+import android.content.ContentResolver;
 import android.content.Context;
+import android.content.Intent;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.ParceledListSlice;
+import android.net.Uri;
 import android.os.Binder;
 import android.os.RemoteException;
+import android.os.UserHandle;
 import android.permission.IPermissionManager;
 import android.util.ArrayMap;
 import android.util.Pair;
 import android.util.Slog;
 
 import com.android.internal.util.ArrayUtils;
+import com.android.server.uri.UriGrantsManagerInternal;
 
 import java.util.Collections;
 import java.util.HashSet;
@@ -58,7 +64,7 @@
     private final IPermissionManager mPermManager;
 
     public PermissionHelper(Context context, IPackageManager packageManager,
-            IPermissionManager permManager) {
+                IPermissionManager permManager) {
         mContext = context;
         mPackageManager = packageManager;
         mPermManager = permManager;
@@ -296,6 +302,19 @@
         return false;
     }
 
+    static void grantUriPermission(final UriGrantsManagerInternal ugmInternal, Uri uri,
+            int sourceUid) {
+        if (uri == null || !ContentResolver.SCHEME_CONTENT.equals(uri.getScheme())) return;
+
+        Binder.withCleanCallingIdentity(() -> {
+            // This will throw a SecurityException if the caller can't grant.
+            ugmInternal.checkGrantUriPermission(sourceUid, null,
+                    ContentProvider.getUriWithoutUserId(uri),
+                    Intent.FLAG_GRANT_READ_URI_PERMISSION,
+                    ContentProvider.getUserIdFromUri(uri, UserHandle.getUserId(sourceUid)));
+        });
+    }
+
     public static class PackagePermission {
         public final String packageName;
         public final @UserIdInt int userId;
diff --git a/services/core/java/com/android/server/notification/PreferencesHelper.java b/services/core/java/com/android/server/notification/PreferencesHelper.java
index 3f799dc..4ebe2fb 100644
--- a/services/core/java/com/android/server/notification/PreferencesHelper.java
+++ b/services/core/java/com/android/server/notification/PreferencesHelper.java
@@ -85,6 +85,7 @@
 import com.android.modules.utils.TypedXmlPullParser;
 import com.android.modules.utils.TypedXmlSerializer;
 import com.android.server.notification.PermissionHelper.PackagePermission;
+import com.android.server.uri.UriGrantsManagerInternal;
 
 import org.json.JSONArray;
 import org.json.JSONException;
@@ -196,6 +197,7 @@
     private final PermissionManager mPermissionManager;
     private final NotificationChannelLogger mNotificationChannelLogger;
     private final AppOpsManager mAppOps;
+    private final UriGrantsManagerInternal mUgmInternal;
 
     private SparseBooleanArray mBadgingEnabled;
     private SparseBooleanArray mBubblesEnabled;
@@ -212,6 +214,7 @@
             ZenModeHelper zenHelper, PermissionHelper permHelper, PermissionManager permManager,
             NotificationChannelLogger notificationChannelLogger,
             AppOpsManager appOpsManager,
+            UriGrantsManagerInternal ugmInternal,
             SysUiStatsEvent.BuilderFactory statsEventBuilderFactory,
             boolean showReviewPermissionsNotification) {
         mContext = context;
@@ -223,6 +226,7 @@
         mNotificationChannelLogger = notificationChannelLogger;
         mAppOps = appOpsManager;
         mStatsEventBuilderFactory = statsEventBuilderFactory;
+        mUgmInternal = ugmInternal;
         mShowReviewPermissionsNotification = showReviewPermissionsNotification;
 
         XML_VERSION = 4;
@@ -1010,6 +1014,11 @@
                 }
                 clearLockedFieldsLocked(channel);
 
+                // Verify that the app has permission to read the sound Uri
+                // Only check for new channels, as regular apps can only set sound
+                // before creating. See: {@link NotificationChannel#setSound}
+                PermissionHelper.grantUriPermission(mUgmInternal, channel.getSound(), uid);
+
                 channel.setImportanceLockedByCriticalDeviceFunction(
                         r.defaultAppLockedImportance || r.fixedImportance);
 
diff --git a/services/core/java/com/android/server/pm/ComputerEngine.java b/services/core/java/com/android/server/pm/ComputerEngine.java
index 78f1fa6..d11d417 100644
--- a/services/core/java/com/android/server/pm/ComputerEngine.java
+++ b/services/core/java/com/android/server/pm/ComputerEngine.java
@@ -67,6 +67,7 @@
 import android.app.ActivityManager;
 import android.app.admin.DevicePolicyManagerInternal;
 import android.content.ComponentName;
+import android.content.ContentProvider;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
@@ -272,7 +273,7 @@
         @Nullable
         public SharedUserSetting getSharedUserFromId(String name) {
             try {
-                return mSettings.getSharedUserLPw(name, 0, 0, false /*create*/);
+                return mSettings.getSharedUserLPw(name, 0, 0, 0, false /*create*/);
             } catch (PackageManagerException ignored) {
                 // This is impossible do to create being false
                 throw new RuntimeException(ignored);
@@ -634,11 +635,11 @@
             String resolvedType, @PackageManager.ResolveInfoFlagsBits long flags, int userId,
             int callingUid, boolean includeInstantApps) {
         if (!mUserManager.exists(userId)) return Collections.emptyList();
-        enforceCrossUserOrProfilePermission(callingUid,
+        enforceCrossUserOrProfilePermission(Binder.getCallingUid(),
                 userId,
                 false /*requireFullPermission*/,
                 false /*checkShell*/,
-                "query intent receivers");
+                "query intent services");
         final String instantAppPkgName = getInstantAppPackageName(callingUid);
         flags = updateFlagsForResolve(flags, userId, callingUid, includeInstantApps,
                 false /* isImplicitImageCaptureIntentAndNotSetByDpc */);
@@ -1517,6 +1518,7 @@
             ai.setVersionCode(ps.getVersionCode());
             ai.flags = ps.getFlags();
             ai.privateFlags = ps.getPrivateFlags();
+            ai.privateFlagsExt = ps.getPrivateFlagsExt();
             pi.applicationInfo = PackageInfoUtils.generateDelegateApplicationInfo(
                     ai, flags, state, userId);
 
@@ -2155,10 +2157,10 @@
             return true;
         }
         if (requireFullPermission) {
-            return hasPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL);
+            return hasPermission(Manifest.permission.INTERACT_ACROSS_USERS_FULL, callingUid);
         }
-        return hasPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)
-                || hasPermission(Manifest.permission.INTERACT_ACROSS_USERS);
+        return hasPermission(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL, callingUid)
+            || hasPermission(Manifest.permission.INTERACT_ACROSS_USERS, callingUid);
     }
 
     /**
@@ -2174,6 +2176,11 @@
                 == PackageManager.PERMISSION_GRANTED;
     }
 
+    private boolean hasPermission(String permission, int uid) {
+        return mContext.checkPermission(permission, Process.INVALID_PID, uid)
+                == PackageManager.PERMISSION_GRANTED;
+    }
+
     public final boolean isCallerSameApp(String packageName, int uid) {
         return isCallerSameApp(packageName, uid, false /* resolveIsolatedUid */);
     }
@@ -4590,7 +4597,7 @@
         final boolean listApex = (flags & MATCH_APEX) != 0;
 
         enforceCrossUserPermission(
-                callingUid,
+                Binder.getCallingUid(),
                 userId,
                 false /* requireFullPermission */,
                 false /* checkShell */,
@@ -4667,8 +4674,14 @@
             int callingUid) {
         if (!mUserManager.exists(userId)) return null;
         flags = updateFlagsForComponent(flags, userId);
-        final ProviderInfo providerInfo = mComponentResolver.queryProvider(this, name, flags,
-                userId);
+
+        // Callers of this API may not always separate the userID and authority. Let's parse it
+        // before resolving
+        String authorityWithoutUserId = ContentProvider.getAuthorityWithoutUserId(name);
+        userId = ContentProvider.getUserIdFromAuthority(name, userId);
+
+        final ProviderInfo providerInfo = mComponentResolver.queryProvider(this,
+                authorityWithoutUserId, flags, userId);
         boolean checkedGrants = false;
         if (providerInfo != null) {
             // Looking for cross-user grants before enforcing the typical cross-users permissions
@@ -4682,7 +4695,7 @@
         if (!checkedGrants) {
             boolean enforceCrossUser = true;
 
-            if (isAuthorityRedirectedForCloneProfile(name)) {
+            if (isAuthorityRedirectedForCloneProfile(authorityWithoutUserId)) {
                 final UserManagerInternal umInternal = mInjector.getUserManagerInternal();
 
                 UserInfo userInfo = umInternal.getUserInfo(UserHandle.getUserId(callingUid));
@@ -5136,7 +5149,7 @@
     @Override
     public int getComponentEnabledSetting(@NonNull ComponentName component, int callingUid,
             @UserIdInt int userId) {
-        enforceCrossUserPermission(callingUid, userId, false /*requireFullPermission*/,
+        enforceCrossUserPermission(Binder.getCallingUid(), userId, false /*requireFullPermission*/,
                 false /*checkShell*/, "getComponentEnabled");
         return getComponentEnabledSettingInternal(component, callingUid, userId);
     }
diff --git a/services/core/java/com/android/server/pm/DeletePackageHelper.java b/services/core/java/com/android/server/pm/DeletePackageHelper.java
index c1d5af5..2d2631a 100644
--- a/services/core/java/com/android/server/pm/DeletePackageHelper.java
+++ b/services/core/java/com/android/server/pm/DeletePackageHelper.java
@@ -611,7 +611,8 @@
                     null /*harmfulAppWarning*/,
                     null /*splashScreenTheme*/,
                     0 /*firstInstallTime*/,
-                    PackageManager.USER_MIN_ASPECT_RATIO_UNSET);
+                    PackageManager.USER_MIN_ASPECT_RATIO_UNSET,
+                    false /*displayCompat*/);
         }
         mPm.mSettings.writeKernelMappingLPr(ps);
     }
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 6ae78343..bc862a9 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -4060,7 +4060,7 @@
             if (!ignoreSharedUserId && parsedPackage.getSharedUserId() != null) {
                 sharedUserSetting = mPm.mSettings.getSharedUserLPw(
                         parsedPackage.getSharedUserId(),
-                        0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/, true /*create*/);
+                        0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/, 0 /* pkgPrivateFlagsExt */, true /*create*/);
             } else {
                 sharedUserSetting = null;
             }
@@ -4753,7 +4753,7 @@
             try {
                 synchronized (mPm.mLock) {
                     sharedUserSetting = mPm.mSettings.getSharedUserLPw(pkg.getSharedUserId(),
-                            0, 0, false);
+                            0, 0, 0, false);
                 }
             } catch (PackageManagerException ignore) {
             }
@@ -4795,7 +4795,7 @@
             synchronized (mPm.mLock) {
                 try {
                     sharedUserSetting = mPm.mSettings.getSharedUserLPw(pkg.getSharedUserId(), 0,
-                            0, false);
+                            0, 0, false);
                 } catch (PackageManagerException ignore) {
                 }
                 if (sharedUserSetting != null && sharedUserSetting.isPrivileged()) {
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index df85b5d..dd5f6f9 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -1892,23 +1892,23 @@
 
         t.traceBegin("addSharedUsers");
         mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
-                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
+                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED, 0);
         mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
-                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
+                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED, 0);
         mSettings.addSharedUserLPw("android.uid.log", LOG_UID,
-                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
+                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED, 0);
         mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,
-                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
+                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED, 0);
         mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,
-                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
+                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED, 0);
         mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
-                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
+                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED, 0);
         mSettings.addSharedUserLPw("android.uid.se", SE_UID,
-                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
+                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED, 0);
         mSettings.addSharedUserLPw("android.uid.networkstack", NETWORKSTACK_UID,
-                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
+                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED, 0);
         mSettings.addSharedUserLPw("android.uid.uwb", UWB_UID,
-                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);
+                ApplicationInfo.FLAG_SYSTEM, ApplicationInfo.PRIVATE_FLAG_PRIVILEGED, 0);
         t.traceEnd();
 
         String separateProcesses = SystemProperties.get("debug.separate_processes");
@@ -6990,6 +6990,24 @@
             mHandler.post(() -> PackageManagerService.this.notifyInstallObserver(packageName,
                     true /* killApp */));
         }
+
+        @Override
+        public void setDisplayCompat(String packageName, int userId, boolean enabled) {
+            final int callingUid = Binder.getCallingUid();
+            final Computer snapshot = snapshotComputer();
+            snapshot.enforceCrossUserPermission(callingUid, userId, false /* requireFullPermission */,
+                    false /* checkShell */, "setDisplayCompat");
+            enforceOwnerRights(snapshot, packageName, callingUid);
+
+            PackageStateInternal packageState = snapshot.getPackageStateForInstalledAndFiltered(
+                    packageName, callingUid, userId);
+            if (packageState == null) {
+                return;
+            }
+
+            PackageManagerService.this.commitPackageStateMutation(null, packageName,
+                state -> state.userState(userId).setDisplayCompat(enabled));
+        }
     }
 
     private void setEnabledOverlayPackages(@UserIdInt int userId,
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 3e9ccac..fdb198b8 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -211,12 +211,12 @@
             String legacyNativeLibraryPath, String primaryCpuAbi,
             String secondaryCpuAbi, String cpuAbiOverride,
             long longVersionCode, int pkgFlags, int pkgPrivateFlags,
-            int sharedUserAppId,
+            int pkgPrivateFlagsExt, int sharedUserAppId,
             String[] usesSdkLibraries, long[] usesSdkLibrariesVersionsMajor,
             String[] usesStaticLibraries, long[] usesStaticLibrariesVersions,
             Map<String, Set<String>> mimeGroups,
             @NonNull UUID domainSetId) {
-        super(pkgFlags, pkgPrivateFlags);
+        super(pkgFlags, pkgPrivateFlags, pkgPrivateFlagsExt);
         this.mName = name;
         this.mRealName = realName;
         this.usesSdkLibraries = usesSdkLibraries;
@@ -875,7 +875,7 @@
             ArraySet<String> enabledComponents, ArraySet<String> disabledComponents,
             int installReason, int uninstallReason,
             String harmfulAppWarning, String splashScreenTheme,
-            long firstInstallTime, int aspectRatio) {
+            long firstInstallTime, int aspectRatio, boolean displayCompat) {
         modifyUserState(userId)
                 .setSuspendParams(suspendParams)
                 .setCeDataInode(ceDataInode)
@@ -895,7 +895,8 @@
                 .setHarmfulAppWarning(harmfulAppWarning)
                 .setSplashScreenTheme(splashScreenTheme)
                 .setFirstInstallTimeMillis(firstInstallTime)
-                .setMinAspectRatio(aspectRatio);
+                .setMinAspectRatio(aspectRatio)
+                .setDisplayCompat(displayCompat);
         onChanged();
     }
 
@@ -913,7 +914,8 @@
                         ? null : otherState.getDisabledComponentsNoCopy().untrackedStorage(),
                 otherState.getInstallReason(), otherState.getUninstallReason(),
                 otherState.getHarmfulAppWarning(), otherState.getSplashScreenTheme(),
-                otherState.getFirstInstallTimeMillis(), otherState.getMinAspectRatio());
+                otherState.getFirstInstallTimeMillis(), otherState.getMinAspectRatio(),
+                otherState.isDisplayCompat());
     }
 
     WatchedArraySet<String> getEnabledComponents(int userId) {
@@ -1108,6 +1110,8 @@
                     state.getLastDisableAppCaller());
             proto.write(PackageProto.UserInfoProto.FIRST_INSTALL_TIME_MS,
                     state.getFirstInstallTimeMillis());
+            proto.write(PackageProto.UserInfoProto.IS_DISPLAY_COMPAT,
+                    state.isDisplayCompat());
             proto.end(userToken);
         }
     }
@@ -1599,10 +1603,10 @@
     }
 
     @DataClass.Generated(
-            time = 1680917079522L,
+            time = 1736540041051L,
             codegenVersion = "1.0.23",
             sourceFile = "frameworks/base/services/core/java/com/android/server/pm/PackageSetting.java",
-            inputSignatures = "private  int mSharedUserAppId\nprivate @android.annotation.Nullable java.util.Map<java.lang.String,java.util.Set<java.lang.String>> mimeGroups\nprivate @java.lang.Deprecated @android.annotation.Nullable java.util.Set<java.lang.String> mOldCodePaths\nprivate @android.annotation.Nullable java.lang.String[] usesSdkLibraries\nprivate @android.annotation.Nullable long[] usesSdkLibrariesVersionsMajor\nprivate @android.annotation.Nullable java.lang.String[] usesStaticLibraries\nprivate @android.annotation.Nullable long[] usesStaticLibrariesVersions\nprivate @android.annotation.Nullable @java.lang.Deprecated java.lang.String legacyNativeLibraryPath\nprivate @android.annotation.NonNull java.lang.String mName\nprivate @android.annotation.Nullable java.lang.String mRealName\nprivate  int mAppId\nprivate @android.annotation.Nullable com.android.server.pm.parsing.pkg.AndroidPackageInternal pkg\nprivate @android.annotation.NonNull java.io.File mPath\nprivate @android.annotation.NonNull java.lang.String mPathString\nprivate  float mLoadingProgress\nprivate  long mLoadingCompletedTime\nprivate @android.annotation.Nullable java.lang.String mPrimaryCpuAbi\nprivate @android.annotation.Nullable java.lang.String mSecondaryCpuAbi\nprivate @android.annotation.Nullable java.lang.String mCpuAbiOverride\nprivate  long mLastModifiedTime\nprivate  long lastUpdateTime\nprivate  long versionCode\nprivate @android.annotation.NonNull com.android.server.pm.PackageSignatures signatures\nprivate  boolean installPermissionsFixed\nprivate @android.annotation.NonNull com.android.server.pm.PackageKeySetData keySetData\nprivate final @android.annotation.NonNull android.util.SparseArray<com.android.server.pm.pkg.PackageUserStateImpl> mUserStates\nprivate @android.annotation.NonNull com.android.server.pm.InstallSource installSource\nprivate @android.annotation.Nullable java.lang.String volumeUuid\nprivate  int categoryOverride\nprivate  boolean updateAvailable\nprivate  boolean forceQueryableOverride\nprivate final @android.annotation.NonNull com.android.server.pm.pkg.PackageStateUnserialized pkgState\nprivate @android.annotation.NonNull java.util.UUID mDomainSetId\nprivate @android.annotation.Nullable java.lang.String mAppMetadataFilePath\nprivate final @android.annotation.NonNull com.android.server.utils.SnapshotCache<com.android.server.pm.PackageSetting> mSnapshot\nprivate  com.android.server.utils.SnapshotCache<com.android.server.pm.PackageSetting> makeCache()\npublic  com.android.server.pm.PackageSetting snapshot()\npublic  void dumpDebug(android.util.proto.ProtoOutputStream,long,java.util.List<android.content.pm.UserInfo>,com.android.server.pm.permission.LegacyPermissionDataProvider)\npublic  com.android.server.pm.PackageSetting setAppId(int)\npublic  com.android.server.pm.PackageSetting setCpuAbiOverride(java.lang.String)\npublic  com.android.server.pm.PackageSetting setFirstInstallTimeFromReplaced(com.android.server.pm.pkg.PackageStateInternal,int[])\npublic  com.android.server.pm.PackageSetting setFirstInstallTime(long,int)\npublic  com.android.server.pm.PackageSetting setForceQueryableOverride(boolean)\npublic  com.android.server.pm.PackageSetting setInstallerPackage(java.lang.String,int)\npublic  com.android.server.pm.PackageSetting setUpdateOwnerPackage(java.lang.String)\npublic  com.android.server.pm.PackageSetting setInstallSource(com.android.server.pm.InstallSource)\n  com.android.server.pm.PackageSetting removeInstallerPackage(java.lang.String)\npublic  com.android.server.pm.PackageSetting setIsOrphaned(boolean)\npublic  com.android.server.pm.PackageSetting setKeySetData(com.android.server.pm.PackageKeySetData)\npublic  com.android.server.pm.PackageSetting setLastModifiedTime(long)\npublic  com.android.server.pm.PackageSetting setLastUpdateTime(long)\npublic  com.android.server.pm.PackageSetting setLongVersionCode(long)\npublic  boolean setMimeGroup(java.lang.String,android.util.ArraySet<java.lang.String>)\npublic  com.android.server.pm.PackageSetting setPkg(com.android.server.pm.pkg.AndroidPackage)\npublic  com.android.server.pm.PackageSetting setPkgStateLibraryFiles(java.util.Collection<java.lang.String>)\npublic  com.android.server.pm.PackageSetting setPrimaryCpuAbi(java.lang.String)\npublic  com.android.server.pm.PackageSetting setSecondaryCpuAbi(java.lang.String)\npublic  com.android.server.pm.PackageSetting setSignatures(com.android.server.pm.PackageSignatures)\npublic  com.android.server.pm.PackageSetting setVolumeUuid(java.lang.String)\npublic @java.lang.Override boolean isExternalStorage()\npublic  com.android.server.pm.PackageSetting setUpdateAvailable(boolean)\npublic  void setSharedUserAppId(int)\npublic @java.lang.Override int getSharedUserAppId()\npublic @java.lang.Override boolean hasSharedUser()\npublic @java.lang.Override java.lang.String toString()\nprotected  void copyMimeGroups(java.util.Map<java.lang.String,java.util.Set<java.lang.String>>)\npublic  void updateFrom(com.android.server.pm.PackageSetting)\n  com.android.server.pm.PackageSetting updateMimeGroups(java.util.Set<java.lang.String>)\npublic @java.lang.Deprecated @java.lang.Override com.android.server.pm.permission.LegacyPermissionState getLegacyPermissionState()\npublic  com.android.server.pm.PackageSetting setInstallPermissionsFixed(boolean)\npublic  boolean isPrivileged()\npublic  boolean isOem()\npublic  boolean isVendor()\npublic  boolean isProduct()\npublic @java.lang.Override boolean isRequiredForSystemUser()\npublic  boolean isSystemExt()\npublic  boolean isOdm()\npublic  boolean isSystem()\npublic  android.content.pm.SigningDetails getSigningDetails()\npublic  com.android.server.pm.PackageSetting setSigningDetails(android.content.pm.SigningDetails)\npublic  void copyPackageSetting(com.android.server.pm.PackageSetting,boolean)\n @com.android.internal.annotations.VisibleForTesting com.android.server.pm.pkg.PackageUserStateImpl modifyUserState(int)\npublic  com.android.server.pm.pkg.PackageUserStateImpl getOrCreateUserState(int)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateInternal readUserState(int)\n  void setEnabled(int,int,java.lang.String)\n  int getEnabled(int)\n  void setInstalled(boolean,int)\n  boolean getInstalled(int)\n  int getInstallReason(int)\n  void setInstallReason(int,int)\n  int getUninstallReason(int)\n  void setUninstallReason(int,int)\n @android.annotation.NonNull android.content.pm.overlay.OverlayPaths getOverlayPaths(int)\n  boolean setOverlayPathsForLibrary(java.lang.String,android.content.pm.overlay.OverlayPaths,int)\n  boolean isAnyInstalled(int[])\n  int[] queryInstalledUsers(int[],boolean)\n  long getCeDataInode(int)\n  void setCeDataInode(long,int)\n  boolean getStopped(int)\n  void setStopped(boolean,int)\n  boolean getNotLaunched(int)\n  void setNotLaunched(boolean,int)\n  boolean getHidden(int)\n  void setHidden(boolean,int)\n  int getDistractionFlags(int)\n  void setDistractionFlags(int,int)\npublic  boolean getInstantApp(int)\n  void setInstantApp(boolean,int)\n  boolean getVirtualPreload(int)\n  void setVirtualPreload(boolean,int)\n  void setUserState(int,long,int,boolean,boolean,boolean,boolean,int,android.util.ArrayMap<java.lang.String,com.android.server.pm.pkg.SuspendParams>,boolean,boolean,java.lang.String,android.util.ArraySet<java.lang.String>,android.util.ArraySet<java.lang.String>,int,int,java.lang.String,java.lang.String,long)\n  void setUserState(int,com.android.server.pm.pkg.PackageUserStateInternal)\n  com.android.server.utils.WatchedArraySet<java.lang.String> getEnabledComponents(int)\n  com.android.server.utils.WatchedArraySet<java.lang.String> getDisabledComponents(int)\n  void setEnabledComponents(com.android.server.utils.WatchedArraySet<java.lang.String>,int)\n  void setDisabledComponents(com.android.server.utils.WatchedArraySet<java.lang.String>,int)\n  void setEnabledComponentsCopy(com.android.server.utils.WatchedArraySet<java.lang.String>,int)\n  void setDisabledComponentsCopy(com.android.server.utils.WatchedArraySet<java.lang.String>,int)\n  com.android.server.pm.pkg.PackageUserStateImpl modifyUserStateComponents(int,boolean,boolean)\n  void addDisabledComponent(java.lang.String,int)\n  void addEnabledComponent(java.lang.String,int)\n  boolean enableComponentLPw(java.lang.String,int)\n  boolean disableComponentLPw(java.lang.String,int)\n  boolean restoreComponentLPw(java.lang.String,int)\n  int getCurrentEnabledStateLPr(java.lang.String,int)\n  void removeUser(int)\npublic  int[] getNotInstalledUserIds()\n  void writePackageUserPermissionsProto(android.util.proto.ProtoOutputStream,long,java.util.List<android.content.pm.UserInfo>,com.android.server.pm.permission.LegacyPermissionDataProvider)\nprotected  void writeUsersInfoToProto(android.util.proto.ProtoOutputStream,long)\n  com.android.server.pm.PackageSetting setPath(java.io.File)\npublic @com.android.internal.annotations.VisibleForTesting boolean overrideNonLocalizedLabelAndIcon(android.content.ComponentName,java.lang.String,java.lang.Integer,int)\npublic  void resetOverrideComponentLabelIcon(int)\npublic @android.annotation.Nullable java.lang.String getSplashScreenTheme(int)\npublic  boolean isIncremental()\npublic  boolean isLoading()\npublic  com.android.server.pm.PackageSetting setLoadingProgress(float)\npublic  com.android.server.pm.PackageSetting setLoadingCompletedTime(long)\npublic  com.android.server.pm.PackageSetting setAppMetadataFilePath(java.lang.String)\npublic @android.annotation.NonNull @java.lang.Override long getVersionCode()\npublic @android.annotation.Nullable @java.lang.Override java.util.Map<java.lang.String,java.util.Set<java.lang.String>> getMimeGroups()\npublic @android.annotation.NonNull @java.lang.Override java.lang.String getPackageName()\npublic @android.annotation.Nullable @java.lang.Override com.android.server.pm.pkg.AndroidPackage getAndroidPackage()\npublic @android.annotation.NonNull android.content.pm.SigningInfo getSigningInfo()\npublic @android.annotation.NonNull @java.lang.Override java.lang.String[] getUsesSdkLibraries()\npublic @android.annotation.NonNull @java.lang.Override long[] getUsesSdkLibrariesVersionsMajor()\npublic @android.annotation.NonNull @java.lang.Override java.lang.String[] getUsesStaticLibraries()\npublic @android.annotation.NonNull @java.lang.Override long[] getUsesStaticLibrariesVersions()\npublic @android.annotation.NonNull @java.lang.Override java.util.List<com.android.server.pm.pkg.SharedLibrary> getSharedLibraryDependencies()\npublic @android.annotation.NonNull com.android.server.pm.PackageSetting addUsesLibraryInfo(android.content.pm.SharedLibraryInfo)\npublic @android.annotation.NonNull @java.lang.Override java.util.List<java.lang.String> getUsesLibraryFiles()\npublic @android.annotation.NonNull com.android.server.pm.PackageSetting addUsesLibraryFile(java.lang.String)\npublic @java.lang.Override boolean isHiddenUntilInstalled()\npublic @android.annotation.NonNull @java.lang.Override long[] getLastPackageUsageTime()\npublic @java.lang.Override boolean isUpdatedSystemApp()\npublic @java.lang.Override boolean isApkInUpdatedApex()\npublic @android.annotation.Nullable @java.lang.Override java.lang.String getApexModuleName()\npublic  com.android.server.pm.PackageSetting setDomainSetId(java.util.UUID)\npublic  com.android.server.pm.PackageSetting setCategoryOverride(int)\npublic  com.android.server.pm.PackageSetting setLegacyNativeLibraryPath(java.lang.String)\npublic  com.android.server.pm.PackageSetting setMimeGroups(java.util.Map<java.lang.String,java.util.Set<java.lang.String>>)\npublic  com.android.server.pm.PackageSetting setOldCodePaths(java.util.Set<java.lang.String>)\npublic  com.android.server.pm.PackageSetting setUsesSdkLibraries(java.lang.String[])\npublic  com.android.server.pm.PackageSetting setUsesSdkLibrariesVersionsMajor(long[])\npublic  com.android.server.pm.PackageSetting setUsesStaticLibraries(java.lang.String[])\npublic  com.android.server.pm.PackageSetting setUsesStaticLibrariesVersions(long[])\npublic  com.android.server.pm.PackageSetting setApexModuleName(java.lang.String)\npublic @android.annotation.NonNull @java.lang.Override com.android.server.pm.pkg.PackageStateUnserialized getTransientState()\npublic @android.annotation.NonNull android.util.SparseArray<? extends PackageUserStateInternal> getUserStates()\npublic  com.android.server.pm.PackageSetting addMimeTypes(java.lang.String,java.util.Set<java.lang.String>)\npublic @android.annotation.NonNull @java.lang.Override com.android.server.pm.pkg.PackageUserState getStateForUser(android.os.UserHandle)\npublic @android.annotation.Nullable java.lang.String getPrimaryCpuAbi()\npublic @android.annotation.Nullable java.lang.String getSecondaryCpuAbi()\npublic @android.annotation.Nullable @java.lang.Override java.lang.String getSeInfo()\npublic @android.annotation.Nullable java.lang.String getPrimaryCpuAbiLegacy()\npublic @android.annotation.Nullable java.lang.String getSecondaryCpuAbiLegacy()\npublic @android.content.pm.ApplicationInfo.HiddenApiEnforcementPolicy @java.lang.Override int getHiddenApiEnforcementPolicy()\npublic @java.lang.Override boolean isApex()\nclass PackageSetting extends com.android.server.pm.SettingBase implements [com.android.server.pm.pkg.PackageStateInternal]\[email protected](genGetters=true, genConstructor=false, genSetters=false, genBuilder=false)")
+            inputSignatures = "private  int mSharedUserAppId\nprivate @android.annotation.Nullable java.util.Map<java.lang.String,java.util.Set<java.lang.String>> mimeGroups\nprivate @java.lang.Deprecated @android.annotation.Nullable java.util.Set<java.lang.String> mOldCodePaths\nprivate @android.annotation.Nullable java.lang.String[] usesSdkLibraries\nprivate @android.annotation.Nullable long[] usesSdkLibrariesVersionsMajor\nprivate @android.annotation.Nullable java.lang.String[] usesStaticLibraries\nprivate @android.annotation.Nullable long[] usesStaticLibrariesVersions\nprivate @android.annotation.Nullable @java.lang.Deprecated java.lang.String legacyNativeLibraryPath\nprivate @android.annotation.NonNull java.lang.String mName\nprivate @android.annotation.Nullable java.lang.String mRealName\nprivate  int mAppId\nprivate @android.annotation.Nullable com.android.server.pm.parsing.pkg.AndroidPackageInternal pkg\nprivate @android.annotation.NonNull java.io.File mPath\nprivate @android.annotation.NonNull java.lang.String mPathString\nprivate  float mLoadingProgress\nprivate  long mLoadingCompletedTime\nprivate @android.annotation.Nullable java.lang.String mPrimaryCpuAbi\nprivate @android.annotation.Nullable java.lang.String mSecondaryCpuAbi\nprivate @android.annotation.Nullable java.lang.String mCpuAbiOverride\nprivate  long mLastModifiedTime\nprivate  long lastUpdateTime\nprivate  long versionCode\nprivate @android.annotation.NonNull com.android.server.pm.PackageSignatures signatures\nprivate  boolean installPermissionsFixed\nprivate @android.annotation.NonNull com.android.server.pm.PackageKeySetData keySetData\nprivate final @android.annotation.NonNull android.util.SparseArray<com.android.server.pm.pkg.PackageUserStateImpl> mUserStates\nprivate @android.annotation.NonNull com.android.server.pm.InstallSource installSource\nprivate @android.annotation.Nullable java.lang.String volumeUuid\nprivate  int categoryOverride\nprivate  boolean updateAvailable\nprivate  boolean forceQueryableOverride\nprivate final @android.annotation.NonNull com.android.server.pm.pkg.PackageStateUnserialized pkgState\nprivate @android.annotation.NonNull java.util.UUID mDomainSetId\nprivate @android.annotation.Nullable java.lang.String mAppMetadataFilePath\nprivate final @android.annotation.NonNull com.android.server.utils.SnapshotCache<com.android.server.pm.PackageSetting> mSnapshot\nprivate  com.android.server.utils.SnapshotCache<com.android.server.pm.PackageSetting> makeCache()\npublic  com.android.server.pm.PackageSetting snapshot()\npublic  void dumpDebug(android.util.proto.ProtoOutputStream,long,java.util.List<android.content.pm.UserInfo>,com.android.server.pm.permission.LegacyPermissionDataProvider)\npublic  com.android.server.pm.PackageSetting setAppId(int)\npublic  com.android.server.pm.PackageSetting setCpuAbiOverride(java.lang.String)\npublic  com.android.server.pm.PackageSetting setFirstInstallTimeFromReplaced(com.android.server.pm.pkg.PackageStateInternal,int[])\npublic  com.android.server.pm.PackageSetting setFirstInstallTime(long,int)\npublic  com.android.server.pm.PackageSetting setForceQueryableOverride(boolean)\npublic  com.android.server.pm.PackageSetting setInstallerPackage(java.lang.String,int)\npublic  com.android.server.pm.PackageSetting setUpdateOwnerPackage(java.lang.String)\npublic  com.android.server.pm.PackageSetting setInstallSource(com.android.server.pm.InstallSource)\n  com.android.server.pm.PackageSetting removeInstallerPackage(java.lang.String)\npublic  com.android.server.pm.PackageSetting setIsOrphaned(boolean)\npublic  com.android.server.pm.PackageSetting setKeySetData(com.android.server.pm.PackageKeySetData)\npublic  com.android.server.pm.PackageSetting setLastModifiedTime(long)\npublic  com.android.server.pm.PackageSetting setLastUpdateTime(long)\npublic  com.android.server.pm.PackageSetting setLongVersionCode(long)\npublic  boolean setMimeGroup(java.lang.String,android.util.ArraySet<java.lang.String>)\npublic  com.android.server.pm.PackageSetting setPkg(com.android.server.pm.pkg.AndroidPackage)\npublic  com.android.server.pm.PackageSetting setPkgStateLibraryFiles(java.util.Collection<java.lang.String>)\npublic  com.android.server.pm.PackageSetting setPrimaryCpuAbi(java.lang.String)\npublic  com.android.server.pm.PackageSetting setSecondaryCpuAbi(java.lang.String)\npublic  com.android.server.pm.PackageSetting setSignatures(com.android.server.pm.PackageSignatures)\npublic  com.android.server.pm.PackageSetting setVolumeUuid(java.lang.String)\npublic @java.lang.Override boolean isExternalStorage()\npublic  com.android.server.pm.PackageSetting setUpdateAvailable(boolean)\npublic  void setSharedUserAppId(int)\npublic @java.lang.Override int getSharedUserAppId()\npublic @java.lang.Override boolean hasSharedUser()\npublic @java.lang.Override java.lang.String toString()\nprotected  void copyMimeGroups(java.util.Map<java.lang.String,java.util.Set<java.lang.String>>)\npublic  void updateFrom(com.android.server.pm.PackageSetting)\n  com.android.server.pm.PackageSetting updateMimeGroups(java.util.Set<java.lang.String>)\npublic @java.lang.Deprecated @java.lang.Override com.android.server.pm.permission.LegacyPermissionState getLegacyPermissionState()\npublic  com.android.server.pm.PackageSetting setInstallPermissionsFixed(boolean)\npublic  boolean isPrivileged()\npublic  boolean isOem()\npublic  boolean isVendor()\npublic  boolean isProduct()\npublic @java.lang.Override boolean isRequiredForSystemUser()\npublic  boolean isSystemExt()\npublic  boolean isOdm()\npublic  boolean isSystem()\npublic  android.content.pm.SigningDetails getSigningDetails()\npublic  com.android.server.pm.PackageSetting setSigningDetails(android.content.pm.SigningDetails)\npublic  void copyPackageSetting(com.android.server.pm.PackageSetting,boolean)\n @com.android.internal.annotations.VisibleForTesting com.android.server.pm.pkg.PackageUserStateImpl modifyUserState(int)\npublic  com.android.server.pm.pkg.PackageUserStateImpl getOrCreateUserState(int)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateInternal readUserState(int)\n  void setEnabled(int,int,java.lang.String)\n  int getEnabled(int)\n  void setInstalled(boolean,int)\n  boolean getInstalled(int)\n  int getInstallReason(int)\n  void setInstallReason(int,int)\n  int getUninstallReason(int)\n  void setUninstallReason(int,int)\n @android.annotation.NonNull android.content.pm.overlay.OverlayPaths getOverlayPaths(int)\n  boolean setOverlayPathsForLibrary(java.lang.String,android.content.pm.overlay.OverlayPaths,int)\n  boolean isAnyInstalled(int[])\n  int[] queryInstalledUsers(int[],boolean)\n  long getCeDataInode(int)\n  void setCeDataInode(long,int)\n  boolean getStopped(int)\n  void setStopped(boolean,int)\n  boolean getNotLaunched(int)\n  void setNotLaunched(boolean,int)\n  boolean getHidden(int)\n  void setHidden(boolean,int)\n  int getDistractionFlags(int)\n  void setDistractionFlags(int,int)\npublic  boolean getInstantApp(int)\n  void setInstantApp(boolean,int)\n  boolean getVirtualPreload(int)\n  void setVirtualPreload(boolean,int)\n  void setUserState(int,long,int,boolean,boolean,boolean,boolean,int,android.util.ArrayMap<java.lang.String,com.android.server.pm.pkg.SuspendParams>,boolean,boolean,java.lang.String,android.util.ArraySet<java.lang.String>,android.util.ArraySet<java.lang.String>,int,int,java.lang.String,java.lang.String,long,int,boolean)\n  void setUserState(int,com.android.server.pm.pkg.PackageUserStateInternal)\n  com.android.server.utils.WatchedArraySet<java.lang.String> getEnabledComponents(int)\n  com.android.server.utils.WatchedArraySet<java.lang.String> getDisabledComponents(int)\n  void setEnabledComponents(com.android.server.utils.WatchedArraySet<java.lang.String>,int)\n  void setDisabledComponents(com.android.server.utils.WatchedArraySet<java.lang.String>,int)\n  void setEnabledComponentsCopy(com.android.server.utils.WatchedArraySet<java.lang.String>,int)\n  void setDisabledComponentsCopy(com.android.server.utils.WatchedArraySet<java.lang.String>,int)\n  com.android.server.pm.pkg.PackageUserStateImpl modifyUserStateComponents(int,boolean,boolean)\n  void addDisabledComponent(java.lang.String,int)\n  void addEnabledComponent(java.lang.String,int)\n  boolean enableComponentLPw(java.lang.String,int)\n  boolean disableComponentLPw(java.lang.String,int)\n  boolean restoreComponentLPw(java.lang.String,int)\n  int getCurrentEnabledStateLPr(java.lang.String,int)\n  void removeUser(int)\npublic  int[] getNotInstalledUserIds()\n  void writePackageUserPermissionsProto(android.util.proto.ProtoOutputStream,long,java.util.List<android.content.pm.UserInfo>,com.android.server.pm.permission.LegacyPermissionDataProvider)\nprotected  void writeUsersInfoToProto(android.util.proto.ProtoOutputStream,long)\n  com.android.server.pm.PackageSetting setPath(java.io.File)\npublic @com.android.internal.annotations.VisibleForTesting boolean overrideNonLocalizedLabelAndIcon(android.content.ComponentName,java.lang.String,java.lang.Integer,int)\npublic  void resetOverrideComponentLabelIcon(int)\npublic @android.annotation.Nullable java.lang.String getSplashScreenTheme(int)\npublic  boolean isIncremental()\npublic  boolean isLoading()\npublic  com.android.server.pm.PackageSetting setLoadingProgress(float)\npublic  com.android.server.pm.PackageSetting setLoadingCompletedTime(long)\npublic  com.android.server.pm.PackageSetting setAppMetadataFilePath(java.lang.String)\npublic @android.annotation.NonNull @java.lang.Override long getVersionCode()\npublic @android.annotation.Nullable @java.lang.Override java.util.Map<java.lang.String,java.util.Set<java.lang.String>> getMimeGroups()\npublic @android.annotation.NonNull @java.lang.Override java.lang.String getPackageName()\npublic @android.annotation.Nullable @java.lang.Override com.android.server.pm.pkg.AndroidPackage getAndroidPackage()\npublic @android.annotation.NonNull android.content.pm.SigningInfo getSigningInfo()\npublic @android.annotation.NonNull @java.lang.Override java.lang.String[] getUsesSdkLibraries()\npublic @android.annotation.NonNull @java.lang.Override long[] getUsesSdkLibrariesVersionsMajor()\npublic @android.annotation.NonNull @java.lang.Override java.lang.String[] getUsesStaticLibraries()\npublic @android.annotation.NonNull @java.lang.Override long[] getUsesStaticLibrariesVersions()\npublic @android.annotation.NonNull @java.lang.Override java.util.List<com.android.server.pm.pkg.SharedLibrary> getSharedLibraryDependencies()\npublic @android.annotation.NonNull com.android.server.pm.PackageSetting addUsesLibraryInfo(android.content.pm.SharedLibraryInfo)\npublic @android.annotation.NonNull @java.lang.Override java.util.List<java.lang.String> getUsesLibraryFiles()\npublic @android.annotation.NonNull com.android.server.pm.PackageSetting addUsesLibraryFile(java.lang.String)\npublic @java.lang.Override boolean isHiddenUntilInstalled()\npublic @android.annotation.NonNull @java.lang.Override long[] getLastPackageUsageTime()\npublic @java.lang.Override boolean isUpdatedSystemApp()\npublic @java.lang.Override boolean isApkInUpdatedApex()\npublic @android.annotation.Nullable @java.lang.Override java.lang.String getApexModuleName()\npublic  com.android.server.pm.PackageSetting setDomainSetId(java.util.UUID)\npublic  com.android.server.pm.PackageSetting setCategoryOverride(int)\npublic  com.android.server.pm.PackageSetting setLegacyNativeLibraryPath(java.lang.String)\npublic  com.android.server.pm.PackageSetting setMimeGroups(java.util.Map<java.lang.String,java.util.Set<java.lang.String>>)\npublic  com.android.server.pm.PackageSetting setOldCodePaths(java.util.Set<java.lang.String>)\npublic  com.android.server.pm.PackageSetting setUsesSdkLibraries(java.lang.String[])\npublic  com.android.server.pm.PackageSetting setUsesSdkLibrariesVersionsMajor(long[])\npublic  com.android.server.pm.PackageSetting setUsesStaticLibraries(java.lang.String[])\npublic  com.android.server.pm.PackageSetting setUsesStaticLibrariesVersions(long[])\npublic  com.android.server.pm.PackageSetting setApexModuleName(java.lang.String)\npublic @android.annotation.NonNull @java.lang.Override com.android.server.pm.pkg.PackageStateUnserialized getTransientState()\npublic @android.annotation.NonNull android.util.SparseArray<? extends PackageUserStateInternal> getUserStates()\npublic  com.android.server.pm.PackageSetting addMimeTypes(java.lang.String,java.util.Set<java.lang.String>)\npublic @android.annotation.NonNull @java.lang.Override com.android.server.pm.pkg.PackageUserState getStateForUser(android.os.UserHandle)\npublic @android.annotation.Nullable java.lang.String getPrimaryCpuAbi()\npublic @android.annotation.Nullable java.lang.String getSecondaryCpuAbi()\npublic @android.annotation.Nullable @java.lang.Override java.lang.String getSeInfo()\npublic @android.annotation.Nullable java.lang.String getPrimaryCpuAbiLegacy()\npublic @android.annotation.Nullable java.lang.String getSecondaryCpuAbiLegacy()\npublic @android.content.pm.ApplicationInfo.HiddenApiEnforcementPolicy @java.lang.Override int getHiddenApiEnforcementPolicy()\npublic @java.lang.Override boolean isApex()\nclass PackageSetting extends com.android.server.pm.SettingBase implements [com.android.server.pm.pkg.PackageStateInternal]\[email protected](genGetters=true, genConstructor=false, genSetters=false, genBuilder=false)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/services/core/java/com/android/server/pm/ScanPackageUtils.java b/services/core/java/com/android/server/pm/ScanPackageUtils.java
index c3106a8..f7bbf81 100644
--- a/services/core/java/com/android/server/pm/ScanPackageUtils.java
+++ b/services/core/java/com/android/server/pm/ScanPackageUtils.java
@@ -131,6 +131,7 @@
         final SharedUserSetting oldSharedUserSetting = request.mOldSharedUserSetting;
         final SharedUserSetting sharedUserSetting = request.mSharedUserSetting;
         final UserHandle user = request.mUser;
+        final int userId = (user == null ? UserHandle.USER_SYSTEM : user.getIdentifier());
         final boolean isPlatformPackage = request.mIsPlatformPackage;
 
         List<String> changedAbiCodePath = null;
@@ -206,6 +207,7 @@
             // PackageSetting to pass in.
             int pkgFlags = PackageInfoUtils.appInfoFlags(parsedPackage, null);
             int pkgPrivateFlags = PackageInfoUtils.appInfoPrivateFlags(parsedPackage, null);
+            int pkgPrivateFlagsExt = PackageInfoUtils.appInfoPrivateFlagsExt(parsedPackage, null, userId);
 
             // REMOVE SharedUserSetting from method; update in a separate call
             pkgSetting = Settings.createNewSetting(parsedPackage.getPackageName(),
@@ -213,8 +215,8 @@
                     destCodeFile, parsedPackage.getNativeLibraryRootDir(),
                     AndroidPackageUtils.getRawPrimaryCpuAbi(parsedPackage),
                     AndroidPackageUtils.getRawSecondaryCpuAbi(parsedPackage),
-                    parsedPackage.getLongVersionCode(), pkgFlags, pkgPrivateFlags, user,
-                    true /*allowInstall*/, instantApp, virtualPreload, isStoppedSystemApp,
+                    parsedPackage.getLongVersionCode(), pkgFlags, pkgPrivateFlags, pkgPrivateFlagsExt,
+                    user, true /*allowInstall*/, instantApp, virtualPreload, isStoppedSystemApp,
                     UserManagerService.getInstance(), usesSdkLibraries,
                     parsedPackage.getUsesSdkLibrariesVersionsMajor(), usesStaticLibraries,
                     parsedPackage.getUsesStaticLibrariesVersions(), parsedPackage.getMimeGroups(),
@@ -235,6 +237,7 @@
                     pkgSetting.getSecondaryCpuAbi(),
                     PackageInfoUtils.appInfoFlags(parsedPackage, pkgSetting),
                     PackageInfoUtils.appInfoPrivateFlags(parsedPackage, pkgSetting),
+                    PackageInfoUtils.appInfoPrivateFlagsExt(parsedPackage, pkgSetting, userId),
                     UserManagerService.getInstance(),
                     usesSdkLibraries, parsedPackage.getUsesSdkLibrariesVersionsMajor(),
                     usesStaticLibraries, parsedPackage.getUsesStaticLibrariesVersions(),
@@ -253,7 +256,6 @@
             PackageManagerService.reportSettingsProblem(Log.WARN, msg);
         }
 
-        final int userId = (user == null ? UserHandle.USER_SYSTEM : user.getIdentifier());
         // for existing packages, change the install state; but, only if it's explicitly specified
         if (!createNewPackage) {
             final boolean instantApp = (scanFlags & SCAN_AS_INSTANT_APP) != 0;
@@ -431,7 +433,8 @@
         // TODO(b/135203078): Remove, move to constructor
         pkgSetting.setPkg(parsedPackage)
                 .setFlags(PackageInfoUtils.appInfoFlags(parsedPackage, pkgSetting))
-                .setPrivateFlags(PackageInfoUtils.appInfoPrivateFlags(parsedPackage, pkgSetting));
+                .setPrivateFlags(PackageInfoUtils.appInfoPrivateFlags(parsedPackage, pkgSetting))
+                .setPrivateFlagsExt(PackageInfoUtils.appInfoPrivateFlagsExt(parsedPackage, pkgSetting, userId));
         if (parsedPackage.getLongVersionCode() != pkgSetting.getVersionCode()) {
             pkgSetting.setLongVersionCode(parsedPackage.getLongVersionCode());
         }
diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java
index 9054c85..7650480 100644
--- a/services/core/java/com/android/server/pm/SettingBase.java
+++ b/services/core/java/com/android/server/pm/SettingBase.java
@@ -34,6 +34,7 @@
     //  and bugs exist where callers query for an unsaved flag.
     private int mPkgFlags;
     private int mPkgPrivateFlags;
+    private int mPkgPrivateFlagsExt;
 
     /**
      * Watchable machinery
@@ -100,9 +101,10 @@
     @Deprecated
     protected final LegacyPermissionState mLegacyPermissionsState = new LegacyPermissionState();
 
-    SettingBase(int pkgFlags, int pkgPrivateFlags) {
+    SettingBase(int pkgFlags, int pkgPrivateFlags, int pkgPrivateFlagsExt) {
         setFlags(pkgFlags);
         setPrivateFlags(pkgPrivateFlags);
+        setPrivateFlagsExt(pkgPrivateFlagsExt);
     }
 
     SettingBase(@Nullable SettingBase orig) {
@@ -114,6 +116,7 @@
     public final void copySettingBase(SettingBase orig) {
         mPkgFlags = orig.mPkgFlags;
         mPkgPrivateFlags = orig.mPkgPrivateFlags;
+        mPkgPrivateFlagsExt = orig.mPkgPrivateFlagsExt;
         mLegacyPermissionsState.copyFrom(orig.mLegacyPermissionsState);
         onChanged();
     }
@@ -135,6 +138,12 @@
         return this;
     }
 
+    public SettingBase setPrivateFlagsExt(int pkgPrivateFlagsExt) {
+        this.mPkgPrivateFlagsExt = pkgPrivateFlagsExt;
+        onChanged();
+        return this;
+    }
+
     public int getFlags() {
         return mPkgFlags;
     }
@@ -142,4 +151,8 @@
     public int getPrivateFlags() {
         return mPkgPrivateFlags;
     }
+
+    public int getPrivateFlagsExt() {
+        return mPkgPrivateFlagsExt;
+    }
 }
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 677a5d1..9f68767 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -361,6 +361,7 @@
     private static final String ATTR_DATABASE_VERSION = "databaseVersion";
     private static final String ATTR_VALUE = "value";
     private static final String ATTR_FIRST_INSTALL_TIME = "first-install-time";
+    private static final String ATTR_DISPLAY_COMPAT = "displayCompat";
 
     private final Handler mHandler;
 
@@ -854,10 +855,10 @@
 
     /** Gets and optionally creates a new shared user id. */
     SharedUserSetting getSharedUserLPw(String name, int pkgFlags, int pkgPrivateFlags,
-            boolean create) throws PackageManagerException {
+            int pkgPrivateFlagsExt, boolean create) throws PackageManagerException {
         SharedUserSetting s = mSharedUsers.get(name);
         if (s == null && create) {
-            s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
+            s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags, pkgPrivateFlagsExt);
             s.mAppId = mAppIds.acquireAndRegisterNewAppId(s);
             if (s.mAppId < 0) {
                 // < 0 means we couldn't assign a userid; throw exception
@@ -920,7 +921,7 @@
                 p.getLegacyNativeLibraryPath(), p.getPrimaryCpuAbiLegacy(),
                 p.getSecondaryCpuAbiLegacy(), p.getCpuAbiOverride(),
                 p.getAppId(), p.getVersionCode(), p.getFlags(), p.getPrivateFlags(),
-                p.getUsesSdkLibraries(), p.getUsesSdkLibrariesVersionsMajor(),
+                p.getPrivateFlagsExt(), p.getUsesSdkLibraries(), p.getUsesSdkLibrariesVersionsMajor(),
                 p.getUsesStaticLibraries(), p.getUsesStaticLibrariesVersions(), p.getMimeGroups(),
                 mDomainVerificationManager.generateNewId());
         if (ret != null) {
@@ -949,7 +950,7 @@
     PackageSetting addPackageLPw(String name, String realName, File codePath,
             String legacyNativeLibraryPathString, String primaryCpuAbiString,
             String secondaryCpuAbiString, String cpuAbiOverrideString, int uid, long vc,
-            int pkgFlags, int pkgPrivateFlags, String[] usesSdkLibraries,
+            int pkgFlags, int pkgPrivateFlags, int pkgPrivateFlagsExt, String[] usesSdkLibraries,
             long[] usesSdkLibrariesVersions, String[] usesStaticLibraries,
             long[] usesStaticLibrariesVersions, Map<String, Set<String>> mimeGroups,
             @NonNull UUID domainSetId) {
@@ -964,8 +965,9 @@
         }
         p = new PackageSetting(name, realName, codePath, legacyNativeLibraryPathString,
                 primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString, vc, pkgFlags,
-                pkgPrivateFlags, 0 /*userId*/, usesSdkLibraries, usesSdkLibrariesVersions,
-                usesStaticLibraries, usesStaticLibrariesVersions, mimeGroups, domainSetId);
+                pkgPrivateFlags, pkgPrivateFlagsExt, 0 /*userId*/, usesSdkLibraries,
+                usesSdkLibrariesVersions, usesStaticLibraries, usesStaticLibrariesVersions,
+                mimeGroups, domainSetId);
         p.setAppId(uid);
         if (mAppIds.registerExistingAppId(uid, p, name)) {
             mPackages.put(name, p);
@@ -974,7 +976,8 @@
         return null;
     }
 
-    SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags, int pkgPrivateFlags) {
+    SharedUserSetting addSharedUserLPw(String name, int uid, int pkgFlags,
+        int pkgPrivateFlags, int pkgPrivateFlagsExt) {
         SharedUserSetting s = mSharedUsers.get(name);
         if (s != null) {
             if (s.mAppId == uid) {
@@ -984,7 +987,7 @@
                     "Adding duplicate shared user, keeping first: " + name);
             return null;
         }
-        s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags);
+        s = new SharedUserSetting(name, pkgFlags, pkgPrivateFlags, pkgPrivateFlagsExt);
         s.mAppId = uid;
         if (mAppIds.registerExistingAppId(uid, s, name)) {
             mSharedUsers.put(name, s);
@@ -1042,7 +1045,7 @@
             PackageSetting disabledPkg, String realPkgName, SharedUserSetting sharedUser,
             File codePath, String legacyNativeLibraryPath, String primaryCpuAbi,
             String secondaryCpuAbi, long versionCode, int pkgFlags, int pkgPrivateFlags,
-            UserHandle installUser, boolean allowInstall, boolean instantApp,
+            int pkgPrivateFlagsExt, UserHandle installUser, boolean allowInstall, boolean instantApp,
             boolean virtualPreload, boolean isStoppedSystemApp, UserManagerService userManager,
             String[] usesSdkLibraries, long[] usesSdkLibrariesVersions,
             String[] usesStaticLibraries, long[] usesStaticLibrariesVersions,
@@ -1068,7 +1071,8 @@
                     .setLastModifiedTime(codePath.lastModified())
                     .setDomainSetId(domainSetId);
             pkgSetting.setFlags(pkgFlags)
-                    .setPrivateFlags(pkgPrivateFlags);
+                    .setPrivateFlags(pkgPrivateFlags)
+                    .setPrivateFlagsExt(pkgPrivateFlagsExt);
         } else {
             int installUserId = installUser != null ? installUser.getIdentifier()
                     : UserHandle.USER_SYSTEM;
@@ -1076,7 +1080,7 @@
             pkgSetting = new PackageSetting(pkgName, realPkgName, codePath,
                     legacyNativeLibraryPath, primaryCpuAbi, secondaryCpuAbi,
                     null /*cpuAbiOverrideString*/, versionCode, pkgFlags, pkgPrivateFlags,
-                    0 /*sharedUserAppId*/, usesSdkLibraries, usesSdkLibrariesVersions,
+                    pkgPrivateFlagsExt, 0 /*sharedUserAppId*/, usesSdkLibraries, usesSdkLibrariesVersions,
                     usesStaticLibraries, usesStaticLibrariesVersions,
                     createMimeGroups(mimeGroupNames), domainSetId);
             pkgSetting.setLastModifiedTime(codePath.lastModified());
@@ -1126,7 +1130,8 @@
                                 null /*harmfulAppWarning*/,
                                 null /*splashscreenTheme*/,
                                 0 /*firstInstallTime*/,
-                                PackageManager.USER_MIN_ASPECT_RATIO_UNSET
+                                PackageManager.USER_MIN_ASPECT_RATIO_UNSET,
+                                false /*displayCompat*/
                         );
                     }
                 }
@@ -1188,7 +1193,7 @@
             @Nullable SharedUserSetting sharedUser,
             @NonNull File codePath, @Nullable String legacyNativeLibraryPath,
             @Nullable String primaryCpuAbi, @Nullable String secondaryCpuAbi, int pkgFlags,
-            int pkgPrivateFlags, @NonNull UserManagerService userManager,
+            int pkgPrivateFlags, int pkgPrivateFlagsExt, @NonNull UserManagerService userManager,
             @Nullable String[] usesSdkLibraries, @Nullable long[] usesSdkLibrariesVersions,
             @Nullable String[] usesStaticLibraries, @Nullable long[] usesStaticLibrariesVersions,
             @Nullable Set<String> mimeGroupNames, @NonNull UUID domainSetId)
@@ -1272,6 +1277,7 @@
         newPkgFlags |= pkgFlags & ApplicationInfo.FLAG_SYSTEM;
         // Only set pkgFlags.
         pkgSetting.setFlags(newPkgFlags);
+        //pkgSetting.setPkgFlags(newPkgFlags, pkgSetting.getPrivateFlags(), pkgSetting.getPrivateFlagsExt());
 
         boolean wasRequiredForSystemUser = (pkgSetting.getPrivateFlags()
                 & ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER) != 0;
@@ -1802,7 +1808,8 @@
                                     null /*harmfulAppWarning*/,
                                     null /* splashScreenTheme*/,
                                     0 /*firstInstallTime*/,
-                                    PackageManager.USER_MIN_ASPECT_RATIO_UNSET
+                                    PackageManager.USER_MIN_ASPECT_RATIO_UNSET,
+                                    false /*displayCompat*/
                             );
                         }
                         return;
@@ -1900,7 +1907,8 @@
                         final int minAspectRatio = parser.getAttributeInt(null,
                                 ATTR_MIN_ASPECT_RATIO,
                                 PackageManager.USER_MIN_ASPECT_RATIO_UNSET);
-
+                        final boolean displayCompat = parser.getAttributeBoolean(null,
+                                ATTR_DISPLAY_COMPAT, false);
                         ArraySet<String> enabledComponents = null;
                         ArraySet<String> disabledComponents = null;
                         PersistableBundle suspendedAppExtras = null;
@@ -1977,7 +1985,7 @@
                                 uninstallReason, harmfulAppWarning, splashScreenTheme,
                                 firstInstallTime != 0 ? firstInstallTime :
                                         origFirstInstallTimes.getOrDefault(name, 0L),
-                                minAspectRatio);
+                                minAspectRatio, displayCompat);
 
                         mDomainVerificationManager.setLegacyUserState(name, userId, verifState);
                     } else if (tagName.equals("preferred-activities")) {
@@ -2282,6 +2290,8 @@
                             serializer.attributeInt(null, ATTR_MIN_ASPECT_RATIO,
                                     ustate.getMinAspectRatio());
                         }
+                        serializer.attributeBoolean(null, ATTR_DISPLAY_COMPAT,
+                                ustate.isDisplayCompat());
                         if (ustate.isSuspended()) {
                             for (int i = 0; i < ustate.getSuspendParams().size(); i++) {
                                 final String suspendingPackage = ustate.getSuspendParams().keyAt(i);
@@ -2984,6 +2994,7 @@
 
         serializer.attributeInt(null, "publicFlags", pkg.getFlags());
         serializer.attributeInt(null, "privateFlags", pkg.getPrivateFlags());
+        serializer.attributeInt(null, "privateFlagsExt", pkg.getPrivateFlagsExt());
         serializer.attributeLongHex(null, "ft", pkg.getLastModifiedTime());
         serializer.attributeLongHex(null, "ut", pkg.getLastUpdateTime());
         serializer.attributeLong(null, "version", pkg.getVersionCode());
@@ -3715,6 +3726,7 @@
 
         int pkgFlags = 0;
         int pkgPrivateFlags = 0;
+        int pkgPrivateFlagsExt = 0;
         pkgFlags |= ApplicationInfo.FLAG_SYSTEM;
         if (codePathStr.contains("/priv-app/")) {
             pkgPrivateFlags |= ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;
@@ -3726,7 +3738,8 @@
         UUID domainSetId = DomainVerificationManagerInternal.DISABLED_ID;
         PackageSetting ps = new PackageSetting(name, realName, new File(codePathStr),
                 legacyNativeLibraryPathStr, primaryCpuAbiStr, secondaryCpuAbiStr, cpuAbiOverrideStr,
-                versionCode, pkgFlags, pkgPrivateFlags, 0 /*sharedUserAppId*/, null, null, null,
+                versionCode, pkgFlags, pkgPrivateFlags, pkgPrivateFlagsExt, 0 /*sharedUserAppId*/,
+                null, null, null,
                 null, null, domainSetId);
         long timeStamp = parser.getAttributeLongHex(null, "ft", 0);
         if (timeStamp == 0) {
@@ -3810,6 +3823,7 @@
         int categoryHint = ApplicationInfo.CATEGORY_UNDEFINED;
         int pkgFlags = 0;
         int pkgPrivateFlags = 0;
+        int pkgPrivateFlagsExt = 0;
         long timeStamp = 0;
         long firstInstallTime = 0;
         long lastUpdateTime = 0;
@@ -3881,6 +3895,13 @@
                     } catch (NumberFormatException e) {
                     }
                 }
+                systemStr = parser.getAttributeValue(null, "privateFlagsExt");
+                if (systemStr != null) {
+                    try {
+                      pkgPrivateFlagsExt = Integer.parseInt(systemStr);
+                    } catch (NumberFormatException e) {
+                    }
+                }
             } else {
                 // Pre-M -- both public and private flags were stored in one "flags" field.
                 systemStr = parser.getAttributeValue(null, "flags");
@@ -3938,7 +3959,7 @@
                 packageSetting = addPackageLPw(name.intern(), realName, new File(codePathStr),
                         legacyNativeLibraryPathStr, primaryCpuAbiString, secondaryCpuAbiString,
                         cpuAbiOverrideString, appId, versionCode, pkgFlags, pkgPrivateFlags,
-                        null /* usesSdkLibraries */, null /* usesSdkLibraryVersions */,
+                        pkgPrivateFlagsExt, null /* usesSdkLibraries */, null /* usesSdkLibraryVersions */,
                         null /* usesStaticLibraries */, null /* usesStaticLibraryVersions */,
                         null /* mimeGroups */, domainSetId);
                 if (PackageManagerService.DEBUG_SETTINGS)
@@ -3957,7 +3978,7 @@
                     packageSetting = new PackageSetting(name.intern(), realName,
                             new File(codePathStr), legacyNativeLibraryPathStr,
                             primaryCpuAbiString, secondaryCpuAbiString, cpuAbiOverrideString,
-                            versionCode, pkgFlags, pkgPrivateFlags, sharedUserAppId,
+                            versionCode, pkgFlags, pkgPrivateFlags, pkgPrivateFlagsExt, sharedUserAppId,
                             null /* usesSdkLibraries */,
                             null /* usesSdkLibrariesVersions */,
                             null /* usesStaticLibraries */,
@@ -4264,6 +4285,7 @@
         String name = null;
         int pkgFlags = 0;
         int pkgPrivateFlags = 0;
+        int pkgPrivateFlagsExt = 0;
         SharedUserSetting su = null;
         {
             name = parser.getAttributeValue(null, ATTR_NAME);
@@ -4281,7 +4303,7 @@
                                 + " has bad appId " + appId + " at "
                                 + parser.getPositionDescription());
             } else {
-                if ((su = addSharedUserLPw(name.intern(), appId, pkgFlags, pkgPrivateFlags))
+                if ((su = addSharedUserLPw(name.intern(), appId, pkgFlags, pkgPrivateFlags, pkgPrivateFlagsExt))
                         == null) {
                     PackageManagerService
                             .reportSettingsProblem(Log.ERROR, "Occurred while parsing settings at "
diff --git a/services/core/java/com/android/server/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java
index a037ae8..5cba9ae 100644
--- a/services/core/java/com/android/server/pm/SharedUserSetting.java
+++ b/services/core/java/com/android/server/pm/SharedUserSetting.java
@@ -56,6 +56,7 @@
     /** @see SharedUserApi#getUidFlags() **/
     int uidFlags;
     int uidPrivateFlags;
+    int uidPrivateFlagsExt;
 
     /** @see SharedUserApi#getSeInfoTargetSdkVersion() **/
     int seInfoTargetSdkVersion;
@@ -97,10 +98,11 @@
             }};
     }
 
-    SharedUserSetting(String _name, int _pkgFlags, int _pkgPrivateFlags) {
-        super(_pkgFlags, _pkgPrivateFlags);
+    SharedUserSetting(String _name, int _pkgFlags, int _pkgPrivateFlags, int _pkgPrivateFlagsExt) {
+        super(_pkgFlags, _pkgPrivateFlags, _pkgPrivateFlagsExt);
         uidFlags =  _pkgFlags;
         uidPrivateFlags = _pkgPrivateFlags;
+        uidPrivateFlagsExt = _pkgPrivateFlagsExt;
         name = _name;
         seInfoTargetSdkVersion = android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
         mPackages = new WatchedArraySet<>();
diff --git a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
index d55f85c..6eb0080 100644
--- a/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
+++ b/services/core/java/com/android/server/pm/parsing/PackageInfoUtils.java
@@ -464,7 +464,7 @@
 
         info.flags |= appInfoFlags(info.flags, pkgSetting);
         info.privateFlags |= appInfoPrivateFlags(info.privateFlags, pkgSetting);
-        info.privateFlagsExt |= appInfoPrivateFlagsExt(info.privateFlagsExt, pkgSetting);
+        info.privateFlagsExt |= appInfoPrivateFlagsExt(info.privateFlagsExt, pkgSetting, userId);
 
         return info;
     }
@@ -972,7 +972,8 @@
 
     /** @see ApplicationInfo#privateFlagsExt */
     public static int appInfoPrivateFlagsExt(AndroidPackage pkg,
-                                             @Nullable PackageStateInternal pkgSetting) {
+                                             @Nullable PackageStateInternal pkgSetting,
+                                             @UserIdInt int userId) {
         var isAllowlistedForHiddenApis = SystemConfig.getInstance().getHiddenApiWhitelistedApps()
                 .contains(pkg.getPackageName());
         // @formatter:off
@@ -981,17 +982,21 @@
                 | flag(pkg.isAttributionsUserVisible(), ApplicationInfo.PRIVATE_FLAG_EXT_ATTRIBUTIONS_ARE_USER_VISIBLE)
                 | flag(pkg.isOnBackInvokedCallbackEnabled(), ApplicationInfo.PRIVATE_FLAG_EXT_ENABLE_ON_BACK_INVOKED_CALLBACK)
                 | flag(isAllowlistedForHiddenApis, ApplicationInfo.PRIVATE_FLAG_EXT_ALLOWLISTED_FOR_HIDDEN_APIS);
-        return appInfoPrivateFlagsExt(pkgWithoutStateFlags, pkgSetting);
+        return appInfoPrivateFlagsExt(pkgWithoutStateFlags, pkgSetting, userId);
         // @formatter:on
     }
 
     /** @see ApplicationInfo#privateFlagsExt */
-    private static int appInfoPrivateFlagsExt(int pkgWithoutStateFlags,
-                                             @Nullable PackageStateInternal pkgSetting) {
+    public static int appInfoPrivateFlagsExt(int pkgWithoutStateFlags,
+                                             @Nullable PackageStateInternal packageState,
+                                             @UserIdInt int userId) {
         // @formatter:off
+        // TODO: Add state specific flags
         int flags = pkgWithoutStateFlags;
-        if (pkgSetting != null) {
-            flags |= flag(pkgSetting.getCpuAbiOverride() != null, ApplicationInfo.PRIVATE_FLAG_EXT_CPU_OVERRIDE);
+        if (packageState != null) {
+            flags |= flag(packageState.getCpuAbiOverride() != null, ApplicationInfo.PRIVATE_FLAG_EXT_CPU_OVERRIDE);
+            flags |= flag(packageState.getUserStateOrDefault(userId).isDisplayCompat(),
+                    ApplicationInfo.PRIVATE_FLAG_EXT_DISPLAY_COMPAT);
         }
         return flags;
         // @formatter:on
diff --git a/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java b/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
index f036835..04cbbc0 100644
--- a/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
+++ b/services/core/java/com/android/server/pm/parsing/pkg/PackageImpl.java
@@ -1674,6 +1674,11 @@
     }
 
     @Override
+    public boolean isDisplayCompat() {
+        return getBoolean(Booleans2.DISPLAY_COMPAT);
+    }
+
+    @Override
     public boolean isResourceOverlay() {
         return getBoolean(Booleans.OVERLAY);
     }
@@ -2167,6 +2172,12 @@
     }
 
     @Override
+    public ParsingPackage setDisplayCompat(boolean value) {
+        setBoolean(Booleans2.DISPLAY_COMPAT, value);
+        return this;
+    }
+
+    @Override
     public PackageImpl setResourceOverlay(boolean value) {
         return setBoolean(Booleans.OVERLAY, value);
     }
@@ -2713,7 +2724,8 @@
     private void assignDerivedFields2() {
         mBaseAppInfoFlags = PackageInfoUtils.appInfoFlags(this, null);
         mBaseAppInfoPrivateFlags = PackageInfoUtils.appInfoPrivateFlags(this, null);
-        mBaseAppInfoPrivateFlagsExt = PackageInfoUtils.appInfoPrivateFlagsExt(this, null);
+        mBaseAppInfoPrivateFlagsExt = PackageInfoUtils.appInfoPrivateFlagsExt(this, null,
+                UserHandle.getUserId(uid));
         String baseAppDataDir = Environment.getDataDirectoryPath(getVolumeUuid()) + File.separator;
         String systemUserSuffix = File.separator + UserHandle.USER_SYSTEM + File.separator;
         mBaseAppDataCredentialProtectedDirForSystemUser = TextUtils.safeIntern(
@@ -3726,5 +3738,6 @@
 
         private static final long STUB = 1L;
         private static final long APEX = 1L << 1;
+        private static final long DISPLAY_COMPAT = 1L << 2;
     }
 }
diff --git a/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java b/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java
index 3d056e8..2f73458 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java
@@ -339,6 +339,7 @@
             private static final int STOPPED = 1 << 4;
             private static final int SUSPENDED = 1 << 5;
             private static final int VIRTUAL_PRELOAD = 1 << 6;
+            private static final int REQUIRES_DISPLAY_COMPAT = 1 << 7;
         }
 
         private int mBooleans;
@@ -403,6 +404,7 @@
             setBoolean(Booleans.SUSPENDED, userState.isSuspended());
             setBoolean(Booleans.VIRTUAL_PRELOAD, userState.isVirtualPreload());
             mFirstInstallTimeMillis = userState.getFirstInstallTimeMillis();
+            setBoolean(Booleans.REQUIRES_DISPLAY_COMPAT, userState.isDisplayCompat());
         }
 
         @Override
@@ -465,6 +467,11 @@
             return newPaths.build();
         }
 
+        @Override
+        public boolean isDisplayCompat() {
+          return getBoolean(Booleans.REQUIRES_DISPLAY_COMPAT);
+        }
+
 
 
         // Code below generated by codegen v1.0.23.
@@ -562,10 +569,10 @@
         }
 
         @DataClass.Generated(
-                time = 1687938966108L,
+                time = 1736544204527L,
                 codegenVersion = "1.0.23",
                 sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java",
-                inputSignatures = "private  int mBooleans\nprivate final  long mCeDataInode\nprivate final @android.annotation.NonNull android.util.ArraySet<java.lang.String> mDisabledComponents\nprivate final @android.content.pm.PackageManager.DistractionRestriction int mDistractionFlags\nprivate final @android.annotation.NonNull android.util.ArraySet<java.lang.String> mEnabledComponents\nprivate final  int mEnabledState\nprivate final @android.annotation.Nullable java.lang.String mHarmfulAppWarning\nprivate final @android.content.pm.PackageManager.InstallReason int mInstallReason\nprivate final @android.annotation.Nullable java.lang.String mLastDisableAppCaller\nprivate final @android.annotation.NonNull android.content.pm.overlay.OverlayPaths mOverlayPaths\nprivate final @android.annotation.NonNull java.util.Map<java.lang.String,android.content.pm.overlay.OverlayPaths> mSharedLibraryOverlayPaths\nprivate final @android.content.pm.PackageManager.UninstallReason int mUninstallReason\nprivate final @android.annotation.Nullable java.lang.String mSplashScreenTheme\nprivate final @android.content.pm.PackageManager.UserMinAspectRatio int mMinAspectRatio\nprivate final  long mFirstInstallTimeMillis\npublic static  com.android.server.pm.pkg.PackageUserState copy(com.android.server.pm.pkg.PackageUserState)\nprivate  void setBoolean(int,boolean)\nprivate  boolean getBoolean(int)\npublic @java.lang.Override boolean isHidden()\npublic @java.lang.Override boolean isInstalled()\npublic @java.lang.Override boolean isInstantApp()\npublic @java.lang.Override boolean isNotLaunched()\npublic @java.lang.Override boolean isStopped()\npublic @java.lang.Override boolean isSuspended()\npublic @java.lang.Override boolean isVirtualPreload()\npublic @java.lang.Override boolean isComponentEnabled(java.lang.String)\npublic @java.lang.Override boolean isComponentDisabled(java.lang.String)\npublic @java.lang.Override android.content.pm.overlay.OverlayPaths getAllOverlayPaths()\nclass UserStateImpl extends java.lang.Object implements [com.android.server.pm.pkg.PackageUserState]\nprivate static final  int HIDDEN\nprivate static final  int INSTALLED\nprivate static final  int INSTANT_APP\nprivate static final  int NOT_LAUNCHED\nprivate static final  int STOPPED\nprivate static final  int SUSPENDED\nprivate static final  int VIRTUAL_PRELOAD\nclass Booleans extends java.lang.Object implements []\[email protected](genConstructor=false)")
+                inputSignatures = "private  int mBooleans\nprivate final  long mCeDataInode\nprivate final @android.annotation.NonNull android.util.ArraySet<java.lang.String> mDisabledComponents\nprivate final @android.content.pm.PackageManager.DistractionRestriction int mDistractionFlags\nprivate final @android.annotation.NonNull android.util.ArraySet<java.lang.String> mEnabledComponents\nprivate final  int mEnabledState\nprivate final @android.annotation.Nullable java.lang.String mHarmfulAppWarning\nprivate final @android.content.pm.PackageManager.InstallReason int mInstallReason\nprivate final @android.annotation.Nullable java.lang.String mLastDisableAppCaller\nprivate final @android.annotation.NonNull android.content.pm.overlay.OverlayPaths mOverlayPaths\nprivate final @android.annotation.NonNull java.util.Map<java.lang.String,android.content.pm.overlay.OverlayPaths> mSharedLibraryOverlayPaths\nprivate final @android.content.pm.PackageManager.UninstallReason int mUninstallReason\nprivate final @android.annotation.Nullable java.lang.String mSplashScreenTheme\nprivate final @android.content.pm.PackageManager.UserMinAspectRatio int mMinAspectRatio\nprivate final  long mFirstInstallTimeMillis\npublic static  com.android.server.pm.pkg.PackageUserState copy(com.android.server.pm.pkg.PackageUserState)\nprivate  void setBoolean(int,boolean)\nprivate  boolean getBoolean(int)\npublic @java.lang.Override boolean isHidden()\npublic @java.lang.Override boolean isInstalled()\npublic @java.lang.Override boolean isInstantApp()\npublic @java.lang.Override boolean isNotLaunched()\npublic @java.lang.Override boolean isStopped()\npublic @java.lang.Override boolean isSuspended()\npublic @java.lang.Override boolean isVirtualPreload()\npublic @java.lang.Override boolean isComponentEnabled(java.lang.String)\npublic @java.lang.Override boolean isComponentDisabled(java.lang.String)\npublic @java.lang.Override android.content.pm.overlay.OverlayPaths getAllOverlayPaths()\npublic @java.lang.Override boolean isDisplayCompat()\nclass UserStateImpl extends java.lang.Object implements [com.android.server.pm.pkg.PackageUserState]\nprivate static final  int HIDDEN\nprivate static final  int INSTALLED\nprivate static final  int INSTANT_APP\nprivate static final  int NOT_LAUNCHED\nprivate static final  int STOPPED\nprivate static final  int SUSPENDED\nprivate static final  int VIRTUAL_PRELOAD\nprivate static final  int REQUIRES_DISPLAY_COMPAT\nclass Booleans extends java.lang.Object implements []\[email protected](genConstructor=false)")
         @Deprecated
         private void __metadata() {}
 
@@ -696,12 +703,17 @@
     }
 
     @DataClass.Generated.Member
+    public @NonNull List<SharedLibrary> getSharedLibraryDependencies() {
+        return mUsesLibraries;
+    }
+
+    @DataClass.Generated.Member
     public @NonNull long[] getUsesStaticLibrariesVersions() {
         return mUsesStaticLibrariesVersions;
     }
 
     @DataClass.Generated.Member
-    public @NonNull List<SharedLibrary> getSharedLibraryDependencies() {
+    public @NonNull List<SharedLibrary> getUsesLibraries() {
         return mUsesLibraries;
     }
 
@@ -737,7 +749,7 @@
     }
 
     @DataClass.Generated(
-            time = 1671671043929L,
+            time = 1736544204566L,
             codegenVersion = "1.0.23",
             sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java",
             inputSignatures = "private  int mBooleans\nprivate final @android.annotation.Nullable com.android.server.pm.pkg.AndroidPackage mAndroidPackage\nprivate final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.Nullable java.lang.String mVolumeUuid\nprivate final  int mAppId\nprivate final  int mCategoryOverride\nprivate final @android.annotation.Nullable java.lang.String mCpuAbiOverride\nprivate final @android.content.pm.ApplicationInfo.HiddenApiEnforcementPolicy int mHiddenApiEnforcementPolicy\nprivate final  long mLastModifiedTime\nprivate final  long mLastUpdateTime\nprivate final  long mLongVersionCode\nprivate final @android.annotation.NonNull java.util.Map<java.lang.String,java.util.Set<java.lang.String>> mMimeGroups\nprivate final @android.annotation.NonNull java.io.File mPath\nprivate final @android.annotation.Nullable java.lang.String mPrimaryCpuAbi\nprivate final @android.annotation.Nullable java.lang.String mSecondaryCpuAbi\nprivate final @android.annotation.Nullable java.lang.String mSeInfo\nprivate final  boolean mHasSharedUser\nprivate final  int mSharedUserAppId\nprivate final @android.annotation.NonNull java.lang.String[] mUsesSdkLibraries\nprivate final @android.annotation.NonNull long[] mUsesSdkLibrariesVersionsMajor\nprivate final @android.annotation.NonNull java.lang.String[] mUsesStaticLibraries\nprivate final @android.annotation.NonNull long[] mUsesStaticLibrariesVersions\nprivate final @android.annotation.NonNull java.util.List<com.android.server.pm.pkg.SharedLibrary> mUsesLibraries\nprivate final @android.annotation.NonNull java.util.List<java.lang.String> mUsesLibraryFiles\nprivate final @android.annotation.NonNull long[] mLastPackageUsageTime\nprivate final @android.annotation.NonNull android.content.pm.SigningInfo mSigningInfo\nprivate final @android.annotation.NonNull android.util.SparseArray<com.android.server.pm.pkg.PackageUserState> mUserStates\nprivate final @android.annotation.Nullable java.lang.String mApexModuleName\npublic static  com.android.server.pm.pkg.PackageState copy(com.android.server.pm.pkg.PackageStateInternal)\nprivate  void setBoolean(int,boolean)\nprivate  boolean getBoolean(int)\npublic @android.annotation.NonNull @java.lang.Override com.android.server.pm.pkg.PackageUserState getStateForUser(android.os.UserHandle)\npublic @java.lang.Override boolean isExternalStorage()\npublic @java.lang.Override boolean isForceQueryableOverride()\npublic @java.lang.Override boolean isHiddenUntilInstalled()\npublic @java.lang.Override boolean isInstallPermissionsFixed()\npublic @java.lang.Override boolean isOdm()\npublic @java.lang.Override boolean isOem()\npublic @java.lang.Override boolean isPrivileged()\npublic @java.lang.Override boolean isProduct()\npublic @java.lang.Override boolean isRequiredForSystemUser()\npublic @java.lang.Override boolean isSystem()\npublic @java.lang.Override boolean isSystemExt()\npublic @java.lang.Override boolean isUpdateAvailable()\npublic @java.lang.Override boolean isUpdatedSystemApp()\npublic @java.lang.Override boolean isApkInUpdatedApex()\npublic @java.lang.Override boolean isVendor()\npublic @java.lang.Override long getVersionCode()\npublic @java.lang.Override boolean hasSharedUser()\npublic @java.lang.Override boolean isApex()\nclass PackageStateImpl extends java.lang.Object implements [com.android.server.pm.pkg.PackageState]\nprivate static final  int SYSTEM\nprivate static final  int EXTERNAL_STORAGE\nprivate static final  int PRIVILEGED\nprivate static final  int OEM\nprivate static final  int VENDOR\nprivate static final  int PRODUCT\nprivate static final  int SYSTEM_EXT\nprivate static final  int REQUIRED_FOR_SYSTEM_USER\nprivate static final  int ODM\nprivate static final  int FORCE_QUERYABLE_OVERRIDE\nprivate static final  int HIDDEN_UNTIL_INSTALLED\nprivate static final  int INSTALL_PERMISSIONS_FIXED\nprivate static final  int UPDATE_AVAILABLE\nprivate static final  int UPDATED_SYSTEM_APP\nprivate static final  int APK_IN_UPDATED_APEX\nclass Booleans extends java.lang.Object implements []\[email protected](genConstructor=false)")
diff --git a/services/core/java/com/android/server/pm/pkg/PackageStateInternal.java b/services/core/java/com/android/server/pm/pkg/PackageStateInternal.java
index f839648..08bb28f 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageStateInternal.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageStateInternal.java
@@ -54,6 +54,7 @@
     // TODO: Remove this in favor of boolean APIs
     int getFlags();
     int getPrivateFlags();
+    int getPrivateFlagsExt();
 
     @NonNull
     SparseArray<? extends PackageUserStateInternal> getUserStates();
diff --git a/services/core/java/com/android/server/pm/pkg/PackageUserState.java b/services/core/java/com/android/server/pm/pkg/PackageUserState.java
index f75d214..3d0059f 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageUserState.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageUserState.java
@@ -225,4 +225,10 @@
      */
     @PackageManager.UserMinAspectRatio
     int getMinAspectRatio();
+
+    /**
+     * @return whether the app requires display compat features
+     * @hide
+     */
+    boolean isDisplayCompat();
 }
diff --git a/services/core/java/com/android/server/pm/pkg/PackageUserStateDefault.java b/services/core/java/com/android/server/pm/pkg/PackageUserStateDefault.java
index 1fb12a8..528d113 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageUserStateDefault.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageUserStateDefault.java
@@ -43,6 +43,11 @@
         return PackageManager.INSTALL_REASON_UNKNOWN;
     }
 
+    @Override
+    public boolean isDisplayCompat() {
+        return false;
+    }
+
     @NonNull
     @Override
     public Map<String, OverlayPaths> getSharedLibraryOverlayPaths() {
diff --git a/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java b/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java
index d911ac1..95a440b 100644
--- a/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java
+++ b/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java
@@ -97,6 +97,8 @@
 
     private @CurrentTimeMillisLong long mFirstInstallTimeMillis;
 
+    private boolean mDisplayCompat;
+
     // TODO(b/239050028): Remove, enforce notifying parent through PMS commit method
     @Nullable
     private Watchable mWatchable;
@@ -154,6 +156,7 @@
         mComponentLabelIconOverrideMap = other.mComponentLabelIconOverrideMap == null
                 ? null : other.mComponentLabelIconOverrideMap.snapshot();
         mFirstInstallTimeMillis = other.mFirstInstallTimeMillis;
+        mDisplayCompat = other.mDisplayCompat;
         mSnapshot = new SnapshotCache.Sealed<>();
     }
 
@@ -563,6 +566,12 @@
         return this;
     }
 
+    public @NonNull PackageUserStateImpl setDisplayCompat(boolean value) {
+        mDisplayCompat = value;
+        onChanged();
+        return this;
+    }
+
     @NonNull
     @Override
     public Map<String, OverlayPaths> getSharedLibraryOverlayPaths() {
@@ -720,6 +729,11 @@
     }
 
     @DataClass.Generated.Member
+    public boolean isDisplayCompat() {
+        return mDisplayCompat;
+    }
+
+    @DataClass.Generated.Member
     public @NonNull SnapshotCache<PackageUserStateImpl> getSnapshot() {
         return mSnapshot;
     }
@@ -792,6 +806,7 @@
                 && Objects.equals(mSuspendParams, that.mSuspendParams)
                 && Objects.equals(mComponentLabelIconOverrideMap, that.mComponentLabelIconOverrideMap)
                 && mFirstInstallTimeMillis == that.mFirstInstallTimeMillis
+                && mDisplayCompat == that.mDisplayCompat
                 && watchableEquals(that.mWatchable)
                 && snapshotEquals(that.mSnapshot);
     }
@@ -825,16 +840,17 @@
         _hash = 31 * _hash + Objects.hashCode(mSuspendParams);
         _hash = 31 * _hash + Objects.hashCode(mComponentLabelIconOverrideMap);
         _hash = 31 * _hash + Long.hashCode(mFirstInstallTimeMillis);
+        _hash = 31 * _hash + Boolean.hashCode(mDisplayCompat);
         _hash = 31 * _hash + watchableHashCode();
         _hash = 31 * _hash + snapshotHashCode();
         return _hash;
     }
 
     @DataClass.Generated(
-            time = 1687938397579L,
+            time = 1736542105812L,
             codegenVersion = "1.0.23",
             sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java",
-            inputSignatures = "protected @android.annotation.Nullable com.android.server.utils.WatchedArraySet<java.lang.String> mDisabledComponentsWatched\nprotected @android.annotation.Nullable com.android.server.utils.WatchedArraySet<java.lang.String> mEnabledComponentsWatched\nprivate  long mCeDataInode\nprivate  boolean mInstalled\nprivate  boolean mStopped\nprivate  boolean mNotLaunched\nprivate  boolean mHidden\nprivate  int mDistractionFlags\nprivate  boolean mInstantApp\nprivate  boolean mVirtualPreload\nprivate @android.content.pm.PackageManager.EnabledState int mEnabledState\nprivate @android.content.pm.PackageManager.InstallReason int mInstallReason\nprivate @android.content.pm.PackageManager.UninstallReason int mUninstallReason\nprivate @android.annotation.Nullable java.lang.String mHarmfulAppWarning\nprivate @android.annotation.Nullable java.lang.String mLastDisableAppCaller\nprivate @android.annotation.Nullable android.content.pm.overlay.OverlayPaths mOverlayPaths\nprotected @android.annotation.Nullable com.android.server.utils.WatchedArrayMap<java.lang.String,android.content.pm.overlay.OverlayPaths> mSharedLibraryOverlayPaths\nprivate @android.annotation.Nullable java.lang.String mSplashScreenTheme\nprivate @android.content.pm.PackageManager.UserMinAspectRatio int mMinAspectRatio\nprivate @android.annotation.Nullable com.android.server.utils.WatchedArrayMap<java.lang.String,com.android.server.pm.pkg.SuspendParams> mSuspendParams\nprivate @android.annotation.Nullable com.android.server.utils.WatchedArrayMap<android.content.ComponentName,android.util.Pair<java.lang.String,java.lang.Integer>> mComponentLabelIconOverrideMap\nprivate @android.annotation.CurrentTimeMillisLong long mFirstInstallTimeMillis\nprivate @android.annotation.Nullable com.android.server.utils.Watchable mWatchable\nfinal @android.annotation.NonNull com.android.server.utils.SnapshotCache<com.android.server.pm.pkg.PackageUserStateImpl> mSnapshot\nprivate  com.android.server.utils.SnapshotCache<com.android.server.pm.pkg.PackageUserStateImpl> makeCache()\nprivate  void onChanged()\npublic @android.annotation.NonNull @java.lang.Override com.android.server.pm.pkg.PackageUserStateImpl snapshot()\npublic @android.annotation.Nullable boolean setOverlayPaths(android.content.pm.overlay.OverlayPaths)\npublic  boolean setSharedLibraryOverlayPaths(java.lang.String,android.content.pm.overlay.OverlayPaths)\npublic @android.annotation.Nullable @java.lang.Override com.android.server.utils.WatchedArraySet<java.lang.String> getDisabledComponentsNoCopy()\npublic @android.annotation.Nullable @java.lang.Override com.android.server.utils.WatchedArraySet<java.lang.String> getEnabledComponentsNoCopy()\npublic @android.annotation.NonNull @java.lang.Override android.util.ArraySet<java.lang.String> getDisabledComponents()\npublic @android.annotation.NonNull @java.lang.Override android.util.ArraySet<java.lang.String> getEnabledComponents()\npublic @java.lang.Override boolean isComponentEnabled(java.lang.String)\npublic @java.lang.Override boolean isComponentDisabled(java.lang.String)\npublic @java.lang.Override android.content.pm.overlay.OverlayPaths getAllOverlayPaths()\npublic @com.android.internal.annotations.VisibleForTesting boolean overrideLabelAndIcon(android.content.ComponentName,java.lang.String,java.lang.Integer)\npublic  void resetOverrideComponentLabelIcon()\npublic @android.annotation.Nullable android.util.Pair<java.lang.String,java.lang.Integer> getOverrideLabelIconForComponent(android.content.ComponentName)\npublic @java.lang.Override boolean isSuspended()\npublic  com.android.server.pm.pkg.PackageUserStateImpl putSuspendParams(java.lang.String,com.android.server.pm.pkg.SuspendParams)\npublic  com.android.server.pm.pkg.PackageUserStateImpl removeSuspension(java.lang.String)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setDisabledComponents(android.util.ArraySet<java.lang.String>)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setEnabledComponents(android.util.ArraySet<java.lang.String>)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setEnabledComponents(com.android.server.utils.WatchedArraySet<java.lang.String>)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setDisabledComponents(com.android.server.utils.WatchedArraySet<java.lang.String>)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setCeDataInode(long)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setInstalled(boolean)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setStopped(boolean)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setNotLaunched(boolean)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setHidden(boolean)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setDistractionFlags(int)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setInstantApp(boolean)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setVirtualPreload(boolean)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setEnabledState(int)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setInstallReason(int)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setUninstallReason(int)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setHarmfulAppWarning(java.lang.String)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setLastDisableAppCaller(java.lang.String)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setSharedLibraryOverlayPaths(android.util.ArrayMap<java.lang.String,android.content.pm.overlay.OverlayPaths>)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setSplashScreenTheme(java.lang.String)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setMinAspectRatio(int)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setSuspendParams(android.util.ArrayMap<java.lang.String,com.android.server.pm.pkg.SuspendParams>)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setComponentLabelIconOverrideMap(android.util.ArrayMap<android.content.ComponentName,android.util.Pair<java.lang.String,java.lang.Integer>>)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setFirstInstallTimeMillis(long)\npublic @android.annotation.NonNull @java.lang.Override java.util.Map<java.lang.String,android.content.pm.overlay.OverlayPaths> getSharedLibraryOverlayPaths()\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setWatchable(com.android.server.utils.Watchable)\nprivate  boolean watchableEquals(com.android.server.utils.Watchable)\nprivate  int watchableHashCode()\nprivate  boolean snapshotEquals(com.android.server.utils.SnapshotCache<com.android.server.pm.pkg.PackageUserStateImpl>)\nprivate  int snapshotHashCode()\nclass PackageUserStateImpl extends com.android.server.utils.WatchableImpl implements [com.android.server.pm.pkg.PackageUserStateInternal, com.android.server.utils.Snappable]\[email protected](genConstructor=false, genBuilder=false, genEqualsHashCode=true)")
+            inputSignatures = "protected @android.annotation.Nullable com.android.server.utils.WatchedArraySet<java.lang.String> mDisabledComponentsWatched\nprotected @android.annotation.Nullable com.android.server.utils.WatchedArraySet<java.lang.String> mEnabledComponentsWatched\nprivate  long mCeDataInode\nprivate  boolean mInstalled\nprivate  boolean mStopped\nprivate  boolean mNotLaunched\nprivate  boolean mHidden\nprivate  int mDistractionFlags\nprivate  boolean mInstantApp\nprivate  boolean mVirtualPreload\nprivate @android.content.pm.PackageManager.EnabledState int mEnabledState\nprivate @android.content.pm.PackageManager.InstallReason int mInstallReason\nprivate @android.content.pm.PackageManager.UninstallReason int mUninstallReason\nprivate @android.annotation.Nullable java.lang.String mHarmfulAppWarning\nprivate @android.annotation.Nullable java.lang.String mLastDisableAppCaller\nprivate @android.annotation.Nullable android.content.pm.overlay.OverlayPaths mOverlayPaths\nprotected @android.annotation.Nullable com.android.server.utils.WatchedArrayMap<java.lang.String,android.content.pm.overlay.OverlayPaths> mSharedLibraryOverlayPaths\nprivate @android.annotation.Nullable java.lang.String mSplashScreenTheme\nprivate @android.content.pm.PackageManager.UserMinAspectRatio int mMinAspectRatio\nprivate @android.annotation.Nullable com.android.server.utils.WatchedArrayMap<java.lang.String,com.android.server.pm.pkg.SuspendParams> mSuspendParams\nprivate @android.annotation.Nullable com.android.server.utils.WatchedArrayMap<android.content.ComponentName,android.util.Pair<java.lang.String,java.lang.Integer>> mComponentLabelIconOverrideMap\nprivate @android.annotation.CurrentTimeMillisLong long mFirstInstallTimeMillis\nprivate  boolean mDisplayCompat\nprivate @android.annotation.Nullable com.android.server.utils.Watchable mWatchable\nfinal @android.annotation.NonNull com.android.server.utils.SnapshotCache<com.android.server.pm.pkg.PackageUserStateImpl> mSnapshot\nprivate  com.android.server.utils.SnapshotCache<com.android.server.pm.pkg.PackageUserStateImpl> makeCache()\nprivate  void onChanged()\npublic @android.annotation.NonNull @java.lang.Override com.android.server.pm.pkg.PackageUserStateImpl snapshot()\npublic @android.annotation.Nullable boolean setOverlayPaths(android.content.pm.overlay.OverlayPaths)\npublic  boolean setSharedLibraryOverlayPaths(java.lang.String,android.content.pm.overlay.OverlayPaths)\npublic @android.annotation.Nullable @java.lang.Override com.android.server.utils.WatchedArraySet<java.lang.String> getDisabledComponentsNoCopy()\npublic @android.annotation.Nullable @java.lang.Override com.android.server.utils.WatchedArraySet<java.lang.String> getEnabledComponentsNoCopy()\npublic @android.annotation.NonNull @java.lang.Override android.util.ArraySet<java.lang.String> getDisabledComponents()\npublic @android.annotation.NonNull @java.lang.Override android.util.ArraySet<java.lang.String> getEnabledComponents()\npublic @java.lang.Override boolean isComponentEnabled(java.lang.String)\npublic @java.lang.Override boolean isComponentDisabled(java.lang.String)\npublic @java.lang.Override android.content.pm.overlay.OverlayPaths getAllOverlayPaths()\npublic @com.android.internal.annotations.VisibleForTesting boolean overrideLabelAndIcon(android.content.ComponentName,java.lang.String,java.lang.Integer)\npublic  void resetOverrideComponentLabelIcon()\npublic @android.annotation.Nullable android.util.Pair<java.lang.String,java.lang.Integer> getOverrideLabelIconForComponent(android.content.ComponentName)\npublic @java.lang.Override boolean isSuspended()\npublic  com.android.server.pm.pkg.PackageUserStateImpl putSuspendParams(java.lang.String,com.android.server.pm.pkg.SuspendParams)\npublic  com.android.server.pm.pkg.PackageUserStateImpl removeSuspension(java.lang.String)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setDisabledComponents(android.util.ArraySet<java.lang.String>)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setEnabledComponents(android.util.ArraySet<java.lang.String>)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setEnabledComponents(com.android.server.utils.WatchedArraySet<java.lang.String>)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setDisabledComponents(com.android.server.utils.WatchedArraySet<java.lang.String>)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setCeDataInode(long)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setInstalled(boolean)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setStopped(boolean)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setNotLaunched(boolean)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setHidden(boolean)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setDistractionFlags(int)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setInstantApp(boolean)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setVirtualPreload(boolean)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setEnabledState(int)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setInstallReason(int)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setUninstallReason(int)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setHarmfulAppWarning(java.lang.String)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setLastDisableAppCaller(java.lang.String)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setSharedLibraryOverlayPaths(android.util.ArrayMap<java.lang.String,android.content.pm.overlay.OverlayPaths>)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setSplashScreenTheme(java.lang.String)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setMinAspectRatio(int)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setSuspendParams(android.util.ArrayMap<java.lang.String,com.android.server.pm.pkg.SuspendParams>)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setComponentLabelIconOverrideMap(android.util.ArrayMap<android.content.ComponentName,android.util.Pair<java.lang.String,java.lang.Integer>>)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setFirstInstallTimeMillis(long)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setDisplayCompat(boolean)\npublic @android.annotation.NonNull @java.lang.Override java.util.Map<java.lang.String,android.content.pm.overlay.OverlayPaths> getSharedLibraryOverlayPaths()\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageUserStateImpl setWatchable(com.android.server.utils.Watchable)\nprivate  boolean watchableEquals(com.android.server.utils.Watchable)\nprivate  int watchableHashCode()\nprivate  boolean snapshotEquals(com.android.server.utils.SnapshotCache<com.android.server.pm.pkg.PackageUserStateImpl>)\nprivate  int snapshotHashCode()\nclass PackageUserStateImpl extends com.android.server.utils.WatchableImpl implements [com.android.server.pm.pkg.PackageUserStateInternal, com.android.server.utils.Snappable]\[email protected](genConstructor=false, genBuilder=false, genEqualsHashCode=true)")
     @Deprecated
     private void __metadata() {}
 
diff --git a/services/core/java/com/android/server/pm/pkg/mutate/PackageStateMutator.java b/services/core/java/com/android/server/pm/pkg/mutate/PackageStateMutator.java
index 8430cf7..8a25a81 100644
--- a/services/core/java/com/android/server/pm/pkg/mutate/PackageStateMutator.java
+++ b/services/core/java/com/android/server/pm/pkg/mutate/PackageStateMutator.java
@@ -449,6 +449,15 @@
                 }
                 return this;
             }
+
+            @NonNull
+            @Override
+            public PackageUserStateWrite setDisplayCompat(boolean enabled) {
+              if (mUserState != null) {
+                  mUserState.setDisplayCompat(enabled);
+              }
+              return null;
+            }
         }
     }
 }
diff --git a/services/core/java/com/android/server/pm/pkg/mutate/PackageUserStateWrite.java b/services/core/java/com/android/server/pm/pkg/mutate/PackageUserStateWrite.java
index 0c6c672..3e58c4d 100644
--- a/services/core/java/com/android/server/pm/pkg/mutate/PackageUserStateWrite.java
+++ b/services/core/java/com/android/server/pm/pkg/mutate/PackageUserStateWrite.java
@@ -73,4 +73,7 @@
     /** @see PackageUserStateImpl#setMinAspectRatio(int) */
     @NonNull
     PackageUserStateWrite setMinAspectRatio(@PackageManager.UserMinAspectRatio int aspectRatio);
+
+    @NonNull
+    PackageUserStateWrite setDisplayCompat(boolean enabled);
 }
diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java
index 7fc3356..c573200 100644
--- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java
+++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackage.java
@@ -396,6 +396,8 @@
 
     ParsingPackage setOnBackInvokedCallbackEnabled(boolean enableOnBackInvokedCallback);
 
+    ParsingPackage setDisplayCompat(boolean displayCompat);
+
     @CallSuper
     ParsedPackage hideAsParsed();
 
@@ -534,4 +536,6 @@
     boolean isNormalScreensSupported();
 
     boolean isSmallScreensSupported();
+
+    boolean isDisplayCompat();
 }
diff --git a/services/core/java/com/android/server/policy/PermissionPolicyService.java b/services/core/java/com/android/server/policy/PermissionPolicyService.java
index 0e99e7e..fec59c4 100644
--- a/services/core/java/com/android/server/policy/PermissionPolicyService.java
+++ b/services/core/java/com/android/server/policy/PermissionPolicyService.java
@@ -348,8 +348,16 @@
                 UserHandle user = UserHandle.getUserHandleForUid(uid);
                 PermissionControllerManager manager = mPermControllerManagers.get(user);
                 if (manager == null) {
-                    manager = new PermissionControllerManager(
-                            getUserContext(getContext(), user), PermissionThread.getHandler());
+                    try {
+                        manager = new PermissionControllerManager(
+                                getUserContext(getContext(), user),
+                                PermissionThread.getHandler());
+                    } catch (IllegalStateException exception) {
+                        // There's a possible race condition when a user is being removed
+                        Log.e(LOG_TAG, "Could not create PermissionControllerManager for user"
+                                        + user, exception);
+                        return;
+                    }
                     mPermControllerManagers.put(user, manager);
                 }
                 manager.updateUserSensitiveForApp(uid);
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 3394282..60b0d78 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -3110,7 +3110,7 @@
                 }
                 break;
             case KeyEvent.KEYCODE_I:
-                if (firstDown && event.isMetaPressed()) {
+                if (firstDown && event.isMetaPressed() && isUserSetupComplete() && !keyguardOn) {
                     showSystemSettings();
                     logKeyboardSystemsEvent(event, KeyboardLogEvent.LAUNCH_SYSTEM_SETTINGS);
                     return true;
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index d7489f2..32e5747 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -5648,6 +5648,15 @@
         return createSafeActivityOptionsWithBalAllowed(ActivityOptions.fromBundle(bOptions));
     }
 
+    void registerCompatScaleProvider(@CompatScaleProvider.CompatScaleModeOrderId int id,
+            @NonNull CompatScaleProvider provider) {
+        mCompatModePackages.registerCompatScaleProvider(id, provider);
+    }
+
+    void unregisterCompatScaleProvider(@CompatScaleProvider.CompatScaleModeOrderId int id) {
+        mCompatModePackages.unregisterCompatScaleProvider(id);
+    }
+
     final class H extends Handler {
         static final int REPORT_TIME_TRACKER_MSG = 1;
         static final int END_POWER_MODE_UNKNOWN_VISIBILITY_MSG = 3;
diff --git a/services/core/java/com/android/server/wm/CompatModePackages.java b/services/core/java/com/android/server/wm/CompatModePackages.java
index c6978fd..12ee5f5 100644
--- a/services/core/java/com/android/server/wm/CompatModePackages.java
+++ b/services/core/java/com/android/server/wm/CompatModePackages.java
@@ -20,7 +20,10 @@
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
+import static com.android.server.wm.CompatScaleProvider.COMPAT_SCALE_MODE_SYSTEM_FIRST;
+import static com.android.server.wm.CompatScaleProvider.COMPAT_SCALE_MODE_SYSTEM_LAST;
 
+import android.annotation.NonNull;
 import android.app.ActivityManager;
 import android.app.AppGlobals;
 import android.app.GameManagerInternal;
@@ -32,6 +35,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.IPackageManager;
 import android.content.res.CompatibilityInfo;
+import android.content.res.CompatibilityInfo.CompatScale;
 import android.content.res.Configuration;
 import android.os.Build;
 import android.os.Handler;
@@ -331,6 +335,7 @@
     private final AtomicFile mFile;
     private final HashMap<String, Integer> mPackages = new HashMap<>();
     private final CompatHandler mHandler;
+    private final SparseArray<CompatScaleProvider> mProviders = new SparseArray<>();
 
     public CompatModePackages(ActivityTaskManagerService service, File systemDir, Handler handler) {
         mService = service;
@@ -441,13 +446,32 @@
 
     public CompatibilityInfo compatibilityInfoForPackageLocked(ApplicationInfo ai) {
         final boolean forceCompat = getPackageCompatModeEnabledLocked(ai);
-        final float compatScale = getCompatScale(ai.packageName, ai.uid);
+        final CompatScale compatScale = getCompatScaleFromProvider(ai.packageName, ai.uid);
+        final float appScale = compatScale != null
+                ? compatScale.mScaleFactor
+                : getCompatScale(ai.packageName, ai.uid, /* checkProvider= */ false);
+        final float densityScale = compatScale != null ? compatScale.mDensityScaleFactor : appScale;
         final Configuration config = mService.getGlobalConfiguration();
         return new CompatibilityInfo(ai, config.screenLayout, config.smallestScreenWidthDp,
-                forceCompat, compatScale);
+                forceCompat, appScale, appScale, densityScale);
     }
 
     float getCompatScale(String packageName, int uid) {
+        return getCompatScale(packageName, uid, /* checkProvider= */ true);
+    }
+
+    private CompatScale getCompatScaleFromProvider(String packageName, int uid) {
+        for (int i = 0; i < mProviders.size(); i++) {
+            final CompatScaleProvider provider = mProviders.valueAt(i);
+            final CompatScale compatScale = provider.getCompatScale(packageName, uid);
+            if (compatScale != null) {
+                return compatScale;
+            }
+        }
+        return null;
+    }
+
+    private float getCompatScale(String packageName, int uid, boolean checkProviders) {
         final UserHandle userHandle = UserHandle.getUserHandleForUid(uid);
         if (mGameManager == null) {
             mGameManager = LocalServices.getService(GameManagerInternal.class);
@@ -474,6 +498,13 @@
             }
         }
 
+        if (checkProviders) {
+            final CompatScale compatScale = getCompatScaleFromProvider(packageName, uid);
+            if (compatScale != null) {
+                return compatScale.mScaleFactor;
+            }
+        }
+
         if (mService.mHasLeanbackFeature) {
             final Configuration config = mService.getGlobalConfiguration();
             final float density = config.densityDpi / (float) DisplayMetrics.DENSITY_DEFAULT;
@@ -530,6 +561,36 @@
         return 1f;
     }
 
+    void registerCompatScaleProvider(@CompatScaleProvider.CompatScaleModeOrderId int id,
+            @NonNull CompatScaleProvider provider) {
+        synchronized (mService.mGlobalLock) {
+            if (mProviders.contains(id)) {
+                throw new IllegalArgumentException("Duplicate id provided: " + id);
+            }
+            if (provider == null) {
+                throw new IllegalArgumentException("The passed CompatScaleProvider "
+                        + "can not be null");
+            }
+            if (!CompatScaleProvider.isValidOrderId(id)) {
+                throw new IllegalArgumentException(
+                        "Provided id " + id + " is not in range of valid ids for system "
+                                + "services [" + COMPAT_SCALE_MODE_SYSTEM_FIRST + ","
+                                + COMPAT_SCALE_MODE_SYSTEM_LAST + "]");
+            }
+            mProviders.put(id, provider);
+        }
+    }
+
+    void unregisterCompatScaleProvider(@CompatScaleProvider.CompatScaleModeOrderId int id) {
+        synchronized (mService.mGlobalLock) {
+            if (!mProviders.contains(id)) {
+                throw new IllegalArgumentException(
+                        "CompatScaleProvider with id (" + id + ") is not registered");
+            }
+            mProviders.remove(id);
+        }
+    }
+
     public int computeCompatModeLocked(ApplicationInfo ai) {
         final CompatibilityInfo info = compatibilityInfoForPackageLocked(ai);
         if (info.alwaysSupportsScreen()) {
diff --git a/services/core/java/com/android/server/wm/CompatScaleProvider.java b/services/core/java/com/android/server/wm/CompatScaleProvider.java
new file mode 100644
index 0000000..6cbeb8a
--- /dev/null
+++ b/services/core/java/com/android/server/wm/CompatScaleProvider.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.server.wm;
+
+import android.annotation.IntDef;
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.content.res.CompatibilityInfo.CompatScale;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * An interface for services that need to provide compatibility scale different than
+ * the default android compatibility.
+ */
+public interface CompatScaleProvider {
+
+    /**
+     * The unique id of each provider registered by a system service which determines the order
+     * it will execute in.
+     */
+    @IntDef(prefix = { "COMPAT_SCALE_MODE_" }, value = {
+        // Order Ids for system services
+        COMPAT_SCALE_MODE_SYSTEM_FIRST,
+        COMPAT_SCALE_MODE_PRODUCT,
+        COMPAT_SCALE_MODE_SYSTEM_LAST, // Update this when adding new ids
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface CompatScaleModeOrderId {}
+
+    /**
+     * The first id, used by the framework to determine the valid range of ids.
+     * @hide
+     */
+    int COMPAT_SCALE_MODE_SYSTEM_FIRST = 0;
+
+    /**
+     * The identifier for a provider which is specific to the type of android product like
+     * Automotive, Wear, TV etc.
+     * @hide
+     */
+    int COMPAT_SCALE_MODE_PRODUCT = 1;
+
+    /**
+     * The final id, used by the framework to determine the valid range of ids. Update this when
+     * adding new ids.
+     * @hide
+     */
+    int COMPAT_SCALE_MODE_SYSTEM_LAST = COMPAT_SCALE_MODE_PRODUCT;
+
+    /**
+     * Returns {@code true} if the id is in the range of valid system services
+     * @hide
+     */
+    static boolean isValidOrderId(int id) {
+        return (id >= COMPAT_SCALE_MODE_SYSTEM_FIRST && id <= COMPAT_SCALE_MODE_SYSTEM_LAST);
+    }
+
+    /**
+     * @return an instance of {@link CompatScale} to apply for the given package
+     */
+    @Nullable
+    CompatScale getCompatScale(@NonNull String packageName, int uid);
+}
diff --git a/services/core/java/com/android/server/wm/LockTaskController.java b/services/core/java/com/android/server/wm/LockTaskController.java
index 830f785..2f963a7 100644
--- a/services/core/java/com/android/server/wm/LockTaskController.java
+++ b/services/core/java/com/android/server/wm/LockTaskController.java
@@ -653,6 +653,10 @@
         if (!isSystemCaller) {
             task.mLockTaskUid = callingUid;
             if (task.mLockTaskAuth == LOCK_TASK_AUTH_PINNABLE) {
+                if (mLockTaskModeTasks.contains(task)) {
+                    Slog.i(TAG_LOCKTASK, "Already locked.");
+                    return;
+                }
                 // startLockTask() called by app, but app is not part of lock task allowlist. Show
                 // app pinning request. We will come back here with isSystemCaller true.
                 ProtoLog.w(WM_DEBUG_LOCKTASK, "Mode default, asking user");
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 7ef90fe..33217b9 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -1291,16 +1291,15 @@
         }
 
         // Update the input-sink (touch-blocking) state now that the animation is finished.
-        SurfaceControl.Transaction inputSinkTransaction = null;
+        boolean scheduleAnimation = false;
         for (int i = 0; i < mParticipants.size(); ++i) {
             final ActivityRecord ar = mParticipants.valueAt(i).asActivityRecord();
             if (ar == null || !ar.isVisible() || ar.getParent() == null) continue;
-            if (inputSinkTransaction == null) {
-                inputSinkTransaction = ar.mWmService.mTransactionFactory.get();
-            }
-            ar.mActivityRecordInputSink.applyChangesToSurfaceIfChanged(inputSinkTransaction);
+            scheduleAnimation = true;
+            ar.mActivityRecordInputSink.applyChangesToSurfaceIfChanged(ar.getPendingTransaction());
         }
-        if (inputSinkTransaction != null) inputSinkTransaction.apply();
+        // To apply pending transactions.
+        if (scheduleAnimation) mController.mAtm.mWindowManager.scheduleAnimationLocked();
 
         // Always schedule stop processing when transition finishes because activities don't
         // stop while they are in a transition thus their stop could still be pending.
diff --git a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
index f3ac7d5..cae95d0 100644
--- a/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
+++ b/services/tests/PackageManagerComponentOverrideTests/src/com/android/server/pm/test/override/PackageManagerComponentLabelIconOverrideTest.kt
@@ -55,6 +55,7 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.Parameterized
+import org.mockito.ArgumentMatchers.eq
 import org.mockito.Mockito.any
 import org.mockito.Mockito.anyInt
 import org.mockito.Mockito.doReturn
@@ -301,8 +302,8 @@
     private fun makePkgSetting(pkgName: String, pkg: AndroidPackageInternal) =
         PackageSetting(
             pkgName, null, File("/test"),
-            null, null, null, null, 0, 0, 0, 0, null, null, null, null, null,
-            UUID.fromString("3f9d52b7-d7b4-406a-a1da-d9f19984c72c")
+            null, null, null, null, 0, 0, 0, 0, 0, null, null, null,
+            null, null, UUID.fromString("3f9d52b7-d7b4-406a-a1da-d9f19984c72c")
         ).apply {
             if (params.isSystem) {
                 this.flags = this.flags or ApplicationInfo.FLAG_SYSTEM
@@ -385,6 +386,10 @@
                     android.Manifest.permission.INTERACT_ACROSS_USERS_FULL)) {
                 PackageManager.PERMISSION_GRANTED
             }
+            whenever(this.checkPermission(
+                eq(android.Manifest.permission.INTERACT_ACROSS_USERS_FULL), anyInt(), anyInt())) {
+                PackageManager.PERMISSION_GRANTED
+            }
         }
         val mockSharedLibrariesImpl: SharedLibrariesImpl = mock {
             whenever(this.snapshot()) { this@mock }
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java
index 7909ba4..e5fc363 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/AppsFilterImplTest.java
@@ -998,7 +998,7 @@
 
         PackageSetting targetSetting = simulateAddPackage(appsFilter, target, DUMMY_TARGET_APPID);
         SharedUserSetting actorSharedSetting = new SharedUserSetting("actorSharedUser",
-                targetSetting.getFlags(), targetSetting.getPrivateFlags());
+                targetSetting.getFlags(), targetSetting.getPrivateFlags(), targetSetting.getPrivateFlagsExt());
         actorSharedSetting.mAppId = 100; /* mimic a valid sharedUserSetting.mAppId */
         PackageSetting overlaySetting =
                 simulateAddPackage(appsFilter, overlay, DUMMY_OVERLAY_APPID);
diff --git a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java
index 16fb012..307d492 100644
--- a/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java
+++ b/services/tests/PackageManagerServiceTests/server/src/com/android/server/pm/PackageManagerSettingsTests.java
@@ -936,7 +936,8 @@
                 INITIAL_VERSION_CODE,
                 ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_HAS_CODE,
                 ApplicationInfo.PRIVATE_FLAG_PRIVILEGED|ApplicationInfo.PRIVATE_FLAG_HIDDEN,
-                0,
+                0, /* pkgPrivateFlagsExt */
+                0, /* sharedUserAppId */
                 null /*usesSdkLibraries*/,
                 null /*usesSdkLibrariesVersions*/,
                 null /*usesStaticLibraries*/,
@@ -961,7 +962,8 @@
                 INITIAL_VERSION_CODE,
                 ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_HAS_CODE,
                 ApplicationInfo.PRIVATE_FLAG_PRIVILEGED|ApplicationInfo.PRIVATE_FLAG_HIDDEN,
-                0,
+                0 /*pkgPrivateFlagsExt*/,
+                0 /*sharedUserAppId*/,
                 null /*usesSdkLibraries*/,
                 null /*usesSdkLibrariesVersions*/,
                 null /*usesStaticLibraries*/,
@@ -971,7 +973,7 @@
         origPkgSetting01.setUserState(0, 100, 1, true, false, false, false, 0, null, false,
                 false, "lastDisabledCaller", new ArraySet<>(new String[]{"enabledComponent1"}),
                 new ArraySet<>(new String[]{"disabledComponent1"}), 0, 0, "harmfulAppWarning",
-                "splashScreenTheme", 1000L, PackageManager.USER_MIN_ASPECT_RATIO_UNSET);
+                "splashScreenTheme", 1000L, PackageManager.USER_MIN_ASPECT_RATIO_UNSET, false);
         final PersistableBundle appExtras1 = createPersistableBundle(
                 PACKAGE_NAME_1, 1L, 0.01, true, "appString1");
         final PersistableBundle launcherExtras1 = createPersistableBundle(
@@ -997,6 +999,7 @@
                 UPDATED_VERSION_CODE,
                 0 /*pkgFlags*/,
                 0 /*pkgPrivateFlags*/,
+                0 /*pkgPrivateFlagsExt*/,
                 0,
                 null /*usesSdkLibraries*/,
                 null /*usesSdkLibrariesVersions*/,
@@ -1020,6 +1023,7 @@
         testPkgSetting01.setInstalled(false /*installed*/, 0 /*userId*/);
         assertThat(testPkgSetting01.getFlags(), is(0));
         assertThat(testPkgSetting01.getPrivateFlags(), is(0));
+        assertThat(testPkgSetting01.getPrivateFlagsExt(), is(0));
         final PackageSetting oldPkgSetting01 = new PackageSetting(testPkgSetting01);
         Settings.updatePackageSetting(
                 testPkgSetting01,
@@ -1032,6 +1036,7 @@
                 "armeabi" /*secondaryCpuAbi*/,
                 0 /*pkgFlags*/,
                 0 /*pkgPrivateFlags*/,
+                0 /*pkgPrivateFlagsExt*/,
                 UserManagerService.getInstance(),
                 null /*usesSdkLibraries*/,
                 null /*usesSdkLibrariesVersions*/,
@@ -1045,6 +1050,7 @@
         assertThat(testPkgSetting01.getSecondaryCpuAbiLegacy(), is("armeabi"));
         assertThat(testPkgSetting01.getFlags(), is(0));
         assertThat(testPkgSetting01.getPrivateFlags(), is(0));
+        assertThat(testPkgSetting01.getPrivateFlagsExt(), is(0));
         final PackageUserState userState = testPkgSetting01.readUserState(0);
         verifyUserState(userState, false /*notLaunched*/,
                 false /*stopped*/, false /*installed*/);
@@ -1058,6 +1064,7 @@
         testPkgSetting01.setInstalled(false /*installed*/, 0 /*userId*/);
         assertThat(testPkgSetting01.getFlags(), is(0));
         assertThat(testPkgSetting01.getPrivateFlags(), is(0));
+        assertThat(testPkgSetting01.getPrivateFlagsExt(), is(0));
         final PackageSetting oldPkgSetting01 = new PackageSetting(testPkgSetting01);
         Settings.updatePackageSetting(
                 testPkgSetting01,
@@ -1070,6 +1077,7 @@
                 "armeabi" /*secondaryCpuAbi*/,
                 ApplicationInfo.FLAG_SYSTEM /*pkgFlags*/,
                 ApplicationInfo.PRIVATE_FLAG_PRIVILEGED /*pkgPrivateFlags*/,
+                0 /*pkgPrivateFlagsExt*/,
                 UserManagerService.getInstance(),
                 null /*usesSdkLibraries*/,
                 null /*usesSdkLibrariesVersions*/,
@@ -1084,6 +1092,7 @@
         assertThat(testPkgSetting01.getFlags(), is(ApplicationInfo.FLAG_SYSTEM));
         assertThat(testPkgSetting01.isSystem(), is(true));
         assertThat(testPkgSetting01.getPrivateFlags(), is(ApplicationInfo.PRIVATE_FLAG_PRIVILEGED));
+        assertThat(testPkgSetting01.getPrivateFlagsExt(), is(0));
         assertThat(testPkgSetting01.isPrivileged(), is(true));
         final PackageUserState userState = testPkgSetting01.readUserState(0);
         verifyUserState(userState,  false /*notLaunched*/,
@@ -1095,7 +1104,8 @@
     public void testUpdatePackageSetting03() {
         Settings settings = makeSettings();
         final SharedUserSetting testUserSetting01 = createSharedUserSetting(
-                settings, "TestUser", 10064, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/);
+                settings, "TestUser", 10064, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/,
+                0 /*pkgPrivateFlagsExt*/);
         final PackageSetting testPkgSetting01 =
                 createPackageSetting(0 /*sharedUserId*/, 0 /*pkgFlags*/);
         try {
@@ -1110,6 +1120,7 @@
                     "armeabi" /*secondaryCpuAbi*/,
                     0 /*pkgFlags*/,
                     0 /*pkgPrivateFlags*/,
+                    0 /*pkgPrivateFlagsExt*/,
                     UserManagerService.getInstance(),
                     null /*usesSdkLibraries*/,
                     null /*usesSdkLibrariesVersions*/,
@@ -1141,6 +1152,7 @@
                 UPDATED_VERSION_CODE /*versionCode*/,
                 ApplicationInfo.FLAG_SYSTEM /*pkgFlags*/,
                 ApplicationInfo.PRIVATE_FLAG_PRIVILEGED /*pkgPrivateFlags*/,
+                0 /*pkgPrivateFlagsExt*/,
                 null /*installUser*/,
                 false /*allowInstall*/,
                 false /*instantApp*/,
@@ -1158,6 +1170,7 @@
         assertThat(testPkgSetting01.getFlags(), is(ApplicationInfo.FLAG_SYSTEM));
         assertThat(testPkgSetting01.isSystem(), is(true));
         assertThat(testPkgSetting01.getPrivateFlags(), is(ApplicationInfo.PRIVATE_FLAG_PRIVILEGED));
+        assertThat(testPkgSetting01.getPrivateFlagsExt(), is(0));
         assertThat(testPkgSetting01.isPrivileged(), is(true));
         assertThat(testPkgSetting01.getPrimaryCpuAbi(), is("arm64-v8a"));
         assertThat(testPkgSetting01.getPrimaryCpuAbiLegacy(), is("arm64-v8a"));
@@ -1186,6 +1199,7 @@
                 INITIAL_VERSION_CODE /*versionCode*/,
                 0 /*pkgFlags*/,
                 0 /*pkgPrivateFlags*/,
+                0 /*pkgPrivateFlagsExt*/,
                 UserHandle.SYSTEM /*installUser*/,
                 true /*allowInstall*/,
                 false /*instantApp*/,
@@ -1203,6 +1217,7 @@
         assertThat(testPkgSetting01.getPackageName(), is(PACKAGE_NAME));
         assertThat(testPkgSetting01.getFlags(), is(0));
         assertThat(testPkgSetting01.getPrivateFlags(), is(0));
+        assertThat(testPkgSetting01.getPrivateFlagsExt(), is(0));
         assertThat(testPkgSetting01.getPrimaryCpuAbi(), is("x86_64"));
         assertThat(testPkgSetting01.getPrimaryCpuAbiLegacy(), is("x86_64"));
         assertThat(testPkgSetting01.getSecondaryCpuAbiLegacy(), is("x86"));
@@ -1217,7 +1232,8 @@
     public void testCreateNewSetting03() {
         Settings settings = makeSettings();
         final SharedUserSetting testUserSetting01 = createSharedUserSetting(
-                settings, "TestUser", 10064, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/);
+                settings, "TestUser", 10064, 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/,
+                0 /*pkgPrivateFlagsExt*/);
         final PackageSetting testPkgSetting01 = Settings.createNewSetting(
                 PACKAGE_NAME,
                 null /*originalPkg*/,
@@ -1231,6 +1247,7 @@
                 INITIAL_VERSION_CODE /*versionCode*/,
                 0 /*pkgFlags*/,
                 0 /*pkgPrivateFlags*/,
+                0 /*pkgPrivateFlagsExt*/,
                 null /*installUser*/,
                 false /*allowInstall*/,
                 false /*instantApp*/,
@@ -1248,6 +1265,7 @@
         assertThat(testPkgSetting01.getPackageName(), is(PACKAGE_NAME));
         assertThat(testPkgSetting01.getFlags(), is(0));
         assertThat(testPkgSetting01.getPrivateFlags(), is(0));
+        assertThat(testPkgSetting01.getPrivateFlagsExt(), is(0));
         assertThat(testPkgSetting01.getPrimaryCpuAbi(), is("x86_64"));
         assertThat(testPkgSetting01.getPrimaryCpuAbiLegacy(), is("x86_64"));
         assertThat(testPkgSetting01.getSecondaryCpuAbi(), is("x86"));
@@ -1277,6 +1295,7 @@
                 UPDATED_VERSION_CODE /*versionCode*/,
                 0 /*pkgFlags*/,
                 0 /*pkgPrivateFlags*/,
+                0 /*pkgPrivateFlagsExt*/,
                 null /*installUser*/,
                 false /*allowInstall*/,
                 false /*instantApp*/,
@@ -1294,6 +1313,7 @@
         assertThat(testPkgSetting01.getPackageName(), is(PACKAGE_NAME));
         assertThat(testPkgSetting01.getFlags(), is(0));
         assertThat(testPkgSetting01.getPrivateFlags(), is(0));
+        assertThat(testPkgSetting01.getPrivateFlagsExt(), is(0));
         assertThat(testPkgSetting01.getPrimaryCpuAbi(), is("arm64-v8a"));
         assertThat(testPkgSetting01.getPrimaryCpuAbiLegacy(), is("arm64-v8a"));
         assertThat(testPkgSetting01.getSecondaryCpuAbi(), is("armeabi"));
@@ -1320,6 +1340,7 @@
                 UPDATED_VERSION_CODE /*versionCode*/,
                 ApplicationInfo.FLAG_SYSTEM /*pkgFlags*/,
                 0 /*pkgPrivateFlags*/,
+                0 /*pkgPrivateFlagsExt*/,
                 UserHandle.SYSTEM /*installUser*/,
                 false /*allowInstall*/,
                 false /*instantApp*/,
@@ -1498,7 +1519,8 @@
     public void testAddPackageSetting() throws PackageManagerException {
         final Settings settings = makeSettings();
         final SharedUserSetting sus1 = new SharedUserSetting(
-                "TestUser", 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/);
+                "TestUser", 0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/,
+                0 /*pkgPrivateFlagsExt*/);
         sus1.mAppId = 10001;
         final PackageSetting ps1 = createPackageSetting("com.foo");
         ps1.setAppId(10001);
@@ -1565,6 +1587,7 @@
         // assertThat(origPkgSetting.pkg, is(testPkgSetting.pkg));
         assertThat(origPkgSetting.getFlags(), is(testPkgSetting.getFlags()));
         assertThat(origPkgSetting.getPrivateFlags(), is(testPkgSetting.getPrivateFlags()));
+        assertThat(origPkgSetting.getPrivateFlagsExt(), is(testPkgSetting.getPrivateFlagsExt()));
         assertSame(origPkgSetting.getPrimaryCpuAbi(), testPkgSetting.getPrimaryCpuAbi());
         assertThat(origPkgSetting.getPrimaryCpuAbi(), is(testPkgSetting.getPrimaryCpuAbi()));
         assertSame(origPkgSetting.getPrimaryCpuAbiLegacy(), testPkgSetting.getPrimaryCpuAbiLegacy());
@@ -1643,12 +1666,13 @@
     }
 
     private SharedUserSetting createSharedUserSetting(Settings settings, String userName,
-            int sharedUserId, int pkgFlags, int pkgPrivateFlags) {
+            int sharedUserId, int pkgFlags, int pkgPrivateFlags, int pkgPrivateFlagsExt) {
         return settings.addSharedUserLPw(
                 userName,
                 sharedUserId,
                 pkgFlags,
-                pkgPrivateFlags);
+                pkgPrivateFlags,
+                pkgPrivateFlagsExt);
     }
     private PackageSetting createPackageSetting(int sharedUserId, int pkgFlags) {
         return new PackageSetting(
@@ -1662,6 +1686,7 @@
                 INITIAL_VERSION_CODE,
                 pkgFlags,
                 0 /*privateFlags*/,
+                0 /*privateExtFlags*/,
                 sharedUserId,
                 null /*usesSdkLibraries*/,
                 null /*usesSdkLibrariesVersions*/,
@@ -1683,6 +1708,7 @@
                 INITIAL_VERSION_CODE,
                 0,
                 0 /*privateFlags*/,
+                0 /*privateExtFlags*/,
                 0,
                 null /*usesSdkLibraries*/,
                 null /*usesSdkLibrariesVersions*/,
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
index 3c75332..f724acb 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/MockSystem.kt
@@ -166,7 +166,7 @@
         }
         whenever(mocks.settings.addPackageLPw(nullable(), nullable(), nullable(), nullable(),
                 nullable(), nullable(), nullable(), nullable(), nullable(), nullable(), nullable(),
-                nullable(), nullable(), nullable(), nullable(), nullable(), nullable())) {
+                nullable(), nullable(), nullable(), nullable(), nullable(), nullable(), nullable())) {
             val name: String = getArgument(0)
             val pendingAdd = mPendingPackageAdds.firstOrNull { it.first == name }
                     ?: return@whenever null
diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceBootTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceBootTest.kt
index da929af..b747242 100644
--- a/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceBootTest.kt
+++ b/services/tests/mockingservicestests/src/com/android/server/pm/PackageManagerServiceBootTest.kt
@@ -70,21 +70,21 @@
         val pm = createPackageManagerService()
         verify(rule.mocks().injector).bootstrap(pm)
         verify(rule.mocks().settings).addSharedUserLPw("android.uid.system",
-                Process.SYSTEM_UID, FLAG_SYSTEM, PRIVATE_FLAG_PRIVILEGED)
+                Process.SYSTEM_UID, FLAG_SYSTEM, PRIVATE_FLAG_PRIVILEGED, 0)
         verify(rule.mocks().settings).addSharedUserLPw("android.uid.phone",
-                Process.PHONE_UID, FLAG_SYSTEM, PRIVATE_FLAG_PRIVILEGED)
+                Process.PHONE_UID, FLAG_SYSTEM, PRIVATE_FLAG_PRIVILEGED, 0)
         verify(rule.mocks().settings).addSharedUserLPw("android.uid.log",
-                Process.LOG_UID, FLAG_SYSTEM, PRIVATE_FLAG_PRIVILEGED)
+                Process.LOG_UID, FLAG_SYSTEM, PRIVATE_FLAG_PRIVILEGED, 0)
         verify(rule.mocks().settings).addSharedUserLPw("android.uid.nfc",
-                Process.NFC_UID, FLAG_SYSTEM, PRIVATE_FLAG_PRIVILEGED)
+                Process.NFC_UID, FLAG_SYSTEM, PRIVATE_FLAG_PRIVILEGED, 0)
         verify(rule.mocks().settings).addSharedUserLPw("android.uid.bluetooth",
-                Process.BLUETOOTH_UID, FLAG_SYSTEM, PRIVATE_FLAG_PRIVILEGED)
+                Process.BLUETOOTH_UID, FLAG_SYSTEM, PRIVATE_FLAG_PRIVILEGED, 0)
         verify(rule.mocks().settings).addSharedUserLPw("android.uid.shell",
-                Process.SHELL_UID, FLAG_SYSTEM, PRIVATE_FLAG_PRIVILEGED)
+                Process.SHELL_UID, FLAG_SYSTEM, PRIVATE_FLAG_PRIVILEGED, 0)
         verify(rule.mocks().settings).addSharedUserLPw("android.uid.se",
-                Process.SE_UID, FLAG_SYSTEM, PRIVATE_FLAG_PRIVILEGED)
+                Process.SE_UID, FLAG_SYSTEM, PRIVATE_FLAG_PRIVILEGED, 0)
         verify(rule.mocks().settings).addSharedUserLPw("android.uid.networkstack",
-                Process.NETWORK_STACK_UID, FLAG_SYSTEM, PRIVATE_FLAG_PRIVILEGED)
+                Process.NETWORK_STACK_UID, FLAG_SYSTEM, PRIVATE_FLAG_PRIVILEGED, 0)
         rule.system().validateFinalState()
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java b/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
index 42be3d3..1a0e91f 100644
--- a/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
+++ b/services/tests/servicestests/src/com/android/server/pm/PackageSettingBuilder.java
@@ -39,6 +39,7 @@
     private long mPVersionCode;
     private int mPkgFlags;
     private int mPrivateFlags;
+    private int mPrivateFlagsExt;
     private int mSharedUserId;
     private String mVolumeUuid;
     private int mAppId;
@@ -110,6 +111,11 @@
         return this;
     }
 
+    public PackageSettingBuilder setPrivateFlagsExt(int privateFlagsExt) {
+        this.mPrivateFlagsExt = privateFlagsExt;
+        return this;
+    }
+
     public PackageSettingBuilder setSharedUserId(int sharedUserId) {
         this.mSharedUserId = sharedUserId;
         return this;
@@ -161,7 +167,7 @@
         final PackageSetting packageSetting = new PackageSetting(mName, mRealName,
                 new File(mCodePath), mLegacyNativeLibraryPathString, mPrimaryCpuAbiString,
                 mSecondaryCpuAbiString, mCpuAbiOverrideString, mPVersionCode, mPkgFlags,
-                mPrivateFlags, mSharedUserId, null /* usesSdkLibraries */,
+                mPrivateFlags, mPrivateFlagsExt, mSharedUserId, null /* usesSdkLibraries */,
                 null /* usesSdkLibrariesVersions */, null /* usesStaticLibraries */,
                 null  /* usesStaticLibrariesVersions */, mMimeGroups, mDomainSetId);
         packageSetting.setSignatures(mSigningDetails != null
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
index 988ab1d..ee0c67d 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ManagedServicesTest.java
@@ -884,7 +884,7 @@
             return true;
         });
 
-        mockServiceInfoWithMetaData(List.of(cn), service, pm, new ArrayMap<>());
+        mockServiceInfoWithMetaData(List.of(cn), service, new ArrayMap<>());
         service.addApprovedList("a", 0, true);
 
         service.reregisterService(cn, 0);
@@ -915,7 +915,7 @@
             return true;
         });
 
-        mockServiceInfoWithMetaData(List.of(cn), service, pm, new ArrayMap<>());
+        mockServiceInfoWithMetaData(List.of(cn), service, new ArrayMap<>());
         service.addApprovedList("a", 0, false);
 
         service.reregisterService(cn, 0);
@@ -946,7 +946,7 @@
             return true;
         });
 
-        mockServiceInfoWithMetaData(List.of(cn), service, pm, new ArrayMap<>());
+        mockServiceInfoWithMetaData(List.of(cn), service, new ArrayMap<>());
         service.addApprovedList("a/a", 0, true);
 
         service.reregisterService(cn, 0);
@@ -977,7 +977,7 @@
             return true;
         });
 
-        mockServiceInfoWithMetaData(List.of(cn), service, pm, new ArrayMap<>());
+        mockServiceInfoWithMetaData(List.of(cn), service, new ArrayMap<>());
         service.addApprovedList("a/a", 0, false);
 
         service.reregisterService(cn, 0);
@@ -1187,64 +1187,6 @@
     }
 
     @Test
-    public void testUpgradeAppNoIntentFilterNoRebind() throws Exception {
-        Context context = spy(getContext());
-        doReturn(true).when(context).bindServiceAsUser(any(), any(), anyInt(), any());
-
-        ManagedServices service = new TestManagedServices(context, mLock, mUserProfiles,
-                mIpm, APPROVAL_BY_COMPONENT);
-
-        List<String> packages = new ArrayList<>();
-        packages.add("package");
-        addExpectedServices(service, packages, 0);
-
-        final ComponentName unapprovedComponent = ComponentName.unflattenFromString("package/C1");
-        final ComponentName approvedComponent = ComponentName.unflattenFromString("package/C2");
-
-        // Both components are approved initially
-        mExpectedPrimaryComponentNames.clear();
-        mExpectedPrimaryPackages.clear();
-        mExpectedPrimaryComponentNames.put(0, "package/C1:package/C2");
-        mExpectedSecondaryComponentNames.clear();
-        mExpectedSecondaryPackages.clear();
-
-        loadXml(service);
-
-        //Component package/C1 loses serviceInterface intent filter
-        ManagedServices.Config config = service.getConfig();
-        when(mPm.queryIntentServicesAsUser(any(), anyInt(), anyInt())).
-            thenAnswer(new Answer<List<ResolveInfo>>() {
-                @Override
-                public List<ResolveInfo> answer(InvocationOnMock invocationOnMock)
-                    throws Throwable {
-                    Object[] args = invocationOnMock.getArguments();
-                    Intent invocationIntent = (Intent) args[0];
-                    if (invocationIntent != null) {
-                        if (invocationIntent.getAction().equals(config.serviceInterface)
-                            && packages.contains(invocationIntent.getPackage())) {
-                            List<ResolveInfo> dummyServices = new ArrayList<>();
-                            ResolveInfo resolveInfo = new ResolveInfo();
-                            ServiceInfo serviceInfo = new ServiceInfo();
-                            serviceInfo.packageName = invocationIntent.getPackage();
-                            serviceInfo.name = approvedComponent.getClassName();
-                            serviceInfo.permission = service.getConfig().bindPermission;
-                            resolveInfo.serviceInfo = serviceInfo;
-                            dummyServices.add(resolveInfo);
-                            return dummyServices;
-                        }
-                    }
-                    return new ArrayList<>();
-                }
-            });
-
-        // Trigger package update
-        service.onPackagesChanged(false, new String[]{"package"}, new int[]{0});
-
-        assertFalse(service.isComponentEnabledForCurrentProfiles(unapprovedComponent));
-        assertTrue(service.isComponentEnabledForCurrentProfiles(approvedComponent));
-    }
-
-    @Test
     public void testSetPackageOrComponentEnabled() throws Exception {
         for (int approvalLevel : new int[] {APPROVAL_BY_COMPONENT, APPROVAL_BY_PACKAGE}) {
             ManagedServices service = new TestManagedServices(getContext(), mLock, mUserProfiles,
@@ -1940,7 +1882,7 @@
         metaDataAutobindAllow.putBoolean(META_DATA_DEFAULT_AUTOBIND, true);
         metaDatas.put(cn_allowed, metaDataAutobindAllow);
 
-        mockServiceInfoWithMetaData(componentNames, service, pm, metaDatas);
+        mockServiceInfoWithMetaData(componentNames, service, metaDatas);
 
         service.addApprovedList(cn_allowed.flattenToString(), 0, true);
         service.addApprovedList(cn_disallowed.flattenToString(), 0, true);
@@ -1985,7 +1927,7 @@
         metaDataAutobindDisallow.putBoolean(META_DATA_DEFAULT_AUTOBIND, false);
         metaDatas.put(cn_disallowed, metaDataAutobindDisallow);
 
-        mockServiceInfoWithMetaData(componentNames, service, pm, metaDatas);
+        mockServiceInfoWithMetaData(componentNames, service, metaDatas);
 
         service.addApprovedList(cn_disallowed.flattenToString(), 0, true);
 
@@ -2024,7 +1966,7 @@
         metaDataAutobindDisallow.putBoolean(META_DATA_DEFAULT_AUTOBIND, false);
         metaDatas.put(cn_disallowed, metaDataAutobindDisallow);
 
-        mockServiceInfoWithMetaData(componentNames, service, pm, metaDatas);
+        mockServiceInfoWithMetaData(componentNames, service, metaDatas);
 
         service.addApprovedList(cn_disallowed.flattenToString(), 0, true);
 
@@ -2079,8 +2021,8 @@
     }
 
     private void mockServiceInfoWithMetaData(List<ComponentName> componentNames,
-            ManagedServices service, PackageManager packageManager,
-            ArrayMap<ComponentName, Bundle> metaDatas) throws RemoteException {
+            ManagedServices service, ArrayMap<ComponentName, Bundle> metaDatas)
+            throws RemoteException {
         when(mIpm.getServiceInfo(any(), anyLong(), anyInt())).thenAnswer(
                 (Answer<ServiceInfo>) invocation -> {
                     ComponentName invocationCn = invocation.getArgument(0);
@@ -2095,39 +2037,6 @@
                     return null;
                 }
         );
-
-        // add components to queryIntentServicesAsUser response
-        final List<String> packages = new ArrayList<>();
-        for (ComponentName cn: componentNames) {
-            packages.add(cn.getPackageName());
-        }
-        ManagedServices.Config config = service.getConfig();
-        when(packageManager.queryIntentServicesAsUser(any(), anyInt(), anyInt())).
-                thenAnswer(new Answer<List<ResolveInfo>>() {
-                @Override
-                public List<ResolveInfo> answer(InvocationOnMock invocationOnMock)
-                    throws Throwable {
-                    Object[] args = invocationOnMock.getArguments();
-                    Intent invocationIntent = (Intent) args[0];
-                    if (invocationIntent != null) {
-                        if (invocationIntent.getAction().equals(config.serviceInterface)
-                            && packages.contains(invocationIntent.getPackage())) {
-                            List<ResolveInfo> dummyServices = new ArrayList<>();
-                            for (ComponentName cn: componentNames) {
-                                ResolveInfo resolveInfo = new ResolveInfo();
-                                ServiceInfo serviceInfo = new ServiceInfo();
-                                serviceInfo.packageName = invocationIntent.getPackage();
-                                serviceInfo.name = cn.getClassName();
-                                serviceInfo.permission = service.getConfig().bindPermission;
-                                resolveInfo.serviceInfo = serviceInfo;
-                                dummyServices.add(resolveInfo);
-                            }
-                            return dummyServices;
-                        }
-                    }
-                    return new ArrayList<>();
-                }
-            });
     }
 
     private void resetComponentsAndPackages() {
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 096478d..dcfb2e6 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -3773,7 +3773,42 @@
 
         doThrow(new SecurityException("no access")).when(mUgmInternal)
                 .checkGrantUriPermission(eq(Process.myUid()), any(), eq(soundUri),
-                    anyInt(), eq(Process.myUserHandle().getIdentifier()));
+                anyInt(), eq(Process.myUserHandle().getIdentifier()));
+
+        mBinderService.updateNotificationChannelFromPrivilegedListener(
+                null, mPkg, Process.myUserHandle(), updatedNotificationChannel);
+
+        verify(mPreferencesHelper, times(1)).updateNotificationChannel(
+                anyString(), anyInt(), any(), anyBoolean(),  anyInt(), anyBoolean());
+
+        verify(mListeners, never()).notifyNotificationChannelChanged(eq(mPkg),
+                eq(Process.myUserHandle()), eq(mTestNotificationChannel),
+                eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
+    }
+
+    @Test
+    public void
+        testUpdateNotificationChannelFromPrivilegedListener_oldSoundNoUriPerm_newSoundHasUriPerm()
+            throws Exception {
+        mService.setPreferencesHelper(mPreferencesHelper);
+        when(mCompanionMgr.getAssociations(mPkg, mUserId))
+                .thenReturn(singletonList(mock(AssociationInfo.class)));
+        when(mPreferencesHelper.getNotificationChannel(eq(mPkg), anyInt(),
+                eq(mTestNotificationChannel.getId()), anyBoolean()))
+                .thenReturn(mTestNotificationChannel);
+
+        // Missing Uri permissions for the old channel sound
+        final Uri oldSoundUri = Settings.System.DEFAULT_NOTIFICATION_URI;
+        doThrow(new SecurityException("no access")).when(mUgmInternal)
+                .checkGrantUriPermission(eq(Process.myUid()), any(), eq(oldSoundUri),
+                anyInt(), eq(Process.myUserHandle().getIdentifier()));
+
+        // Has Uri permissions for the old channel sound
+        final Uri newSoundUri = Uri.parse("content://media/test/sound/uri");
+        final NotificationChannel updatedNotificationChannel = new NotificationChannel(
+                TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
+        updatedNotificationChannel.setSound(newSoundUri,
+                updatedNotificationChannel.getAudioAttributes());
 
         mBinderService.updateNotificationChannelFromPrivilegedListener(
                 null, PKG, Process.myUserHandle(), updatedNotificationChannel);
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
index 81d939f..8cad5fd 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/PreferencesHelperTest.java
@@ -41,6 +41,9 @@
 import static android.app.NotificationManager.IMPORTANCE_NONE;
 import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
 import static android.app.NotificationManager.VISIBILITY_NO_OVERRIDE;
+import static android.content.ContentResolver.SCHEME_ANDROID_RESOURCE;
+import static android.content.ContentResolver.SCHEME_CONTENT;
+import static android.content.ContentResolver.SCHEME_FILE;
 import static android.media.AudioAttributes.CONTENT_TYPE_SONIFICATION;
 import static android.media.AudioAttributes.USAGE_NOTIFICATION;
 import static android.os.UserHandle.USER_SYSTEM;
@@ -84,6 +87,7 @@
 import static org.mockito.Mockito.clearInvocations;
 import static org.mockito.Mockito.doAnswer;
 import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
@@ -115,6 +119,7 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Parcel;
+import android.os.Process;
 import android.os.RemoteCallback;
 import android.os.RemoteException;
 import android.os.UserHandle;
@@ -331,6 +336,7 @@
 
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager,
+                mUgmInternal,
                 mStatsEventBuilderFactory, false);
         resetZenModeHelper();
 
@@ -678,7 +684,7 @@
     @Test
     public void testReadXml_oldXml_migrates() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mStatsEventBuilderFactory, true);
+                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, true);
 
         String xml = "<ranking version=\"2\">\n"
                 + "<package name=\"" + PKG_N_MR1 + "\" uid=\"" + UID_N_MR1
@@ -744,7 +750,7 @@
     @Test
     public void testReadXml_oldXml_backup_migratesWhenPkgInstalled() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
+                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
 
         when(mPm.getPackageUidAsUser("pkg1", USER_SYSTEM)).thenReturn(UNKNOWN_UID);
         when(mPm.getPackageUidAsUser("pkg2", USER_SYSTEM)).thenReturn(UNKNOWN_UID);
@@ -822,7 +828,7 @@
     @Test
     public void testReadXml_newXml_noMigration_showPermissionNotification() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mStatsEventBuilderFactory, true);
+                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, true);
 
         String xml = "<ranking version=\"3\">\n"
                 + "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n"
@@ -879,7 +885,7 @@
     @Test
     public void testReadXml_newXml_permissionNotificationOff() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
+                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
 
         String xml = "<ranking version=\"3\">\n"
                 + "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n"
@@ -936,7 +942,7 @@
     @Test
     public void testReadXml_newXml_noMigration_noPermissionNotification() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mStatsEventBuilderFactory, true);
+                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, true);
 
         String xml = "<ranking version=\"4\">\n"
                 + "<package name=\"" + PKG_N_MR1 + "\" show_badge=\"true\">\n"
@@ -992,7 +998,7 @@
     @Test
     public void testReadXml_oldXml_migration_NoUid() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
+                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
 
         when(mPm.getPackageUidAsUser("something", USER_SYSTEM)).thenReturn(UNKNOWN_UID);
         String xml = "<ranking version=\"2\">\n"
@@ -1025,7 +1031,7 @@
     @Test
     public void testReadXml_newXml_noMigration_NoUid() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
+                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
 
         when(mPm.getPackageUidAsUser("something", USER_SYSTEM)).thenReturn(UNKNOWN_UID);
         String xml = "<ranking version=\"3\">\n"
@@ -1057,7 +1063,7 @@
     @Test
     public void testChannelXmlForNonBackup_postMigration() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
+                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
 
         ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
         appPermissions.put(new Pair<>(1, "first"), new Pair<>(true, false));
@@ -1143,7 +1149,7 @@
     @Test
     public void testChannelXmlForBackup_postMigration() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
+                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
 
         ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
         appPermissions.put(new Pair<>(1, "first"), new Pair<>(true, false));
@@ -1235,7 +1241,7 @@
     @Test
     public void testChannelXmlForBackup_postMigration_noExternal() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
+                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
 
         ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
         appPermissions.put(new Pair<>(UID_P, PKG_P), new Pair<>(true, false));
@@ -1320,7 +1326,7 @@
     @Test
     public void testChannelXmlForBackup_postMigration_noLocalSettings() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
+                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
 
         ArrayMap<Pair<Integer, String>, Pair<Boolean, Boolean>> appPermissions = new ArrayMap<>();
         appPermissions.put(new Pair<>(1, "first"), new Pair<>(true, false));
@@ -1467,7 +1473,6 @@
         assertTrue(actualChannel.isSoundRestored());
     }
 
-
     /**
      * Although we don't make backups with uncanonicalized uris anymore, we used to, so we have to
      * handle its restore properly.
@@ -1533,7 +1538,7 @@
                 new FileNotFoundException("")).thenReturn(resId);
 
         mHelper = new PreferencesHelper(mContext, mPm, mHandler, mMockZenModeHelper,
-                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mStatsEventBuilderFactory, false);
+                mPermissionHelper, mPermissionManager, mLogger, mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
 
         NotificationChannel channel =
                 new NotificationChannel("id", "name", IMPORTANCE_LOW);
@@ -2479,7 +2484,7 @@
         when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger,
-                mAppOpsManager, mStatsEventBuilderFactory, false);
+                mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
         mHelper.syncChannelsBypassingDnd();
 
         // create notification channel that can bypass dnd, but app is blocked
@@ -2510,7 +2515,7 @@
         when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger,
-                mAppOpsManager, mStatsEventBuilderFactory, false);
+                mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
         mHelper.syncChannelsBypassingDnd();
 
         // create notification channel that can bypass dnd, but app is blocked
@@ -2535,7 +2540,7 @@
         when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger,
-                mAppOpsManager, mStatsEventBuilderFactory, false);
+                mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
         mHelper.syncChannelsBypassingDnd();
 
         // create notification channel that can bypass dnd, but app is blocked
@@ -2590,7 +2595,7 @@
         when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger,
-                mAppOpsManager, mStatsEventBuilderFactory, false);
+                mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
         mHelper.syncChannelsBypassingDnd();
         assertFalse(mHelper.areChannelsBypassingDnd());
         verify(mMockZenModeHelper, times(1)).setNotificationPolicy(any(), anyInt(), anyBoolean());
@@ -2604,7 +2609,7 @@
         when(mMockZenModeHelper.getNotificationPolicy()).thenReturn(mTestNotificationPolicy);
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger,
-                mAppOpsManager, mStatsEventBuilderFactory, false);
+                mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
         assertFalse(mHelper.areChannelsBypassingDnd());
         verify(mMockZenModeHelper, never()).setNotificationPolicy(any(), anyInt(), anyBoolean());
         resetZenModeHelper();
@@ -2701,6 +2706,61 @@
     }
 
     @Test
+    public void testCreateChannel_noSoundUriPermission_contentSchemeVerified() {
+        final Uri sound = Uri.parse(SCHEME_CONTENT + "://media/test/sound/uri");
+
+        doThrow(new SecurityException("no access")).when(mUgmInternal)
+                .checkGrantUriPermission(eq(UID_N_MR1), any(), eq(sound),
+                    anyInt(), eq(Process.myUserHandle().getIdentifier()));
+
+        final NotificationChannel channel = new NotificationChannel("id2", "name2",
+                NotificationManager.IMPORTANCE_DEFAULT);
+        channel.setSound(sound, mAudioAttributes);
+
+        assertThrows(SecurityException.class,
+                () -> mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel,
+                    true, false, UID_N_MR1, false));
+        assertThat(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId(), true))
+                .isNull();
+    }
+
+    @Test
+    public void testCreateChannel_noSoundUriPermission_fileSchemaIgnored() {
+        final Uri sound = Uri.parse(SCHEME_FILE + "://path/sound");
+
+        doThrow(new SecurityException("no access")).when(mUgmInternal)
+                .checkGrantUriPermission(eq(UID_N_MR1), any(), any(),
+                    anyInt(), eq(Process.myUserHandle().getIdentifier()));
+
+        final NotificationChannel channel = new NotificationChannel("id2", "name2",
+                NotificationManager.IMPORTANCE_DEFAULT);
+        channel.setSound(sound, mAudioAttributes);
+
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false, UID_N_MR1,
+                false);
+        assertThat(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId(), true)
+                .getSound()).isEqualTo(sound);
+    }
+
+    @Test
+    public void testCreateChannel_noSoundUriPermission_resourceSchemaIgnored() {
+        final Uri sound = Uri.parse(SCHEME_ANDROID_RESOURCE + "://resId/sound");
+
+        doThrow(new SecurityException("no access")).when(mUgmInternal)
+                .checkGrantUriPermission(eq(UID_N_MR1), any(), any(),
+                    anyInt(), eq(Process.myUserHandle().getIdentifier()));
+
+        final NotificationChannel channel = new NotificationChannel("id2", "name2",
+                NotificationManager.IMPORTANCE_DEFAULT);
+        channel.setSound(sound, mAudioAttributes);
+
+        mHelper.createNotificationChannel(PKG_N_MR1, UID_N_MR1, channel, true, false, UID_N_MR1,
+                false);
+        assertThat(mHelper.getNotificationChannel(PKG_N_MR1, UID_N_MR1, channel.getId(), true)
+                .getSound()).isEqualTo(sound);
+    }
+
+    @Test
     public void testPermanentlyDeleteChannels() throws Exception {
         NotificationChannel channel1 =
                 new NotificationChannel("id1", "name1", NotificationManager.IMPORTANCE_HIGH);
@@ -3707,7 +3767,7 @@
                 + "</ranking>\n";
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger,
-                mAppOpsManager, mStatsEventBuilderFactory, false);
+                mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
         loadByteArrayXml(preQXml.getBytes(), true, USER_SYSTEM);
 
         assertEquals(PreferencesHelper.DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS,
@@ -3721,7 +3781,7 @@
         ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger,
-                mAppOpsManager, mStatsEventBuilderFactory, false);
+                mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
         loadStreamXml(baos, false, UserHandle.USER_ALL);
 
         assertEquals(!PreferencesHelper.DEFAULT_HIDE_SILENT_STATUS_BAR_ICONS,
@@ -3791,7 +3851,7 @@
         ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger,
-                mAppOpsManager, mStatsEventBuilderFactory, false);
+                mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
         loadStreamXml(baos, false, UserHandle.USER_ALL);
 
         assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O));
@@ -3804,7 +3864,7 @@
         ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger,
-                mAppOpsManager, mStatsEventBuilderFactory, false);
+                mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
         loadStreamXml(baos, false, UserHandle.USER_ALL);
 
         assertEquals("other", mHelper.getNotificationDelegate(PKG_O, UID_O));
@@ -3818,7 +3878,7 @@
         ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger,
-                mAppOpsManager, mStatsEventBuilderFactory, false);
+                mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
         loadStreamXml(baos, false, UserHandle.USER_ALL);
 
         assertNull(mHelper.getNotificationDelegate(PKG_O, UID_O));
@@ -3834,7 +3894,7 @@
         ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger,
-                mAppOpsManager, mStatsEventBuilderFactory, false);
+                mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
         loadStreamXml(baos, false, UserHandle.USER_ALL);
 
         assertEquals(BUBBLE_PREFERENCE_NONE, mHelper.getBubblePreference(PKG_O, UID_O));
@@ -3890,7 +3950,7 @@
         ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger,
-                mAppOpsManager, mStatsEventBuilderFactory, false);
+                mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
         loadStreamXml(baos, false, UserHandle.USER_ALL);
 
         assertEquals(BUBBLE_PREFERENCE_SELECTED, mHelper.getBubblePreference(PKG_O, UID_O));
@@ -3928,7 +3988,7 @@
         ByteArrayOutputStream baos = writeXmlAndPurge(PKG_O, UID_O, false, UserHandle.USER_ALL);
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger,
-                mAppOpsManager, mStatsEventBuilderFactory, false);
+                mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
         loadStreamXml(baos, false, UserHandle.USER_ALL);
 
         assertEquals(mHelper.getBubblePreference(PKG_O, UID_O), BUBBLE_PREFERENCE_NONE);
@@ -4586,7 +4646,7 @@
     public void testPlaceholderConversationId_shortcutRequired() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger,
-                mAppOpsManager, mStatsEventBuilderFactory, false);
+                mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
 
         final String xml = "<ranking version=\"1\">\n"
                 + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n"
@@ -4606,7 +4666,7 @@
     public void testNormalConversationId_shortcutRequired() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger,
-                mAppOpsManager, mStatsEventBuilderFactory, false);
+                mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
 
         final String xml = "<ranking version=\"1\">\n"
                 + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n"
@@ -4626,7 +4686,7 @@
     public void testNoConversationId_shortcutRequired() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger,
-                mAppOpsManager, mStatsEventBuilderFactory, false);
+                mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
 
         final String xml = "<ranking version=\"1\">\n"
                 + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n"
@@ -4646,7 +4706,7 @@
     public void testDeleted_noTime() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger,
-                mAppOpsManager, mStatsEventBuilderFactory, false);
+                mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
 
         final String xml = "<ranking version=\"1\">\n"
                 + "<package name=\"" + PKG_O + "\" uid=\"" + UID_O + "\" >\n"
@@ -4666,7 +4726,7 @@
     public void testDeleted_twice() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger,
-                mAppOpsManager, mStatsEventBuilderFactory, false);
+                mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
 
         mHelper.createNotificationChannel(
                 PKG_P, UID_P, new NotificationChannel("id", "id", 2), true, false,
@@ -4681,7 +4741,7 @@
     public void testDeleted_recentTime() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger,
-                mAppOpsManager, mStatsEventBuilderFactory, false);
+                mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
 
         mHelper.createNotificationChannel(
                 PKG_P, UID_P, new NotificationChannel("id", "id", 2), true, false,
@@ -4700,7 +4760,7 @@
         parser.nextTag();
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger,
-                mAppOpsManager, mStatsEventBuilderFactory, false);
+                mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
         mHelper.readXml(parser, true, USER_SYSTEM);
 
         NotificationChannel nc = mHelper.getNotificationChannel(PKG_P, UID_P, "id", true);
@@ -4712,7 +4772,7 @@
     public void testUnDelete_time() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger,
-                mAppOpsManager, mStatsEventBuilderFactory, false);
+                mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
 
         mHelper.createNotificationChannel(
                 PKG_P, UID_P, new NotificationChannel("id", "id", 2), true, false,
@@ -4734,7 +4794,7 @@
     public void testDeleted_longTime() throws Exception {
         mHelper = new PreferencesHelper(getContext(), mPm, mHandler, mMockZenModeHelper,
                 mPermissionHelper, mPermissionManager, mLogger,
-                mAppOpsManager, mStatsEventBuilderFactory, false);
+                mAppOpsManager, mUgmInternal, mStatsEventBuilderFactory, false);
 
         long time = System.currentTimeMillis() - (DateUtils.DAY_IN_MILLIS * 30);
 
diff --git a/services/tests/wmtests/src/com/android/server/wm/CompatScaleProviderTest.java b/services/tests/wmtests/src/com/android/server/wm/CompatScaleProviderTest.java
new file mode 100644
index 0000000..b2ff128
--- /dev/null
+++ b/services/tests/wmtests/src/com/android/server/wm/CompatScaleProviderTest.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.wm;
+
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
+
+import static org.junit.Assert.assertThrows;
+import static org.mockito.Mockito.inOrder;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+
+import android.platform.test.annotations.Presubmit;
+
+import androidx.test.filters.SmallTest;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.InOrder;
+
+/**
+ * Tests for the {@link CompatScaleProvider} interface.
+ * See {@link CompatModePackages} class for implementation.
+ *
+ * Build/Install/Run:
+ * atest WmTests:CompatScaleProviderTest
+ */
+@SmallTest
+@Presubmit
+public class CompatScaleProviderTest extends SystemServiceTestsBase {
+    private static final String TEST_PACKAGE = "compat.mode.packages";
+    static final int TEST_USER_ID = 1;
+
+    private ActivityTaskManagerService mAtm;
+
+    /**
+     * setup method before every test.
+     */
+    @Before
+    public void setUp() {
+        mAtm = mSystemServicesTestRule.getActivityTaskManagerService();
+    }
+
+    /**
+     * Registering a {@link CompatScaleProvider} with an invalid id should throw an exception.
+     */
+    @Test
+    public void registerCompatScaleProviderWithInvalidId() {
+        CompatScaleProvider compatScaleProvider = mock(CompatScaleProvider.class);
+        assertThrows(
+                IllegalArgumentException.class,
+                () ->  mAtm.registerCompatScaleProvider(-1, compatScaleProvider)
+        );
+    }
+
+    /**
+     * Registering a {@code null} {@link CompatScaleProvider} should throw an exception.
+     */
+    @Test
+    public void registerCompatScaleProviderFailIfCallbackIsNull() {
+        assertThrows(
+                IllegalArgumentException.class,
+                () ->  mAtm.registerCompatScaleProvider(
+                            CompatScaleProvider.COMPAT_SCALE_MODE_PRODUCT, null)
+        );
+    }
+
+    /**
+     * Registering a {@link CompatScaleProvider} with a already registered id should throw an
+     * exception.
+     */
+    @Test
+    public void registerCompatScaleProviderFailIfIdIsAlreadyRegistered() {
+        CompatScaleProvider compatScaleProvider = mock(CompatScaleProvider.class);
+        mAtm.registerCompatScaleProvider(CompatScaleProvider.COMPAT_SCALE_MODE_PRODUCT,
+                compatScaleProvider);
+        assertThrows(
+                IllegalArgumentException.class,
+                () ->  mAtm.registerCompatScaleProvider(
+                            CompatScaleProvider.COMPAT_SCALE_MODE_PRODUCT, compatScaleProvider)
+        );
+        mAtm.unregisterCompatScaleProvider(CompatScaleProvider.COMPAT_SCALE_MODE_PRODUCT);
+    }
+
+    /**
+     * Successfully registering a {@link CompatScaleProvider} with should result in callbacks
+     * getting called.
+     */
+    @Test
+    public void registerCompatScaleProviderSuccessfully() {
+        CompatScaleProvider compatScaleProvider = mock(CompatScaleProvider.class);
+        mAtm.registerCompatScaleProvider(CompatScaleProvider.COMPAT_SCALE_MODE_PRODUCT,
+                compatScaleProvider);
+        mAtm.mCompatModePackages.getCompatScale(TEST_PACKAGE, TEST_USER_ID);
+        verify(compatScaleProvider, times(1)).getCompatScale(TEST_PACKAGE, TEST_USER_ID);
+        mAtm.unregisterCompatScaleProvider(CompatScaleProvider.COMPAT_SCALE_MODE_PRODUCT);
+    }
+
+    /**
+     * Unregistering a {@link CompatScaleProvider} with a unregistered id should throw an exception.
+     */
+    @Test
+    public void unregisterCompatScaleProviderFailIfIdNotRegistered() {
+        assertThrows(
+                IllegalArgumentException.class,
+                () ->  mAtm.unregisterCompatScaleProvider(
+                            CompatScaleProvider.COMPAT_SCALE_MODE_PRODUCT)
+        );
+    }
+
+    /**
+     * Unregistering a {@link CompatScaleProvider} with an invalid id should throw an exception.
+     */
+    @Test
+    public void unregisterCompatScaleProviderFailIfIdNotInRange() {
+        assertThrows(
+                IllegalArgumentException.class,
+                () ->  mAtm.unregisterCompatScaleProvider(-1)
+        );
+    }
+
+    /**
+     * Successfully unregistering a {@link CompatScaleProvider} should stop the callbacks from
+     * getting called.
+     */
+    @Test
+    public void unregisterCompatScaleProviderSuccessfully() {
+        CompatScaleProvider compatScaleProvider = mock(CompatScaleProvider.class);
+        mAtm.registerCompatScaleProvider(CompatScaleProvider.COMPAT_SCALE_MODE_PRODUCT,
+                compatScaleProvider);
+        mAtm.unregisterCompatScaleProvider(CompatScaleProvider.COMPAT_SCALE_MODE_PRODUCT);
+        mAtm.mCompatModePackages.getCompatScale(TEST_PACKAGE, TEST_USER_ID);
+        verify(compatScaleProvider, never()).getCompatScale(TEST_PACKAGE, TEST_USER_ID);
+    }
+
+    /**
+     * Order of calling {@link CompatScaleProvider} is same as the id that was used for
+     * registering it.
+     */
+    @Test
+    public void registerCompatScaleProviderRespectsOrderId() {
+        CompatScaleProvider systemCompatScaleProvider = mock(CompatScaleProvider.class);
+        CompatScaleProvider productCompatScaleProvider = mock(CompatScaleProvider.class);
+        mAtm.registerCompatScaleProvider(CompatScaleProvider.COMPAT_SCALE_MODE_SYSTEM_FIRST,
+                systemCompatScaleProvider);
+        mAtm.registerCompatScaleProvider(CompatScaleProvider.COMPAT_SCALE_MODE_PRODUCT,
+                productCompatScaleProvider);
+        mAtm.mCompatModePackages.getCompatScale(TEST_PACKAGE, TEST_USER_ID);
+        InOrder inOrder = inOrder(systemCompatScaleProvider, productCompatScaleProvider);
+        inOrder.verify(systemCompatScaleProvider).getCompatScale(TEST_PACKAGE, TEST_USER_ID);
+        inOrder.verify(productCompatScaleProvider).getCompatScale(TEST_PACKAGE, TEST_USER_ID);
+    }
+}
diff --git a/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
index 1d14dc3..587a2363 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LockTaskControllerTest.java
@@ -239,6 +239,11 @@
         verifyLockTaskStarted(STATUS_BAR_MASK_PINNED, DISABLE2_NONE);
         // THEN screen pinning toast should be shown
         verify(mStatusBarService).showPinningEnterExitToast(eq(true /* entering */));
+
+        // WHEN the app calls startLockTaskMode while the Task is already locked
+        mLockTaskController.startLockTaskMode(tr, false, TEST_UID);
+        // THEN a pinning request should NOT be shown
+        verify(mStatusBarManagerInternal, never()).showScreenPinningRequest(anyInt());
     }
 
     @Test
diff --git a/telecomm/java/android/telecom/StatusHints.java b/telecomm/java/android/telecom/StatusHints.java
index 5f0c8d72..31b84ff 100644
--- a/telecomm/java/android/telecom/StatusHints.java
+++ b/telecomm/java/android/telecom/StatusHints.java
@@ -27,6 +27,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.UserHandle;
+import android.util.Log;
 
 import com.android.internal.annotations.VisibleForTesting;
 
@@ -40,6 +41,7 @@
     private final CharSequence mLabel;
     private Icon mIcon;
     private final Bundle mExtras;
+    private static final String TAG = StatusHints.class.getSimpleName();
 
     /**
      * @hide
@@ -150,17 +152,37 @@
         // incompatible types.
         if (icon != null && (icon.getType() == Icon.TYPE_URI
                 || icon.getType() == Icon.TYPE_URI_ADAPTIVE_BITMAP)) {
-            String encodedUser = icon.getUri().getEncodedUserInfo();
-            // If there is no encoded user, the URI is calling into the calling user space
-            if (encodedUser != null) {
-                int userId = Integer.parseInt(encodedUser);
-                // Do not try to save the icon if the user id isn't in the calling user space.
-                if (userId != callingUserHandle.getIdentifier()) return null;
+            int callingUserId = callingUserHandle.getIdentifier();
+            int requestingUserId = getUserIdFromAuthority(
+                    icon.getUri().getAuthority(), callingUserId);
+            if (callingUserId != requestingUserId) {
+                return null;
             }
+
         }
         return icon;
     }
 
+    /**
+     * Derives the user id from the authority or the default user id if none could be found.
+     * @param auth
+     * @param defaultUserId
+     * @return The user id from the given authority.
+     * @hide
+     */
+    public static int getUserIdFromAuthority(String auth, int defaultUserId) {
+        if (auth == null) return defaultUserId;
+        int end = auth.lastIndexOf('@');
+        if (end == -1) return defaultUserId;
+        String userIdString = auth.substring(0, end);
+        try {
+            return Integer.parseInt(userIdString);
+        } catch (NumberFormatException e) {
+            Log.w(TAG, "Error parsing userId." + e);
+            return UserHandle.USER_NULL;
+        }
+    }
+
     @Override
     public void writeToParcel(Parcel out, int flags) {
         out.writeCharSequence(mLabel);