Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6add2584 authored by Winson's avatar Winson Committed by Winson Chiu
Browse files

Add PackageState#getApexModuleName

Tracks the name of the APEX module for both APEX and APK-in-APEX
PackageStates.

This involves inferring the module name from the ActiveApexInfo
associated with each APEX scan partition. This is set on each
APK found in that parition and also set on disabled settings
for a package where the APK-in-APEX has been updated to a /data
variant.

The test also validates that clearing the APEX from the system
image will also un-associate the apexModuleName, since it
downgrades the package to a regular non-system, non-APK-in-APEX
/data package.

Also adds a package dump --include-apex option to print APEX
PackageStates like any other regular APK.

Bug: 261913353

Test: atest ApexUpdateTest

Change-Id: Ic2806a4df8eac4843d9d3358a349b3d335a7455b
parent b3fb718c
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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
+2 −0
Original line number Diff line number Diff line
@@ -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;
+1 −0
Original line number Diff line number Diff line
@@ -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;

+9 −17
Original line number Diff line number Diff line
@@ -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);
        }
+56 −14
Original line number Diff line number Diff line
@@ -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 {
Loading