summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Songchun Fan <schfan@google.com> 2021-11-01 17:13:19 +0000
committer Songchun Fan <schfan@google.com> 2021-11-10 21:29:45 +0000
commitd7917c5235763d253da5c973cc5d8c632b4c537c (patch)
tree611e34206886bb4d20f265e3278a50731052e32c
parent7582c4acccee649a98d5db12c809d831c05d41ac (diff)
Move more install-related code into InstallPackageHelper
The goal is to move code blocks that modify mPackages and mSettings into one place (InstallPackageHelper). + Some clean up in InitAndSystemPackageHelper. BUG: 198177734 BUG: 201815903 Test: manual Change-Id: I965d59207d5d2963e76feeb6db72100ab7de0e82
-rw-r--r--services/core/java/com/android/server/pm/InitAndSystemPackageHelper.java380
-rw-r--r--services/core/java/com/android/server/pm/InstallPackageHelper.java410
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java38
-rw-r--r--services/core/java/com/android/server/pm/ScanPackageHelper.java151
-rw-r--r--services/core/java/com/android/server/pm/StorageEventHelper.java4
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);