diff options
| author | 2022-09-22 22:02:26 +0000 | |
|---|---|---|
| committer | 2022-09-22 22:02:26 +0000 | |
| commit | 5f96cfb4c3dcd2c225dde08a69b126db02fc34cf (patch) | |
| tree | cd2a4a92df81d39aab71ea41e2771b5efae496fd | |
| parent | b05c9b15f4541ee32d0cbf768232a8910da2d59d (diff) | |
| parent | fc54f25194213dfcfe632df700f7df84c0db3d7d (diff) | |
Merge changes I7850ea5b,I9759b7dd
* changes:
Prepare PackageState/PackageUserState for API
Add runtime unmodifiable check for PackageState
20 files changed, 756 insertions, 78 deletions
diff --git a/services/core/java/com/android/server/pm/ApexPackageInfo.java b/services/core/java/com/android/server/pm/ApexPackageInfo.java index 4dd9c49321b2..672ae2eb0fb2 100644 --- a/services/core/java/com/android/server/pm/ApexPackageInfo.java +++ b/services/core/java/com/android/server/pm/ApexPackageInfo.java @@ -329,17 +329,15 @@ class ApexPackageInfo { ApexInfo ai = parsingApexInfo.get(parseResult.scanFile); if (throwable == null) { - // Calling hideAsFinal to assign derived fields for the app info flags. - parseResult.parsedPackage.hideAsFinal(); - // TODO: When ENABLE_FEATURE_SCAN_APEX is finalized, remove this and the entire // calling path code ScanPackageUtils.applyPolicy(parseResult.parsedPackage, PackageManagerService.SCAN_AS_SYSTEM, mPackageManager == null ? null : mPackageManager.getPlatformPackage(), false); - results.add(new ApexManager.ScanResult( - ai, parseResult.parsedPackage, parseResult.parsedPackage.getPackageName())); + // Calling hideAsFinal to assign derived fields for the app info flags. + AndroidPackage finalPkg = parseResult.parsedPackage.hideAsFinal(); + results.add(new ApexManager.ScanResult(ai, finalPkg, finalPkg.getPackageName())); } else if (throwable instanceof PackageManagerException) { throw new IllegalStateException("Unable to parse: " + ai.modulePath, throwable); } else { diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index 2354868e256e..1746d93c99b9 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -3451,8 +3451,8 @@ final class InstallPackageHelper { if (throwable == null) { try { - AndroidPackage pkg = addForInitLI( - parseResult.parsedPackage, newParseFlags, newScanFlags, null); + addForInitLI(parseResult.parsedPackage, newParseFlags, newScanFlags, null); + AndroidPackage pkg = parseResult.parsedPackage.hideAsFinal(); if (ai.isFactory && !ai.isActive) { disableSystemPackageLPw(pkg); } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index b2f3d5835989..9481f8a7da87 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -210,6 +210,7 @@ import com.android.server.pm.permission.LegacyPermissionManagerService; import com.android.server.pm.permission.PermissionManagerService; import com.android.server.pm.permission.PermissionManagerServiceInternal; import com.android.server.pm.pkg.AndroidPackage; +import com.android.server.pm.pkg.PackageState; import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.pm.pkg.PackageUserState; import com.android.server.pm.pkg.PackageUserStateInternal; @@ -222,6 +223,7 @@ import com.android.server.pm.pkg.mutate.PackageUserStateWrite; import com.android.server.pm.pkg.parsing.ParsingPackageUtils; import com.android.server.pm.resolution.ComponentResolver; import com.android.server.pm.resolution.ComponentResolverApi; +import com.android.server.pm.snapshot.PackageDataSnapshot; import com.android.server.pm.verify.domain.DomainVerificationManagerInternal; import com.android.server.pm.verify.domain.DomainVerificationService; import com.android.server.pm.verify.domain.proxy.DomainVerificationProxy; diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java index 4764a5c41db4..03f17bde8886 100644 --- a/services/core/java/com/android/server/pm/PackageSetting.java +++ b/services/core/java/com/android/server/pm/PackageSetting.java @@ -1208,11 +1208,23 @@ public class PackageSetting extends SettingBase implements PackageStateInternal } @NonNull + public PackageSetting addUsesLibraryInfo(@NonNull SharedLibraryInfo value) { + pkgState.addUsesLibraryInfo(value); + return this; + } + + @NonNull @Override public List<String> getUsesLibraryFiles() { return pkgState.getUsesLibraryFiles(); } + @NonNull + public PackageSetting addUsesLibraryFile(String value) { + pkgState.addUsesLibraryFile(value); + return this; + } + @Override public boolean isHiddenUntilInstalled() { return pkgState.isHiddenUntilInstalled(); 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 70aca99f04e5..fe63deccec4b 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 @@ -385,16 +385,16 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal, @Nullable @DataClass.ParcelWith(Parcelling.BuiltIn.ForBoolean.class) private Boolean requestRawExternalStorageAccess; - // TODO(chiuwinson): Non-null - @Nullable - private ArraySet<String> mimeGroups; + @NonNull + @DataClass.ParcelWith(Parcelling.BuiltIn.ForInternedStringSet.class) + private Set<String> mimeGroups = emptySet(); // Usually there's code to set enabled to true during parsing, but it's possible to install // an APK targeting <R that doesn't contain an <application> tag. That code would be skipped // and never assign this, so initialize this to true for those cases. private long mBooleans = Booleans.ENABLED; private long mBooleans2; - @Nullable - private Set<String> mKnownActivityEmbeddingCerts; + @NonNull + private Set<String> mKnownActivityEmbeddingCerts = emptySet(); // Derived fields private long mLongVersionCode; private int mLocaleConfigRes; @@ -549,7 +549,7 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal, if (mimeGroups != null && mimeGroups.size() > 500) { throw new IllegalStateException("Max limit on number of MIME Groups reached"); } - mimeGroups = ArrayUtils.add(mimeGroups, filter.getMimeGroup(groupIndex)); + mimeGroups = CollectionUtils.add(mimeGroups, filter.getMimeGroup(groupIndex)); } } } @@ -935,8 +935,7 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal, @NonNull @Override public Set<String> getKnownActivityEmbeddingCerts() { - return mKnownActivityEmbeddingCerts == null ? Collections.emptySet() - : mKnownActivityEmbeddingCerts; + return mKnownActivityEmbeddingCerts; } @Override @@ -1949,8 +1948,7 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal, } @Override - public ParsingPackage setKnownActivityEmbeddingCerts( - @Nullable Set<String> knownEmbeddingCerts) { + public ParsingPackage setKnownActivityEmbeddingCerts(@NonNull Set<String> knownEmbeddingCerts) { mKnownActivityEmbeddingCerts = knownEmbeddingCerts; return this; } @@ -2516,7 +2514,7 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal, appInfo.setVersionCode(mLongVersionCode); appInfo.setAppClassNamesByProcess(buildAppClassNamesByProcess()); appInfo.setLocaleConfigRes(mLocaleConfigRes); - if (mKnownActivityEmbeddingCerts != null) { + if (!mKnownActivityEmbeddingCerts.isEmpty()) { appInfo.setKnownActivityEmbeddingCerts(mKnownActivityEmbeddingCerts); } @@ -2593,11 +2591,11 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal, @Override public AndroidPackageInternal hideAsFinal() { - // TODO(b/135203078): Lock as immutable if (mStorageUuid == null) { assignDerivedFields(); } assignDerivedFields2(); + makeImmutable(); return this; } @@ -2613,6 +2611,48 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal, baseAppDataDir + Environment.DIR_USER_DE + systemUserSuffix); } + private void makeImmutable() { + usesLibraries = Collections.unmodifiableList(usesLibraries); + usesOptionalLibraries = Collections.unmodifiableList(usesOptionalLibraries); + usesNativeLibraries = Collections.unmodifiableList(usesNativeLibraries); + usesOptionalNativeLibraries = Collections.unmodifiableList(usesOptionalNativeLibraries); + originalPackages = Collections.unmodifiableList(originalPackages); + adoptPermissions = Collections.unmodifiableList(adoptPermissions); + requestedPermissions = Collections.unmodifiableList(requestedPermissions); + protectedBroadcasts = Collections.unmodifiableList(protectedBroadcasts); + apexSystemServices = Collections.unmodifiableList(apexSystemServices); + + activities = Collections.unmodifiableList(activities); + receivers = Collections.unmodifiableList(receivers); + services = Collections.unmodifiableList(services); + providers = Collections.unmodifiableList(providers); + permissions = Collections.unmodifiableList(permissions); + permissionGroups = Collections.unmodifiableList(permissionGroups); + instrumentations = Collections.unmodifiableList(instrumentations); + + overlayables = Collections.unmodifiableMap(overlayables); + libraryNames = Collections.unmodifiableList(libraryNames); + usesStaticLibraries = Collections.unmodifiableList(usesStaticLibraries); + usesSdkLibraries = Collections.unmodifiableList(usesSdkLibraries); + configPreferences = Collections.unmodifiableList(configPreferences); + reqFeatures = Collections.unmodifiableList(reqFeatures); + featureGroups = Collections.unmodifiableList(featureGroups); + usesPermissions = Collections.unmodifiableList(usesPermissions); + usesSdkLibraries = Collections.unmodifiableList(usesSdkLibraries); + implicitPermissions = Collections.unmodifiableList(implicitPermissions); + upgradeKeySets = Collections.unmodifiableSet(upgradeKeySets); + keySetMapping = Collections.unmodifiableMap(keySetMapping); + attributions = Collections.unmodifiableList(attributions); + preferredActivityFilters = Collections.unmodifiableList(preferredActivityFilters); + processes = Collections.unmodifiableMap(processes); + mProperties = Collections.unmodifiableMap(mProperties); + queriesIntents = Collections.unmodifiableList(queriesIntents); + queriesPackages = Collections.unmodifiableList(queriesPackages); + queriesProviders = Collections.unmodifiableSet(queriesProviders); + mimeGroups = Collections.unmodifiableSet(mimeGroups); + mKnownActivityEmbeddingCerts = Collections.unmodifiableSet(mKnownActivityEmbeddingCerts); + } + @Override public long getLongVersionCode() { return PackageInfo.composeLongVersionCode(versionCodeMajor, versionCode); @@ -3041,7 +3081,7 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal, dest.writeIntArray(this.splitRevisionCodes); sForBoolean.parcel(this.resizeableActivity, dest, flags); dest.writeInt(this.autoRevokePermissions); - dest.writeArraySet(this.mimeGroups); + sForInternedStringSet.parcel(this.mimeGroups, dest, flags); dest.writeInt(this.gwpAsanMode); dest.writeSparseIntArray(this.minExtensionVersions); dest.writeMap(this.mProperties); @@ -3201,7 +3241,7 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal, this.resizeableActivity = sForBoolean.unparcel(in); this.autoRevokePermissions = in.readInt(); - this.mimeGroups = (ArraySet<String>) in.readArraySet(boot); + this.mimeGroups = sForInternedStringSet.unparcel(in); this.gwpAsanMode = in.readInt(); this.minExtensionVersions = in.readSparseIntArray(); this.mProperties = in.readHashMap(boot); @@ -3224,6 +3264,9 @@ public class PackageImpl implements ParsedPackage, AndroidPackageInternal, assignDerivedFields(); assignDerivedFields2(); + + // Do not call makeImmutable here as cached parsing will need + // to mutate this instance before it's finalized. } @NonNull diff --git a/services/core/java/com/android/server/pm/pkg/AndroidPackage.java b/services/core/java/com/android/server/pm/pkg/AndroidPackage.java index 8a82d6e41464..e07b77e7bc5b 100644 --- a/services/core/java/com/android/server/pm/pkg/AndroidPackage.java +++ b/services/core/java/com/android/server/pm/pkg/AndroidPackage.java @@ -18,7 +18,6 @@ package com.android.server.pm.pkg; import android.annotation.NonNull; import android.annotation.Nullable; -import android.annotation.SystemApi; import android.content.ComponentName; import android.content.Intent; import android.content.pm.ActivityInfo; @@ -59,19 +58,17 @@ import java.util.List; import java.util.Map; import java.util.Set; -/** - * Explicit interface used for consumers like mainline who need a {@link SystemApi @SystemApi} form - * of {@link AndroidPackage}. - * - * @hide - */ +/** @hide */ //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER) @Immutable public interface AndroidPackage { + // Methods below this comment are not yet exposed as API + /** * @see ApplicationInfo#areAttributionsUserVisible() * @see R.styleable#AndroidManifestApplication_attributionsAreUserVisible + * @hide */ @Nullable boolean areAttributionsUserVisible(); @@ -87,6 +84,7 @@ public interface AndroidPackage { * * @see ActivityInfo * @see PackageInfo#activities + * @hide */ @Immutable.Ignore @NonNull @@ -97,12 +95,14 @@ public interface AndroidPackage { * ParsingPackageUtils#TAG_ADOPT_PERMISSIONS}. * * @see R.styleable#AndroidManifestOriginalPackage_name + * @hide */ @NonNull List<String> getAdoptPermissions(); /** * @see R.styleable#AndroidManifestApexSystemService + * @hide */ @Immutable.Ignore @NonNull @@ -111,10 +111,12 @@ public interface AndroidPackage { /** * @see ApplicationInfo#appComponentFactory * @see R.styleable#AndroidManifestApplication_appComponentFactory + * @hide */ @Nullable String getAppComponentFactory(); + /** @hide */ @Immutable.Ignore @NonNull List<ParsedAttribution> getAttributions(); @@ -123,12 +125,14 @@ public interface AndroidPackage { * @see ApplicationInfo#AUTO_REVOKE_ALLOWED * @see ApplicationInfo#AUTO_REVOKE_DISCOURAGED * @see ApplicationInfo#AUTO_REVOKE_DISALLOWED + * @hide */ int getAutoRevokePermissions(); /** * @see ApplicationInfo#backupAgentName * @see R.styleable#AndroidManifestApplication_backupAgent + * @hide */ @Nullable String getBackupAgentName(); @@ -136,30 +140,35 @@ public interface AndroidPackage { /** * @see ApplicationInfo#banner * @see R.styleable#AndroidManifestApplication_banner + * @hide */ int getBanner(); /** * @see ApplicationInfo#sourceDir * @see ApplicationInfo#getBaseCodePath + * @hide */ @NonNull String getBaseApkPath(); /** * @see PackageInfo#baseRevisionCode + * @hide */ int getBaseRevisionCode(); /** * @see ApplicationInfo#category * @see R.styleable#AndroidManifestApplication_appCategory + * @hide */ int getCategory(); /** * @see ApplicationInfo#classLoaderName * @see R.styleable#AndroidManifestApplication_classLoader + * @hide */ @Nullable String getClassLoaderName(); @@ -167,6 +176,7 @@ public interface AndroidPackage { /** * @see ApplicationInfo#className * @see R.styleable#AndroidManifestApplication_name + * @hide */ @Nullable String getClassName(); @@ -174,18 +184,21 @@ public interface AndroidPackage { /** * @see ApplicationInfo#compatibleWidthLimitDp * @see R.styleable#AndroidManifestSupportsScreens_compatibleWidthLimitDp + * @hide */ int getCompatibleWidthLimitDp(); /** * @see ApplicationInfo#compileSdkVersion * @see R.styleable#AndroidManifest_compileSdkVersion + * @hide */ int getCompileSdkVersion(); /** * @see ApplicationInfo#compileSdkVersionCodename * @see R.styleable#AndroidManifest_compileSdkVersionCodename + * @hide */ @Nullable String getCompileSdkVersionCodeName(); @@ -193,6 +206,7 @@ public interface AndroidPackage { /** * @see PackageInfo#configPreferences * @see R.styleable#AndroidManifestUsesConfiguration + * @hide */ @Immutable.Ignore @NonNull @@ -201,18 +215,21 @@ public interface AndroidPackage { /** * @see ApplicationInfo#dataExtractionRulesRes * @see R.styleable#AndroidManifestApplication_dataExtractionRules + * @hide */ int getDataExtractionRules(); /** * @see ApplicationInfo#descriptionRes * @see R.styleable#AndroidManifestApplication_description + * @hide */ int getDescriptionRes(); /** * @see PackageInfo#featureGroups * @see R.styleable#AndroidManifestUsesFeature + * @hide */ @Immutable.Ignore @NonNull @@ -221,12 +238,14 @@ public interface AndroidPackage { /** * @see ApplicationInfo#fullBackupContent * @see R.styleable#AndroidManifestApplication_fullBackupContent + * @hide */ int getFullBackupContent(); /** * @see ApplicationInfo#getGwpAsanMode() * @see R.styleable#AndroidManifestApplication_gwpAsanMode + * @hide */ @ApplicationInfo.GwpAsanMode int getGwpAsanMode(); @@ -234,12 +253,14 @@ public interface AndroidPackage { /** * @see ApplicationInfo#iconRes * @see R.styleable#AndroidManifestApplication_icon + * @hide */ int getIconRes(); /** * Permissions requested but not in the manifest. These may have been split or migrated from * previous versions/definitions. + * @hide */ @NonNull List<String> getImplicitPermissions(); @@ -247,12 +268,14 @@ public interface AndroidPackage { /** * @see ApplicationInfo#installLocation * @see R.styleable#AndroidManifest_installLocation + * @hide */ int getInstallLocation(); /** * @see InstrumentationInfo * @see PackageInfo#instrumentation + * @hide */ @Immutable.Ignore @NonNull @@ -264,6 +287,7 @@ public interface AndroidPackage { * * @see R.styleable#AndroidManifestKeySet * @see R.styleable#AndroidManifestPublicKey + * @hide */ @Immutable.Ignore @NonNull @@ -272,6 +296,7 @@ public interface AndroidPackage { /** * @see ApplicationInfo#mKnownActivityEmbeddingCerts * @see R.styleable#AndroidManifestApplication_knownActivityEmbeddingCerts + * @hide */ @SuppressWarnings("JavadocReference") @NonNull @@ -280,12 +305,14 @@ public interface AndroidPackage { /** * @see ApplicationInfo#labelRes * @see R.styleable#AndroidManifestApplication_label + * @hide */ int getLabelRes(); /** * @see ApplicationInfo#largestWidthLimitDp * @see R.styleable#AndroidManifestSupportsScreens_largestWidthLimitDp + * @hide */ int getLargestWidthLimitDp(); @@ -293,6 +320,7 @@ public interface AndroidPackage { * Library names this package is declared as, for use by other packages with "uses-library". * * @see R.styleable#AndroidManifestLibrary + * @hide */ @NonNull List<String> getLibraryNames(); @@ -301,23 +329,27 @@ public interface AndroidPackage { * The resource ID used to provide the application's locales configuration. * * @see R.styleable#AndroidManifestApplication_localeConfig + * @hide */ int getLocaleConfigRes(); /** * @see ApplicationInfo#logo * @see R.styleable#AndroidManifestApplication_logo + * @hide */ int getLogo(); /** * @see PackageInfo#getLongVersionCode() + * @hide */ long getLongVersionCode(); /** * @see ApplicationInfo#manageSpaceActivityName * @see R.styleable#AndroidManifestApplication_manageSpaceActivity + * @hide */ @Nullable String getManageSpaceActivityName(); @@ -325,6 +357,7 @@ public interface AndroidPackage { /** * The package name as declared in the manifest, since the package can be renamed. For example, * static shared libs use synthetic package names. + * @hide */ @NonNull String getManifestPackageName(); @@ -332,39 +365,46 @@ public interface AndroidPackage { /** * @see ApplicationInfo#maxAspectRatio * @see R.styleable#AndroidManifestApplication_maxAspectRatio + * @hide */ float getMaxAspectRatio(); /** * @see R.styleable#AndroidManifestUsesSdk_maxSdkVersion + * @hide */ int getMaxSdkVersion(); /** * @see ApplicationInfo#getMemtagMode() * @see R.styleable#AndroidManifestApplication_memtagMode + * @hide */ @ApplicationInfo.MemtagMode int getMemtagMode(); /** * TODO(b/135203078): Make all the Bundles immutable (and non-null by shared empty reference?) + * @hide */ @Immutable.Ignore @Nullable Bundle getMetaData(); + /** @hide */ @Nullable Set<String> getMimeGroups(); /** * @see ApplicationInfo#minAspectRatio * @see R.styleable#AndroidManifestApplication_minAspectRatio + * @hide */ float getMinAspectRatio(); /** * @see R.styleable#AndroidManifestExtensionSdk + * @hide */ @Immutable.Ignore @Nullable @@ -373,24 +413,28 @@ public interface AndroidPackage { /** * @see ApplicationInfo#minSdkVersion * @see R.styleable#AndroidManifestUsesSdk_minSdkVersion + * @hide */ int getMinSdkVersion(); /** * @see ApplicationInfo#getNativeHeapZeroInitialized() * @see R.styleable#AndroidManifestApplication_nativeHeapZeroInitialized + * @hide */ @ApplicationInfo.NativeHeapZeroInitialized int getNativeHeapZeroInitialized(); /** * @see ApplicationInfo#nativeLibraryDir + * @hide */ @Nullable String getNativeLibraryDir(); /** * @see ApplicationInfo#nativeLibraryRootDir + * @hide */ @Nullable String getNativeLibraryRootDir(); @@ -398,6 +442,7 @@ public interface AndroidPackage { /** * @see ApplicationInfo#networkSecurityConfigRes * @see R.styleable#AndroidManifestApplication_networkSecurityConfig + * @hide */ int getNetworkSecurityConfigRes(); @@ -407,6 +452,7 @@ public interface AndroidPackage { * * @see ApplicationInfo#nonLocalizedLabel * @see R.styleable#AndroidManifestApplication_label + * @hide */ @Nullable CharSequence getNonLocalizedLabel(); @@ -416,6 +462,7 @@ public interface AndroidPackage { * available. * * @see R.styleable#AndroidManifestOriginalPackage} + * @hide */ @NonNull List<String> getOriginalPackages(); @@ -423,6 +470,7 @@ public interface AndroidPackage { /** * @see PackageInfo#overlayCategory * @see R.styleable#AndroidManifestResourceOverlay_category + * @hide */ @Nullable String getOverlayCategory(); @@ -430,12 +478,14 @@ public interface AndroidPackage { /** * @see PackageInfo#overlayPriority * @see R.styleable#AndroidManifestResourceOverlay_priority + * @hide */ int getOverlayPriority(); /** * @see PackageInfo#overlayTarget * @see R.styleable#AndroidManifestResourceOverlay_targetPackage + * @hide */ @Nullable String getOverlayTarget(); @@ -443,24 +493,28 @@ public interface AndroidPackage { /** * @see PackageInfo#targetOverlayableName * @see R.styleable#AndroidManifestResourceOverlay_targetName + * @hide */ @Nullable String getOverlayTargetOverlayableName(); /** * Map of overlayable name to actor name. + * @hide */ @NonNull Map<String, String> getOverlayables(); /** * @see PackageInfo#packageName + * @hide */ String getPackageName(); /** * @see ApplicationInfo#scanSourceDir * @see ApplicationInfo#getCodePath + * @hide */ @NonNull String getPath(); @@ -468,12 +522,14 @@ public interface AndroidPackage { /** * @see ApplicationInfo#permission * @see R.styleable#AndroidManifestApplication_permission + * @hide */ @Nullable String getPermission(); /** * @see android.content.pm.PermissionGroupInfo + * @hide */ @Immutable.Ignore @NonNull @@ -482,6 +538,7 @@ public interface AndroidPackage { /** * @see PermissionInfo * @see PackageInfo#permissions + * @hide */ @Immutable.Ignore @NonNull @@ -492,6 +549,7 @@ public interface AndroidPackage { * <p> * Map of component className to intent info inside that component. TODO(b/135203078): Is this * actually used/working? + * @hide */ @Immutable.Ignore @NonNull @@ -500,12 +558,14 @@ public interface AndroidPackage { /** * @see ApplicationInfo#processName * @see R.styleable#AndroidManifestApplication_process + * @hide */ @NonNull String getProcessName(); /** * @see android.content.pm.ProcessInfo + * @hide */ @Immutable.Ignore @NonNull @@ -513,6 +573,7 @@ public interface AndroidPackage { /** * Returns the properties set on the application + * @hide */ @Immutable.Ignore @NonNull @@ -522,6 +583,7 @@ public interface AndroidPackage { * System protected broadcasts. * * @see R.styleable#AndroidManifestProtectedBroadcast + * @hide */ @NonNull List<String> getProtectedBroadcasts(); @@ -537,6 +599,7 @@ public interface AndroidPackage { * * @see ProviderInfo * @see PackageInfo#providers + * @hide */ @Immutable.Ignore @NonNull @@ -546,6 +609,7 @@ public interface AndroidPackage { * Intents that this package may query or require and thus requires visibility into. * * @see R.styleable#AndroidManifestQueriesIntent + * @hide */ @Immutable.Ignore @NonNull @@ -555,6 +619,7 @@ public interface AndroidPackage { * Other packages that this package may query or require and thus requires visibility into. * * @see R.styleable#AndroidManifestQueriesPackage + * @hide */ @NonNull List<String> getQueriesPackages(); @@ -563,6 +628,7 @@ public interface AndroidPackage { * Authorities that this package may query or require and thus requires visibility into. * * @see R.styleable#AndroidManifestQueriesProvider + * @hide */ @NonNull Set<String> getQueriesProviders(); @@ -583,6 +649,7 @@ public interface AndroidPackage { * * @see ActivityInfo * @see PackageInfo#receivers + * @hide */ @Immutable.Ignore @NonNull @@ -591,6 +658,7 @@ public interface AndroidPackage { /** * @see PackageInfo#reqFeatures * @see R.styleable#AndroidManifestUsesFeature + * @hide */ @Immutable.Ignore @NonNull @@ -603,6 +671,7 @@ public interface AndroidPackage { * * @see PackageInfo#requestedPermissions * @see R.styleable#AndroidManifestUsesPermission + * @hide */ @NonNull List<String> getRequestedPermissions(); @@ -610,6 +679,7 @@ public interface AndroidPackage { /** * @see PackageInfo#requiredAccountType * @see R.styleable#AndroidManifestApplication_requiredAccountType + * @hide */ @Nullable String getRequiredAccountType(); @@ -617,6 +687,7 @@ public interface AndroidPackage { /** * @see ApplicationInfo#requiresSmallestWidthDp * @see R.styleable#AndroidManifestSupportsScreens_requiresSmallestWidthDp + * @hide */ int getRequiresSmallestWidthDp(); @@ -626,6 +697,7 @@ public interface AndroidPackage { * * @see ApplicationInfo#PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE * @see ApplicationInfo#PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_UNRESIZEABLE + * @hide */ @Nullable Boolean getResizeableActivity(); @@ -634,6 +706,7 @@ public interface AndroidPackage { * SHA-512 hash of the only APK that can be used to update a system package. * * @see R.styleable#AndroidManifestRestrictUpdate + * @hide */ @Immutable.Ignore @Nullable @@ -644,6 +717,7 @@ public interface AndroidPackage { * * @see PackageInfo#restrictedAccountType * @see R.styleable#AndroidManifestApplication_restrictedAccountType + * @hide */ @Nullable String getRestrictedAccountType(); @@ -651,22 +725,26 @@ public interface AndroidPackage { /** * @see ApplicationInfo#roundIconRes * @see R.styleable#AndroidManifestApplication_roundIcon + * @hide */ int getRoundIconRes(); /** * @see R.styleable#AndroidManifestSdkLibrary_name + * @hide */ @Nullable String getSdkLibName(); /** * @see R.styleable#AndroidManifestSdkLibrary_versionMajor + * @hide */ int getSdkLibVersionMajor(); /** * @see ApplicationInfo#secondaryNativeLibraryDir + * @hide */ @Nullable String getSecondaryNativeLibraryDir(); @@ -682,6 +760,7 @@ public interface AndroidPackage { * * @see ServiceInfo * @see PackageInfo#services + * @hide */ @Immutable.Ignore @NonNull @@ -690,6 +769,7 @@ public interface AndroidPackage { /** * @see PackageInfo#sharedUserId * @see R.styleable#AndroidManifest_sharedUserId + * @hide */ @Nullable String getSharedUserId(); @@ -697,12 +777,14 @@ public interface AndroidPackage { /** * @see PackageInfo#sharedUserLabel * @see R.styleable#AndroidManifest_sharedUserLabel + * @hide */ int getSharedUserLabel(); /** * The signature data of all APKs in this package, which must be exactly the same across the * base and splits. + * @hide */ @Immutable.Ignore @NonNull @@ -711,6 +793,7 @@ public interface AndroidPackage { /** * @see ApplicationInfo#splitClassLoaderNames * @see R.styleable#AndroidManifestApplication_classLoader + * @hide */ @Immutable.Ignore @Nullable @@ -719,6 +802,7 @@ public interface AndroidPackage { /** * @see ApplicationInfo#splitSourceDirs * @see ApplicationInfo#getSplitCodePaths + * @hide */ @Immutable.Ignore @NonNull @@ -726,6 +810,7 @@ public interface AndroidPackage { /** * @see ApplicationInfo#splitDependencies + * @hide */ @Immutable.Ignore @NonNull @@ -733,6 +818,7 @@ public interface AndroidPackage { /** * Flags of any split APKs; ordered by parsed splitName + * @hide */ @Immutable.Ignore @Nullable @@ -743,6 +829,7 @@ public interface AndroidPackage { * * @see ApplicationInfo#splitNames * @see PackageInfo#splitNames + * @hide */ @Immutable.Ignore @NonNull @@ -750,6 +837,7 @@ public interface AndroidPackage { /** * @see PackageInfo#splitRevisionCodes + * @hide */ @Immutable.Ignore @NonNull @@ -757,30 +845,35 @@ public interface AndroidPackage { /** * @see R.styleable#AndroidManifestStaticLibrary_name + * @hide */ @Nullable String getStaticSharedLibName(); /** * @see R.styleable#AndroidManifestStaticLibrary_version + * @hide */ long getStaticSharedLibVersion(); /** * @see ApplicationInfo#targetSandboxVersion * @see R.styleable#AndroidManifest_targetSandboxVersion + * @hide */ int getTargetSandboxVersion(); /** * @see ApplicationInfo#targetSdkVersion * @see R.styleable#AndroidManifestUsesSdk_targetSdkVersion + * @hide */ int getTargetSdkVersion(); /** * @see ApplicationInfo#taskAffinity * @see R.styleable#AndroidManifestApplication_taskAffinity + * @hide */ @Nullable String getTaskAffinity(); @@ -788,12 +881,14 @@ public interface AndroidPackage { /** * @see ApplicationInfo#theme * @see R.styleable#AndroidManifestApplication_theme + * @hide */ int getTheme(); /** * @see ApplicationInfo#uiOptions * @see R.styleable#AndroidManifestApplication_uiOptions + * @hide */ int getUiOptions(); @@ -802,6 +897,7 @@ public interface AndroidPackage { * {@link android.os.UserHandle#SYSTEM}. * * @deprecated Use {@link PackageState#getAppId()} instead. + * @hide */ @Deprecated int getUid(); @@ -811,18 +907,21 @@ public interface AndroidPackage { * ParsingPackageUtils#TAG_KEY_SETS}. * * @see R.styleable#AndroidManifestUpgradeKeySet + * @hide */ @NonNull Set<String> getUpgradeKeySets(); /** * @see R.styleable#AndroidManifestUsesLibrary + * @hide */ @NonNull List<String> getUsesLibraries(); /** * @see R.styleable#AndroidManifestUsesNativeLibrary + * @hide */ @NonNull List<String> getUsesNativeLibraries(); @@ -833,6 +932,7 @@ public interface AndroidPackage { * absence manually. * * @see R.styleable#AndroidManifestUsesLibrary + * @hide */ @NonNull List<String> getUsesOptionalLibraries(); @@ -843,10 +943,12 @@ public interface AndroidPackage { * handle absence manually. * * @see R.styleable#AndroidManifestUsesNativeLibrary + * @hide */ @NonNull List<String> getUsesOptionalNativeLibraries(); + /** @hide */ @Immutable.Ignore @NonNull List<ParsedUsesPermission> getUsesPermissions(); @@ -855,12 +957,14 @@ public interface AndroidPackage { * TODO(b/135203078): Move SDK library stuff to an inner data class * * @see R.styleable#AndroidManifestUsesSdkLibrary + * @hide */ @NonNull List<String> getUsesSdkLibraries(); /** * @see R.styleable#AndroidManifestUsesSdkLibrary_certDigest + * @hide */ @Immutable.Ignore @Nullable @@ -868,6 +972,7 @@ public interface AndroidPackage { /** * @see R.styleable#AndroidManifestUsesSdkLibrary_versionMajor + * @hide */ @Immutable.Ignore @Nullable @@ -877,12 +982,14 @@ public interface AndroidPackage { * TODO(b/135203078): Move static library stuff to an inner data class * * @see R.styleable#AndroidManifestUsesStaticLibrary + * @hide */ @NonNull List<String> getUsesStaticLibraries(); /** * @see R.styleable#AndroidManifestUsesStaticLibrary_certDigest + * @hide */ @Immutable.Ignore @Nullable @@ -890,6 +997,7 @@ public interface AndroidPackage { /** * @see R.styleable#AndroidManifestUsesStaticLibrary_version + * @hide */ @Immutable.Ignore @Nullable @@ -897,60 +1005,72 @@ public interface AndroidPackage { /** * @see PackageInfo#versionName + * @hide */ @Nullable String getVersionName(); /** * @see ApplicationInfo#volumeUuid + * @hide */ @Nullable String getVolumeUuid(); + /** @hide */ @Nullable String getZygotePreloadName(); + /** @hide */ boolean hasPreserveLegacyExternalStorage(); /** * @see ApplicationInfo#PRIVATE_FLAG_EXT_REQUEST_FOREGROUND_SERVICE_EXEMPTION * @see R.styleable#AndroidManifestApplication_requestForegroundServiceExemption + * @hide */ boolean hasRequestForegroundServiceExemption(); /** * @see ApplicationInfo#getRequestRawExternalStorageAccess() * @see R.styleable#AndroidManifestApplication_requestRawExternalStorageAccess + * @hide */ Boolean hasRequestRawExternalStorageAccess(); /** * @see ApplicationInfo#PRIVATE_FLAG_ALLOW_AUDIO_PLAYBACK_CAPTURE + * @hide */ boolean isAllowAudioPlaybackCapture(); /** * @see ApplicationInfo#FLAG_ALLOW_BACKUP + * @hide */ boolean isAllowBackup(); /** * @see ApplicationInfo#FLAG_ALLOW_CLEAR_USER_DATA + * @hide */ boolean isAllowClearUserData(); /** * @see ApplicationInfo#PRIVATE_FLAG_ALLOW_CLEAR_USER_DATA_ON_FAILED_RESTORE + * @hide */ boolean isAllowClearUserDataOnFailedRestore(); /** * @see ApplicationInfo#PRIVATE_FLAG_ALLOW_NATIVE_HEAP_POINTER_TAGGING + * @hide */ boolean isAllowNativeHeapPointerTagging(); /** * @see ApplicationInfo#FLAG_ALLOW_TASK_REPARENTING + * @hide */ boolean isAllowTaskReparenting(); @@ -960,115 +1080,138 @@ public interface AndroidPackage { * * @see R.styleable#AndroidManifestSupportsScreens_anyDensity * @see ApplicationInfo#FLAG_SUPPORTS_SCREEN_DENSITIES + * @hide */ boolean isAnyDensity(); + /** @hide */ boolean isApex(); /** * @see ApplicationInfo#PRIVATE_FLAG_BACKUP_IN_FOREGROUND + * @hide */ boolean isBackupInForeground(); /** * @see ApplicationInfo#FLAG_HARDWARE_ACCELERATED + * @hide */ boolean isBaseHardwareAccelerated(); /** * @see ApplicationInfo#PRIVATE_FLAG_CANT_SAVE_STATE + * @hide */ boolean isCantSaveState(); /** * @see PackageInfo#coreApp + * @hide */ boolean isCoreApp(); /** * @see ApplicationInfo#crossProfile + * @hide */ boolean isCrossProfile(); /** * @see ApplicationInfo#FLAG_DEBUGGABLE + * @hide */ boolean isDebuggable(); /** * @see ApplicationInfo#PRIVATE_FLAG_DEFAULT_TO_DEVICE_PROTECTED_STORAGE + * @hide */ boolean isDefaultToDeviceProtectedStorage(); /** * @see ApplicationInfo#PRIVATE_FLAG_DIRECT_BOOT_AWARE + * @hide */ boolean isDirectBootAware(); /** * @see ApplicationInfo#enabled * @see R.styleable#AndroidManifestApplication_enabled + * @hide */ boolean isEnabled(); /** * @see ApplicationInfo#FLAG_EXTERNAL_STORAGE + * @hide */ boolean isExternalStorage(); /** * @see ApplicationInfo#FLAG_EXTRACT_NATIVE_LIBS + * @hide */ boolean isExtractNativeLibs(); /** * @see ApplicationInfo#FLAG_FACTORY_TEST + * @hide */ boolean isFactoryTest(); /** * @see R.styleable#AndroidManifestApplication_forceQueryable + * @hide */ boolean isForceQueryable(); /** * @see ApplicationInfo#FLAG_FULL_BACKUP_ONLY + * @hide */ boolean isFullBackupOnly(); /** * @see ApplicationInfo#FLAG_IS_GAME + * @hide */ @Deprecated boolean isGame(); /** * @see ApplicationInfo#FLAG_HAS_CODE + * @hide */ boolean isHasCode(); /** * @see ApplicationInfo#PRIVATE_FLAG_HAS_DOMAIN_URLS + * @hide */ boolean isHasDomainUrls(); /** * @see ApplicationInfo#PRIVATE_FLAG_HAS_FRAGILE_USER_DATA + * @hide */ boolean isHasFragileUserData(); /** * @see ApplicationInfo#PRIVATE_FLAG_ISOLATED_SPLIT_LOADING + * @hide */ boolean isIsolatedSplitLoading(); /** * @see ApplicationInfo#FLAG_KILL_AFTER_RESTORE + * @hide */ boolean isKillAfterRestore(); /** * @see ApplicationInfo#FLAG_LARGE_HEAP + * @hide */ boolean isLargeHeap(); @@ -1077,83 +1220,99 @@ public interface AndroidPackage { * smaller than the current SDK version. * * @see R.styleable#AndroidManifest_sharedUserMaxSdkVersion + * @hide */ boolean isLeavingSharedUid(); /** * @see ApplicationInfo#FLAG_MULTIARCH + * @hide */ boolean isMultiArch(); /** * @see ApplicationInfo#nativeLibraryRootRequiresIsa + * @hide */ boolean isNativeLibraryRootRequiresIsa(); /** * @see ApplicationInfo#PRIVATE_FLAG_ODM + * @hide */ boolean isOdm(); /** * @see ApplicationInfo#PRIVATE_FLAG_OEM + * @hide */ boolean isOem(); /** * @see R.styleable#AndroidManifestApplication_enableOnBackInvokedCallback + * @hide */ boolean isOnBackInvokedCallbackEnabled(); /** * @see ApplicationInfo#PRIVATE_FLAG_IS_RESOURCE_OVERLAY * @see ApplicationInfo#isResourceOverlay() + * @hide */ boolean isOverlay(); /** * @see PackageInfo#mOverlayIsStatic + * @hide */ boolean isOverlayIsStatic(); /** * @see ApplicationInfo#PRIVATE_FLAG_PARTIALLY_DIRECT_BOOT_AWARE + * @hide */ boolean isPartiallyDirectBootAware(); /** * @see ApplicationInfo#FLAG_PERSISTENT + * @hide */ boolean isPersistent(); /** * @see ApplicationInfo#PRIVATE_FLAG_PRIVILEGED + * @hide */ boolean isPrivileged(); /** * @see ApplicationInfo#PRIVATE_FLAG_PRODUCT + * @hide */ boolean isProduct(); /** * @see ApplicationInfo#PRIVATE_FLAG_EXT_PROFILEABLE + * @hide */ boolean isProfileable(); /** * @see ApplicationInfo#PRIVATE_FLAG_PROFILEABLE_BY_SHELL + * @hide */ boolean isProfileableByShell(); /** * @see ApplicationInfo#PRIVATE_FLAG_REQUEST_LEGACY_EXTERNAL_STORAGE + * @hide */ boolean isRequestLegacyExternalStorage(); /** * @see PackageInfo#requiredForAllUsers * @see R.styleable#AndroidManifestApplication_requiredForAllUsers + * @hide */ boolean isRequiredForAllUsers(); @@ -1162,6 +1321,7 @@ public interface AndroidPackage { * when the application's user data is cleared. * * @see R.styleable#AndroidManifestApplication_resetEnabledSettingsOnAppDataCleared + * @hide */ boolean isResetEnabledSettingsOnAppDataCleared(); @@ -1171,36 +1331,43 @@ public interface AndroidPackage { * * @see R.styleable#AndroidManifestSupportsScreens_resizeable * @see ApplicationInfo#FLAG_RESIZEABLE_FOR_SCREENS + * @hide */ boolean isResizeable(); /** * @see ApplicationInfo#PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE_VIA_SDK_VERSION + * @hide */ boolean isResizeableActivityViaSdkVersion(); /** * @see ApplicationInfo#FLAG_RESTORE_ANY_VERSION + * @hide */ boolean isRestoreAnyVersion(); /** * True means that this package/app contains an SDK library. + * @hide */ boolean isSdkLibrary(); /** * @see ApplicationInfo#PRIVATE_FLAG_SIGNED_WITH_PLATFORM_KEY + * @hide */ boolean isSignedWithPlatformKey(); /** * @see ApplicationInfo#PRIVATE_FLAG_STATIC_SHARED_LIBRARY + * @hide */ boolean isStaticSharedLibrary(); /** * @see PackageInfo#isStub + * @hide */ boolean isStub(); @@ -1210,6 +1377,7 @@ public interface AndroidPackage { * * @see R.styleable#AndroidManifestSupportsScreens_xlargeScreens * @see ApplicationInfo#FLAG_SUPPORTS_XLARGE_SCREENS + * @hide */ boolean isSupportsExtraLargeScreens(); @@ -1219,6 +1387,7 @@ public interface AndroidPackage { * * @see R.styleable#AndroidManifestSupportsScreens_largeScreens * @see ApplicationInfo#FLAG_SUPPORTS_LARGE_SCREENS + * @hide */ boolean isSupportsLargeScreens(); @@ -1227,11 +1396,13 @@ public interface AndroidPackage { * * @see R.styleable#AndroidManifestSupportsScreens_normalScreens * @see ApplicationInfo#FLAG_SUPPORTS_NORMAL_SCREENS + * @hide */ boolean isSupportsNormalScreens(); /** * @see ApplicationInfo#FLAG_SUPPORTS_RTL + * @hide */ boolean isSupportsRtl(); @@ -1241,21 +1412,25 @@ public interface AndroidPackage { * * @see R.styleable#AndroidManifestSupportsScreens_smallScreens * @see ApplicationInfo#FLAG_SUPPORTS_SMALL_SCREENS + * @hide */ boolean isSupportsSmallScreens(); /** * @see ApplicationInfo#FLAG_SYSTEM + * @hide */ boolean isSystem(); /** * @see ApplicationInfo#PRIVATE_FLAG_SYSTEM_EXT + * @hide */ boolean isSystemExt(); /** * @see ApplicationInfo#FLAG_TEST_ONLY + * @hide */ boolean isTestOnly(); @@ -1265,26 +1440,31 @@ public interface AndroidPackage { * cpuAbiOverride is also set. * * @see R.attr#use32bitAbi + * @hide */ boolean isUse32BitAbi(); /** * @see ApplicationInfo#PRIVATE_FLAG_USE_EMBEDDED_DEX + * @hide */ boolean isUseEmbeddedDex(); /** * @see ApplicationInfo#FLAG_USES_CLEARTEXT_TRAFFIC + * @hide */ boolean isUsesCleartextTraffic(); /** * @see ApplicationInfo#PRIVATE_FLAG_USES_NON_SDK_API + * @hide */ boolean isUsesNonSdkApi(); /** * @see ApplicationInfo#PRIVATE_FLAG_VENDOR + * @hide */ boolean isVendor(); @@ -1294,11 +1474,13 @@ public interface AndroidPackage { * @see R.styleable#AndroidManifestActivity_visibleToInstantApps * @see R.styleable#AndroidManifestProvider_visibleToInstantApps * @see R.styleable#AndroidManifestService_visibleToInstantApps + * @hide */ boolean isVisibleToInstantApps(); /** * @see ApplicationInfo#FLAG_VM_SAFE_MODE + * @hide */ boolean isVmSafeMode(); } diff --git a/services/core/java/com/android/server/pm/pkg/PackageState.java b/services/core/java/com/android/server/pm/pkg/PackageState.java index 12e9671f301a..c0e063de5780 100644 --- a/services/core/java/com/android/server/pm/pkg/PackageState.java +++ b/services/core/java/com/android/server/pm/pkg/PackageState.java @@ -21,37 +21,20 @@ import android.annotation.Nullable; import android.annotation.Size; import android.annotation.UserIdInt; import android.content.pm.ApplicationInfo; -import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.SharedLibraryInfo; import android.content.pm.SigningInfo; import android.processor.immutability.Immutable; import android.util.SparseArray; -import com.android.server.pm.PackageSetting; -import com.android.server.pm.Settings; - import java.io.File; import java.util.List; import java.util.Map; import java.util.Set; /** - * The API surface for a {@link PackageSetting}. Methods are expected to return immutable objects. - * This may mean copying data on each invocation until related classes are refactored to be - * immutable. - * <p> - * Note that until immutability or read-only caching is enabled, {@link PackageSetting} cannot be - * returned directly, so {@link PackageStateImpl} is used to temporarily copy the data. This is a - * relatively expensive operation since it has to create an object for every package, but it's much - * lighter than the alternative of generating {@link PackageInfo} objects. - * <p> - * TODO: Documentation TODO: Currently missing, should be exposed as API? - * <ul> - * <li>keySetData</li> - * <li>installSource</li> - * <li>incrementalStates</li> - * </ul> + * The exposed system server process API for package data, shared with the internal + * PackageManagerService implementation. All returned data is guaranteed immutable. * * @hide */ @@ -59,28 +42,61 @@ import java.util.Set; @Immutable public interface PackageState { + // Methods below this comment are not yet exposed as API + + /* + * Until immutability or read-only caching is enabled, {@link PackageSetting} cannot be + * returned directly, so {@link PackageStateImpl} is used to temporarily copy the data. + * This is a relatively expensive operation since it has to create an object for every package, + * but it's much lighter than the alternative of generating {@link PackageInfo} objects. + * <p> + * TODO: Documentation + * TODO: Currently missing, should be exposed as API? + * - keySetData + * - installSource + * - incrementalStates + */ + + // Non-doc comment invisible to API consumers: + // Guidelines: + // - All return values should prefer non-null, immutable interfaces with only exposed getters + // - Unless null itself communicates something important + // - If the type is a Java collection type, it must be wrapped with unmodifiable + // - All type names must be non-suffixed, with any internal types being refactored to suffix + // with _Internal as necessary + // - No exposure of raw values that are overridden during parsing, such as CPU ABI + // - Mirroring another available system or public API is not enough justification to violate + // these guidelines + /** * This can be null whenever a physical APK on device is missing. This can be the result of * removing an external storage device where the APK resides. - * <p> - * This will result in the system reading the {@link PackageSetting} from disk, but without - * being able to parse the base APK's AndroidManifest.xml to read all of its metadata. The data - * that is written and read in {@link Settings} includes a minimal set of metadata needed to - * perform other checks in the system. - * <p> + * <p/> + * This will result in the system reading the state from disk, but without being able to parse + * the base APK's AndroidManifest.xml to read all of its metadata. The only available data that + * is written and read is the minimal set required to perform other checks in the system. + * <p/> * This is important in order to enforce uniqueness within the system, as the package, even if * on a removed storage device, is still considered installed. Another package of the same * application ID or declaring the same permissions or similar cannot be installed. - * <p> + * <p/> * Re-attaching the storage device to make the APK available should allow the user to use the * app once the device reboots or otherwise re-scans it. + * <p/> + * This can also occur in an device OTA situation where the package is no longer parseable on + * an updated SDK version, causing it to be rejectd, but the state associated with it retained, + * similarly to if the package had been uninstalled with the --keep-data option. + * + * @hide */ @Nullable AndroidPackage getAndroidPackage(); /** * The non-user-specific UID, or the UID if the user ID is - * {@link android.os.UserHandle#USER_SYSTEM}. + * {@link android.os.UserHandle#SYSTEM}. + * + * @hide */ int getAppId(); @@ -89,6 +105,7 @@ public interface PackageState { * applied if the application itself does not declare a category. * * @see AndroidPackage#getCategory() + * @hide */ int getCategoryOverride(); @@ -96,6 +113,8 @@ public interface PackageState { * The install time CPU override, if any. This value is written at install time * and doesn't change during the life of an install. If non-null, * {@link #getPrimaryCpuAbi()} will also contain the same value. + * + * @hide */ @Nullable String getCpuAbiOverride(); @@ -103,6 +122,8 @@ public interface PackageState { /** * In epoch milliseconds. The last modified time of the file directory which houses the app * APKs. Only updated on package update; does not track realtime modifications. + * + * @hide */ long getLastModifiedTime(); @@ -110,6 +131,8 @@ public interface PackageState { * An aggregation across the framework of the last time an app was used for a particular reason. * Keys are indexes into the array represented by {@link PackageManager.NotifyReason}, values * are in epoch milliseconds. + * + * @hide */ @Immutable.Ignore @Size(PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT) @@ -119,12 +142,15 @@ public interface PackageState { /** * In epoch milliseconds. The timestamp of the last time the package on device went through * an update package installation. + * + * @hide */ long getLastUpdateTime(); /** * Cached here in case the physical code directory on device is unmounted. * @see AndroidPackage#getLongVersionCode() + * @hide */ long getVersionCode(); @@ -132,37 +158,43 @@ public interface PackageState { * Maps mime group name to the set of Mime types in a group. Mime groups declared by app are * populated with empty sets at construction. Mime groups can not be created/removed at runtime, * thus keys in this map should not change. + * + * @hide */ @NonNull Map<String, Set<String>> getMimeGroups(); /** * @see AndroidPackage#getPackageName() + * @hide */ @NonNull String getPackageName(); /** - * TODO: Rename this to getCodePath * @see AndroidPackage#getPath() + * @hide */ @NonNull File getPath(); /** * @see ApplicationInfo#primaryCpuAbi + * @hide */ @Nullable String getPrimaryCpuAbi(); /** * @see ApplicationInfo#secondaryCpuAbi + * @hide */ @Nullable String getSecondaryCpuAbi(); /** * Whether the package shares the same user ID as other packages + * @hide */ boolean hasSharedUser(); @@ -172,13 +204,16 @@ public interface PackageState { * * @return the app ID of the shared user that this package is a part of, or -1 if it's not part * of a shared user. + * @hide */ int getSharedUserAppId(); + /** @hide */ @Immutable.Ignore @NonNull SigningInfo getSigningInfo(); + /** @hide */ @Immutable.Ignore @NonNull SparseArray<? extends PackageUserState> getUserStates(); @@ -186,6 +221,7 @@ public interface PackageState { /** * @return the result of {@link #getUserStates()}.get(userId) or * {@link PackageUserState#DEFAULT} if the state doesn't exist. + * @hide */ @NonNull default PackageUserState getUserStateOrDefault(@UserIdInt int userId) { @@ -197,12 +233,14 @@ public interface PackageState { * The actual files resolved for each shared library. * * @see R.styleable#AndroidManifestUsesLibrary + * @hide */ @NonNull List<String> getUsesLibraryFiles(); /** * @see R.styleable#AndroidManifestUsesLibrary + * @hide */ @Immutable.Ignore @NonNull @@ -210,6 +248,7 @@ public interface PackageState { /** * @see R.styleable#AndroidManifestUsesSdkLibrary + * @hide */ @Immutable.Ignore @NonNull @@ -217,6 +256,7 @@ public interface PackageState { /** * @see R.styleable#AndroidManifestUsesSdkLibrary_versionMajor + * @hide */ @Immutable.Ignore @NonNull @@ -224,6 +264,7 @@ public interface PackageState { /** * @see R.styleable#AndroidManifestUsesStaticLibrary + * @hide */ @Immutable.Ignore @NonNull @@ -231,6 +272,7 @@ public interface PackageState { /** * @see R.styleable#AndroidManifestUsesStaticLibrary_version + * @hide */ @Immutable.Ignore @NonNull @@ -238,18 +280,22 @@ public interface PackageState { /** * @see AndroidPackage#getVolumeUuid() + * @hide */ @Nullable String getVolumeUuid(); /** * @see AndroidPackage#isExternalStorage() + * @hide */ boolean isExternalStorage(); /** * Whether a package was installed --force-queryable such that it is always queryable by any * package, regardless of their manifest content. + * + * @hide */ boolean isForceQueryableOverride(); @@ -258,67 +304,82 @@ public interface PackageState { * * @see PackageManager#MATCH_HIDDEN_UNTIL_INSTALLED_COMPONENTS * @see PackageManager#setSystemAppState + * @hide */ boolean isHiddenUntilInstalled(); /** * @see com.android.server.pm.permission.UserPermissionState + * @hide */ boolean isInstallPermissionsFixed(); /** * @see AndroidPackage#isOdm() + * @hide */ boolean isOdm(); /** * @see AndroidPackage#isOem() + * @hide */ boolean isOem(); /** * @see AndroidPackage#isPrivileged() + * @hide */ boolean isPrivileged(); /** * @see AndroidPackage#isProduct() + * @hide */ boolean isProduct(); /** * @see ApplicationInfo#PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER + * @hide */ boolean isRequiredForSystemUser(); /** * @see AndroidPackage#isSystem() + * @hide */ boolean isSystem(); /** * @see AndroidPackage#isSystemExt() + * @hide */ boolean isSystemExt(); /** * Whether or not an update is available. Ostensibly only for instant apps. + * @hide */ boolean isUpdateAvailable(); /** * Whether this app is on the /data partition having been upgraded from a preinstalled app on a * system partition. + * + * @hide */ boolean isUpdatedSystemApp(); /** * Whether this app is packaged in an updated apex. + * + * @hide */ boolean isApkInUpdatedApex(); /** * @see AndroidPackage#isVendor() + * @hide */ boolean isVendor(); } 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 eac084228b81..28309c77f8cf 100644 --- a/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java +++ b/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java @@ -33,6 +33,7 @@ import com.android.server.pm.PackageSetting; import com.android.server.pm.Settings; import java.io.File; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; @@ -170,7 +171,7 @@ public class PackageStateImpl implements PackageState { mLastModifiedTime = pkgState.getLastModifiedTime(); mLastUpdateTime = pkgState.getLastUpdateTime(); mLongVersionCode = pkgState.getVersionCode(); - mMimeGroups = pkgState.getMimeGroups(); + mMimeGroups = Collections.unmodifiableMap(pkgState.getMimeGroups()); mPath = pkgState.getPath(); mPrimaryCpuAbi = pkgState.getPrimaryCpuAbi(); mSecondaryCpuAbi = pkgState.getSecondaryCpuAbi(); @@ -180,8 +181,8 @@ public class PackageStateImpl implements PackageState { mUsesSdkLibrariesVersionsMajor = pkgState.getUsesSdkLibrariesVersionsMajor(); mUsesStaticLibraries = pkgState.getUsesStaticLibraries(); mUsesStaticLibrariesVersions = pkgState.getUsesStaticLibrariesVersions(); - mUsesLibraryInfos = pkgState.getUsesLibraryInfos(); - mUsesLibraryFiles = pkgState.getUsesLibraryFiles(); + mUsesLibraryInfos = Collections.unmodifiableList(pkgState.getUsesLibraryInfos()); + mUsesLibraryFiles = Collections.unmodifiableList(pkgState.getUsesLibraryFiles()); setBoolean(Booleans.FORCE_QUERYABLE_OVERRIDE, pkgState.isForceQueryableOverride()); setBoolean(Booleans.HIDDEN_UNTIL_INSTALLED, pkgState.isHiddenUntilInstalled()); setBoolean(Booleans.INSTALL_PERMISSIONS_FIXED, pkgState.isInstallPermissionsFixed()); @@ -195,8 +196,8 @@ public class PackageStateImpl implements PackageState { int userStatesSize = userStates.size(); mUserStates = new SparseArray<>(userStatesSize); for (int index = 0; index < userStatesSize; index++) { - mUserStates.put(mUserStates.keyAt(index), - UserStateImpl.copy(mUserStates.valueAt(index))); + mUserStates.put(userStates.keyAt(index), + UserStateImpl.copy(userStates.valueAt(index))); } } 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 84799ea29423..8f5795bc47eb 100644 --- a/services/core/java/com/android/server/pm/pkg/PackageStateInternal.java +++ b/services/core/java/com/android/server/pm/pkg/PackageStateInternal.java @@ -31,6 +31,7 @@ import java.util.UUID; /** * Exposes internal types for internal usage of {@link PackageState}. + * @hide */ public interface PackageStateInternal extends PackageState { diff --git a/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java b/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java index 2c8b977b2bd6..1ae00d3c31f5 100644 --- a/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java +++ b/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java @@ -23,6 +23,7 @@ import android.annotation.Nullable; import android.content.pm.PackageManager; import android.content.pm.SharedLibraryInfo; +import com.android.internal.util.CollectionUtils; import com.android.internal.util.DataClass; import com.android.server.pm.PackageSetting; @@ -38,6 +39,7 @@ import java.util.stream.Collectors; * * These fields are also not copied into any cloned PackageSetting, to preserve the old behavior * where they would be lost implicitly by re-generating the package object. + * @hide */ @DataClass(genSetters = true, genConstructor = false, genBuilder = false) @DataClass.Suppress({"setLastPackageUsageTimeInMills", "setPackageSetting"}) @@ -69,6 +71,18 @@ public class PackageStateUnserialized { mPackageSetting = packageSetting; } + @NonNull + public PackageStateUnserialized addUsesLibraryInfo(@NonNull SharedLibraryInfo value) { + usesLibraryInfos = CollectionUtils.add(usesLibraryInfos, value); + return this; + } + + @NonNull + public PackageStateUnserialized addUsesLibraryFile(@NonNull String value) { + usesLibraryFiles = CollectionUtils.add(usesLibraryFiles, value); + return this; + } + private long[] lazyInitLastPackageUsageTimeInMills() { return new long[PackageManager.NOTIFY_PACKAGE_USE_REASONS_COUNT]; } diff --git a/services/core/java/com/android/server/pm/pkg/PackageStateUtils.java b/services/core/java/com/android/server/pm/pkg/PackageStateUtils.java index a883a059de0a..9749cfa6d82b 100644 --- a/services/core/java/com/android/server/pm/pkg/PackageStateUtils.java +++ b/services/core/java/com/android/server/pm/pkg/PackageStateUtils.java @@ -24,6 +24,7 @@ import android.util.SparseArray; import com.android.server.pm.pkg.component.ParsedMainComponent; +/** @hide */ public class PackageStateUtils { public static boolean isMatch(PackageState packageState, long flags) { 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 2d2538553bb6..a1b6f1d69751 100644 --- a/services/core/java/com/android/server/pm/pkg/PackageUserState.java +++ b/services/core/java/com/android/server/pm/pkg/PackageUserState.java @@ -26,9 +26,8 @@ import android.util.ArraySet; import java.util.Map; + /** - * The API surface for {@link PackageUserStateInternal}, for use by in-process mainline consumers. - * * The parent of this class is {@link PackageState}, which handles non-user state, exposing this * interface for per-user state. * @@ -36,123 +35,164 @@ import java.util.Map; */ // TODO(b/173807334): Expose API //@SystemApi(client = SystemApi.Client.SYSTEM_SERVER) -@Immutable.Ignore(reason = "Exposed through PackageState pending refactor") +@Immutable public interface PackageUserState { - /** @hide */ + /** + * @hide + */ @NonNull PackageUserState DEFAULT = PackageUserStateInternal.DEFAULT; /** * Combination of {@link #getOverlayPaths()} and {@link #getSharedLibraryOverlayPaths()} + * * @hide */ + @Immutable.Ignore @Nullable OverlayPaths getAllOverlayPaths(); /** * Credential encrypted /data partition inode. + * + * @hide */ long getCeDataInode(); /** * Fully qualified class names of components explicitly disabled. + * + * @hide */ @NonNull ArraySet<String> getDisabledComponents(); + /** + * @hide + */ @PackageManager.DistractionRestriction int getDistractionFlags(); /** * Fully qualified class names of components explicitly enabled. + * + * @hide */ @NonNull ArraySet<String> getEnabledComponents(); /** * Retrieve the effective enabled state of the package itself. + * + * @hide */ @PackageManager.EnabledState int getEnabledState(); /** + * @hide * @see PackageManager#setHarmfulAppWarning(String, CharSequence) */ @Nullable String getHarmfulAppWarning(); + /** + * @hide + */ @PackageManager.InstallReason int getInstallReason(); /** * Tracks the last calling package to set a specific enabled state for the package. + * + * @hide */ @Nullable String getLastDisableAppCaller(); - /** @hide */ + /** + * @hide + */ + @Immutable.Ignore @Nullable OverlayPaths getOverlayPaths(); - /** @hide */ + /** + * @hide + */ + @Immutable.Ignore @NonNull Map<String, OverlayPaths> getSharedLibraryOverlayPaths(); + /** + * @hide + */ @PackageManager.UninstallReason int getUninstallReason(); /** * @return whether the given fully qualified class name is explicitly enabled + * @hide */ boolean isComponentEnabled(@NonNull String componentName); /** * @return {@link #isComponentEnabled(String)} but for explicitly disabled + * @hide */ boolean isComponentDisabled(@NonNull String componentName); /** + * @hide * @see PackageManager#setApplicationHiddenSettingAsUser(String, boolean, UserHandle) */ boolean isHidden(); /** * @return whether the package is marked as installed for all users + * @hide */ boolean isInstalled(); /** * @return whether the package is marked as an ephemeral app, which restricts permissions, * features, visibility + * @hide */ boolean isInstantApp(); /** * @return whether the package has not been launched since being explicitly stopped + * @hide */ boolean isNotLaunched(); /** * @return whether the package has been stopped, which can occur if it's force-stopped, data * cleared, or just been installed + * @hide */ boolean isStopped(); /** * @return whether the package has been suspended, maybe by the device admin, disallowing its * launch + * @hide */ boolean isSuspended(); /** * @return whether the package was installed as a virtual preload, which may be done as part * of device infrastructure auto installation outside of the initial device image + * @hide */ boolean isVirtualPreload(); /** * The "package:type/entry" form of the theme resource ID previously set as the splash screen. + * + * @hide * @see android.window.SplashScreen#setSplashScreenTheme(int) * @see android.content.res.Resources#getResourceName(int) */ @@ -163,8 +203,10 @@ public interface PackageUserState { * In epoch milliseconds. The timestamp of the first install of the app of the particular user * on the device, surviving past app updates. Different users might have a different first * install time. - * + * <p/> * This does not survive full removal of the app (i.e., uninstalls for all users). + * + * @hide */ long getFirstInstallTime(); } 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 daa4545b4a4a..2d2e062961d2 100644 --- a/services/core/java/com/android/server/pm/pkg/PackageUserStateDefault.java +++ b/services/core/java/com/android/server/pm/pkg/PackageUserStateDefault.java @@ -30,6 +30,7 @@ import com.android.server.utils.WatchedArraySet; import java.util.Collections; import java.util.Map; +/** @hide */ class PackageUserStateDefault implements PackageUserStateInternal { @Override 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 da22b1796ac3..a536f90fea6b 100644 --- a/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java +++ b/services/core/java/com/android/server/pm/pkg/PackageUserStateImpl.java @@ -41,6 +41,7 @@ import java.util.Collections; import java.util.Map; import java.util.Objects; +/** @hide */ @DataClass(genConstructor = false, genBuilder = false, genEqualsHashCode = true) @DataClass.Suppress({"mOverlayPathsLock", "mOverlayPaths", "mSharedLibraryOverlayPathsLock", "mSharedLibraryOverlayPaths", "setOverlayPaths", "setCachedOverlayPaths"}) diff --git a/services/core/java/com/android/server/pm/pkg/PackageUserStateInternal.java b/services/core/java/com/android/server/pm/pkg/PackageUserStateInternal.java index 96225c012999..46cc830130ef 100644 --- a/services/core/java/com/android/server/pm/pkg/PackageUserStateInternal.java +++ b/services/core/java/com/android/server/pm/pkg/PackageUserStateInternal.java @@ -29,6 +29,8 @@ import com.android.server.utils.WatchedArraySet; * Internal variant of {@link PackageUserState} that includes data not exposed as API. This is * still read-only and should be used inside system server code when possible over the * implementation. + * + * @hide */ public interface PackageUserStateInternal extends PackageUserState, FrameworkPackageUserState { diff --git a/services/core/java/com/android/server/pm/pkg/SharedUserApi.java b/services/core/java/com/android/server/pm/pkg/SharedUserApi.java index 55c305ce812f..063f577bce5f 100644 --- a/services/core/java/com/android/server/pm/pkg/SharedUserApi.java +++ b/services/core/java/com/android/server/pm/pkg/SharedUserApi.java @@ -27,6 +27,7 @@ import com.android.server.pm.pkg.component.ParsedProcess; import java.util.List; +/** @hide */ public interface SharedUserApi { @NonNull diff --git a/services/tests/PackageManagerServiceTests/unit/Android.bp b/services/tests/PackageManagerServiceTests/unit/Android.bp index 1bcc3d1f70ad..1c6ba33bd279 100644 --- a/services/tests/PackageManagerServiceTests/unit/Android.bp +++ b/services/tests/PackageManagerServiceTests/unit/Android.bp @@ -35,6 +35,7 @@ android_test { "kotlin-reflect", "services.core", "servicestests-utils", + "servicestests-core-utils", "truth-prebuilt", ], platform_apis: true, diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt index 5361041c4aff..b41fd39b355c 100644 --- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt +++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/AndroidPackageTest.kt @@ -23,7 +23,6 @@ import android.content.pm.FeatureGroupInfo import android.content.pm.FeatureInfo import android.content.pm.PackageManager import android.content.pm.SigningDetails -import com.android.server.pm.pkg.parsing.ParsingPackage import android.net.Uri import android.os.Bundle import android.os.Parcelable @@ -65,6 +64,7 @@ class AndroidPackageTest : ParcelableComponentTest(AndroidPackage::class, Packag "addMimeGroupsFromComponent", "assignDerivedFields", "assignDerivedFields2", + "makeImmutable", "buildFakeForDeletion", "buildAppClassNamesByProcess", "capPermissionPriorities", @@ -219,6 +219,7 @@ class AndroidPackageTest : ParcelableComponentTest(AndroidPackage::class, Packag AndroidPackage::isNativeLibraryRootRequiresIsa, AndroidPackage::isOdm, AndroidPackage::isOem, + AndroidPackage::isOnBackInvokedCallbackEnabled, AndroidPackage::isOverlay, AndroidPackage::isOverlayIsStatic, AndroidPackage::isPartiallyDirectBootAware, @@ -279,7 +280,7 @@ class AndroidPackageTest : ParcelableComponentTest(AndroidPackage::class, Packag adder(AndroidPackage::getUsesOptionalNativeLibraries, "testUsesOptionalNativeLibrary"), getSetByValue( AndroidPackage::areAttributionsUserVisible, - ParsingPackage::setAttributionsAreUserVisible, + PackageImpl::setAttributionsAreUserVisible, true ), getSetByValue2( @@ -513,11 +514,6 @@ class AndroidPackageTest : ParcelableComponentTest(AndroidPackage::class, Packag } ), getter(AndroidPackage::getKnownActivityEmbeddingCerts, setOf("TESTEMBEDDINGCERT")), - getSetByValue( - AndroidPackage::isOnBackInvokedCallbackEnabled, - ParsingPackage::setOnBackInvokedCallbackEnabled, - true - ) ) override fun initialObject() = PackageImpl.forParsing( @@ -560,10 +556,13 @@ class AndroidPackageTest : ParcelableComponentTest(AndroidPackage::class, Packag .setSplitHasCode(1, false) .setSplitClassLoaderName(0, "testSplitClassLoaderNameZero") .setSplitClassLoaderName(1, "testSplitClassLoaderNameOne") - .addUsesSdkLibrary("testSdk", 2L, arrayOf("testCertDigest1")) .addUsesStaticLibrary("testStatic", 3L, arrayOf("testCertDigest2")) + override fun finalizeObject(parcelable: Parcelable) { + (parcelable as PackageImpl).hideAsParsed().hideAsFinal() + } + override fun extraAssertions(before: Parcelable, after: Parcelable) { super.extraAssertions(before, after) after as PackageImpl diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableComponentTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableComponentTest.kt index e16a1871f8b8..37bb9354df1c 100644 --- a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableComponentTest.kt +++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/parsing/parcelling/ParcelableComponentTest.kt @@ -293,12 +293,21 @@ abstract class ParcelableComponentTest( first?.let { property(it) } == second?.let { property(it) } } - @Test - fun valueComparison() { + fun buildBefore(): Pair<List<Param>, Parcelable> { val params = baseParams.mapNotNull(::buildParams) + extraParams().filterNotNull() val before = initialObject() params.forEach { it.setFunction(arrayOf(before, it.value())) } + finalizeObject(before) + return params to before + } + + protected open fun finalizeObject(parcelable: Parcelable) { + } + + @Test + fun valueComparison() { + val (params, before) = buildBefore() val parcel = Parcel.obtain() writeToParcel(parcel, before) @@ -307,6 +316,15 @@ abstract class ParcelableComponentTest( parcel.setDataPosition(0) + val baseline = initialObject() + finalizeObject(baseline) + + val baselineParcel = Parcel.obtain() + writeToParcel(baselineParcel, baseline) + + // Check that something substantial actually changed in the test object + expect.that(parcel.dataSize()).isGreaterThan(baselineParcel.dataSize()) + val after = creator.createFromParcel(parcel) expect.withMessage("Mismatched write and read data sizes") @@ -314,6 +332,7 @@ abstract class ParcelableComponentTest( .isEqualTo(dataSize) parcel.recycle() + baselineParcel.recycle() runAssertions(params, before, after) } diff --git a/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/pkg/PackageStateTest.kt b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/pkg/PackageStateTest.kt new file mode 100644 index 000000000000..7e9e433c29ac --- /dev/null +++ b/services/tests/PackageManagerServiceTests/unit/src/com/android/server/pm/test/pkg/PackageStateTest.kt @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2022 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.server.pm.test.pkg + +import android.content.Intent +import android.content.pm.overlay.OverlayPaths +import android.content.pm.PackageManager +import android.content.pm.PathPermission +import android.content.pm.SharedLibraryInfo +import android.content.pm.VersionedPackage +import android.os.PatternMatcher +import android.util.ArraySet +import com.android.server.pm.PackageSetting +import com.android.server.pm.PackageSettingBuilder +import com.android.server.pm.parsing.pkg.PackageImpl +import com.android.server.pm.pkg.AndroidPackage +import com.android.server.pm.pkg.PackageState +import com.android.server.pm.pkg.PackageStateImpl +import com.android.server.pm.pkg.PackageUserState +import com.android.server.pm.pkg.PackageUserStateImpl +import com.android.server.pm.pkg.component.ParsedActivity +import com.android.server.pm.pkg.component.ParsedActivityImpl +import com.android.server.pm.pkg.component.ParsedComponentImpl +import com.android.server.pm.pkg.component.ParsedInstrumentation +import com.android.server.pm.pkg.component.ParsedIntentInfoImpl +import com.android.server.pm.pkg.component.ParsedPermission +import com.android.server.pm.pkg.component.ParsedPermissionGroup +import com.android.server.pm.pkg.component.ParsedPermissionImpl +import com.android.server.pm.pkg.component.ParsedProcess +import com.android.server.pm.pkg.component.ParsedProcessImpl +import com.android.server.pm.pkg.component.ParsedProvider +import com.android.server.pm.pkg.component.ParsedProviderImpl +import com.android.server.pm.pkg.component.ParsedService +import com.android.server.pm.test.parsing.parcelling.AndroidPackageTest +import com.google.common.truth.Expect +import org.junit.Rule +import org.junit.Test +import org.junit.rules.TemporaryFolder +import kotlin.contracts.ExperimentalContracts +import kotlin.reflect.KClass +import kotlin.reflect.KFunction +import kotlin.reflect.KType +import kotlin.reflect.full.isSubtypeOf +import kotlin.reflect.full.memberFunctions +import kotlin.reflect.full.starProjectedType + +class PackageStateTest { + + companion object { + private val IGNORED_TYPES = listOf( + "java.io.File", + "java.lang.Boolean", + "java.lang.Byte", + "java.lang.CharSequence", + "java.lang.Character", + "java.lang.Double", + "java.lang.Float", + "java.lang.Integer", + "java.lang.Long", + "java.lang.Short", + "java.lang.String", + "java.lang.Void", + ) + // STOPSHIP: Remove these and fix the implementations + private val IGNORED_FUNCTIONS = listOf( + ParsedActivity::getIntents, + ParsedActivity::getKnownActivityEmbeddingCerts, + ParsedActivity::getProperties, + ParsedInstrumentation::getIntents, + ParsedInstrumentation::getIntents, + ParsedInstrumentation::getProperties, + ParsedInstrumentation::getProperties, + ParsedPermission::getIntents, + ParsedPermission::getProperties, + ParsedPermissionGroup::getIntents, + ParsedPermissionGroup::getProperties, + ParsedProcess::getAppClassNamesByPackage, + ParsedProvider::getIntents, + ParsedProvider::getPathPermissions, + ParsedProvider::getProperties, + ParsedProvider::getUriPermissionPatterns, + ParsedService::getIntents, + ParsedService::getProperties, + SharedLibraryInfo::getAllCodePaths, + SharedLibraryInfo::getDependencies, + Intent::getCategories, + PackageUserState::getDisabledComponents, + PackageUserState::getEnabledComponents, + PackageUserState::getSharedLibraryOverlayPaths, + OverlayPaths::getOverlayPaths, + OverlayPaths::getResourceDirs, + ) + } + + @get:Rule + val tempFolder = TemporaryFolder() + + @get:Rule + val expect = Expect.create() + + private val collectionType = MutableCollection::class.starProjectedType + private val mapType = Map::class.starProjectedType + + @OptIn(ExperimentalContracts::class) + @Test + fun collectionImmutability() { + val seenTypes = mutableSetOf<KType>() + val (_, pkg) = AndroidPackageTest().buildBefore() + val packageState = PackageSettingBuilder() + .setPackage(pkg as AndroidPackage) + .setCodePath(tempFolder.newFile().path) + .build() + + fillMissingData(packageState, pkg as PackageImpl) + + visitType(seenTypes, emptyList(), PackageStateImpl.copy(packageState), + PackageState::class.starProjectedType) + visitType(seenTypes, emptyList(), pkg, AndroidPackage::class.starProjectedType) + visitType(seenTypes, emptyList(), packageState.getUserStateOrDefault(0), + PackageUserState::class.starProjectedType) + + // Don't check empties for defaults since their collections will always be empty + visitType(seenTypes, emptyList(), PackageUserState.DEFAULT, + PackageUserState::class.starProjectedType, enforceNonEmpty = false) + + // Check that some minimum number of functions were validated, + // in case the type checking breaks somehow + expect.that(seenTypes.size).isGreaterThan(10) + } + + /** + * Fill fields in [PackageState] and its children that are not filled by [AndroidPackageTest]. + * Real objects and real invocations of the live APIs are necessary to ensure that the test + * mirrors real device behavior. + */ + private fun fillMissingData(pkgSetting: PackageSetting, pkg: PackageImpl) { + pkgSetting.addUsesLibraryFile("usesLibraryFile") + pkgSetting.addUsesLibraryInfo(SharedLibraryInfo( + "path", + "packageName", + listOf(tempFolder.newFile().path), + "name", + 1, + 0, + VersionedPackage("versionedPackage0", 1), + listOf(VersionedPackage("versionedPackage1", 2)), + emptyList(), + false + )) + pkgSetting.addMimeTypes("mimeGroup", setOf("mimeType")) + pkgSetting.getOrCreateUserState(0).apply { + setEnabledComponents(ArraySet<String>().apply { add("com.test.EnabledComponent") }) + setDisabledComponents(ArraySet<String>().apply { add("com.test.DisabledComponent") }) + setSharedLibraryOverlayPaths("sharedLibrary", + OverlayPaths.Builder().addApkPath("/test/overlay.apk").build()) + } + + val property = PackageManager.Property("propertyName", 1, "com.test", null) + listOf( + pkg.activities, + pkg.receivers, + pkg.providers, + pkg.services, + pkg.instrumentations, + pkg.permissions, + pkg.permissionGroups + ).map { it.first() as ParsedComponentImpl } + .forEach { + it.addIntent(ParsedIntentInfoImpl()) + it.addProperty(property) + } + + (pkg.activities.first() as ParsedActivityImpl).knownActivityEmbeddingCerts = + setOf("TESTEMBEDDINGCERT") + + (pkg.permissions.first() as ParsedPermissionImpl).knownCerts = setOf("TESTEMBEDDINGCERT") + + (pkg.providers.first() as ParsedProviderImpl).apply { + addPathPermission(PathPermission("pattern", PatternMatcher.PATTERN_LITERAL, + "readPermission", "writerPermission")) + addUriPermissionPattern(PatternMatcher("*", PatternMatcher.PATTERN_LITERAL)) + } + + (pkg.processes.values.first() as ParsedProcessImpl).apply { + deniedPermissions = setOf("deniedPermission") + putAppClassNameForPackage("package", "className") + } + } + + private fun visitType( + seenTypes: MutableSet<KType>, + parentChain: List<String>, + impl: Any, + type: KType, + enforceNonEmpty: Boolean = true + ) { + if (!seenTypes.add(type)) return + val kClass = type.classifier as KClass<*> + val qualifiedName = kClass.qualifiedName!! + if (IGNORED_TYPES.contains(qualifiedName)) return + + val newChain = parentChain + kClass.simpleName!! + val newChainText = newChain.joinToString() + + val filteredFunctions = kClass.memberFunctions + .filter { + // Size 1 because the impl receiver counts as a parameter + it.parameters.size == 1 + } + .filterNot(IGNORED_FUNCTIONS::contains) + + filteredFunctions.filter { it.returnType.isSubtypeOf(collectionType) } + .forEach { + val collection = it.call(impl) + if (collection as? MutableCollection<*> == null) { + expect.withMessage("Method $newChainText ${it.name} cannot return null") + .fail() + return@forEach + } + + val value = try { + collection.stream().findFirst().get()!! + } catch (e: Exception) { + if (enforceNonEmpty) { + expect.withMessage("Method $newChainText ${it.name} returns empty") + .that(e) + .isNull() + return@forEach + } else null + } + + if (value != null) { + it.returnType.arguments.forEach { + visitType(seenTypes, newChain, value, it.type!!) + } + } + + // Must test clear last in case it works and actually clears the collection + expectUnsupported(newChain, it) { collection.clear() } + } + filteredFunctions.filter { it.returnType.isSubtypeOf(mapType) } + .forEach { + val map = it.call(impl) + if (map as? MutableMap<*, *> == null) { + expect.withMessage("Method $newChainText ${it.name} cannot return null") + .fail() + return@forEach + } + + val entry = try { + map.entries.stream().findFirst().get()!! + } catch (e: Exception) { + expect.withMessage("Method $newChainText ${it.name} returns empty") + .that(e) + .isNull() + return@forEach + } + + visitType(seenTypes, newChain, entry.key!!, it.returnType.arguments[0].type!!) + visitType(seenTypes, newChain, entry.value!!, it.returnType.arguments[1].type!!) + + // Must test clear last in case it works and actually clears the map + expectUnsupported(newChain, it) { map.clear() } + } + } + + private fun expectUnsupported( + parentChain: List<String>, + function: KFunction<*>, + block: () -> Unit + ) { + val exception = try { + block() + null + } catch (e: UnsupportedOperationException) { + e + } + + expect.withMessage("Method ${parentChain.joinToString()} $function doesn't throw") + .that(exception) + .isNotNull() + } +}
\ No newline at end of file |