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);