diff options
5 files changed, 504 insertions, 479 deletions
diff --git a/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java b/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java index 239a9d7151c7..fac73f553826 100644 --- a/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java +++ b/services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java @@ -16,13 +16,10 @@ package com.android.server.pm; -import static android.content.pm.PackageManager.INSTALL_SUCCEEDED; -import static android.content.pm.parsing.ApkLiteParseUtils.isApkFile; 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.DEBUG_PACKAGE_SCANNING; import static com.android.server.pm.PackageManagerService.SCAN_AS_APK_IN_APEX; import static com.android.server.pm.PackageManagerService.SCAN_AS_PRIVILEGED; import static com.android.server.pm.PackageManagerService.SCAN_AS_SYSTEM; @@ -33,23 +30,18 @@ import static com.android.server.pm.PackageManagerService.SCAN_NO_DEX; import static com.android.server.pm.PackageManagerService.SCAN_REQUIRE_KNOWN; import static com.android.server.pm.PackageManagerService.SYSTEM_PARTITIONS; import static com.android.server.pm.PackageManagerService.TAG; -import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo; import android.annotation.Nullable; -import android.content.pm.ApplicationInfo; -import android.content.pm.PackageManager; import android.content.pm.parsing.ParsingPackageUtils; import android.os.Environment; import android.os.SystemClock; import android.os.Trace; import android.util.ArrayMap; import android.util.EventLog; -import android.util.Log; import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.content.om.OverlayConfig; -import com.android.internal.util.ArrayUtils; import com.android.internal.util.FrameworkStatsLog; import com.android.server.EventLogTags; import com.android.server.pm.parsing.PackageCacher; @@ -69,13 +61,12 @@ import java.util.concurrent.ExecutorService; */ final class InitAndSystemPackageHelper { private final PackageManagerService mPm; - private final RemovePackageHelper mRemovePackageHelper; - private final AppDataHelper mAppDataHelper; private final List<ScanPartition> mDirsToScanAsSystem; private final int mScanFlags; private final int mSystemParseFlags; private final int mSystemScanFlags; + private final InstallPackageHelper mInstallPackageHelper; /** * Tracks new system packages [received in an OTA] that we expect to @@ -85,11 +76,9 @@ final class InitAndSystemPackageHelper { private final ArrayMap<String, File> mExpectingBetter = new ArrayMap<>(); // TODO(b/198166813): remove PMS dependency - InitAndSystemPackageHelper(PackageManagerService pm, RemovePackageHelper removePackageHelper, - AppDataHelper appDataHelper) { + InitAndSystemPackageHelper(PackageManagerService pm) { mPm = pm; - mRemovePackageHelper = removePackageHelper; - mAppDataHelper = appDataHelper; + mInstallPackageHelper = new InstallPackageHelper(pm); mDirsToScanAsSystem = getSystemScanPartitions(); // Set flag to monitor and not change apk file paths when scanning install directories. int scanFlags = SCAN_BOOTING | SCAN_INITIAL; @@ -158,61 +147,6 @@ final class InitAndSystemPackageHelper { consumer -> mPm.forEachPackage( pkg -> consumer.accept(pkg, pkg.isSystem(), apkInApexPreInstalledPaths.get(pkg.getPackageName())))); - cleanupSystemPackagesAndInstallStubs(packageParser, executorService, packageSettings, - startTime, userIds); - packageParser.close(); - return overlayConfig; - } - /** - * First part of init dir scanning - */ - @GuardedBy({"mPm.mInstallLock", "mPm.mLock"}) - private void scanSystemDirs(PackageParser2 packageParser, ExecutorService executorService) { - File frameworkDir = new File(Environment.getRootDirectory(), "framework"); - - // Collect vendor/product/system_ext overlay packages. (Do this before scanning - // any apps.) - // For security and version matching reason, only consider overlay packages if they - // reside in the right directory. - for (int i = mDirsToScanAsSystem.size() - 1; i >= 0; i--) { - final ScanPartition partition = mDirsToScanAsSystem.get(i); - if (partition.getOverlayFolder() == null) { - continue; - } - scanDirTracedLI(partition.getOverlayFolder(), mSystemParseFlags, - mSystemScanFlags | partition.scanFlag, 0, - packageParser, executorService); - } - - scanDirTracedLI(frameworkDir, mSystemParseFlags, - mSystemScanFlags | SCAN_NO_DEX | SCAN_AS_PRIVILEGED, 0, - packageParser, executorService); - if (!mPm.mPackages.containsKey("android")) { - throw new IllegalStateException( - "Failed to load frameworks package; check log for warnings"); - } - - for (int i = 0, size = mDirsToScanAsSystem.size(); i < size; i++) { - final ScanPartition partition = mDirsToScanAsSystem.get(i); - if (partition.getPrivAppFolder() != null) { - scanDirTracedLI(partition.getPrivAppFolder(), mSystemParseFlags, - mSystemScanFlags | SCAN_AS_PRIVILEGED | partition.scanFlag, 0, - packageParser, executorService); - } - scanDirTracedLI(partition.getAppFolder(), mSystemParseFlags, - mSystemScanFlags | partition.scanFlag, 0, - packageParser, executorService); - } - } - - /** - * Second part of init dir scanning - */ - @GuardedBy({"mPm.mInstallLock", "mPm.mLock"}) - private void cleanupSystemPackagesAndInstallStubs(PackageParser2 packageParser, - ExecutorService executorService, - WatchedArrayMap<String, PackageSetting> packageSettings, - long startTime, int[] userIds) { // Prune any system packages that no longer exist. final List<String> possiblyDeletedUpdatedSystemApps = new ArrayList<>(); // Stub packages must either be replaced with full versions in the /data @@ -221,77 +155,9 @@ final class InitAndSystemPackageHelper { if (!mPm.isOnlyCoreApps()) { // do this first before mucking with mPackages for the "expecting better" case - final int numPackages = mPm.mPackages.size(); - for (int index = 0; index < numPackages; index++) { - final AndroidPackage pkg = mPm.mPackages.valueAt(index); - if (pkg.isStub()) { - stubSystemApps.add(pkg.getPackageName()); - } - } - - // Iterates PackageSettings in reversed order because the item could be removed - // during the iteration. - for (int index = packageSettings.size() - 1; index >= 0; index--) { - final PackageSetting ps = packageSettings.valueAt(index); - - /* - * If this is not a system app, it can't be a - * disable system app. - */ - if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) { - continue; - } - - /* - * If the package is scanned, it's not erased. - */ - final AndroidPackage scannedPkg = mPm.mPackages.get(ps.getPackageName()); - final PackageSetting disabledPs = - mPm.mSettings.getDisabledSystemPkgLPr(ps.getPackageName()); - if (scannedPkg != null) { - /* - * If the system app is both scanned and in the - * disabled packages list, then it must have been - * added via OTA. Remove it from the currently - * scanned package so the previously user-installed - * application can be scanned. - */ - if (disabledPs != null) { - logCriticalInfo(Log.WARN, - "Expecting better updated system app for " - + ps.getPackageName() - + "; removing system app. Last known" - + " codePath=" + ps.getPathString() - + ", versionCode=" + ps.getVersionCode() - + "; scanned versionCode=" - + scannedPkg.getLongVersionCode()); - mRemovePackageHelper.removePackageLI(scannedPkg, true); - mExpectingBetter.put(ps.getPackageName(), ps.getPath()); - } - - continue; - } - - if (disabledPs == null) { - logCriticalInfo(Log.WARN, "System package " + ps.getPackageName() - + " no longer exists; its data will be wiped"); - mRemovePackageHelper.removePackageDataLIF(ps, userIds, null, 0, false); - } else { - // we still have a disabled system package, but, it still might have - // been removed. check the code path still exists and check there's - // still a package. the latter can happen if an OTA keeps the same - // code path, but, changes the package name. - if (disabledPs.getPath() == null || !disabledPs.getPath().exists() - || disabledPs.getPkg() == null) { - possiblyDeletedUpdatedSystemApps.add(ps.getPackageName()); - } else { - // We're expecting that the system app should remain disabled, but add - // it to expecting better to recover in case the data version cannot - // be scanned. - mExpectingBetter.put(disabledPs.getPackageName(), disabledPs.getPath()); - } - } - } + updateStubSystemAppsList(stubSystemApps); + mInstallPackageHelper.prepareSystemPackageCleanUp(packageSettings, + possiblyDeletedUpdatedSystemApps, mExpectingBetter, userIds); } final int cachedSystemApps = PackageCacher.sCachedPackageReadCount.get(); @@ -312,6 +178,7 @@ final class InitAndSystemPackageHelper { systemScanTime / systemPackagesCount); //CHECKSTYLE:ON IndentationCheck } + if (!mPm.isOnlyCoreApps()) { EventLog.writeEvent(EventLogTags.BOOT_PROGRESS_PMS_DATA_SCAN_START, SystemClock.uptimeMillis()); @@ -327,110 +194,14 @@ final class InitAndSystemPackageHelper { } if (!mPm.isOnlyCoreApps()) { - final ScanPackageHelper scanPackageHelper = new ScanPackageHelper(mPm); - // Remove disable package settings for updated system apps that were - // removed via an OTA. If the update is no longer present, remove the - // app completely. Otherwise, revoke their system privileges. - for (int i = possiblyDeletedUpdatedSystemApps.size() - 1; i >= 0; --i) { - final String packageName = possiblyDeletedUpdatedSystemApps.get(i); - final AndroidPackage pkg = mPm.mPackages.get(packageName); - final String msg; - - // remove from the disabled system list; do this first so any future - // scans of this package are performed without this state - mPm.mSettings.removeDisabledSystemPackageLPw(packageName); - - if (pkg == null) { - // should have found an update, but, we didn't; remove everything - msg = "Updated system package " + packageName - + " no longer exists; removing its data"; - // Actual deletion of code and data will be handled by later - // reconciliation step - } else { - // found an update; revoke system privileges - msg = "Updated system package " + packageName - + " no longer exists; rescanning package on data"; - - // NOTE: We don't do anything special if a stub is removed from the - // system image. But, if we were [like removing the uncompressed - // version from the /data partition], this is where it'd be done. - - // remove the package from the system and re-scan it without any - // special privileges - mRemovePackageHelper.removePackageLI(pkg, true); - try { - final File codePath = new File(pkg.getPath()); - scanPackageHelper.scanPackageTracedLI(codePath, 0, mScanFlags, 0, null); - } catch (PackageManagerException e) { - Slog.e(TAG, "Failed to parse updated, ex-system package: " - + e.getMessage()); - } - } - - // one final check. if we still have a package setting [ie. it was - // previously scanned and known to the system], but, we don't have - // a package [ie. there was an error scanning it from the /data - // partition], completely remove the package data. - final PackageSetting ps = mPm.mSettings.getPackageLPr(packageName); - if (ps != null && mPm.mPackages.get(packageName) == null) { - mRemovePackageHelper.removePackageDataLIF(ps, userIds, null, 0, false); - - } - logCriticalInfo(Log.WARN, msg); - } - - /* - * Make sure all system apps that we expected to appear on - * the userdata partition actually showed up. If they never - * appeared, crawl back and revive the system version. - */ - for (int i = 0; i < mExpectingBetter.size(); i++) { - final String packageName = mExpectingBetter.keyAt(i); - if (!mPm.mPackages.containsKey(packageName)) { - final File scanFile = mExpectingBetter.valueAt(i); - - logCriticalInfo(Log.WARN, "Expected better " + packageName - + " but never showed up; reverting to system"); - - @ParsingPackageUtils.ParseFlags int reparseFlags = 0; - @PackageManagerService.ScanFlags int rescanFlags = 0; - for (int i1 = mDirsToScanAsSystem.size() - 1; i1 >= 0; i1--) { - final ScanPartition partition = mDirsToScanAsSystem.get(i1); - if (partition.containsPrivApp(scanFile)) { - reparseFlags = mSystemParseFlags; - rescanFlags = mSystemScanFlags | SCAN_AS_PRIVILEGED - | partition.scanFlag; - break; - } - if (partition.containsApp(scanFile)) { - reparseFlags = mSystemParseFlags; - rescanFlags = mSystemScanFlags | partition.scanFlag; - break; - } - } - if (rescanFlags == 0) { - Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile); - continue; - } - mPm.mSettings.enableSystemPackageLPw(packageName); - - try { - final AndroidPackage newPkg = scanPackageHelper.scanPackageTracedLI( - scanFile, reparseFlags, rescanFlags, 0, null); - // We rescanned a stub, add it to the list of stubbed system packages - if (newPkg.isStub()) { - stubSystemApps.add(packageName); - } - } catch (PackageManagerException e) { - Slog.e(TAG, "Failed to parse original system package: " - + e.getMessage()); - } - } - } + mInstallPackageHelper.cleanupDisabledPackageSettings(possiblyDeletedUpdatedSystemApps, + userIds, mScanFlags); + mInstallPackageHelper.checkExistingBetterPackages(mExpectingBetter, + stubSystemApps, mSystemScanFlags, mSystemParseFlags); // Uncompress and install any stubbed system applications. // This must be done last to ensure all stubs are replaced or disabled. - new InstallPackageHelper(mPm).installSystemStubPackages(stubSystemApps, mScanFlags); + mInstallPackageHelper.installSystemStubPackages(stubSystemApps, mScanFlags); final int cachedNonSystemApps = PackageCacher.sCachedPackageReadCount.get() - cachedSystemApps; @@ -454,93 +225,72 @@ final class InitAndSystemPackageHelper { mExpectingBetter.clear(); mPm.mSettings.pruneRenamedPackagesLPw(); + packageParser.close(); + return overlayConfig; } + /** + * First part of init dir scanning + */ @GuardedBy({"mPm.mInstallLock", "mPm.mLock"}) - private void scanDirTracedLI(File scanDir, final int parseFlags, int scanFlags, - long currentTime, PackageParser2 packageParser, ExecutorService executorService) { - Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir [" + scanDir.getAbsolutePath() + "]"); - try { - scanDirLI(scanDir, parseFlags, scanFlags, currentTime, packageParser, executorService); - } finally { - Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); - } - } + private void scanSystemDirs(PackageParser2 packageParser, ExecutorService executorService) { + File frameworkDir = new File(Environment.getRootDirectory(), "framework"); - @GuardedBy({"mPm.mInstallLock", "mPm.mLock"}) - private void scanDirLI(File scanDir, int parseFlags, int scanFlags, long currentTime, - PackageParser2 packageParser, ExecutorService executorService) { - final File[] files = scanDir.listFiles(); - if (ArrayUtils.isEmpty(files)) { - Log.d(TAG, "No files in app dir " + scanDir); - return; + // Collect vendor/product/system_ext overlay packages. (Do this before scanning + // any apps.) + // For security and version matching reason, only consider overlay packages if they + // reside in the right directory. + for (int i = mDirsToScanAsSystem.size() - 1; i >= 0; i--) { + final ScanPartition partition = mDirsToScanAsSystem.get(i); + if (partition.getOverlayFolder() == null) { + continue; + } + scanDirTracedLI(partition.getOverlayFolder(), mSystemParseFlags, + mSystemScanFlags | partition.scanFlag, 0, + packageParser, executorService); } - if (DEBUG_PACKAGE_SCANNING) { - Log.d(TAG, "Scanning app dir " + scanDir + " scanFlags=" + scanFlags - + " flags=0x" + Integer.toHexString(parseFlags)); + scanDirTracedLI(frameworkDir, mSystemParseFlags, + mSystemScanFlags | SCAN_NO_DEX | SCAN_AS_PRIVILEGED, 0, + packageParser, executorService); + if (!mPm.mPackages.containsKey("android")) { + throw new IllegalStateException( + "Failed to load frameworks package; check log for warnings"); } - ParallelPackageParser parallelPackageParser = - new ParallelPackageParser(packageParser, executorService); - - // Submit files for parsing in parallel - int fileCount = 0; - for (File file : files) { - final boolean isPackage = (isApkFile(file) || file.isDirectory()) - && !PackageInstallerService.isStageName(file.getName()); - if (!isPackage) { - // Ignore entries which are not packages - continue; + for (int i = 0, size = mDirsToScanAsSystem.size(); i < size; i++) { + final ScanPartition partition = mDirsToScanAsSystem.get(i); + if (partition.getPrivAppFolder() != null) { + scanDirTracedLI(partition.getPrivAppFolder(), mSystemParseFlags, + mSystemScanFlags | SCAN_AS_PRIVILEGED | partition.scanFlag, 0, + packageParser, executorService); } - parallelPackageParser.submit(file, parseFlags); - fileCount++; + scanDirTracedLI(partition.getAppFolder(), mSystemParseFlags, + mSystemScanFlags | partition.scanFlag, 0, + packageParser, executorService); } + } - final ScanPackageHelper scanPackageHelper = new ScanPackageHelper(mPm); - // Process results one by one - for (; fileCount > 0; fileCount--) { - ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take(); - Throwable throwable = parseResult.throwable; - int errorCode = PackageManager.INSTALL_SUCCEEDED; - String errorMsg = null; - - if (throwable == null) { - // TODO(b/194319951): move lower in the scan chain - // Static shared libraries have synthetic package names - if (parseResult.parsedPackage.isStaticSharedLibrary()) { - PackageManagerService.renameStaticSharedLibraryPackage( - parseResult.parsedPackage); - } - try { - scanPackageHelper.addForInitLI(parseResult.parsedPackage, parseFlags, scanFlags, - currentTime, null); - } catch (PackageManagerException e) { - errorCode = e.error; - errorMsg = "Failed to scan " + parseResult.scanFile + ": " + e.getMessage(); - Slog.w(TAG, errorMsg); - } - } else if (throwable instanceof PackageManagerException) { - PackageManagerException e = (PackageManagerException) throwable; - errorCode = e.error; - errorMsg = "Failed to parse " + parseResult.scanFile + ": " + e.getMessage(); - Slog.w(TAG, errorMsg); - } else { - throw new IllegalStateException("Unexpected exception occurred while parsing " - + parseResult.scanFile, throwable); - } - - if ((scanFlags & SCAN_AS_APK_IN_APEX) != 0 && errorCode != INSTALL_SUCCEEDED) { - mPm.mApexManager.reportErrorWithApkInApex(scanDir.getAbsolutePath(), errorMsg); + @GuardedBy("mPm.mLock") + private void updateStubSystemAppsList(List<String> stubSystemApps) { + final int numPackages = mPm.mPackages.size(); + for (int index = 0; index < numPackages; index++) { + final AndroidPackage pkg = mPm.mPackages.valueAt(index); + if (pkg.isStub()) { + stubSystemApps.add(pkg.getPackageName()); } + } + } - // Delete invalid userdata apps - if ((scanFlags & SCAN_AS_SYSTEM) == 0 - && errorCode != PackageManager.INSTALL_SUCCEEDED) { - logCriticalInfo(Log.WARN, - "Deleting invalid package at " + parseResult.scanFile); - mRemovePackageHelper.removeCodePathLI(parseResult.scanFile); - } + @GuardedBy({"mPm.mInstallLock", "mPm.mLock"}) + private void scanDirTracedLI(File scanDir, final int parseFlags, int scanFlags, + long currentTime, PackageParser2 packageParser, ExecutorService executorService) { + Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir [" + scanDir.getAbsolutePath() + "]"); + try { + mInstallPackageHelper.installSystemPackagesFromDir(scanDir, parseFlags, scanFlags, + currentTime, packageParser, executorService); + } 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 8ba8e45e2936..1175ca816a92 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -36,8 +36,10 @@ import static android.content.pm.PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES; import static android.content.pm.PackageManager.INSTALL_REASON_DEVICE_RESTORE; import static android.content.pm.PackageManager.INSTALL_REASON_DEVICE_SETUP; +import static android.content.pm.PackageManager.INSTALL_SUCCEEDED; import static android.content.pm.PackageManager.UNINSTALL_REASON_UNKNOWN; import static android.content.pm.SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V4; +import static android.content.pm.parsing.ApkLiteParseUtils.isApkFile; import static android.os.PowerExemptionManager.REASON_PACKAGE_REPLACED; import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; import static android.os.incremental.IncrementalManager.isIncrementalPath; @@ -159,9 +161,9 @@ import com.android.server.pm.parsing.pkg.AndroidPackageUtils; import com.android.server.pm.parsing.pkg.ParsedPackage; import com.android.server.pm.permission.Permission; import com.android.server.pm.permission.PermissionManagerServiceInternal; -import com.android.server.pm.pkg.PackageUserState; import com.android.server.pm.pkg.PackageStateInternal; import com.android.server.rollback.RollbackManagerInternal; +import com.android.server.utils.WatchedArrayMap; import com.android.server.utils.WatchedLongSparseArray; import dalvik.system.VMRuntime; @@ -185,6 +187,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; +import java.util.concurrent.ExecutorService; final class InstallPackageHelper { /** @@ -196,6 +199,8 @@ final class InstallPackageHelper { private final AppDataHelper mAppDataHelper; private final PackageManagerServiceInjector mInjector; private final BroadcastHelper mBroadcastHelper; + private final RemovePackageHelper mRemovePackageHelper; + private final ScanPackageHelper mScanPackageHelper; // TODO(b/198166813): remove PMS dependency InstallPackageHelper(PackageManagerService pm, AppDataHelper appDataHelper) { @@ -203,6 +208,8 @@ final class InstallPackageHelper { mInjector = pm.mInjector; mAppDataHelper = appDataHelper; mBroadcastHelper = new BroadcastHelper(mInjector); + mRemovePackageHelper = new RemovePackageHelper(pm); + mScanPackageHelper = new ScanPackageHelper(pm); } InstallPackageHelper(PackageManagerService pm) { @@ -214,6 +221,8 @@ final class InstallPackageHelper { mInjector = injector; mAppDataHelper = new AppDataHelper(pm, mInjector); mBroadcastHelper = new BroadcastHelper(injector); + mRemovePackageHelper = new RemovePackageHelper(pm); + mScanPackageHelper = new ScanPackageHelper(pm); } @GuardedBy("mPm.mLock") @@ -1132,7 +1141,6 @@ final class InstallPackageHelper { new ArrayMap<>(requests.size()); final Map<String, Boolean> createdAppId = new ArrayMap<>(requests.size()); boolean success = false; - final ScanPackageHelper scanPackageHelper = new ScanPackageHelper(mPm); try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackagesLI"); for (InstallRequest request : requests) { @@ -1161,7 +1169,7 @@ final class InstallPackageHelper { installResults.put(packageName, request.mInstallResult); installArgs.put(packageName, request.mArgs); try { - final ScanResult result = scanPackageHelper.scanPackageTracedLI( + final ScanResult result = mScanPackageHelper.scanPackageTracedLI( prepareResult.mPackageToScan, prepareResult.mParseFlags, prepareResult.mScanFlags, System.currentTimeMillis(), request.mArgs.mUser, request.mArgs.mAbiOverride); @@ -1174,8 +1182,7 @@ final class InstallPackageHelper { + " in multi-package install request."); return; } - createdAppId.put(packageName, - scanPackageHelper.optimisticallyRegisterAppId(result)); + createdAppId.put(packageName, optimisticallyRegisterAppId(result)); versionInfos.put(result.mPkgSetting.getPkg().getPackageName(), mPm.getSettingsVersionForPackage(result.mPkgSetting.getPkg())); if (result.mStaticSharedLibraryInfo != null) { @@ -1253,7 +1260,7 @@ final class InstallPackageHelper { for (ScanResult result : preparedScans.values()) { if (createdAppId.getOrDefault(result.mRequest.mParsedPackage.getPackageName(), false)) { - scanPackageHelper.cleanUpAppIdCreation(result); + cleanUpAppIdCreation(result); } } // TODO(b/194319951): create a more descriptive reason than unknown @@ -3357,9 +3364,8 @@ final class InstallPackageHelper { } final RemovePackageHelper removePackageHelper = new RemovePackageHelper(mPm); removePackageHelper.removePackageLI(stubPkg, true /*chatty*/); - final ScanPackageHelper scanPackageHelper = new ScanPackageHelper(mPm); try { - return scanPackageHelper.scanPackageTracedLI(scanFile, parseFlags, scanFlags, 0, null); + return scanSystemPackageTracedLI(scanFile, parseFlags, scanFlags, 0, null); } catch (PackageManagerException e) { Slog.w(TAG, "Failed to install compressed system package:" + stubPkg.getPackageName(), e); @@ -3509,9 +3515,7 @@ final class InstallPackageHelper { | ParsingPackageUtils.PARSE_MUST_BE_APK | ParsingPackageUtils.PARSE_IS_SYSTEM_DIR; @PackageManagerService.ScanFlags int scanFlags = mPm.getSystemPackageScanFlags(codePath); - final ScanPackageHelper scanPackageHelper = new ScanPackageHelper(mPm); - final AndroidPackage pkg = - scanPackageHelper.scanPackageTracedLI( + final AndroidPackage pkg = scanSystemPackageTracedLI( codePath, parseFlags, scanFlags, 0 /*currentTime*/, null); PackageSetting pkgSetting = mPm.mSettings.getPackageLPr(pkg.getPackageName()); @@ -3582,4 +3586,388 @@ final class InstallPackageHelper { } } + @GuardedBy("mPm.mLock") + public void prepareSystemPackageCleanUp( + WatchedArrayMap<String, PackageSetting> packageSettings, + List<String> possiblyDeletedUpdatedSystemApps, + ArrayMap<String, File> expectingBetter, int[] userIds) { + // Iterates PackageSettings in reversed order because the item could be removed + // during the iteration. + for (int index = packageSettings.size() - 1; index >= 0; index--) { + final PackageSetting ps = packageSettings.valueAt(index); + final String packageName = ps.getPackageName(); + /* + * If this is not a system app, it can't be a + * disable system app. + */ + if ((ps.pkgFlags & ApplicationInfo.FLAG_SYSTEM) == 0) { + continue; + } + + /* + * If the package is scanned, it's not erased. + */ + final AndroidPackage scannedPkg = mPm.mPackages.get(packageName); + final PackageSetting disabledPs = + mPm.mSettings.getDisabledSystemPkgLPr(packageName); + if (scannedPkg != null) { + /* + * If the system app is both scanned and in the + * disabled packages list, then it must have been + * added via OTA. Remove it from the currently + * scanned package so the previously user-installed + * application can be scanned. + */ + if (disabledPs != null) { + logCriticalInfo(Log.WARN, + "Expecting better updated system app for " + + packageName + + "; removing system app. Last known" + + " codePath=" + ps.getPathString() + + ", versionCode=" + ps.getVersionCode() + + "; scanned versionCode=" + + scannedPkg.getLongVersionCode()); + mRemovePackageHelper.removePackageLI(scannedPkg, true); + expectingBetter.put(ps.getPackageName(), ps.getPath()); + } + + continue; + } + + if (disabledPs == null) { + logCriticalInfo(Log.WARN, "System package " + packageName + + " no longer exists; its data will be wiped"); + mRemovePackageHelper.removePackageDataLIF(ps, userIds, null, 0, false); + } else { + // we still have a disabled system package, but, it still might have + // been removed. check the code path still exists and check there's + // still a package. the latter can happen if an OTA keeps the same + // code path, but, changes the package name. + if (disabledPs.getPath() == null || !disabledPs.getPath().exists() + || disabledPs.getPkg() == null) { + possiblyDeletedUpdatedSystemApps.add(packageName); + } else { + // We're expecting that the system app should remain disabled, but add + // it to expecting better to recover in case the data version cannot + // be scanned. + expectingBetter.put(disabledPs.getPackageName(), disabledPs.getPath()); + } + } + } + } + + @GuardedBy("mPm.mLock") + // Remove disable package settings for updated system apps that were + // removed via an OTA. If the update is no longer present, remove the + // app completely. Otherwise, revoke their system privileges. + public void cleanupDisabledPackageSettings(List<String> possiblyDeletedUpdatedSystemApps, + int[] userIds, int scanFlags) { + for (int i = possiblyDeletedUpdatedSystemApps.size() - 1; i >= 0; --i) { + final String packageName = possiblyDeletedUpdatedSystemApps.get(i); + final AndroidPackage pkg = mPm.mPackages.get(packageName); + final String msg; + + // remove from the disabled system list; do this first so any future + // scans of this package are performed without this state + mPm.mSettings.removeDisabledSystemPackageLPw(packageName); + + if (pkg == null) { + // should have found an update, but, we didn't; remove everything + msg = "Updated system package " + packageName + + " no longer exists; removing its data"; + // Actual deletion of code and data will be handled by later + // reconciliation step + } else { + // found an update; revoke system privileges + msg = "Updated system package " + packageName + + " no longer exists; rescanning package on data"; + + // NOTE: We don't do anything special if a stub is removed from the + // system image. But, if we were [like removing the uncompressed + // version from the /data partition], this is where it'd be done. + + // remove the package from the system and re-scan it without any + // special privileges + mRemovePackageHelper.removePackageLI(pkg, true); + try { + final File codePath = new File(pkg.getPath()); + scanSystemPackageTracedLI(codePath, 0, scanFlags, 0, null); + } catch (PackageManagerException e) { + Slog.e(TAG, "Failed to parse updated, ex-system package: " + + e.getMessage()); + } + } + + // one final check. if we still have a package setting [ie. it was + // previously scanned and known to the system], but, we don't have + // a package [ie. there was an error scanning it from the /data + // partition], completely remove the package data. + final PackageSetting ps = mPm.mSettings.getPackageLPr(packageName); + if (ps != null && mPm.mPackages.get(packageName) == null) { + mRemovePackageHelper.removePackageDataLIF(ps, userIds, null, 0, false); + } + logCriticalInfo(Log.WARN, msg); + } + } + + @GuardedBy({"mPm.mInstallLock", "mPm.mLock"}) + public void installSystemPackagesFromDir(File scanDir, int parseFlags, int scanFlags, + long currentTime, PackageParser2 packageParser, ExecutorService executorService) { + final File[] files = scanDir.listFiles(); + if (ArrayUtils.isEmpty(files)) { + Log.d(TAG, "No files in app dir " + scanDir); + return; + } + + if (DEBUG_PACKAGE_SCANNING) { + Log.d(TAG, "Scanning app dir " + scanDir + " scanFlags=" + scanFlags + + " flags=0x" + Integer.toHexString(parseFlags)); + } + ParallelPackageParser parallelPackageParser = + new ParallelPackageParser(packageParser, executorService); + + // Submit files for parsing in parallel + int fileCount = 0; + for (File file : files) { + final boolean isPackage = (isApkFile(file) || file.isDirectory()) + && !PackageInstallerService.isStageName(file.getName()); + if (!isPackage) { + // Ignore entries which are not packages + continue; + } + parallelPackageParser.submit(file, parseFlags); + fileCount++; + } + + // Process results one by one + for (; fileCount > 0; fileCount--) { + ParallelPackageParser.ParseResult parseResult = parallelPackageParser.take(); + Throwable throwable = parseResult.throwable; + int errorCode = PackageManager.INSTALL_SUCCEEDED; + String errorMsg = null; + + if (throwable == null) { + // TODO(b/194319951): move lower in the scan chain + // Static shared libraries have synthetic package names + if (parseResult.parsedPackage.isStaticSharedLibrary()) { + PackageManagerService.renameStaticSharedLibraryPackage( + parseResult.parsedPackage); + } + try { + addForInitLI(parseResult.parsedPackage, parseFlags, scanFlags, currentTime, + null); + } catch (PackageManagerException e) { + errorCode = e.error; + errorMsg = "Failed to scan " + parseResult.scanFile + ": " + e.getMessage(); + Slog.w(TAG, errorMsg); + } + } else if (throwable instanceof PackageManagerException) { + PackageManagerException e = (PackageManagerException) throwable; + errorCode = e.error; + errorMsg = "Failed to parse " + parseResult.scanFile + ": " + e.getMessage(); + Slog.w(TAG, errorMsg); + } else { + throw new IllegalStateException("Unexpected exception occurred while parsing " + + parseResult.scanFile, throwable); + } + + if ((scanFlags & SCAN_AS_APK_IN_APEX) != 0 && errorCode != INSTALL_SUCCEEDED) { + mPm.mApexManager.reportErrorWithApkInApex(scanDir.getAbsolutePath(), errorMsg); + } + + // Delete invalid userdata apps + if ((scanFlags & SCAN_AS_SYSTEM) == 0 + && errorCode != PackageManager.INSTALL_SUCCEEDED) { + logCriticalInfo(Log.WARN, + "Deleting invalid package at " + parseResult.scanFile); + mRemovePackageHelper.removeCodePathLI(parseResult.scanFile); + } + } + } + + /** + * Make sure all system apps that we expected to appear on + * the userdata partition actually showed up. If they never + * appeared, crawl back and revive the system version. + */ + @GuardedBy("mPm.mLock") + public void checkExistingBetterPackages(ArrayMap<String, File> expectingBetterPackages, + List<String> stubSystemApps, int systemScanFlags, int systemParseFlags) { + for (int i = 0; i < expectingBetterPackages.size(); i++) { + final String packageName = expectingBetterPackages.keyAt(i); + if (mPm.mPackages.containsKey(packageName)) { + continue; + } + final File scanFile = expectingBetterPackages.valueAt(i); + + logCriticalInfo(Log.WARN, "Expected better " + packageName + + " but never showed up; reverting to system"); + + final Pair<Integer, Integer> rescanAndReparseFlags = + mPm.getSystemPackageRescanFlagsAndReparseFlags(scanFile, + systemScanFlags, systemParseFlags); + @PackageManagerService.ScanFlags int rescanFlags = rescanAndReparseFlags.first; + @ParsingPackageUtils.ParseFlags int reparseFlags = rescanAndReparseFlags.second; + + if (rescanFlags == 0) { + Slog.e(TAG, "Ignoring unexpected fallback path " + scanFile); + continue; + } + mPm.mSettings.enableSystemPackageLPw(packageName); + + try { + final AndroidPackage newPkg = scanSystemPackageTracedLI( + scanFile, reparseFlags, rescanFlags, 0, null); + // We rescanned a stub, add it to the list of stubbed system packages + if (newPkg.isStub()) { + stubSystemApps.add(packageName); + } + } catch (PackageManagerException e) { + Slog.e(TAG, "Failed to parse original system package: " + + e.getMessage()); + } + } + } + + /** + * Traces a package scan. + * @see #scanSystemPackageLI(File, int, int, long, UserHandle) + */ + @GuardedBy({"mPm.mInstallLock", "mPm.mLock"}) + public AndroidPackage scanSystemPackageTracedLI(File scanFile, final int parseFlags, + int scanFlags, long currentTime, UserHandle user) throws PackageManagerException { + Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage [" + scanFile.toString() + "]"); + try { + return scanSystemPackageLI(scanFile, parseFlags, scanFlags, currentTime, user); + } finally { + Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); + } + } + + /** + * Scans a package and returns the newly parsed package. + * Returns {@code null} in case of errors and the error code is stored in mLastScanError + */ + @GuardedBy({"mPm.mInstallLock", "mPm.mLock"}) + private AndroidPackage scanSystemPackageLI(File scanFile, int parseFlags, int scanFlags, + long currentTime, UserHandle user) throws PackageManagerException { + if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile); + + Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage"); + final ParsedPackage parsedPackage; + try (PackageParser2 pp = mInjector.getScanningPackageParser()) { + parsedPackage = pp.parsePackage(scanFile, parseFlags, false); + } finally { + Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); + } + + // Static shared libraries have synthetic package names + if (parsedPackage.isStaticSharedLibrary()) { + PackageManagerService.renameStaticSharedLibraryPackage(parsedPackage); + } + + return addForInitLI(parsedPackage, parseFlags, scanFlags, currentTime, user); + } + + /** + * Adds a new package to the internal data structures during platform initialization. + * <p>After adding, the package is known to the system and available for querying. + * <p>For packages located on the device ROM [eg. packages located in /system, /vendor, + * etc...], additional checks are performed. Basic verification [such as ensuring + * matching signatures, checking version codes, etc...] occurs if the package is + * identical to a previously known package. If the package fails a signature check, + * the version installed on /data will be removed. If the version of the new package + * is less than or equal than the version on /data, it will be ignored. + * <p>Regardless of the package location, the results are applied to the internal + * structures and the package is made available to the rest of the system. + * <p>NOTE: The return value should be removed. It's the passed in package object. + */ + @GuardedBy({"mPm.mLock", "mPm.mInstallLock"}) + private AndroidPackage addForInitLI(ParsedPackage parsedPackage, + @ParsingPackageUtils.ParseFlags int parseFlags, + @PackageManagerService.ScanFlags int scanFlags, long currentTime, + @Nullable UserHandle user) throws PackageManagerException { + + final Pair<ScanResult, Boolean> scanResultPair = mScanPackageHelper.scanSystemPackageLI( + parsedPackage, parseFlags, scanFlags, currentTime, user); + final ScanResult scanResult = scanResultPair.first; + boolean shouldHideSystemApp = scanResultPair.second; + if (scanResult.mSuccess) { + synchronized (mPm.mLock) { + boolean appIdCreated = false; + try { + final String pkgName = scanResult.mPkgSetting.getPackageName(); + final Map<String, ReconciledPackage> reconcileResult = + reconcilePackagesLocked( + new ReconcileRequest( + Collections.singletonMap(pkgName, scanResult), + mPm.mSharedLibraries, + mPm.mPackages, + Collections.singletonMap( + pkgName, + mPm.getSettingsVersionForPackage( + parsedPackage)), + Collections.singletonMap(pkgName, + mPm.getSharedLibLatestVersionSetting( + scanResult))), + mPm.mSettings.getKeySetManagerService(), mInjector); + appIdCreated = optimisticallyRegisterAppId(scanResult); + commitReconciledScanResultLocked( + reconcileResult.get(pkgName), mPm.mUserManager.getUserIds()); + } catch (PackageManagerException e) { + if (appIdCreated) { + cleanUpAppIdCreation(scanResult); + } + throw e; + } + } + } + + if (shouldHideSystemApp) { + synchronized (mPm.mLock) { + mPm.mSettings.disableSystemPackageLPw(parsedPackage.getPackageName(), true); + } + } + if (mPm.mIncrementalManager != null && isIncrementalPath(parsedPackage.getPath())) { + if (scanResult.mPkgSetting != null && scanResult.mPkgSetting.isPackageLoading()) { + // Continue monitoring loading progress of active incremental packages + mPm.mIncrementalManager.registerLoadingProgressCallback(parsedPackage.getPath(), + new IncrementalProgressListener(parsedPackage.getPackageName(), mPm)); + } + } + return scanResult.mPkgSetting.getPkg(); + } + + /** + * Prepares the system to commit a {@link ScanResult} in a way that will not fail by registering + * the app ID required for reconcile. + * @return {@code true} if a new app ID was registered and will need to be cleaned up on + * failure. + */ + private boolean optimisticallyRegisterAppId(@NonNull ScanResult result) + throws PackageManagerException { + if (!result.mExistingSettingCopied || result.needsNewAppId()) { + synchronized (mPm.mLock) { + // THROWS: when we can't allocate a user id. add call to check if there's + // enough space to ensure we won't throw; otherwise, don't modify state + return mPm.mSettings.registerAppIdLPw(result.mPkgSetting, result.needsNewAppId()); + } + } + return false; + } + + /** + * Reverts any app ID creation that were made by + * {@link #optimisticallyRegisterAppId(ScanResult)}. Note: this is only necessary if the + * referenced method returned true. + */ + private void cleanUpAppIdCreation(@NonNull ScanResult result) { + // iff we've acquired an app ID for a new package setting, remove it so that it can be + // acquired by another request. + if (result.mPkgSetting.getAppId() > 0) { + mPm.mSettings.removeAppIdLPw(result.mPkgSetting.getAppId()); + } + } + + } diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index e71ac1aab711..a74b20115576 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -146,13 +146,7 @@ import android.content.pm.parsing.component.ParsedInstrumentation; import android.content.pm.parsing.component.ParsedIntentInfo; import android.content.pm.parsing.component.ParsedMainComponent; import android.content.pm.parsing.component.ParsedProvider; - -import com.android.server.pm.pkg.PackageStateInternal; -import com.android.server.pm.pkg.PackageStateUtils; -import com.android.server.pm.pkg.PackageUserState; -import com.android.server.pm.pkg.PackageUserStateInternal; import android.content.pm.pkg.PackageUserStateUtils; -import com.android.server.pm.pkg.SuspendParams; import android.content.res.Resources; import android.database.ContentObserver; import android.graphics.Bitmap; @@ -257,6 +251,11 @@ import com.android.server.pm.permission.PermissionManagerServiceInternal; import com.android.server.pm.pkg.AndroidPackageApi; import com.android.server.pm.pkg.PackageState; import com.android.server.pm.pkg.PackageStateImpl; +import com.android.server.pm.pkg.PackageStateInternal; +import com.android.server.pm.pkg.PackageStateUtils; +import com.android.server.pm.pkg.PackageUserState; +import com.android.server.pm.pkg.PackageUserStateInternal; +import com.android.server.pm.pkg.SuspendParams; 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; @@ -1829,8 +1828,7 @@ public class PackageManagerService extends IPackageManager.Stub mBroadcastHelper = new BroadcastHelper(mInjector); mAppDataHelper = new AppDataHelper(this); mRemovePackageHelper = new RemovePackageHelper(this, mAppDataHelper); - mInitAndSystemPackageHelper = new InitAndSystemPackageHelper(this, mRemovePackageHelper, - mAppDataHelper); + mInitAndSystemPackageHelper = new InitAndSystemPackageHelper(this); mDeletePackageHelper = new DeletePackageHelper(this, mRemovePackageHelper, mAppDataHelper); mPreferredActivityHelper = new PreferredActivityHelper(this); @@ -11186,4 +11184,28 @@ public class PackageManagerService extends IPackageManager.Stub } return scanFlags; } + + Pair<Integer, Integer> getSystemPackageRescanFlagsAndReparseFlags(File scanFile, + int systemScanFlags, int systemParseFlags) { + List<ScanPartition> dirsToScanAsSystem = + mInitAndSystemPackageHelper.getDirsToScanAsSystem(); + @ParsingPackageUtils.ParseFlags int reparseFlags = 0; + @PackageManagerService.ScanFlags int rescanFlags = 0; + for (int i1 = dirsToScanAsSystem.size() - 1; i1 >= 0; i1--) { + final ScanPartition partition = dirsToScanAsSystem.get(i1); + if (partition.containsPrivApp(scanFile)) { + reparseFlags = systemParseFlags; + rescanFlags = systemScanFlags | SCAN_AS_PRIVILEGED + | partition.scanFlag; + break; + } + if (partition.containsApp(scanFile)) { + reparseFlags = systemParseFlags; + rescanFlags = systemScanFlags | partition.scanFlag; + break; + } + } + return new Pair<>(rescanFlags, reparseFlags); + } + } diff --git a/services/core/java/com/android/server/pm/ScanPackageHelper.java b/services/core/java/com/android/server/pm/ScanPackageHelper.java index 731c6ca7c30d..abe13ad6f258 100644 --- a/services/core/java/com/android/server/pm/ScanPackageHelper.java +++ b/services/core/java/com/android/server/pm/ScanPackageHelper.java @@ -23,7 +23,6 @@ import static android.content.pm.PackageManager.INSTALL_FAILED_PACKAGE_CHANGED; import static android.content.pm.PackageManager.INSTALL_FAILED_PROCESS_NOT_DEFINED; import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_NO_CERTIFICATES; import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER; -import static android.os.incremental.IncrementalManager.isIncrementalPath; import static com.android.server.pm.InstructionSets.getAppDexInstructionSets; import static com.android.server.pm.PackageManagerService.DEBUG_ABI_SELECTION; @@ -92,7 +91,6 @@ import com.android.internal.security.VerityUtils; import com.android.internal.util.ArrayUtils; import com.android.server.SystemConfig; import com.android.server.pm.parsing.PackageInfoUtils; -import com.android.server.pm.parsing.PackageParser2; import com.android.server.pm.parsing.library.PackageBackwardCompatibility; import com.android.server.pm.parsing.pkg.AndroidPackage; import com.android.server.pm.parsing.pkg.AndroidPackageUtils; @@ -106,7 +104,6 @@ import java.io.IOException; import java.security.DigestException; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; -import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Objects; @@ -118,66 +115,17 @@ import java.util.UUID; */ final class ScanPackageHelper { final PackageManagerService mPm; - final InstallPackageHelper mInstallPackageHelper; final PackageManagerServiceInjector mInjector; // TODO(b/198166813): remove PMS dependency public ScanPackageHelper(PackageManagerService pm) { mPm = pm; mInjector = pm.mInjector; - mInstallPackageHelper = new InstallPackageHelper(mPm, mInjector); } ScanPackageHelper(PackageManagerService pm, PackageManagerServiceInjector injector) { mPm = pm; mInjector = injector; - mInstallPackageHelper = new InstallPackageHelper(mPm, injector); - } - - /** - * Prepares the system to commit a {@link ScanResult} in a way that will not fail by registering - * the app ID required for reconcile. - * @return {@code true} if a new app ID was registered and will need to be cleaned up on - * failure. - */ - public boolean optimisticallyRegisterAppId(@NonNull ScanResult result) - throws PackageManagerException { - if (!result.mExistingSettingCopied || result.needsNewAppId()) { - synchronized (mPm.mLock) { - // THROWS: when we can't allocate a user id. add call to check if there's - // enough space to ensure we won't throw; otherwise, don't modify state - return mPm.mSettings.registerAppIdLPw(result.mPkgSetting, result.needsNewAppId()); - } - } - return false; - } - - /** - * Reverts any app ID creation that were made by - * {@link #optimisticallyRegisterAppId(ScanResult)}. Note: this is only necessary if the - * referenced method returned true. - */ - public void cleanUpAppIdCreation(@NonNull ScanResult result) { - // iff we've acquired an app ID for a new package setting, remove it so that it can be - // acquired by another request. - if (result.mPkgSetting.getAppId() > 0) { - mPm.mSettings.removeAppIdLPw(result.mPkgSetting.getAppId()); - } - } - - /** - * Traces a package scan. - * @see #scanPackageLI(File, int, int, long, UserHandle) - */ - @GuardedBy({"mPm.mInstallLock", "mPm.mLock"}) - public AndroidPackage scanPackageTracedLI(File scanFile, final int parseFlags, - int scanFlags, long currentTime, UserHandle user) throws PackageManagerException { - Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage [" + scanFile.toString() + "]"); - try { - return scanPackageLI(scanFile, parseFlags, scanFlags, currentTime, user); - } finally { - Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); - } } /** @@ -197,31 +145,6 @@ final class ScanPackageHelper { } } - /** - * Scans a package and returns the newly parsed package. - * Returns {@code null} in case of errors and the error code is stored in mLastScanError - */ - @GuardedBy({"mPm.mInstallLock", "mPm.mLock"}) - private AndroidPackage scanPackageLI(File scanFile, int parseFlags, int scanFlags, - long currentTime, UserHandle user) throws PackageManagerException { - if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile); - - Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage"); - final ParsedPackage parsedPackage; - try (PackageParser2 pp = mInjector.getScanningPackageParser()) { - parsedPackage = pp.parsePackage(scanFile, parseFlags, false); - } finally { - Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); - } - - // Static shared libraries have synthetic package names - if (parsedPackage.isStaticSharedLibrary()) { - PackageManagerService.renameStaticSharedLibraryPackage(parsedPackage); - } - - return addForInitLI(parsedPackage, parseFlags, scanFlags, currentTime, user); - } - // TODO(b/199937291): scanPackageNewLI() and scanPackageOnlyLI() should be merged. // But, first, committing the results / removing app data needs to be moved up a level to the // callers of this method. Also, we need to solve the problem of potentially creating a new @@ -748,22 +671,7 @@ final class ScanPackageHelper { return scanFlags; } - - /** - * Adds a new package to the internal data structures during platform initialization. - * <p>After adding, the package is known to the system and available for querying. - * <p>For packages located on the device ROM [eg. packages located in /system, /vendor, - * etc...], additional checks are performed. Basic verification [such as ensuring - * matching signatures, checking version codes, etc...] occurs if the package is - * identical to a previously known package. If the package fails a signature check, - * the version installed on /data will be removed. If the version of the new package - * is less than or equal than the version on /data, it will be ignored. - * <p>Regardless of the package location, the results are applied to the internal - * structures and the package is made available to the rest of the system. - * <p>NOTE: The return value should be removed. It's the passed in package object. - */ - @GuardedBy({"mPm.mLock", "mPm.mInstallLock"}) - public AndroidPackage addForInitLI(ParsedPackage parsedPackage, + public Pair<ScanResult, Boolean> scanSystemPackageLI(ParsedPackage parsedPackage, @ParsingPackageUtils.ParseFlags int parseFlags, @PackageManagerService.ScanFlags int scanFlags, long currentTime, @Nullable UserHandle user) throws PackageManagerException { @@ -828,7 +736,7 @@ final class ScanPackageHelper { // we're updating the disabled package, so, scan it as the package setting boolean isPlatformPackage = platformPackage != null && platformPackage.getPackageName().equals( - parsedPackage.getPackageName()); + parsedPackage.getPackageName()); final ScanRequest request = new ScanRequest(parsedPackage, sharedUserSetting, null, disabledPkgSetting /* pkgSetting */, null /* disabledPkgSetting */, null /* originalPkgSetting */, @@ -872,7 +780,7 @@ final class ScanPackageHelper { final InstallArgs args = new FileInstallArgs( pkgSetting.getPathString(), getAppDexInstructionSets( - pkgSetting.getPrimaryCpuAbi(), pkgSetting.getSecondaryCpuAbi()), mPm); + pkgSetting.getPrimaryCpuAbi(), pkgSetting.getSecondaryCpuAbi()), mPm); args.cleanUpResourcesLI(); synchronized (mPm.mLock) { mPm.mSettings.enableSystemPackageLPw(pkgSetting.getPackageName()); @@ -957,7 +865,7 @@ final class ScanPackageHelper { + parsedPackage.getPath()); InstallArgs args = new FileInstallArgs( pkgSetting.getPathString(), getAppDexInstructionSets( - pkgSetting.getPrimaryCpuAbi(), pkgSetting.getSecondaryCpuAbi()), + pkgSetting.getPrimaryCpuAbi(), pkgSetting.getSecondaryCpuAbi()), mPm); synchronized (mPm.mInstallLock) { args.cleanUpResourcesLI(); @@ -977,52 +885,9 @@ final class ScanPackageHelper { } } - final ScanResult scanResult = scanPackageNewLI(parsedPackage, parseFlags, scanFlags - | SCAN_UPDATE_SIGNATURE, currentTime, user, null); - if (scanResult.mSuccess) { - synchronized (mPm.mLock) { - boolean appIdCreated = false; - try { - final String pkgName = scanResult.mPkgSetting.getPackageName(); - final Map<String, ReconciledPackage> reconcileResult = - mInstallPackageHelper.reconcilePackagesLocked( - new ReconcileRequest( - Collections.singletonMap(pkgName, scanResult), - mPm.mSharedLibraries, - mPm.mPackages, - Collections.singletonMap( - pkgName, - mPm.getSettingsVersionForPackage( - parsedPackage)), - Collections.singletonMap(pkgName, - mPm.getSharedLibLatestVersionSetting( - scanResult))), - mPm.mSettings.getKeySetManagerService(), mInjector); - appIdCreated = optimisticallyRegisterAppId(scanResult); - mInstallPackageHelper.commitReconciledScanResultLocked( - reconcileResult.get(pkgName), mPm.mUserManager.getUserIds()); - } catch (PackageManagerException e) { - if (appIdCreated) { - cleanUpAppIdCreation(scanResult); - } - throw e; - } - } - } - - if (shouldHideSystemApp) { - synchronized (mPm.mLock) { - mPm.mSettings.disableSystemPackageLPw(parsedPackage.getPackageName(), true); - } - } - if (mPm.mIncrementalManager != null && isIncrementalPath(parsedPackage.getPath())) { - if (pkgSetting != null && pkgSetting.isPackageLoading()) { - // Continue monitoring loading progress of active incremental packages - mPm.mIncrementalManager.registerLoadingProgressCallback(parsedPackage.getPath(), - new IncrementalProgressListener(parsedPackage.getPackageName(), mPm)); - } - } - return scanResult.mPkgSetting.getPkg(); + final ScanResult scanResult = scanPackageNewLI(parsedPackage, parseFlags, + scanFlags | SCAN_UPDATE_SIGNATURE, currentTime, user, null); + return new Pair<>(scanResult, shouldHideSystemApp); } /** @@ -1085,7 +950,7 @@ final class ScanPackageHelper { && ps.getLastModifiedTime() == lastModifiedTime && !InstallPackageHelper.isCompatSignatureUpdateNeeded(settingsVersionForPackage) && !InstallPackageHelper.isRecoverSignatureUpdateNeeded( - settingsVersionForPackage)) { + settingsVersionForPackage)) { if (ps.getSigningDetails().getSignatures() != null && ps.getSigningDetails().getSignatures().length != 0 && ps.getSigningDetails().getSignatureSchemeVersion() diff --git a/services/core/java/com/android/server/pm/StorageEventHelper.java b/services/core/java/com/android/server/pm/StorageEventHelper.java index b49c8dacce2b..12e644dde65a 100644 --- a/services/core/java/com/android/server/pm/StorageEventHelper.java +++ b/services/core/java/com/android/server/pm/StorageEventHelper.java @@ -136,7 +136,7 @@ public final class StorageEventHelper extends StorageEventListener { final Settings.VersionInfo ver; final List<PackageSetting> packages; - final ScanPackageHelper scanPackageHelper = new ScanPackageHelper(mPm); + final InstallPackageHelper installPackageHelper = new InstallPackageHelper(mPm); synchronized (mPm.mLock) { ver = mPm.mSettings.findOrCreateVersion(volumeUuid); packages = mPm.mSettings.getVolumePackagesLPr(volumeUuid); @@ -147,7 +147,7 @@ public final class StorageEventHelper extends StorageEventListener { synchronized (mPm.mInstallLock) { final AndroidPackage pkg; try { - pkg = scanPackageHelper.scanPackageTracedLI( + pkg = installPackageHelper.scanSystemPackageTracedLI( ps.getPath(), parseFlags, SCAN_INITIAL, 0, null); loaded.add(pkg); |