diff options
22 files changed, 369 insertions, 55 deletions
diff --git a/services/core/java/com/android/server/pm/ApexManager.java b/services/core/java/com/android/server/pm/ApexManager.java index 71593e10d45b..5e62b56c7bcd 100644 --- a/services/core/java/com/android/server/pm/ApexManager.java +++ b/services/core/java/com/android/server/pm/ApexManager.java @@ -138,7 +138,7 @@ public abstract class ApexManager { this.activeApexChanged = activeApexChanged; } - private ActiveApexInfo(ApexInfo apexInfo) { + public ActiveApexInfo(ApexInfo apexInfo) { this( apexInfo.moduleName, new File(Environment.getApexDirectory() + File.separator diff --git a/services/core/java/com/android/server/pm/DumpHelper.java b/services/core/java/com/android/server/pm/DumpHelper.java index 3385a09e49db..fcaaa90dbc8a 100644 --- a/services/core/java/com/android/server/pm/DumpHelper.java +++ b/services/core/java/com/android/server/pm/DumpHelper.java @@ -111,6 +111,8 @@ final class DumpHelper { dumpState.setOptionEnabled(DumpState.OPTION_DUMP_ALL_COMPONENTS); } else if ("-f".equals(opt)) { dumpState.setOptionEnabled(DumpState.OPTION_SHOW_FILTERS); + } else if ("--include-apex".equals(opt)) { + dumpState.setOptionEnabled(DumpState.OPTION_INCLUDE_APEX); } else if ("--proto".equals(opt)) { dumpProto(snapshot, fd); return; diff --git a/services/core/java/com/android/server/pm/DumpState.java b/services/core/java/com/android/server/pm/DumpState.java index 6225753cc38f..0bdce21f885f 100644 --- a/services/core/java/com/android/server/pm/DumpState.java +++ b/services/core/java/com/android/server/pm/DumpState.java @@ -51,6 +51,7 @@ public final class DumpState { public static final int OPTION_SHOW_FILTERS = 1 << 0; public static final int OPTION_DUMP_ALL_COMPONENTS = 1 << 1; public static final int OPTION_SKIP_PERMISSIONS = 1 << 2; + public static final int OPTION_INCLUDE_APEX = 1 << 3; private int mTypes; diff --git a/services/core/java/com/android/server/pm/InitAppsHelper.java b/services/core/java/com/android/server/pm/InitAppsHelper.java index 6825dd7832ce..5c4447eb99a4 100644 --- a/services/core/java/com/android/server/pm/InitAppsHelper.java +++ b/services/core/java/com/android/server/pm/InitAppsHelper.java @@ -21,11 +21,9 @@ import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; import static com.android.internal.util.FrameworkStatsLog.BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_DATA_APP_AVG_SCAN_TIME; import static com.android.internal.util.FrameworkStatsLog.BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_SYSTEM_APP_AVG_SCAN_TIME; import static com.android.server.pm.PackageManagerService.SCAN_AS_APK_IN_APEX; -import static com.android.server.pm.PackageManagerService.SCAN_AS_FACTORY; import static com.android.server.pm.PackageManagerService.SCAN_AS_PRIVILEGED; import static com.android.server.pm.PackageManagerService.SCAN_AS_SYSTEM; import static com.android.server.pm.PackageManagerService.SCAN_BOOTING; -import static com.android.server.pm.PackageManagerService.SCAN_DROP_CACHE; import static com.android.server.pm.PackageManagerService.SCAN_FIRST_BOOT_OR_UPGRADE; import static com.android.server.pm.PackageManagerService.SCAN_INITIAL; import static com.android.server.pm.PackageManagerService.SCAN_NO_DEX; @@ -147,14 +145,7 @@ final class InitAppsHelper { sp.getFolder().getAbsolutePath()) || apexInfo.preInstalledApexPath.getAbsolutePath().startsWith( sp.getFolder().getAbsolutePath() + File.separator)) { - int additionalScanFlag = SCAN_AS_APK_IN_APEX; - if (apexInfo.isFactory) { - additionalScanFlag |= SCAN_AS_FACTORY; - } - if (apexInfo.activeApexChanged) { - additionalScanFlag |= SCAN_DROP_CACHE; - } - return new ScanPartition(apexInfo.apexDirectory, sp, additionalScanFlag); + return new ScanPartition(apexInfo.apexDirectory, sp, apexInfo); } } return null; @@ -266,7 +257,7 @@ final class InitAppsHelper { } scanDirTracedLI(mPm.getAppInstallDir(), 0, - mScanFlags | SCAN_REQUIRE_KNOWN, packageParser, mExecutorService); + mScanFlags | SCAN_REQUIRE_KNOWN, packageParser, mExecutorService, null); List<Runnable> unfinishedTasks = mExecutorService.shutdownNow(); if (!unfinishedTasks.isEmpty()) { @@ -335,12 +326,12 @@ final class InitAppsHelper { } scanDirTracedLI(partition.getOverlayFolder(), mSystemParseFlags, mSystemScanFlags | partition.scanFlag, - packageParser, executorService); + packageParser, executorService, partition.apexInfo); } scanDirTracedLI(frameworkDir, mSystemParseFlags, mSystemScanFlags | SCAN_NO_DEX | SCAN_AS_PRIVILEGED, - packageParser, executorService); + packageParser, executorService, null); if (!mPm.mPackages.containsKey("android")) { throw new IllegalStateException( "Failed to load frameworks package; check log for warnings"); @@ -352,11 +343,11 @@ final class InitAppsHelper { scanDirTracedLI(partition.getPrivAppFolder(), mSystemParseFlags, mSystemScanFlags | SCAN_AS_PRIVILEGED | partition.scanFlag, - packageParser, executorService); + packageParser, executorService, partition.apexInfo); } scanDirTracedLI(partition.getAppFolder(), mSystemParseFlags, mSystemScanFlags | partition.scanFlag, - packageParser, executorService); + packageParser, executorService, partition.apexInfo); } } @@ -373,7 +364,8 @@ final class InitAppsHelper { @GuardedBy({"mPm.mInstallLock", "mPm.mLock"}) private void scanDirTracedLI(File scanDir, int parseFlags, int scanFlags, - PackageParser2 packageParser, ExecutorService executorService) { + PackageParser2 packageParser, ExecutorService executorService, + @Nullable ApexManager.ActiveApexInfo apexInfo) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir [" + scanDir.getAbsolutePath() + "]"); try { if ((scanFlags & SCAN_AS_APK_IN_APEX) != 0) { @@ -381,7 +373,7 @@ final class InitAppsHelper { parseFlags |= PARSE_APK_IN_APEX; } mInstallPackageHelper.installPackagesFromDir(scanDir, parseFlags, - scanFlags, packageParser, executorService); + scanFlags, packageParser, executorService, apexInfo); } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index 28a074b4e5d4..4e5f77f82d8a 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -367,10 +367,11 @@ final class InstallPackageHelper { if ((scanFlags & SCAN_AS_APK_IN_APEX) != 0) { boolean isFactory = (scanFlags & SCAN_AS_FACTORY) != 0; - pkgSetting.getPkgState().setApkInApex(true); pkgSetting.getPkgState().setApkInUpdatedApex(!isFactory); } + pkgSetting.getPkgState().setApexModuleName(request.getApexModuleName()); + // TODO(toddke): Consider a method specifically for modifying the Package object // post scan; or, moving this stuff out of the Package object since it has nothing // to do with the package on disk. @@ -1716,6 +1717,7 @@ final class InstallPackageHelper { + ", old=" + oldPackage); } request.setReturnCode(PackageManager.INSTALL_SUCCEEDED); + request.setApexModuleName(oldPackageState.getApexModuleName()); targetParseFlags = systemParseFlags; targetScanFlags = systemScanFlags; } else { // non system replace @@ -3172,7 +3174,7 @@ final class InstallPackageHelper { final RemovePackageHelper removePackageHelper = new RemovePackageHelper(mPm); removePackageHelper.removePackage(stubPkg, true /*chatty*/); try { - return scanSystemPackageTracedLI(scanFile, parseFlags, scanFlags); + return scanSystemPackageTracedLI(scanFile, parseFlags, scanFlags, null); } catch (PackageManagerException e) { Slog.w(TAG, "Failed to install compressed system package:" + stubPkg.getPackageName(), e); @@ -3304,7 +3306,7 @@ final class InstallPackageHelper { | ParsingPackageUtils.PARSE_IS_SYSTEM_DIR; @PackageManagerService.ScanFlags int scanFlags = mPm.getSystemPackageScanFlags(codePath); final AndroidPackage pkg = scanSystemPackageTracedLI( - codePath, parseFlags, scanFlags); + codePath, parseFlags, scanFlags, null); synchronized (mPm.mLock) { PackageSetting pkgSetting = mPm.mSettings.getPackageLPr(pkg.getPackageName()); @@ -3484,7 +3486,7 @@ final class InstallPackageHelper { try { final File codePath = new File(pkg.getPath()); synchronized (mPm.mInstallLock) { - scanSystemPackageTracedLI(codePath, 0, scanFlags); + scanSystemPackageTracedLI(codePath, 0, scanFlags, null); } } catch (PackageManagerException e) { Slog.e(TAG, "Failed to parse updated, ex-system package: " @@ -3563,7 +3565,8 @@ final class InstallPackageHelper { if (throwable == null) { try { - addForInitLI(parseResult.parsedPackage, newParseFlags, newScanFlags, null); + addForInitLI(parseResult.parsedPackage, newParseFlags, newScanFlags, null, + new ApexManager.ActiveApexInfo(ai)); AndroidPackage pkg = parseResult.parsedPackage.hideAsFinal(); if (ai.isFactory && !ai.isActive) { disableSystemPackageLPw(pkg); @@ -3585,8 +3588,8 @@ final class InstallPackageHelper { @GuardedBy({"mPm.mInstallLock", "mPm.mLock"}) public void installPackagesFromDir(File scanDir, int parseFlags, - int scanFlags, PackageParser2 packageParser, - ExecutorService executorService) { + int scanFlags, PackageParser2 packageParser, ExecutorService executorService, + @Nullable ApexManager.ActiveApexInfo apexInfo) { final File[] files = scanDir.listFiles(); if (ArrayUtils.isEmpty(files)) { Log.d(TAG, "No files in app dir " + scanDir); @@ -3634,7 +3637,7 @@ final class InstallPackageHelper { } try { addForInitLI(parseResult.parsedPackage, parseFlags, scanFlags, - new UserHandle(UserHandle.USER_SYSTEM)); + new UserHandle(UserHandle.USER_SYSTEM), apexInfo); } catch (PackageManagerException e) { errorCode = e.error; errorMsg = "Failed to scan " + parseResult.scanFile + ": " + e.getMessage(); @@ -3697,7 +3700,7 @@ final class InstallPackageHelper { try { synchronized (mPm.mInstallLock) { final AndroidPackage newPkg = scanSystemPackageTracedLI( - scanFile, reparseFlags, rescanFlags); + scanFile, reparseFlags, rescanFlags, null); // We rescanned a stub, add it to the list of stubbed system packages if (newPkg.isStub()) { stubSystemApps.add(packageName); @@ -3716,10 +3719,11 @@ final class InstallPackageHelper { */ @GuardedBy("mPm.mInstallLock") public AndroidPackage scanSystemPackageTracedLI(File scanFile, final int parseFlags, - int scanFlags) throws PackageManagerException { + int scanFlags, @Nullable ApexManager.ActiveApexInfo apexInfo) + throws PackageManagerException { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage [" + scanFile.toString() + "]"); try { - return scanSystemPackageLI(scanFile, parseFlags, scanFlags); + return scanSystemPackageLI(scanFile, parseFlags, scanFlags, apexInfo); } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } @@ -3730,7 +3734,8 @@ final class InstallPackageHelper { * Returns {@code null} in case of errors and the error code is stored in mLastScanError */ @GuardedBy("mPm.mInstallLock") - private AndroidPackage scanSystemPackageLI(File scanFile, int parseFlags, int scanFlags) + private AndroidPackage scanSystemPackageLI(File scanFile, int parseFlags, int scanFlags, + @Nullable ApexManager.ActiveApexInfo apexInfo) throws PackageManagerException { if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile); @@ -3748,7 +3753,7 @@ final class InstallPackageHelper { } return addForInitLI(parsedPackage, parseFlags, scanFlags, - new UserHandle(UserHandle.USER_SYSTEM)); + new UserHandle(UserHandle.USER_SYSTEM), apexInfo); } /** @@ -3768,7 +3773,26 @@ final class InstallPackageHelper { private AndroidPackage addForInitLI(ParsedPackage parsedPackage, @ParsingPackageUtils.ParseFlags int parseFlags, @PackageManagerService.ScanFlags int scanFlags, - @Nullable UserHandle user) throws PackageManagerException { + @Nullable UserHandle user, @Nullable ApexManager.ActiveApexInfo activeApexInfo) + throws PackageManagerException { + PackageSetting disabledPkgSetting; + synchronized (mPm.mLock) { + disabledPkgSetting = + mPm.mSettings.getDisabledSystemPkgLPr(parsedPackage.getPackageName()); + if (activeApexInfo != null && disabledPkgSetting != null) { + // When a disabled system package is scanned, its final PackageSetting is actually + // skipped and not added to any data structures, instead relying on the disabled + // setting read from the persisted Settings XML file. This persistence does not + // include the APEX module name, so here, re-set it from the active APEX info. + // + // This also has the (beneficial) side effect where if a package disappears from an + // APEX, leaving only a /data copy, it will lose its apexModuleName. + // + // This must be done before scanSystemPackageLI as that will throw in the case of a + // system -> data package. + disabledPkgSetting.setApexModuleName(activeApexInfo.apexModuleName); + } + } final Pair<ScanResult, Boolean> scanResultPair = scanSystemPackageLI( parsedPackage, parseFlags, scanFlags, user); @@ -3777,6 +3801,24 @@ final class InstallPackageHelper { final InstallRequest installRequest = new InstallRequest( parsedPackage, parseFlags, scanFlags, user, scanResult); + String existingApexModuleName = null; + synchronized (mPm.mLock) { + var existingPkgSetting = mPm.mSettings.getPackageLPr(parsedPackage.getPackageName()); + if (existingPkgSetting != null) { + existingApexModuleName = existingPkgSetting.getApexModuleName(); + } + } + + if (activeApexInfo != null) { + installRequest.setApexModuleName(activeApexInfo.apexModuleName); + } else { + if (disabledPkgSetting != null) { + installRequest.setApexModuleName(disabledPkgSetting.getApexModuleName()); + } else if (existingApexModuleName != null) { + installRequest.setApexModuleName(existingApexModuleName); + } + } + synchronized (mPm.mLock) { boolean appIdCreated = false; try { diff --git a/services/core/java/com/android/server/pm/InstallRequest.java b/services/core/java/com/android/server/pm/InstallRequest.java index 878c1c159797..e6d99eb66291 100644 --- a/services/core/java/com/android/server/pm/InstallRequest.java +++ b/services/core/java/com/android/server/pm/InstallRequest.java @@ -44,6 +44,7 @@ import android.util.Slog; import com.android.server.pm.parsing.pkg.ParsedPackage; 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.parsing.ParsingPackageUtils; @@ -107,6 +108,12 @@ final class InstallRequest { @Nullable private ApexInfo mApexInfo; + /** + * For tracking {@link PackageState#getApexModuleName()}. + */ + @Nullable + private String mApexModuleName; + @Nullable private ScanResult mScanResult; @@ -348,6 +355,11 @@ final class InstallRequest { } @Nullable + public String getApexModuleName() { + return mApexModuleName; + } + + @Nullable public String getSourceInstallerPackageName() { return mInstallArgs.mInstallSource.mInstallerPackageName; } @@ -644,6 +656,10 @@ final class InstallRequest { mApexInfo = apexInfo; } + public void setApexModuleName(@Nullable String apexModuleName) { + mApexModuleName = apexModuleName; + } + public void setPkg(AndroidPackage pkg) { mPkg = pkg; } diff --git a/services/core/java/com/android/server/pm/InstallingSession.java b/services/core/java/com/android/server/pm/InstallingSession.java index 439b54259554..8fa74ef431f9 100644 --- a/services/core/java/com/android/server/pm/InstallingSession.java +++ b/services/core/java/com/android/server/pm/InstallingSession.java @@ -609,6 +609,7 @@ class InstallingSession { // processApkInstallRequests() fails. Need a way to keep info stored in apexd // and PMS in sync in the face of install failures. request.setApexInfo(apexInfo); + request.setApexModuleName(apexInfo.moduleName); mPm.mHandler.post(() -> processApkInstallRequests(true, requests)); return; } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 92bbb7e86327..9cc03340b08d 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -716,7 +716,7 @@ public class PackageManagerService implements PackageSender, TestUtilityService * The list of all system partitions that may contain packages in ascending order of * specificity (the more generic, the earlier in the list a partition appears). */ - @VisibleForTesting(visibility = Visibility.PRIVATE) + @VisibleForTesting(visibility = Visibility.PACKAGE) public static final List<ScanPartition> SYSTEM_PARTITIONS = Collections.unmodifiableList( PackagePartitions.getOrderedPartitions(ScanPartition::new)); diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java index 6562de96388f..53fdfaad38ac 100644 --- a/services/core/java/com/android/server/pm/PackageSetting.java +++ b/services/core/java/com/android/server/pm/PackageSetting.java @@ -1262,6 +1262,12 @@ public class PackageSetting extends SettingBase implements PackageStateInternal return pkgState.isApkInUpdatedApex(); } + @Nullable + @Override + public String getApexModuleName() { + return pkgState.getApexModuleName(); + } + public PackageSetting setDomainSetId(@NonNull UUID domainSetId) { mDomainSetId = domainSetId; onChanged(); @@ -1317,6 +1323,11 @@ public class PackageSetting extends SettingBase implements PackageStateInternal return this; } + public PackageSetting setApexModuleName(@Nullable String apexModuleName) { + pkgState.setApexModuleName(apexModuleName); + return this; + } + @NonNull @Override public PackageStateUnserialized getTransientState() { diff --git a/services/core/java/com/android/server/pm/ScanPartition.java b/services/core/java/com/android/server/pm/ScanPartition.java index e1d2b3bcfefe..9ee6035f6f1a 100644 --- a/services/core/java/com/android/server/pm/ScanPartition.java +++ b/services/core/java/com/android/server/pm/ScanPartition.java @@ -16,13 +16,17 @@ package com.android.server.pm; +import static com.android.server.pm.PackageManagerService.SCAN_AS_APK_IN_APEX; +import static com.android.server.pm.PackageManagerService.SCAN_AS_FACTORY; import static com.android.server.pm.PackageManagerService.SCAN_AS_ODM; import static com.android.server.pm.PackageManagerService.SCAN_AS_OEM; import static com.android.server.pm.PackageManagerService.SCAN_AS_PRODUCT; import static com.android.server.pm.PackageManagerService.SCAN_AS_SYSTEM_EXT; import static com.android.server.pm.PackageManagerService.SCAN_AS_VENDOR; +import static com.android.server.pm.PackageManagerService.SCAN_DROP_CACHE; import android.annotation.NonNull; +import android.annotation.Nullable; import android.content.pm.PackagePartitions; import com.android.internal.annotations.VisibleForTesting; @@ -32,14 +36,18 @@ import java.io.File; /** * List of partitions to be scanned during system boot */ -@VisibleForTesting +@VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) public class ScanPartition extends PackagePartitions.SystemPartition { @PackageManagerService.ScanFlags public final int scanFlag; + @Nullable + public final ApexManager.ActiveApexInfo apexInfo; + public ScanPartition(@NonNull PackagePartitions.SystemPartition partition) { super(partition); scanFlag = scanFlagForPartition(partition); + apexInfo = null; } /** @@ -48,9 +56,21 @@ public class ScanPartition extends PackagePartitions.SystemPartition { * partition along with any specified additional scan flags. */ public ScanPartition(@NonNull File folder, @NonNull ScanPartition original, - @PackageManagerService.ScanFlags int additionalScanFlag) { + @Nullable ApexManager.ActiveApexInfo apexInfo) { super(folder, original); - this.scanFlag = original.scanFlag | additionalScanFlag; + var scanFlags = original.scanFlag; + this.apexInfo = apexInfo; + if (apexInfo != null) { + scanFlags |= SCAN_AS_APK_IN_APEX; + if (apexInfo.isFactory) { + scanFlags |= SCAN_AS_FACTORY; + } + if (apexInfo.activeApexChanged) { + scanFlags |= SCAN_DROP_CACHE; + } + } + //noinspection WrongConstant + this.scanFlag = scanFlags; } private static int scanFlagForPartition(PackagePartitions.SystemPartition partition) { diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index 97fb0c2e3fe9..aedf78255422 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -5052,6 +5052,7 @@ public final class Settings implements Watchable, Snappable { pw.print(prefix); pw.print(" privatePkgFlags="); printFlags(pw, ps.getPrivateFlags(), PRIVATE_FLAG_DUMP_SPEC); pw.println(); + pw.print(prefix); pw.print(" apexModuleName="); pw.println(ps.getApexModuleName()); if (pkg != null && pkg.getOverlayTarget() != null) { pw.print(prefix); pw.print(" overlayTarget="); pw.println(pkg.getOverlayTarget()); @@ -5263,7 +5264,8 @@ public final class Settings implements Watchable, Snappable { && !packageName.equals(ps.getPackageName())) { continue; } - if (ps.getPkg() != null && ps.getPkg().isApex()) { + if (ps.getPkg() != null && ps.getPkg().isApex() + && !dumpState.isOptionEnabled(DumpState.OPTION_INCLUDE_APEX)) { // Filter APEX packages which will be dumped in the APEX section continue; } @@ -5319,7 +5321,8 @@ public final class Settings implements Watchable, Snappable { && !packageName.equals(ps.getPackageName())) { continue; } - if (ps.getPkg() != null && ps.getPkg().isApex()) { + if (ps.getPkg() != null && ps.getPkg().isApex() + && !dumpState.isOptionEnabled(DumpState.OPTION_INCLUDE_APEX)) { // Filter APEX packages which will be dumped in the APEX section continue; } diff --git a/services/core/java/com/android/server/pm/StorageEventHelper.java b/services/core/java/com/android/server/pm/StorageEventHelper.java index 4f7c2bdf3057..23156d177abf 100644 --- a/services/core/java/com/android/server/pm/StorageEventHelper.java +++ b/services/core/java/com/android/server/pm/StorageEventHelper.java @@ -158,7 +158,7 @@ public final class StorageEventHelper extends StorageEventListener { final AndroidPackage pkg; try { pkg = installPackageHelper.scanSystemPackageTracedLI( - ps.getPath(), parseFlags, SCAN_INITIAL); + ps.getPath(), parseFlags, SCAN_INITIAL, null); loaded.add(pkg); } catch (PackageManagerException e) { 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 5fdead0a8883..a12c9d0498a1 100644 --- a/services/core/java/com/android/server/pm/pkg/PackageState.java +++ b/services/core/java/com/android/server/pm/pkg/PackageState.java @@ -417,4 +417,11 @@ public interface PackageState { * @hide */ boolean isVendor(); + + /** + * The name of the APEX module containing this package, if it is an APEX or APK-in-APEX. + * @hide + */ + @Nullable + String getApexModuleName(); } 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 8dee8ee2fa57..bc6dab41fc7e 100644 --- a/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java +++ b/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java @@ -154,6 +154,8 @@ public class PackageStateImpl implements PackageState { private final SigningInfo mSigningInfo; @NonNull private final SparseArray<PackageUserState> mUserStates; + @Nullable + private final String mApexModuleName; private PackageStateImpl(@NonNull PackageState pkgState, @Nullable AndroidPackage pkg) { mAndroidPackage = pkg; @@ -206,6 +208,8 @@ public class PackageStateImpl implements PackageState { mUserStates.put(userStates.keyAt(index), UserStateImpl.copy(userStates.valueAt(index))); } + + mApexModuleName = pkgState.getApexModuleName(); } @NonNull @@ -714,6 +718,11 @@ public class PackageStateImpl implements PackageState { } @DataClass.Generated.Member + public @Nullable String getApexModuleName() { + return mApexModuleName; + } + + @DataClass.Generated.Member public @NonNull PackageStateImpl setBooleans( int value) { mBooleans = value; return this; @@ -723,7 +732,7 @@ public class PackageStateImpl implements PackageState { time = 1671671043929L, codegenVersion = "1.0.23", sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/PackageStateImpl.java", - inputSignatures = "private int mBooleans\nprivate final @android.annotation.Nullable com.android.server.pm.pkg.AndroidPackage mAndroidPackage\nprivate final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.Nullable java.lang.String mVolumeUuid\nprivate final int mAppId\nprivate final int mCategoryOverride\nprivate final @android.annotation.Nullable java.lang.String mCpuAbiOverride\nprivate final @android.content.pm.ApplicationInfo.HiddenApiEnforcementPolicy int mHiddenApiEnforcementPolicy\nprivate final long mLastModifiedTime\nprivate final long mLastUpdateTime\nprivate final long mLongVersionCode\nprivate final @android.annotation.NonNull java.util.Map<java.lang.String,java.util.Set<java.lang.String>> mMimeGroups\nprivate final @android.annotation.NonNull java.io.File mPath\nprivate final @android.annotation.Nullable java.lang.String mPrimaryCpuAbi\nprivate final @android.annotation.Nullable java.lang.String mSecondaryCpuAbi\nprivate final @android.annotation.Nullable java.lang.String mSeInfo\nprivate final boolean mHasSharedUser\nprivate final int mSharedUserAppId\nprivate final @android.annotation.NonNull java.lang.String[] mUsesSdkLibraries\nprivate final @android.annotation.NonNull long[] mUsesSdkLibrariesVersionsMajor\nprivate final @android.annotation.NonNull java.lang.String[] mUsesStaticLibraries\nprivate final @android.annotation.NonNull long[] mUsesStaticLibrariesVersions\nprivate final @android.annotation.NonNull java.util.List<com.android.server.pm.pkg.SharedLibrary> mUsesLibraries\nprivate final @android.annotation.NonNull java.util.List<java.lang.String> mUsesLibraryFiles\nprivate final @android.annotation.NonNull long[] mLastPackageUsageTime\nprivate final @android.annotation.NonNull android.content.pm.SigningInfo mSigningInfo\nprivate final @android.annotation.NonNull android.util.SparseArray<com.android.server.pm.pkg.PackageUserState> mUserStates\npublic static com.android.server.pm.pkg.PackageState copy(com.android.server.pm.pkg.PackageStateInternal)\nprivate void setBoolean(int,boolean)\nprivate boolean getBoolean(int)\npublic @android.annotation.NonNull @java.lang.Override com.android.server.pm.pkg.PackageUserState getStateForUser(android.os.UserHandle)\npublic @java.lang.Override boolean isExternalStorage()\npublic @java.lang.Override boolean isForceQueryableOverride()\npublic @java.lang.Override boolean isHiddenUntilInstalled()\npublic @java.lang.Override boolean isInstallPermissionsFixed()\npublic @java.lang.Override boolean isOdm()\npublic @java.lang.Override boolean isOem()\npublic @java.lang.Override boolean isPrivileged()\npublic @java.lang.Override boolean isProduct()\npublic @java.lang.Override boolean isRequiredForSystemUser()\npublic @java.lang.Override boolean isSystem()\npublic @java.lang.Override boolean isSystemExt()\npublic @java.lang.Override boolean isUpdateAvailable()\npublic @java.lang.Override boolean isUpdatedSystemApp()\npublic @java.lang.Override boolean isApkInUpdatedApex()\npublic @java.lang.Override boolean isVendor()\npublic @java.lang.Override long getVersionCode()\npublic @java.lang.Override boolean hasSharedUser()\npublic @java.lang.Override boolean isApex()\nclass PackageStateImpl extends java.lang.Object implements [com.android.server.pm.pkg.PackageState]\nprivate static final int SYSTEM\nprivate static final int EXTERNAL_STORAGE\nprivate static final int PRIVILEGED\nprivate static final int OEM\nprivate static final int VENDOR\nprivate static final int PRODUCT\nprivate static final int SYSTEM_EXT\nprivate static final int REQUIRED_FOR_SYSTEM_USER\nprivate static final int ODM\nprivate static final int FORCE_QUERYABLE_OVERRIDE\nprivate static final int HIDDEN_UNTIL_INSTALLED\nprivate static final int INSTALL_PERMISSIONS_FIXED\nprivate static final int UPDATE_AVAILABLE\nprivate static final int UPDATED_SYSTEM_APP\nprivate static final int APK_IN_UPDATED_APEX\nclass Booleans extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false)") + inputSignatures = "private int mBooleans\nprivate final @android.annotation.Nullable com.android.server.pm.pkg.AndroidPackage mAndroidPackage\nprivate final @android.annotation.NonNull java.lang.String mPackageName\nprivate final @android.annotation.Nullable java.lang.String mVolumeUuid\nprivate final int mAppId\nprivate final int mCategoryOverride\nprivate final @android.annotation.Nullable java.lang.String mCpuAbiOverride\nprivate final @android.content.pm.ApplicationInfo.HiddenApiEnforcementPolicy int mHiddenApiEnforcementPolicy\nprivate final long mLastModifiedTime\nprivate final long mLastUpdateTime\nprivate final long mLongVersionCode\nprivate final @android.annotation.NonNull java.util.Map<java.lang.String,java.util.Set<java.lang.String>> mMimeGroups\nprivate final @android.annotation.NonNull java.io.File mPath\nprivate final @android.annotation.Nullable java.lang.String mPrimaryCpuAbi\nprivate final @android.annotation.Nullable java.lang.String mSecondaryCpuAbi\nprivate final @android.annotation.Nullable java.lang.String mSeInfo\nprivate final boolean mHasSharedUser\nprivate final int mSharedUserAppId\nprivate final @android.annotation.NonNull java.lang.String[] mUsesSdkLibraries\nprivate final @android.annotation.NonNull long[] mUsesSdkLibrariesVersionsMajor\nprivate final @android.annotation.NonNull java.lang.String[] mUsesStaticLibraries\nprivate final @android.annotation.NonNull long[] mUsesStaticLibrariesVersions\nprivate final @android.annotation.NonNull java.util.List<com.android.server.pm.pkg.SharedLibrary> mUsesLibraries\nprivate final @android.annotation.NonNull java.util.List<java.lang.String> mUsesLibraryFiles\nprivate final @android.annotation.NonNull long[] mLastPackageUsageTime\nprivate final @android.annotation.NonNull android.content.pm.SigningInfo mSigningInfo\nprivate final @android.annotation.NonNull android.util.SparseArray<com.android.server.pm.pkg.PackageUserState> mUserStates\nprivate final @android.annotation.Nullable java.lang.String mApexModuleName\npublic static com.android.server.pm.pkg.PackageState copy(com.android.server.pm.pkg.PackageStateInternal)\nprivate void setBoolean(int,boolean)\nprivate boolean getBoolean(int)\npublic @android.annotation.NonNull @java.lang.Override com.android.server.pm.pkg.PackageUserState getStateForUser(android.os.UserHandle)\npublic @java.lang.Override boolean isExternalStorage()\npublic @java.lang.Override boolean isForceQueryableOverride()\npublic @java.lang.Override boolean isHiddenUntilInstalled()\npublic @java.lang.Override boolean isInstallPermissionsFixed()\npublic @java.lang.Override boolean isOdm()\npublic @java.lang.Override boolean isOem()\npublic @java.lang.Override boolean isPrivileged()\npublic @java.lang.Override boolean isProduct()\npublic @java.lang.Override boolean isRequiredForSystemUser()\npublic @java.lang.Override boolean isSystem()\npublic @java.lang.Override boolean isSystemExt()\npublic @java.lang.Override boolean isUpdateAvailable()\npublic @java.lang.Override boolean isUpdatedSystemApp()\npublic @java.lang.Override boolean isApkInUpdatedApex()\npublic @java.lang.Override boolean isVendor()\npublic @java.lang.Override long getVersionCode()\npublic @java.lang.Override boolean hasSharedUser()\npublic @java.lang.Override boolean isApex()\nclass PackageStateImpl extends java.lang.Object implements [com.android.server.pm.pkg.PackageState]\nprivate static final int SYSTEM\nprivate static final int EXTERNAL_STORAGE\nprivate static final int PRIVILEGED\nprivate static final int OEM\nprivate static final int VENDOR\nprivate static final int PRODUCT\nprivate static final int SYSTEM_EXT\nprivate static final int REQUIRED_FOR_SYSTEM_USER\nprivate static final int ODM\nprivate static final int FORCE_QUERYABLE_OVERRIDE\nprivate static final int HIDDEN_UNTIL_INSTALLED\nprivate static final int INSTALL_PERMISSIONS_FIXED\nprivate static final int UPDATE_AVAILABLE\nprivate static final int UPDATED_SYSTEM_APP\nprivate static final int APK_IN_UPDATED_APEX\nclass Booleans extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genConstructor=false)") @Deprecated private void __metadata() {} 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 57fbfe91193b..19c08866e348 100644 --- a/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java +++ b/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java @@ -54,7 +54,6 @@ public class PackageStateUnserialized { private List<String> usesLibraryFiles = emptyList(); private boolean updatedSystemApp; - private boolean apkInApex; private boolean apkInUpdatedApex; @NonNull @@ -70,6 +69,9 @@ public class PackageStateUnserialized { @NonNull private final PackageSetting mPackageSetting; + @Nullable + private String mApexModuleName; + public PackageStateUnserialized(@NonNull PackageSetting packageSetting) { mPackageSetting = packageSetting; } @@ -138,11 +140,11 @@ public class PackageStateUnserialized { } this.updatedSystemApp = other.updatedSystemApp; - this.apkInApex = other.apkInApex; this.apkInUpdatedApex = other.apkInUpdatedApex; this.lastPackageUsageTimeInMills = other.lastPackageUsageTimeInMills; this.overrideSeInfo = other.overrideSeInfo; this.seInfo = other.seInfo; + this.mApexModuleName = other.mApexModuleName; mPackageSetting.onChanged(); } @@ -187,12 +189,6 @@ public class PackageStateUnserialized { return this; } - public PackageStateUnserialized setApkInApex(boolean value) { - apkInApex = value; - mPackageSetting.onChanged(); - return this; - } - public PackageStateUnserialized setApkInUpdatedApex(boolean value) { apkInUpdatedApex = value; mPackageSetting.onChanged(); @@ -218,6 +214,13 @@ public class PackageStateUnserialized { return this; } + @NonNull + public PackageStateUnserialized setApexModuleName(@NonNull String value) { + mApexModuleName = value; + mPackageSetting.onChanged(); + return this; + } + // Code below generated by codegen v1.0.23. @@ -254,11 +257,6 @@ public class PackageStateUnserialized { } @DataClass.Generated.Member - public boolean isApkInApex() { - return apkInApex; - } - - @DataClass.Generated.Member public boolean isApkInUpdatedApex() { return apkInUpdatedApex; } @@ -292,11 +290,16 @@ public class PackageStateUnserialized { return mPackageSetting; } + @DataClass.Generated.Member + public @Nullable String getApexModuleName() { + return mApexModuleName; + } + @DataClass.Generated( - time = 1666291743725L, + time = 1671483772254L, codegenVersion = "1.0.23", sourceFile = "frameworks/base/services/core/java/com/android/server/pm/pkg/PackageStateUnserialized.java", - inputSignatures = "private boolean hiddenUntilInstalled\nprivate @android.annotation.NonNull java.util.List<com.android.server.pm.pkg.SharedLibraryWrapper> usesLibraryInfos\nprivate @android.annotation.NonNull java.util.List<java.lang.String> usesLibraryFiles\nprivate boolean updatedSystemApp\nprivate boolean apkInApex\nprivate boolean apkInUpdatedApex\nprivate volatile @android.annotation.NonNull long[] lastPackageUsageTimeInMills\nprivate @android.annotation.Nullable java.lang.String overrideSeInfo\nprivate @android.annotation.NonNull java.lang.String seInfo\nprivate final @android.annotation.NonNull com.android.server.pm.PackageSetting mPackageSetting\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageStateUnserialized addUsesLibraryInfo(com.android.server.pm.pkg.SharedLibraryWrapper)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageStateUnserialized addUsesLibraryFile(java.lang.String)\nprivate long[] lazyInitLastPackageUsageTimeInMills()\npublic com.android.server.pm.pkg.PackageStateUnserialized setLastPackageUsageTimeInMills(int,long)\npublic long getLatestPackageUseTimeInMills()\npublic long getLatestForegroundPackageUseTimeInMills()\npublic void updateFrom(com.android.server.pm.pkg.PackageStateUnserialized)\npublic @android.annotation.NonNull java.util.List<android.content.pm.SharedLibraryInfo> getNonNativeUsesLibraryInfos()\npublic com.android.server.pm.pkg.PackageStateUnserialized setHiddenUntilInstalled(boolean)\npublic com.android.server.pm.pkg.PackageStateUnserialized setUsesLibraryInfos(java.util.List<android.content.pm.SharedLibraryInfo>)\npublic com.android.server.pm.pkg.PackageStateUnserialized setUsesLibraryFiles(java.util.List<java.lang.String>)\npublic com.android.server.pm.pkg.PackageStateUnserialized setUpdatedSystemApp(boolean)\npublic com.android.server.pm.pkg.PackageStateUnserialized setApkInApex(boolean)\npublic com.android.server.pm.pkg.PackageStateUnserialized setApkInUpdatedApex(boolean)\npublic com.android.server.pm.pkg.PackageStateUnserialized setLastPackageUsageTimeInMills(long)\npublic com.android.server.pm.pkg.PackageStateUnserialized setOverrideSeInfo(java.lang.String)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageStateUnserialized setSeInfo(java.lang.String)\nclass PackageStateUnserialized extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genSetters=true, genConstructor=false, genBuilder=false)") + inputSignatures = "private boolean hiddenUntilInstalled\nprivate @android.annotation.NonNull java.util.List<com.android.server.pm.pkg.SharedLibraryWrapper> usesLibraryInfos\nprivate @android.annotation.NonNull java.util.List<java.lang.String> usesLibraryFiles\nprivate boolean updatedSystemApp\nprivate boolean apkInUpdatedApex\nprivate volatile @android.annotation.NonNull long[] lastPackageUsageTimeInMills\nprivate @android.annotation.Nullable java.lang.String overrideSeInfo\nprivate @android.annotation.NonNull java.lang.String seInfo\nprivate final @android.annotation.NonNull com.android.server.pm.PackageSetting mPackageSetting\nprivate @android.annotation.Nullable java.lang.String mApexModuleName\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageStateUnserialized addUsesLibraryInfo(com.android.server.pm.pkg.SharedLibraryWrapper)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageStateUnserialized addUsesLibraryFile(java.lang.String)\nprivate long[] lazyInitLastPackageUsageTimeInMills()\npublic com.android.server.pm.pkg.PackageStateUnserialized setLastPackageUsageTimeInMills(int,long)\npublic long getLatestPackageUseTimeInMills()\npublic long getLatestForegroundPackageUseTimeInMills()\npublic void updateFrom(com.android.server.pm.pkg.PackageStateUnserialized)\npublic @android.annotation.NonNull java.util.List<android.content.pm.SharedLibraryInfo> getNonNativeUsesLibraryInfos()\npublic com.android.server.pm.pkg.PackageStateUnserialized setHiddenUntilInstalled(boolean)\npublic com.android.server.pm.pkg.PackageStateUnserialized setUsesLibraryInfos(java.util.List<android.content.pm.SharedLibraryInfo>)\npublic com.android.server.pm.pkg.PackageStateUnserialized setUsesLibraryFiles(java.util.List<java.lang.String>)\npublic com.android.server.pm.pkg.PackageStateUnserialized setUpdatedSystemApp(boolean)\npublic com.android.server.pm.pkg.PackageStateUnserialized setApkInUpdatedApex(boolean)\npublic com.android.server.pm.pkg.PackageStateUnserialized setLastPackageUsageTimeInMills(long)\npublic com.android.server.pm.pkg.PackageStateUnserialized setOverrideSeInfo(java.lang.String)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageStateUnserialized setSeInfo(java.lang.String)\npublic @android.annotation.NonNull com.android.server.pm.pkg.PackageStateUnserialized setApexModuleName(java.lang.String)\nclass PackageStateUnserialized extends java.lang.Object implements []\n@com.android.internal.util.DataClass(genSetters=true, genConstructor=false, genBuilder=false)") @Deprecated private void __metadata() {} diff --git a/services/tests/PackageManagerServiceTests/host/Android.bp b/services/tests/PackageManagerServiceTests/host/Android.bp index 83677c2a2242..47e7a37e9352 100644 --- a/services/tests/PackageManagerServiceTests/host/Android.bp +++ b/services/tests/PackageManagerServiceTests/host/Android.bp @@ -30,11 +30,16 @@ java_test_host { "truth-prebuilt", ], static_libs: [ + "ApexInstallHelper", "cts-host-utils", "frameworks-base-hostutils", "PackageManagerServiceHostTestsIntentVerifyUtils", ], test_suites: ["general-tests"], + data: [ + ":PackageManagerTestApex", + ":PackageManagerTestApexApp", + ], java_resources: [ ":PackageManagerTestOverlayActor", ":PackageManagerTestOverlay", diff --git a/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/ApexUpdateTest.kt b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/ApexUpdateTest.kt new file mode 100644 index 000000000000..44b4e303565c --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/src/com/android/server/pm/test/ApexUpdateTest.kt @@ -0,0 +1,117 @@ +/* + * 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 + +import com.android.modules.testing.utils.ApexInstallHelper +import com.android.tradefed.invoker.TestInformation +import com.android.tradefed.testtype.DeviceJUnit4ClassRunner +import com.android.tradefed.testtype.junit4.BaseHostJUnit4Test +import com.android.tradefed.testtype.junit4.BeforeClassWithInfo +import com.google.common.truth.Truth.assertThat +import org.junit.After +import org.junit.AfterClass +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@RunWith(DeviceJUnit4ClassRunner::class) +class ApexUpdateTest : BaseHostJUnit4Test() { + + companion object { + private const val APEX_NAME = "com.android.server.pm.test.apex" + private const val APK_IN_APEX_NAME = "$APEX_NAME.app" + private const val APK_FILE_NAME = "PackageManagerTestApexApp.apk" + + private lateinit var apexInstallHelper: ApexInstallHelper + + @JvmStatic + @BeforeClassWithInfo + fun initApexHelper(testInformation: TestInformation) { + apexInstallHelper = ApexInstallHelper(testInformation) + } + + @JvmStatic + @AfterClass + fun revertChanges() { + apexInstallHelper.revertChanges() + } + } + + @Before + @After + fun uninstallApp() { + device.uninstallPackage(APK_IN_APEX_NAME) + } + + @Test + fun apexModuleName() { + // Install the test APEX and assert it's returned as the APEX module itself + // (null when not --include-apex) + apexInstallHelper.pushApexAndReboot("PackageManagerTestApex.apex") + assertModuleName(APEX_NAME).isNull() + assertModuleName(APEX_NAME, includeApex = true).isEqualTo(APEX_NAME) + + // Check the APK-in-APEX, ensuring there is only 1 active package + assertModuleName(APK_IN_APEX_NAME).isEqualTo(APEX_NAME) + assertModuleName(APK_IN_APEX_NAME, hidden = true).isNull() + + // Then install a /data update to the APK-in-APEX + device.installPackage(testInformation.getDependencyFile(APK_FILE_NAME, false), false) + + // Verify same as above + assertModuleName(APEX_NAME, includeApex = true).isEqualTo(APEX_NAME) + assertModuleName(APK_IN_APEX_NAME).isEqualTo(APEX_NAME) + + // But also check that the /data variant now has a hidden package + assertModuleName(APK_IN_APEX_NAME, hidden = true).isEqualTo(APEX_NAME) + + // Reboot the device and check that values are preserved + device.reboot() + assertModuleName(APEX_NAME, includeApex = true).isEqualTo(APEX_NAME) + assertModuleName(APK_IN_APEX_NAME).isEqualTo(APEX_NAME) + assertModuleName(APK_IN_APEX_NAME, hidden = true).isEqualTo(APEX_NAME) + + // Revert the install changes (delete system image APEX) and check that it's gone + apexInstallHelper.revertChanges() + assertModuleName(APEX_NAME, includeApex = true).isNull() + + // Verify the module name is no longer associated with the APK-in-APEX, + // which is now just a regular /data APK with no hidden system variant. + // The assertion for the valid /data APK uses "null" because the value + // printed for normal packages is "apexModuleName=null". As opposed to + // a literal null indicating the package variant doesn't exist + assertModuleName(APK_IN_APEX_NAME).isEqualTo("null") + assertModuleName(APK_IN_APEX_NAME, hidden = true).isEqualTo(null) + } + + private fun assertModuleName( + packageName: String, + hidden: Boolean = false, + includeApex: Boolean = false + ) = assertThat( + device.executeShellCommand( + "dumpsys package ${"--include-apex".takeIf { includeApex }} $packageName" + ) + .lineSequence() + .map(String::trim) + .dropWhile { !it.startsWith(if (hidden) "Hidden system packages:" else "Packages:")} + .dropWhile { !it.startsWith("Package [$packageName]") } + .takeWhile { !it.startsWith("User 0:") } + .firstOrNull { it.startsWith("apexModuleName=") } + ?.removePrefix("apexModuleName=") + ) +} diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/Apex/Android.bp b/services/tests/PackageManagerServiceTests/host/test-apps/Apex/Android.bp new file mode 100644 index 000000000000..aef365e9d5fc --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/test-apps/Apex/Android.bp @@ -0,0 +1,40 @@ +// +// 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 { + default_applicable_licenses: ["Android-Apache-2.0"], +} + +apex { + name: "PackageManagerTestApex", + apps: ["PackageManagerTestApexApp"], + androidManifest: "AndroidManifestApex.xml", + file_contexts: ":apex.test-file_contexts", + key: "apex.test.key", + certificate: ":apex.test.certificate", + min_sdk_version: "33", + installable: true, + updatable: true, +} + +android_test_helper_app { + name: "PackageManagerTestApexApp", + manifest: "AndroidManifestApp.xml", + sdk_version: "33", + min_sdk_version: "33", + apex_available: ["PackageManagerTestApex"], + certificate: ":apex.test.certificate", +} diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/Apex/AndroidManifestApex.xml b/services/tests/PackageManagerServiceTests/host/test-apps/Apex/AndroidManifestApex.xml new file mode 100644 index 000000000000..575b2bc74940 --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/test-apps/Apex/AndroidManifestApex.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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. + --> + +<manifest package="com.android.server.pm.test.apex"> + <application/> +</manifest> diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/Apex/AndroidManifestApp.xml b/services/tests/PackageManagerServiceTests/host/test-apps/Apex/AndroidManifestApp.xml new file mode 100644 index 000000000000..87fb5cc2c14a --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/test-apps/Apex/AndroidManifestApp.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + ~ 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. + --> + +<manifest package="com.android.server.pm.test.apex.app"> + <application/> +</manifest> diff --git a/services/tests/PackageManagerServiceTests/host/test-apps/Apex/apex_manifest.json b/services/tests/PackageManagerServiceTests/host/test-apps/Apex/apex_manifest.json new file mode 100644 index 000000000000..b89581d1e0ca --- /dev/null +++ b/services/tests/PackageManagerServiceTests/host/test-apps/Apex/apex_manifest.json @@ -0,0 +1,4 @@ +{ + "name": "com.android.server.pm.test.apex", + "version": 1 +} diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java b/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java index 2f909aa7b191..5b0e2f3800c3 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java +++ b/services/tests/mockingservicestests/src/com/android/server/pm/ApexManagerTest.java @@ -518,6 +518,7 @@ public class ApexManagerTest { apexInfo.isActive = isActive; apexInfo.isFactory = isFactory; apexInfo.modulePath = apexFile.getPath(); + apexInfo.preinstalledModulePath = apexFile.getPath(); return apexInfo; } |