Loading core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java +34 −0 Original line number Diff line number Diff line Loading @@ -410,6 +410,11 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal, private int mLocaleConfigRes; private boolean mAllowCrossUidActivitySwitchFromBelow; @Nullable private int[] mAlternateLauncherIconResIds; @Nullable private int[] mAlternateLauncherLabelResIds; private List<AndroidPackageSplit> mSplits; @NonNull Loading Loading @@ -874,6 +879,18 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal, return adoptPermissions; } @Nullable @Override public int[] getAlternateLauncherIconResIds() { return mAlternateLauncherIconResIds; } @Nullable @Override public int[] getAlternateLauncherLabelResIds() { return mAlternateLauncherLabelResIds; } @NonNull @Override public List<ParsedApexSystemService> getApexSystemServices() { Loading Loading @@ -1887,6 +1904,19 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal, return setBoolean(Booleans.ALLOW_NATIVE_HEAP_POINTER_TAGGING, value); } @Override public PackageImpl setAlternateLauncherIconResIds(@Nullable int[] alternateLauncherIconResIds) { this.mAlternateLauncherIconResIds = alternateLauncherIconResIds; return this; } @Override public PackageImpl setAlternateLauncherLabelResIds( @Nullable int[] alternateLauncherLabelResIds) { this.mAlternateLauncherLabelResIds = alternateLauncherLabelResIds; return this; } @Override public PackageImpl setTaskReparentingAllowed(boolean value) { return setBoolean(Booleans.ALLOW_TASK_REPARENTING, value); Loading Loading @@ -3273,6 +3303,8 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal, dest.writeLong(this.mBooleans2); dest.writeBoolean(this.mAllowCrossUidActivitySwitchFromBelow); dest.writeInt(this.mIntentMatchingFlags); dest.writeIntArray(this.mAlternateLauncherIconResIds); dest.writeIntArray(this.mAlternateLauncherLabelResIds); } private void writeFeatureFlagState(@NonNull Parcel dest) { Loading Loading @@ -3465,6 +3497,8 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal, this.mBooleans2 = in.readLong(); this.mAllowCrossUidActivitySwitchFromBelow = in.readBoolean(); this.mIntentMatchingFlags = in.readInt(); this.mAlternateLauncherIconResIds = in.createIntArray(); this.mAlternateLauncherLabelResIds = in.createIntArray(); assignDerivedFields(); assignDerivedFields2(); Loading core/java/com/android/internal/pm/pkg/parsing/ParsingPackage.java +12 −0 Original line number Diff line number Diff line Loading @@ -413,6 +413,18 @@ public interface ParsingPackage { ParsingPackage setOnBackInvokedCallbackEnabled(boolean enableOnBackInvokedCallback); /** * Set the drawable resources id array of the alternate icons that are parsing from the * AndroidManifest file */ ParsingPackage setAlternateLauncherIconResIds(int[] alternateLauncherIconResIds); /** * Set the string resources id array of the alternate labels that are parsing from the * AndroidManifest file */ ParsingPackage setAlternateLauncherLabelResIds(int[] alternateLauncherLabelResIds); @CallSuper ParsedPackage hideAsParsed(); Loading core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java +115 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.ConfigurationInfo; import android.content.pm.FeatureGroupInfo; import android.content.pm.FeatureInfo; import android.content.pm.Flags; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.Property; Loading Loading @@ -154,6 +155,13 @@ public class ParsingPackageUtils { private static final String TAG = ParsingUtils.TAG; // It is the maximum length of the typedArray of {@link android.R.attr#alternateIcons} // and {@link android.R.attr#alternateLabels}. private static final int MAXIMUM_LAUNCHER_ALTERNATE_IDS_LENGTH = 500; private static final String TYPE_STRING = "string"; private static final String TYPE_DRAWABLE = "drawable"; public static final boolean DEBUG_JAR = false; public static final boolean DEBUG_BACKUP = false; public static final float DEFAULT_PRE_O_MAX_ASPECT_RATIO = 1.86f; Loading Loading @@ -2021,6 +2029,24 @@ public class ParsingPackageUtils { pkg.setManageSpaceActivityName(manageSpaceActivityName); } if (Flags.changeLauncherBadging()) { ParseResult<int[]> result = drawableResIdArray(input, sa, res, R.styleable.AndroidManifestApplication_alternateLauncherIcons, MAXIMUM_LAUNCHER_ALTERNATE_IDS_LENGTH); if (result.isError()) { return input.error(result); } pkg.setAlternateLauncherIconResIds(result.getResult()); result = stringResIdArray(input, sa, res, R.styleable.AndroidManifestApplication_alternateLauncherLabels, MAXIMUM_LAUNCHER_ALTERNATE_IDS_LENGTH); if (result.isError()) { return input.error(result); } pkg.setAlternateLauncherLabelResIds(result.getResult()); } if (pkg.isBackupAllowed()) { // backupAgent, killAfterRestore, fullBackupContent, backupInForeground, // and restoreAnyVersion are only relevant if backup is possible for the Loading Loading @@ -3395,6 +3421,95 @@ public class ParsingPackageUtils { return sa.getResourceId(attribute, 0); } /** * Parse the drawable resource id array in the typed array {@code resourceId} * if available. If {@code maxSize} is not zero, only parse and preserve at most * {@code maxSize} ids. */ private static ParseResult<int[]> drawableResIdArray(ParseInput input, @NonNull TypedArray sa, @NonNull Resources res, int resourceId, int maxSize) { return resIdArray(input, sa, res, resourceId, TYPE_DRAWABLE, maxSize); } /** * Parse the string resource id array in the typed array {@code resourceId} * if available. If {@code maxSize} is not zero, only parse and preserve at most * {@code maxSize} ids. */ private static ParseResult<int[]> stringResIdArray(ParseInput input, @NonNull TypedArray sa, @NonNull Resources res, int resourceId, int maxSize) { return resIdArray(input, sa, res, resourceId, TYPE_STRING, maxSize); } /** * Parse the resource id array in the typed array {@code resourceId} * if available. If {@code maxSize} is larger than zero, only parse and preserve * at most {@code maxSize} ids that type is matched to the {@code expectedTypeName}. * Because the TypedArray allows mixed types in an array, if {@code expectedTypeName} * is null, it means don't check the type. */ private static ParseResult<int[]> resIdArray(ParseInput input, @NonNull TypedArray sa, @NonNull Resources res, int resourceId, @Nullable String expectedTypeName, int maxSize) { if (!sa.hasValue(resourceId)) { return input.success(null); } final int typeArrayResId = sa.getResourceId(resourceId, /* defValue= */ 0); if (typeArrayResId == 0) { return input.success(null); } // Parse the typedArray try (TypedArray typedArray = res.obtainTypedArray(typeArrayResId)) { final String typedArrayName = res.getResourceName(typeArrayResId); final int length = typedArray.length(); if (maxSize > 0 && length > maxSize) { return input.error(TextUtils.formatSimple( "The length of the typedArray (%s) is larger than %d.", typedArrayName, maxSize)); } Set<Integer> resourceIdSet = new ArraySet<>(); for (int i = 0; i < length; i++) { final int id = typedArray.getResourceId(i, /* defValue= */ 0); // Add the id when the conditions are all matched: // 1. The resource Id is not 0 // 2. The type is the expected type // 3. The id is not duplicated if (id == 0) { return input.error(TextUtils.formatSimple( "There is an item that is not a resource id in the typedArray (%s).", typedArrayName)); } try { if (resourceIdSet.contains(id)) { return input.error(TextUtils.formatSimple( "There is a duplicated resource (%s) in the typedArray (%s).", res.getResourceName(id), typedArrayName)); } final String typeName = res.getResourceTypeName(id); if (expectedTypeName != null && !TextUtils.equals(typeName, expectedTypeName)) { return input.error(TextUtils.formatSimple( "There is a resource (%s) in the typedArray (%s) that is not a" + " %s type.", res.getResourceName(id), typedArrayName, expectedTypeName)); } } catch (Resources.NotFoundException e) { return input.error(TextUtils.formatSimple( "There is a resource in the typedArray (%s) that is not found in" + " the app resources.", typedArrayName)); } resourceIdSet.add(id); } if (resourceIdSet.isEmpty()) { return input.success(null); } return input.success(resourceIdSet.stream().mapToInt(i -> i).toArray()); } } private static String string(@StyleableRes int attribute, TypedArray sa) { return sa.getString(attribute); } Loading core/java/com/android/server/pm/pkg/AndroidPackage.java +22 −0 Original line number Diff line number Diff line Loading @@ -90,6 +90,28 @@ import java.util.UUID; @Immutable public interface AndroidPackage { /** * An array containing the drawable resources that used for the launcher * activity icons. * * @see R.attr#alternateLauncherIcons * @hide */ @Immutable.Ignore @Nullable int[] getAlternateLauncherIconResIds(); /** * An array containing the string resources that used for the launcher * activity labels. * * @see R.attr#alternateLauncherLabels * @hide */ @Immutable.Ignore @Nullable int[] getAlternateLauncherLabelResIds(); /** * @see ApplicationInfo#className * @see R.styleable#AndroidManifestApplication_name Loading services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt +28 −0 Original line number Diff line number Diff line Loading @@ -582,6 +582,34 @@ class AndroidPackageTest : ParcelableComponentTest(AndroidPackage::class, Packag PackageImpl::setSystemExt, true ), getSetByValue( AndroidPackage::getAlternateLauncherIconResIds, PackageImpl::setAlternateLauncherIconResIds, intArrayOf(3, 5, 7), compare = { first, second -> equalBy( first, second, { it.size }, { it[0] }, { it[1] }, { it[2] } ) } ), getSetByValue( AndroidPackage::getAlternateLauncherLabelResIds, PackageImpl::setAlternateLauncherLabelResIds, intArrayOf(3, 5, 7), compare = { first, second -> equalBy( first, second, { it.size }, { it[0] }, { it[1] }, { it[2] } ) } ), ) override fun initialObject() = PackageImpl.forParsing( Loading Loading
core/java/com/android/internal/pm/parsing/pkg/PackageImpl.java +34 −0 Original line number Diff line number Diff line Loading @@ -410,6 +410,11 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal, private int mLocaleConfigRes; private boolean mAllowCrossUidActivitySwitchFromBelow; @Nullable private int[] mAlternateLauncherIconResIds; @Nullable private int[] mAlternateLauncherLabelResIds; private List<AndroidPackageSplit> mSplits; @NonNull Loading Loading @@ -874,6 +879,18 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal, return adoptPermissions; } @Nullable @Override public int[] getAlternateLauncherIconResIds() { return mAlternateLauncherIconResIds; } @Nullable @Override public int[] getAlternateLauncherLabelResIds() { return mAlternateLauncherLabelResIds; } @NonNull @Override public List<ParsedApexSystemService> getApexSystemServices() { Loading Loading @@ -1887,6 +1904,19 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal, return setBoolean(Booleans.ALLOW_NATIVE_HEAP_POINTER_TAGGING, value); } @Override public PackageImpl setAlternateLauncherIconResIds(@Nullable int[] alternateLauncherIconResIds) { this.mAlternateLauncherIconResIds = alternateLauncherIconResIds; return this; } @Override public PackageImpl setAlternateLauncherLabelResIds( @Nullable int[] alternateLauncherLabelResIds) { this.mAlternateLauncherLabelResIds = alternateLauncherLabelResIds; return this; } @Override public PackageImpl setTaskReparentingAllowed(boolean value) { return setBoolean(Booleans.ALLOW_TASK_REPARENTING, value); Loading Loading @@ -3273,6 +3303,8 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal, dest.writeLong(this.mBooleans2); dest.writeBoolean(this.mAllowCrossUidActivitySwitchFromBelow); dest.writeInt(this.mIntentMatchingFlags); dest.writeIntArray(this.mAlternateLauncherIconResIds); dest.writeIntArray(this.mAlternateLauncherLabelResIds); } private void writeFeatureFlagState(@NonNull Parcel dest) { Loading Loading @@ -3465,6 +3497,8 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal, this.mBooleans2 = in.readLong(); this.mAllowCrossUidActivitySwitchFromBelow = in.readBoolean(); this.mIntentMatchingFlags = in.readInt(); this.mAlternateLauncherIconResIds = in.createIntArray(); this.mAlternateLauncherLabelResIds = in.createIntArray(); assignDerivedFields(); assignDerivedFields2(); Loading
core/java/com/android/internal/pm/pkg/parsing/ParsingPackage.java +12 −0 Original line number Diff line number Diff line Loading @@ -413,6 +413,18 @@ public interface ParsingPackage { ParsingPackage setOnBackInvokedCallbackEnabled(boolean enableOnBackInvokedCallback); /** * Set the drawable resources id array of the alternate icons that are parsing from the * AndroidManifest file */ ParsingPackage setAlternateLauncherIconResIds(int[] alternateLauncherIconResIds); /** * Set the string resources id array of the alternate labels that are parsing from the * AndroidManifest file */ ParsingPackage setAlternateLauncherLabelResIds(int[] alternateLauncherLabelResIds); @CallSuper ParsedPackage hideAsParsed(); Loading
core/java/com/android/internal/pm/pkg/parsing/ParsingPackageUtils.java +115 −0 Original line number Diff line number Diff line Loading @@ -46,6 +46,7 @@ import android.content.pm.ApplicationInfo; import android.content.pm.ConfigurationInfo; import android.content.pm.FeatureGroupInfo; import android.content.pm.FeatureInfo; import android.content.pm.Flags; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.PackageManager.Property; Loading Loading @@ -154,6 +155,13 @@ public class ParsingPackageUtils { private static final String TAG = ParsingUtils.TAG; // It is the maximum length of the typedArray of {@link android.R.attr#alternateIcons} // and {@link android.R.attr#alternateLabels}. private static final int MAXIMUM_LAUNCHER_ALTERNATE_IDS_LENGTH = 500; private static final String TYPE_STRING = "string"; private static final String TYPE_DRAWABLE = "drawable"; public static final boolean DEBUG_JAR = false; public static final boolean DEBUG_BACKUP = false; public static final float DEFAULT_PRE_O_MAX_ASPECT_RATIO = 1.86f; Loading Loading @@ -2021,6 +2029,24 @@ public class ParsingPackageUtils { pkg.setManageSpaceActivityName(manageSpaceActivityName); } if (Flags.changeLauncherBadging()) { ParseResult<int[]> result = drawableResIdArray(input, sa, res, R.styleable.AndroidManifestApplication_alternateLauncherIcons, MAXIMUM_LAUNCHER_ALTERNATE_IDS_LENGTH); if (result.isError()) { return input.error(result); } pkg.setAlternateLauncherIconResIds(result.getResult()); result = stringResIdArray(input, sa, res, R.styleable.AndroidManifestApplication_alternateLauncherLabels, MAXIMUM_LAUNCHER_ALTERNATE_IDS_LENGTH); if (result.isError()) { return input.error(result); } pkg.setAlternateLauncherLabelResIds(result.getResult()); } if (pkg.isBackupAllowed()) { // backupAgent, killAfterRestore, fullBackupContent, backupInForeground, // and restoreAnyVersion are only relevant if backup is possible for the Loading Loading @@ -3395,6 +3421,95 @@ public class ParsingPackageUtils { return sa.getResourceId(attribute, 0); } /** * Parse the drawable resource id array in the typed array {@code resourceId} * if available. If {@code maxSize} is not zero, only parse and preserve at most * {@code maxSize} ids. */ private static ParseResult<int[]> drawableResIdArray(ParseInput input, @NonNull TypedArray sa, @NonNull Resources res, int resourceId, int maxSize) { return resIdArray(input, sa, res, resourceId, TYPE_DRAWABLE, maxSize); } /** * Parse the string resource id array in the typed array {@code resourceId} * if available. If {@code maxSize} is not zero, only parse and preserve at most * {@code maxSize} ids. */ private static ParseResult<int[]> stringResIdArray(ParseInput input, @NonNull TypedArray sa, @NonNull Resources res, int resourceId, int maxSize) { return resIdArray(input, sa, res, resourceId, TYPE_STRING, maxSize); } /** * Parse the resource id array in the typed array {@code resourceId} * if available. If {@code maxSize} is larger than zero, only parse and preserve * at most {@code maxSize} ids that type is matched to the {@code expectedTypeName}. * Because the TypedArray allows mixed types in an array, if {@code expectedTypeName} * is null, it means don't check the type. */ private static ParseResult<int[]> resIdArray(ParseInput input, @NonNull TypedArray sa, @NonNull Resources res, int resourceId, @Nullable String expectedTypeName, int maxSize) { if (!sa.hasValue(resourceId)) { return input.success(null); } final int typeArrayResId = sa.getResourceId(resourceId, /* defValue= */ 0); if (typeArrayResId == 0) { return input.success(null); } // Parse the typedArray try (TypedArray typedArray = res.obtainTypedArray(typeArrayResId)) { final String typedArrayName = res.getResourceName(typeArrayResId); final int length = typedArray.length(); if (maxSize > 0 && length > maxSize) { return input.error(TextUtils.formatSimple( "The length of the typedArray (%s) is larger than %d.", typedArrayName, maxSize)); } Set<Integer> resourceIdSet = new ArraySet<>(); for (int i = 0; i < length; i++) { final int id = typedArray.getResourceId(i, /* defValue= */ 0); // Add the id when the conditions are all matched: // 1. The resource Id is not 0 // 2. The type is the expected type // 3. The id is not duplicated if (id == 0) { return input.error(TextUtils.formatSimple( "There is an item that is not a resource id in the typedArray (%s).", typedArrayName)); } try { if (resourceIdSet.contains(id)) { return input.error(TextUtils.formatSimple( "There is a duplicated resource (%s) in the typedArray (%s).", res.getResourceName(id), typedArrayName)); } final String typeName = res.getResourceTypeName(id); if (expectedTypeName != null && !TextUtils.equals(typeName, expectedTypeName)) { return input.error(TextUtils.formatSimple( "There is a resource (%s) in the typedArray (%s) that is not a" + " %s type.", res.getResourceName(id), typedArrayName, expectedTypeName)); } } catch (Resources.NotFoundException e) { return input.error(TextUtils.formatSimple( "There is a resource in the typedArray (%s) that is not found in" + " the app resources.", typedArrayName)); } resourceIdSet.add(id); } if (resourceIdSet.isEmpty()) { return input.success(null); } return input.success(resourceIdSet.stream().mapToInt(i -> i).toArray()); } } private static String string(@StyleableRes int attribute, TypedArray sa) { return sa.getString(attribute); } Loading
core/java/com/android/server/pm/pkg/AndroidPackage.java +22 −0 Original line number Diff line number Diff line Loading @@ -90,6 +90,28 @@ import java.util.UUID; @Immutable public interface AndroidPackage { /** * An array containing the drawable resources that used for the launcher * activity icons. * * @see R.attr#alternateLauncherIcons * @hide */ @Immutable.Ignore @Nullable int[] getAlternateLauncherIconResIds(); /** * An array containing the string resources that used for the launcher * activity labels. * * @see R.attr#alternateLauncherLabels * @hide */ @Immutable.Ignore @Nullable int[] getAlternateLauncherLabelResIds(); /** * @see ApplicationInfo#className * @see R.styleable#AndroidManifestApplication_name Loading
services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt +28 −0 Original line number Diff line number Diff line Loading @@ -582,6 +582,34 @@ class AndroidPackageTest : ParcelableComponentTest(AndroidPackage::class, Packag PackageImpl::setSystemExt, true ), getSetByValue( AndroidPackage::getAlternateLauncherIconResIds, PackageImpl::setAlternateLauncherIconResIds, intArrayOf(3, 5, 7), compare = { first, second -> equalBy( first, second, { it.size }, { it[0] }, { it[1] }, { it[2] } ) } ), getSetByValue( AndroidPackage::getAlternateLauncherLabelResIds, PackageImpl::setAlternateLauncherLabelResIds, intArrayOf(3, 5, 7), compare = { first, second -> equalBy( first, second, { it.size }, { it[0] }, { it[1] }, { it[2] } ) } ), ) override fun initialObject() = PackageImpl.forParsing( Loading