diff options
| author | 2022-10-06 19:45:06 -0700 | |
|---|---|---|
| committer | 2022-10-24 21:19:35 -0700 | |
| commit | 378c4815671736de334cde8fd42e742e8e83b681 (patch) | |
| tree | f4c0d3786d4b90abce364d473dc594d0eee037f6 | |
| parent | 4f1033f742553979d333415b6e75e51d3b039777 (diff) | |
[pm] merge CommitRequest, PrepareResult, ReconcileRequest into InstallRequest
BUG: 238678399
Test: atest com.android.server.pm.ScanTests
Change-Id: I9f7d17d458318da89a6e47cdf9a0989825b1dbe5
15 files changed, 590 insertions, 516 deletions
diff --git a/services/core/java/com/android/server/pm/CommitRequest.java b/services/core/java/com/android/server/pm/CommitRequest.java deleted file mode 100644 index d1a6002590f2..000000000000 --- a/services/core/java/com/android/server/pm/CommitRequest.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.pm; - -import android.annotation.NonNull; - -import java.util.Map; - -/** - * Package state to commit to memory and disk after reconciliation has completed. - */ -final class CommitRequest { - final Map<String, ReconciledPackage> mReconciledPackages; - @NonNull final int[] mAllUsers; - - CommitRequest(Map<String, ReconciledPackage> reconciledPackages, - @NonNull int[] allUsers) { - mReconciledPackages = reconciledPackages; - mAllUsers = allUsers; - } -} diff --git a/services/core/java/com/android/server/pm/InitAppsHelper.java b/services/core/java/com/android/server/pm/InitAppsHelper.java index f6472a739979..6f5909615db2 100644 --- a/services/core/java/com/android/server/pm/InitAppsHelper.java +++ b/services/core/java/com/android/server/pm/InitAppsHelper.java @@ -352,8 +352,7 @@ final class InitAppsHelper { } @GuardedBy({"mPm.mInstallLock", "mPm.mLock"}) - private void scanDirTracedLI(File scanDir, - int parseFlags, int scanFlags, + private void scanDirTracedLI(File scanDir, int parseFlags, int scanFlags, PackageParser2 packageParser, ExecutorService executorService) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanDir [" + scanDir.getAbsolutePath() + "]"); try { diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java index 30ecc1cb4e8f..9d007c92bcc5 100644 --- a/services/core/java/com/android/server/pm/InstallPackageHelper.java +++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java @@ -245,50 +245,42 @@ final class InstallPackageHelper { @GuardedBy("mPm.mLock") public AndroidPackage commitReconciledScanResultLocked( @NonNull ReconciledPackage reconciledPkg, int[] allUsers) { - final ScanResult result = reconciledPkg.mScanResult; - final ScanRequest request = result.mRequest; + final InstallRequest request = reconciledPkg.mInstallRequest; // TODO(b/135203078): Move this even further away - ParsedPackage parsedPackage = request.mParsedPackage; - if ("android".equals(parsedPackage.getPackageName())) { + ParsedPackage parsedPackage = request.getParsedPackage(); + if (parsedPackage != null && "android".equals(parsedPackage.getPackageName())) { // TODO(b/135203078): Move this to initial parse parsedPackage.setVersionCode(mPm.getSdkVersion()) .setVersionCodeMajor(0); } - final AndroidPackage oldPkg = request.mOldPkg; - final @ParsingPackageUtils.ParseFlags int parseFlags = request.mParseFlags; - final @PackageManagerService.ScanFlags int scanFlags = request.mScanFlags; - final PackageSetting oldPkgSetting = request.mOldPkgSetting; - final PackageSetting originalPkgSetting = request.mOriginalPkgSetting; - final UserHandle user = request.mUser; - final String realPkgName = request.mRealPkgName; - final List<String> changedAbiCodePath = result.mChangedAbiCodePath; + final @PackageManagerService.ScanFlags int scanFlags = request.getScanFlags(); + final PackageSetting oldPkgSetting = request.getScanRequestOldPackageSetting(); + final PackageSetting originalPkgSetting = request.getScanRequestOriginalPackageSetting(); + final String realPkgName = request.getRealPackageName(); + final List<String> changedAbiCodePath = request.getChangedAbiCodePath(); final PackageSetting pkgSetting; - if (request.mPkgSetting != null) { + if (request.getScanRequestPackageSetting() != null) { SharedUserSetting requestSharedUserSetting = mPm.mSettings.getSharedUserSettingLPr( - request.mPkgSetting); + request.getScanRequestPackageSetting()); SharedUserSetting resultSharedUserSetting = mPm.mSettings.getSharedUserSettingLPr( - result.mPkgSetting); + request.getScanRequestPackageSetting()); if (requestSharedUserSetting != null && requestSharedUserSetting != resultSharedUserSetting) { // shared user changed, remove from old shared user - requestSharedUserSetting.removePackage(request.mPkgSetting); + requestSharedUserSetting.removePackage(request.getScanRequestPackageSetting()); // Prune unused SharedUserSetting if (mPm.mSettings.checkAndPruneSharedUserLPw(requestSharedUserSetting, false)) { // Set the app ID in removed info for UID_REMOVED broadcasts - if (reconciledPkg.mInstallRequest != null - && reconciledPkg.mInstallRequest.getRemovedInfo() != null) { - reconciledPkg.mInstallRequest.getRemovedInfo().mRemovedAppId = - requestSharedUserSetting.mAppId; - } + request.setRemovedAppId(requestSharedUserSetting.mAppId); } } } - if (result.mExistingSettingCopied) { - pkgSetting = request.mPkgSetting; - pkgSetting.updateFrom(result.mPkgSetting); + if (request.isExistingSettingCopied()) { + pkgSetting = request.getScanRequestPackageSetting(); + pkgSetting.updateFrom(request.getScannedPackageSetting()); } else { - pkgSetting = result.mPkgSetting; + pkgSetting = request.getScannedPackageSetting(); if (originalPkgSetting != null) { mPm.mSettings.addRenamedPackageLPw( AndroidPackageUtils.getRealPackageOrNull(parsedPackage), @@ -308,26 +300,23 @@ final class InstallPackageHelper { mPm.mSettings.convertSharedUserSettingsLPw(sharedUserSetting); } } - if (reconciledPkg.mInstallRequest != null - && reconciledPkg.mInstallRequest.isForceQueryableOverride()) { + if (request.isForceQueryableOverride()) { pkgSetting.setForceQueryableOverride(true); } // If this is part of a standard install, set the initiating package name, else rely on // previous device state. - if (reconciledPkg.mInstallRequest != null) { - InstallSource installSource = reconciledPkg.mInstallRequest.getInstallSource(); - if (installSource != null) { - if (installSource.initiatingPackageName != null) { - final PackageSetting ips = mPm.mSettings.getPackageLPr( - installSource.initiatingPackageName); - if (ips != null) { - installSource = installSource.setInitiatingPackageSignatures( - ips.getSignatures()); - } + InstallSource installSource = request.getInstallSource(); + if (installSource != null) { + if (installSource.initiatingPackageName != null) { + final PackageSetting ips = mPm.mSettings.getPackageLPr( + installSource.initiatingPackageName); + if (ips != null) { + installSource = installSource.setInitiatingPackageSignatures( + ips.getSignatures()); } - pkgSetting.setInstallSource(installSource); } + pkgSetting.setInstallSource(installSource); } if ((scanFlags & SCAN_AS_APK_IN_APEX) != 0) { @@ -382,10 +371,9 @@ final class InstallPackageHelper { } } - final int userId = user == null ? 0 : user.getIdentifier(); + final int userId = request.getUserId(); // Modify state for the given package setting - commitPackageSettings(pkg, oldPkg, pkgSetting, oldPkgSetting, scanFlags, - (parseFlags & ParsingPackageUtils.PARSE_CHATTY) != 0 /*chatty*/, reconciledPkg); + commitPackageSettings(pkg, pkgSetting, oldPkgSetting, reconciledPkg); if (pkgSetting.getInstantApp(userId)) { mPm.mInstantAppRegistry.addInstantApp(userId, pkgSetting.getAppId()); } @@ -401,11 +389,14 @@ final class InstallPackageHelper { * Adds a scanned package to the system. When this method is finished, the package will * be available for query, resolution, etc... */ - private void commitPackageSettings(@NonNull AndroidPackage pkg, @Nullable AndroidPackage oldPkg, + private void commitPackageSettings(@NonNull AndroidPackage pkg, @NonNull PackageSetting pkgSetting, @Nullable PackageSetting oldPkgSetting, - final @PackageManagerService.ScanFlags int scanFlags, boolean chatty, ReconciledPackage reconciledPkg) { final String pkgName = pkg.getPackageName(); + final InstallRequest request = reconciledPkg.mInstallRequest; + final AndroidPackage oldPkg = request.getScanRequestOldPackage(); + final int scanFlags = request.getScanFlags(); + final boolean chatty = (request.getParseFlags() & ParsingPackageUtils.PARSE_CHATTY) != 0; if (mPm.mCustomResolverComponentName != null && mPm.mCustomResolverComponentName.getPackageName().equals(pkg.getPackageName())) { mPm.setUpCustomResolverActivity(pkg, pkgSetting); @@ -421,9 +412,7 @@ final class InstallPackageHelper { reconciledPkg.mAllowedSharedLibraryInfos, reconciledPkg.getCombinedAvailablePackages(), scanFlags); - if (reconciledPkg.mInstallRequest != null) { - reconciledPkg.mInstallRequest.setLibraryConsumers(clientLibPkgs); - } + request.setLibraryConsumers(clientLibPkgs); if ((scanFlags & SCAN_BOOTING) != 0) { // No apps can run during boot scan, so they don't need to be frozen @@ -438,8 +427,7 @@ final class InstallPackageHelper { mPm.snapshotComputer().checkPackageFrozen(pkgName); } - final boolean isReplace = - reconciledPkg.mPrepareResult != null && reconciledPkg.mPrepareResult.mReplace; + final boolean isReplace = request.isReplace(); // Also need to kill any apps that are dependent on the library, except the case of // installation of new version static shared library. if (clientLibPkgs != null) { @@ -705,6 +693,9 @@ final class InstallPackageHelper { * Returns whether the restore successfully completed. */ private boolean performBackupManagerRestore(int userId, int token, InstallRequest request) { + if (request.getPkg() == null) { + return false; + } IBackupManager iBackupManager = mInjector.getIBackupManager(); if (iBackupManager != null) { // For backwards compatibility as USER_ALL previously routed directly to USER_SYSTEM @@ -743,6 +734,9 @@ final class InstallPackageHelper { * Returns whether the restore successfully completed. */ private boolean performRollbackManagerRestore(int userId, int token, InstallRequest request) { + if (request.getPkg() == null) { + return false; + } final String packageName = request.getPkg().getPackageName(); final int[] allUsers = mPm.mUserManager.getUserIds(); final int[] installedUsers; @@ -810,22 +804,16 @@ final class InstallPackageHelper { */ @GuardedBy("mPm.mInstallLock") private void installPackagesLI(List<InstallRequest> requests) { - final Map<String, ScanResult> preparedScans = new ArrayMap<>(requests.size()); - final Map<String, PrepareResult> prepareResults = new ArrayMap<>(requests.size()); - final Map<String, InstallRequest> installRequests = new ArrayMap<>(requests.size()); + final Set<String> scannedPackages = new ArraySet<>(requests.size()); final Map<String, Settings.VersionInfo> versionInfos = new ArrayMap<>(requests.size()); final Map<String, Boolean> createdAppId = new ArrayMap<>(requests.size()); boolean success = false; try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "installPackagesLI"); for (InstallRequest request : requests) { - // TODO(b/109941548): remove this once we've pulled everything from it and into - // scan, reconcile or commit. - final PrepareResult prepareResult; try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "preparePackage"); - prepareResult = - preparePackageLI(request); + preparePackageLI(request); } catch (PrepareFailure prepareFailure) { request.setError(prepareFailure.error, prepareFailure.getMessage()); @@ -835,28 +823,31 @@ final class InstallPackageHelper { } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } - request.setReturnCode(PackageManager.INSTALL_SUCCEEDED); - request.setInstallerPackageName(request.getSourceInstallerPackageName()); - final String packageName = prepareResult.mPackageToScan.getPackageName(); - prepareResults.put(packageName, prepareResult); - installRequests.put(packageName, request); + final ParsedPackage packageToScan = request.getParsedPackage(); + if (packageToScan == null) { + request.setError(INSTALL_FAILED_SESSION_INVALID, + "Failed to obtain package to scan"); + return; + } + request.setReturnCode(PackageManager.INSTALL_SUCCEEDED); + final String packageName = packageToScan.getPackageName(); try { - final ScanResult result = scanPackageTracedLI( - prepareResult.mPackageToScan, prepareResult.mParseFlags, - prepareResult.mScanFlags, System.currentTimeMillis(), - request.getUser(), request.getAbiOverride()); - if (null != preparedScans.put(result.mPkgSetting.getPkg().getPackageName(), - result)) { + final ScanResult scanResult = scanPackageTracedLI(request.getParsedPackage(), + request.getParseFlags(), request.getScanFlags(), + System.currentTimeMillis(), request.getUser(), + request.getAbiOverride()); + request.setScanResult(scanResult); + if (!scannedPackages.add(packageName)) { request.setError( PackageManager.INSTALL_FAILED_DUPLICATE_PACKAGE, "Duplicate package " - + result.mPkgSetting.getPkg().getPackageName() + + packageName + " in multi-package install request."); return; } if (!checkNoAppStorageIsConsistent( - result.mRequest.mOldPkg, result.mPkgSetting.getPkg())) { + request.getScanRequestOldPackage(), packageToScan)) { // TODO: INSTALL_FAILED_UPDATE_INCOMPATIBLE is about incomptabible // signatures. Is there a better error code? request.setError( @@ -865,31 +856,28 @@ final class InstallPackageHelper { + PackageManager.PROPERTY_NO_APP_DATA_STORAGE); return; } - final boolean isApex = (result.mRequest.mScanFlags & SCAN_AS_APEX) != 0; + final boolean isApex = (request.getScanFlags() & SCAN_AS_APEX) != 0; if (!isApex) { - createdAppId.put(packageName, optimisticallyRegisterAppId(result)); + createdAppId.put(packageName, optimisticallyRegisterAppId(request)); } else { - result.mPkgSetting.setAppId(Process.INVALID_UID); + request.getScannedPackageSetting().setAppId(Process.INVALID_UID); } - versionInfos.put(result.mPkgSetting.getPkg().getPackageName(), - mPm.getSettingsVersionForPackage(result.mPkgSetting.getPkg())); + versionInfos.put(packageName, + mPm.getSettingsVersionForPackage(packageToScan)); } catch (PackageManagerException e) { request.setError("Scanning Failed.", e); return; } } - CommitRequest commitRequest; + Map<String, ReconciledPackage> reconciledPackages; synchronized (mPm.mLock) { - ReconcileRequest reconcileRequest = new ReconcileRequest(preparedScans, - installRequests, prepareResults, - Collections.unmodifiableMap(mPm.mPackages), versionInfos); - Map<String, ReconciledPackage> reconciledPackages; try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "reconcilePackages"); reconciledPackages = ReconcilePackageUtils.reconcilePackages( - reconcileRequest, mSharedLibraries, - mPm.mSettings.getKeySetManagerService(), mPm.mSettings); + requests, Collections.unmodifiableMap(mPm.mPackages), + versionInfos, mSharedLibraries, mPm.mSettings.getKeySetManagerService(), + mPm.mSettings); } catch (ReconcileFailure e) { for (InstallRequest request : requests) { request.setError("Reconciliation failed...", e); @@ -900,15 +888,13 @@ final class InstallPackageHelper { } try { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "commitPackages"); - commitRequest = new CommitRequest(reconciledPackages, - mPm.mUserManager.getUserIds()); - commitPackagesLocked(commitRequest); + commitPackagesLocked(reconciledPackages, mPm.mUserManager.getUserIds()); success = true; } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } } - executePostCommitStepsLIF(commitRequest); + executePostCommitStepsLIF(reconciledPackages); } finally { if (success) { for (InstallRequest request : requests) { @@ -932,10 +918,10 @@ final class InstallPackageHelper { request.getDataLoaderType(), request.getUser(), mContext); } } else { - for (ScanResult result : preparedScans.values()) { - if (createdAppId.getOrDefault(result.mRequest.mParsedPackage.getPackageName(), - false)) { - cleanUpAppIdCreation(result); + for (InstallRequest installRequest : requests) { + if (installRequest.getParsedPackage() != null && createdAppId.getOrDefault( + installRequest.getParsedPackage().getPackageName(), false)) { + cleanUpAppIdCreation(installRequest); } } // TODO(b/194319951): create a more descriptive reason than unknown @@ -968,8 +954,7 @@ final class InstallPackageHelper { } @GuardedBy("mPm.mInstallLock") - private PrepareResult preparePackageLI(InstallRequest request) - throws PrepareFailure { + private void preparePackageLI(InstallRequest request) throws PrepareFailure { final int installFlags = request.getInstallFlags(); final boolean onExternal = request.getVolumeUuid() != null; final boolean instantApp = ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0); @@ -1550,8 +1535,7 @@ final class InstallPackageHelper { // don't allow an upgrade from full to ephemeral if (isInstantApp) { - if (request.getUser() == null - || request.getUserId() == UserHandle.USER_ALL) { + if (request.getUserId() == UserHandle.USER_ALL) { for (int currentUser : allUsers) { if (!ps.getInstantApp(currentUser)) { // can't downgrade from full to instant @@ -1624,7 +1608,6 @@ final class InstallPackageHelper { targetParseFlags = systemParseFlags; targetScanFlags = systemScanFlags; } else { // non system replace - replace = true; if (DEBUG_INSTALL) { Slog.d(TAG, "replaceNonSystemPackageLI: new=" + parsedPackage + ", old=" @@ -1634,7 +1617,6 @@ final class InstallPackageHelper { } else { // new package install ps = null; disabledPs = null; - replace = false; oldPackage = null; // Remember this for later, in case we need to rollback this install String pkgName1 = parsedPackage.getPackageName(); @@ -1665,7 +1647,7 @@ final class InstallPackageHelper { // we're passing the freezer back to be closed in a later phase of install shouldCloseFreezerBeforeReturn = false; - return new PrepareResult(replace, targetScanFlags, targetParseFlags, + request.setPrepareResult(replace, targetScanFlags, targetParseFlags, oldPackage, parsedPackage, replace /* clearCodeCache */, sysPkg, ps, disabledPs); } finally { @@ -1894,19 +1876,18 @@ final class InstallPackageHelper { } @GuardedBy("mPm.mLock") - private void commitPackagesLocked(final CommitRequest request) { + private void commitPackagesLocked(Map<String, ReconciledPackage> reconciledPackages, + @NonNull int[] allUsers) { // TODO: remove any expected failures from this method; this should only be able to fail due // to unavoidable errors (I/O, etc.) - for (ReconciledPackage reconciledPkg : request.mReconciledPackages.values()) { - final ScanResult scanResult = reconciledPkg.mScanResult; - final ScanRequest scanRequest = scanResult.mRequest; - final ParsedPackage parsedPackage = scanRequest.mParsedPackage; - final String packageName = parsedPackage.getPackageName(); + for (ReconciledPackage reconciledPkg : reconciledPackages.values()) { final InstallRequest installRequest = reconciledPkg.mInstallRequest; + final ParsedPackage parsedPackage = installRequest.getParsedPackage(); + final String packageName = parsedPackage.getPackageName(); final RemovePackageHelper removePackageHelper = new RemovePackageHelper(mPm); final DeletePackageHelper deletePackageHelper = new DeletePackageHelper(mPm); - if (reconciledPkg.mPrepareResult.mReplace) { + if (installRequest.isReplace()) { AndroidPackage oldPackage = mPm.mPackages.get(packageName); // Set the update and install times @@ -1914,15 +1895,16 @@ final class InstallPackageHelper { .getPackageStateInternal(oldPackage.getPackageName()); // TODO(b/225756739): For rebootless APEX, consider using lastUpdateMillis provided // by apexd to be more accurate. - reconciledPkg.mPkgSetting - .setFirstInstallTimeFromReplaced(deletedPkgSetting, request.mAllUsers) - .setLastUpdateTime(System.currentTimeMillis()); + installRequest.setScannedPackageSettingFirstInstallTimeFromReplaced( + deletedPkgSetting, allUsers); + installRequest.setScannedPackageSettingLastUpdateTime( + System.currentTimeMillis()); installRequest.getRemovedInfo().mBroadcastAllowList = mPm.mAppsFilter.getVisibilityAllowList(mPm.snapshotComputer(), - reconciledPkg.mPkgSetting, request.mAllUsers, - mPm.mSettings.getPackagesLocked()); - if (reconciledPkg.mPrepareResult.mSystem) { + installRequest.getScannedPackageSetting(), + allUsers, mPm.mSettings.getPackagesLocked()); + if (installRequest.isSystem()) { // Remove existing system package removePackageHelper.removePackage(oldPackage, true); if (!disableSystemPackageLPw(oldPackage)) { @@ -1942,7 +1924,7 @@ final class InstallPackageHelper { // Settings will be written during the call to updateSettingsLI(). deletePackageHelper.executeDeletePackage( reconciledPkg.mDeletePackageAction, packageName, - true, request.mAllUsers, false); + true, allUsers, false); } catch (SystemDeleteException e) { if (mPm.mIsEngBuild) { throw new RuntimeException("Unexpected failure", e); @@ -1952,7 +1934,7 @@ final class InstallPackageHelper { // Successfully deleted the old package; proceed with replace. // Update the in-memory copy of the previous code paths. PackageSetting ps1 = mPm.mSettings.getPackageLPr( - reconciledPkg.mPrepareResult.mExistingPackage.getPackageName()); + installRequest.getExistingPackageName()); if ((installRequest.getInstallFlags() & PackageManager.DONT_KILL_APP) == 0) { Set<String> oldCodePaths = ps1.getOldCodePaths(); @@ -1977,9 +1959,8 @@ final class InstallPackageHelper { } } - AndroidPackage pkg = commitReconciledScanResultLocked( - reconciledPkg, request.mAllUsers); - updateSettingsLI(pkg, reconciledPkg, request.mAllUsers, installRequest); + AndroidPackage pkg = commitReconciledScanResultLocked(reconciledPkg, allUsers); + updateSettingsLI(pkg, allUsers, installRequest); final PackageSetting ps = mPm.mSettings.getPackageLPr(packageName); if (ps != null) { @@ -2000,12 +1981,12 @@ final class InstallPackageHelper { return mPm.mSettings.disableSystemPackageLPw(oldPkg.getPackageName(), true); } - private void updateSettingsLI(AndroidPackage newPackage, ReconciledPackage reconciledPkg, + private void updateSettingsLI(AndroidPackage newPackage, int[] allUsers, InstallRequest installRequest) { - updateSettingsInternalLI(newPackage, reconciledPkg, allUsers, installRequest); + updateSettingsInternalLI(newPackage, allUsers, installRequest); } - private void updateSettingsInternalLI(AndroidPackage pkg, ReconciledPackage reconciledPkg, + private void updateSettingsInternalLI(AndroidPackage pkg, int[] allUsers, InstallRequest installRequest) { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "updateSettings"); @@ -2175,8 +2156,7 @@ final class InstallPackageHelper { } final int autoRevokePermissionsMode = installRequest.getAutoRevokePermissionsMode(); permissionParamsBuilder.setAutoRevokePermissionsMode(autoRevokePermissionsMode); - final ScanResult scanResult = reconciledPkg.mScanResult; - mPm.mPermissionManager.onPackageInstalled(pkg, scanResult.mPreviousAppId, + mPm.mPermissionManager.onPackageInstalled(pkg, installRequest.getPreviousAppId(), permissionParamsBuilder.build(), userId); // Apply restricted settings on potentially dangerous packages. if (installRequest.getPackageSource() == PackageInstaller.PACKAGE_SOURCE_LOCAL_FILE @@ -2216,14 +2196,13 @@ final class InstallPackageHelper { * locks on {@link com.android.server.pm.PackageManagerService.mLock}. */ @GuardedBy("mPm.mInstallLock") - private void executePostCommitStepsLIF(CommitRequest commitRequest) { + private void executePostCommitStepsLIF(Map<String, ReconciledPackage> reconciledPackages) { final ArraySet<IncrementalStorage> incrementalStorages = new ArraySet<>(); - for (ReconciledPackage reconciledPkg : commitRequest.mReconciledPackages.values()) { - final boolean instantApp = ((reconciledPkg.mScanResult.mRequest.mScanFlags - & SCAN_AS_INSTANT_APP) != 0); - final boolean isApex = ((reconciledPkg.mScanResult.mRequest.mScanFlags - & SCAN_AS_APEX) != 0); - final AndroidPackage pkg = reconciledPkg.mPkgSetting.getPkg(); + for (ReconciledPackage reconciledPkg : reconciledPackages.values()) { + final InstallRequest installRequest = reconciledPkg.mInstallRequest; + final boolean instantApp = ((installRequest.getScanFlags() & SCAN_AS_INSTANT_APP) != 0); + final boolean isApex = ((installRequest.getScanFlags() & SCAN_AS_APEX) != 0); + final AndroidPackage pkg = installRequest.getScannedPackageSetting().getPkg(); final String packageName = pkg.getPackageName(); final String codePath = pkg.getPath(); final boolean onIncremental = mIncrementalManager != null @@ -2238,12 +2217,12 @@ final class InstallPackageHelper { } // Hardcode previousAppId to 0 to disable any data migration (http://b/221088088) mAppDataHelper.prepareAppDataPostCommitLIF(pkg, 0); - if (reconciledPkg.mPrepareResult.mClearCodeCache) { + if (installRequest.isClearCodeCache()) { mAppDataHelper.clearAppDataLIF(pkg, UserHandle.USER_ALL, FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL | Installer.FLAG_CLEAR_CODE_CACHE_ONLY); } - if (reconciledPkg.mPrepareResult.mReplace) { + if (installRequest.isReplace()) { mDexManager.notifyPackageUpdated(pkg.getPackageName(), pkg.getBaseApkPath(), pkg.getSplitCodePaths()); } @@ -2252,14 +2231,13 @@ final class InstallPackageHelper { // This needs to be done before invoking dexopt so that any install-time profile // can be used for optimizations. mArtManagerService.prepareAppProfiles( - pkg, - mPm.resolveUserIds(reconciledPkg.mInstallRequest.getUserId()), + pkg, mPm.resolveUserIds(installRequest.getUserId()), /* updateReferenceProfileContent= */ true); // Compute the compilation reason from the installation scenario. final int compilationReason = mDexManager.getCompilationReasonForInstallScenario( - reconciledPkg.mInstallRequest.getInstallScenario()); + installRequest.getInstallScenario()); // Construct the DexoptOptions early to see if we should skip running dexopt. // @@ -2268,10 +2246,8 @@ final class InstallPackageHelper { // // Also, don't fail application installs if the dexopt step fails. final boolean isBackupOrRestore = - reconciledPkg.mInstallRequest.getInstallReason() - == INSTALL_REASON_DEVICE_RESTORE - || reconciledPkg.mInstallRequest.getInstallReason() - == INSTALL_REASON_DEVICE_SETUP; + installRequest.getInstallReason() == INSTALL_REASON_DEVICE_RESTORE + || installRequest.getInstallReason() == INSTALL_REASON_DEVICE_SETUP; final int dexoptFlags = DexoptOptions.DEXOPT_BOOT_COMPLETE | DexoptOptions.DEXOPT_INSTALL_WITH_DEX_METADATA_FILE @@ -2323,22 +2299,14 @@ final class InstallPackageHelper { } Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "dexopt"); - ScanResult result = reconciledPkg.mScanResult; // This mirrors logic from commitReconciledScanResultLocked, where the library files // needed for dexopt are assigned. - // TODO: Fix this to have 1 mutable PackageSetting for scan/install. If the previous - // setting needs to be passed to have a comparison, hide it behind an immutable - // interface. There's no good reason to have 3 different ways to access the real - // PackageSetting object, only one of which is actually correct. - PackageSetting realPkgSetting = result.mExistingSettingCopied - ? result.mRequest.mPkgSetting : result.mPkgSetting; - if (realPkgSetting == null) { - realPkgSetting = reconciledPkg.mPkgSetting; - } + PackageSetting realPkgSetting = installRequest.getRealPackageSetting(); // Unfortunately, the updated system app flag is only tracked on this PackageSetting - boolean isUpdatedSystemApp = reconciledPkg.mPkgSetting.getPkgState() + boolean isUpdatedSystemApp = + installRequest.getScannedPackageSetting().getPkgState() .isUpdatedSystemApp(); realPkgSetting.getPkgState().setUpdatedSystemApp(isUpdatedSystemApp); @@ -3059,7 +3027,7 @@ final class InstallPackageHelper { final RemovePackageHelper removePackageHelper = new RemovePackageHelper(mPm); removePackageHelper.removePackage(stubPkg, true /*chatty*/); try { - return scanSystemPackageTracedLI(scanFile, parseFlags, scanFlags, null); + return scanSystemPackageTracedLI(scanFile, parseFlags, scanFlags); } catch (PackageManagerException e) { Slog.w(TAG, "Failed to install compressed system package:" + stubPkg.getPackageName(), e); @@ -3191,7 +3159,7 @@ final class InstallPackageHelper { | ParsingPackageUtils.PARSE_IS_SYSTEM_DIR; @PackageManagerService.ScanFlags int scanFlags = mPm.getSystemPackageScanFlags(codePath); final AndroidPackage pkg = scanSystemPackageTracedLI( - codePath, parseFlags, scanFlags, null); + codePath, parseFlags, scanFlags); synchronized (mPm.mLock) { PackageSetting pkgSetting = mPm.mSettings.getPackageLPr(pkg.getPackageName()); @@ -3371,7 +3339,7 @@ final class InstallPackageHelper { try { final File codePath = new File(pkg.getPath()); synchronized (mPm.mInstallLock) { - scanSystemPackageTracedLI(codePath, 0, scanFlags, null); + scanSystemPackageTracedLI(codePath, 0, scanFlags); } } catch (PackageManagerException e) { Slog.e(TAG, "Failed to parse updated, ex-system package: " @@ -3521,7 +3489,7 @@ final class InstallPackageHelper { } try { addForInitLI(parseResult.parsedPackage, parseFlags, scanFlags, - null); + new UserHandle(UserHandle.USER_SYSTEM)); } catch (PackageManagerException e) { errorCode = e.error; errorMsg = "Failed to scan " + parseResult.scanFile + ": " + e.getMessage(); @@ -3584,7 +3552,7 @@ final class InstallPackageHelper { try { synchronized (mPm.mInstallLock) { final AndroidPackage newPkg = scanSystemPackageTracedLI( - scanFile, reparseFlags, rescanFlags, null); + scanFile, reparseFlags, rescanFlags); // We rescanned a stub, add it to the list of stubbed system packages if (newPkg.isStub()) { stubSystemApps.add(packageName); @@ -3603,10 +3571,10 @@ final class InstallPackageHelper { */ @GuardedBy("mPm.mInstallLock") public AndroidPackage scanSystemPackageTracedLI(File scanFile, final int parseFlags, - int scanFlags, UserHandle user) throws PackageManagerException { + int scanFlags) throws PackageManagerException { Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "scanPackage [" + scanFile.toString() + "]"); try { - return scanSystemPackageLI(scanFile, parseFlags, scanFlags, user); + return scanSystemPackageLI(scanFile, parseFlags, scanFlags); } finally { Trace.traceEnd(TRACE_TAG_PACKAGE_MANAGER); } @@ -3617,8 +3585,8 @@ final class InstallPackageHelper { * Returns {@code null} in case of errors and the error code is stored in mLastScanError */ @GuardedBy("mPm.mInstallLock") - private AndroidPackage scanSystemPackageLI(File scanFile, int parseFlags, int scanFlags, - UserHandle user) throws PackageManagerException { + private AndroidPackage scanSystemPackageLI(File scanFile, int parseFlags, int scanFlags) + throws PackageManagerException { if (DEBUG_INSTALL) Slog.d(TAG, "Parsing: " + scanFile); Trace.traceBegin(TRACE_TAG_PACKAGE_MANAGER, "parsePackage"); @@ -3634,7 +3602,8 @@ final class InstallPackageHelper { PackageManagerService.renameStaticSharedLibraryPackage(parsedPackage); } - return addForInitLI(parsedPackage, parseFlags, scanFlags, user); + return addForInitLI(parsedPackage, parseFlags, scanFlags, + new UserHandle(UserHandle.USER_SYSTEM)); } /** @@ -3660,33 +3629,32 @@ final class InstallPackageHelper { parsedPackage, parseFlags, scanFlags, 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 ReconcileRequest reconcileRequest = new ReconcileRequest( - Collections.singletonMap(pkgName, scanResult), - mPm.mPackages, - Collections.singletonMap(pkgName, - mPm.getSettingsVersionForPackage(parsedPackage))); - final Map<String, ReconciledPackage> reconcileResult = - ReconcilePackageUtils.reconcilePackages(reconcileRequest, - mSharedLibraries, mPm.mSettings.getKeySetManagerService(), - mPm.mSettings); - if ((scanFlags & SCAN_AS_APEX) == 0) { - appIdCreated = optimisticallyRegisterAppId(scanResult); - } else { - scanResult.mPkgSetting.setAppId(Process.INVALID_UID); - } - commitReconciledScanResultLocked(reconcileResult.get(pkgName), - mPm.mUserManager.getUserIds()); - } catch (PackageManagerException e) { - if (appIdCreated) { - cleanUpAppIdCreation(scanResult); - } - throw e; + final InstallRequest installRequest = new InstallRequest( + parsedPackage, parseFlags, scanFlags, user, scanResult); + + synchronized (mPm.mLock) { + boolean appIdCreated = false; + try { + final String pkgName = scanResult.mPkgSetting.getPackageName(); + final Map<String, ReconciledPackage> reconcileResult = + ReconcilePackageUtils.reconcilePackages( + Collections.singletonList(installRequest), + mPm.mPackages, Collections.singletonMap(pkgName, + mPm.getSettingsVersionForPackage(parsedPackage)), + mSharedLibraries, mPm.mSettings.getKeySetManagerService(), + mPm.mSettings); + if ((scanFlags & SCAN_AS_APEX) == 0) { + appIdCreated = optimisticallyRegisterAppId(installRequest); + } else { + installRequest.setScannedPackageSettingAppId(Process.INVALID_UID); } + commitReconciledScanResultLocked(reconcileResult.get(pkgName), + mPm.mUserManager.getUserIds()); + } catch (PackageManagerException e) { + if (appIdCreated) { + cleanUpAppIdCreation(installRequest); + } + throw e; } } @@ -3711,13 +3679,14 @@ final class InstallPackageHelper { * @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) + private boolean optimisticallyRegisterAppId(@NonNull InstallRequest installRequest) throws PackageManagerException { - if (!result.mExistingSettingCopied || result.needsNewAppId()) { + if (!installRequest.isExistingSettingCopied() || installRequest.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 mPm.mSettings.registerAppIdLPw(installRequest.getScannedPackageSetting(), + installRequest.needsNewAppId()); } } return false; @@ -3725,15 +3694,16 @@ final class InstallPackageHelper { /** * Reverts any app ID creation that were made by - * {@link #optimisticallyRegisterAppId(ScanResult)}. Note: this is only necessary if the + * {@link #optimisticallyRegisterAppId(InstallRequest)}. Note: this is only necessary if the * referenced method returned true. */ - private void cleanUpAppIdCreation(@NonNull ScanResult result) { + private void cleanUpAppIdCreation(@NonNull InstallRequest installRequest) { // 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) { + if (installRequest.getScannedPackageSetting() != null + && installRequest.getScannedPackageSetting().getAppId() > 0) { synchronized (mPm.mLock) { - mPm.mSettings.removeAppIdLPw(result.mPkgSetting.getAppId()); + mPm.mSettings.removeAppIdLPw(installRequest.getScannedPackageSetting().getAppId()); } } } @@ -3857,7 +3827,6 @@ final class InstallPackageHelper { } } - @GuardedBy("mPm.mInstallLock") private Pair<ScanResult, Boolean> scanSystemPackageLI(ParsedPackage parsedPackage, @ParsingPackageUtils.ParseFlags int parseFlags, @PackageManagerService.ScanFlags int scanFlags, diff --git a/services/core/java/com/android/server/pm/InstallRequest.java b/services/core/java/com/android/server/pm/InstallRequest.java index 36bbf41bffe6..573082a58255 100644 --- a/services/core/java/com/android/server/pm/InstallRequest.java +++ b/services/core/java/com/android/server/pm/InstallRequest.java @@ -18,6 +18,7 @@ package com.android.server.pm; import static android.content.pm.PackageManager.INSTALL_REASON_UNKNOWN; import static android.content.pm.PackageManager.INSTALL_SCENARIO_DEFAULT; +import static android.os.Process.INVALID_UID; import static com.android.server.pm.PackageManagerService.TAG; @@ -29,13 +30,19 @@ import android.content.pm.DataLoaderType; import android.content.pm.IPackageInstallObserver2; import android.content.pm.PackageInstaller; import android.content.pm.PackageManager; +import android.content.pm.SharedLibraryInfo; import android.content.pm.SigningDetails; import android.net.Uri; +import android.os.Build; +import android.os.Process; import android.os.UserHandle; import android.util.ExceptionUtils; import android.util.Slog; +import com.android.server.pm.parsing.pkg.ParsedPackage; import com.android.server.pm.pkg.AndroidPackage; +import com.android.server.pm.pkg.PackageStateInternal; +import com.android.server.pm.pkg.parsing.ParsingPackageUtils; import java.io.File; import java.util.ArrayList; @@ -45,13 +52,59 @@ final class InstallRequest { private final int mUserId; @Nullable private final InstallArgs mInstallArgs; - @NonNull - private final PackageInstalledInfo mInstalledInfo; @Nullable private Runnable mPostInstallRunnable; @Nullable private PackageRemovedInfo mRemovedInfo; + private @PackageManagerService.ScanFlags int mScanFlags; + private @ParsingPackageUtils.ParseFlags int mParseFlags; + private boolean mReplace; + + @Nullable /* The original Package if it is being replaced, otherwise {@code null} */ + private AndroidPackage mExistingPackage; + /** parsed package to be scanned */ + @Nullable + private ParsedPackage mParsedPackage; + private boolean mClearCodeCache; + private boolean mSystem; + @Nullable + private PackageSetting mOriginalPs; + @Nullable + private PackageSetting mDisabledPs; + + /** Package Installed Info */ + @Nullable + private String mName; + private int mUid = -1; + // The set of users that originally had this package installed. + @Nullable + private int[] mOrigUsers; + // The set of users that now have this package installed. + @Nullable + private int[] mNewUsers; + @Nullable + private AndroidPackage mPkg; + private int mReturnCode; + @Nullable + private String mReturnMsg; + // The set of packages consuming this shared library or null if no consumers exist. + @Nullable + private ArrayList<AndroidPackage> mLibraryConsumers; + @Nullable + private PackageFreezer mFreezer; + /** The package this package replaces */ + @Nullable + private String mOrigPackage; + @Nullable + private String mOrigPermission; + // The ApexInfo returned by ApexManager#installPackage, used by rebootless APEX install + @Nullable + private ApexInfo mApexInfo; + + @Nullable + private ScanResult mScanResult; + // New install InstallRequest(InstallingSession params) { mUserId = params.getUser().getIdentifier(); @@ -63,7 +116,6 @@ final class InstallRequest { params.mTraceMethod, params.mTraceCookie, params.mSigningDetails, params.mInstallReason, params.mInstallScenario, params.mForceQueryableOverride, params.mDataLoaderType, params.mPackageSource); - mInstalledInfo = new PackageInstalledInfo(); } // Install existing package as user @@ -71,56 +123,56 @@ final class InstallRequest { Runnable runnable) { mUserId = userId; mInstallArgs = null; - mInstalledInfo = new PackageInstalledInfo(); - mInstalledInfo.mReturnCode = returnCode; - mInstalledInfo.mPkg = pkg; - mInstalledInfo.mNewUsers = newUsers; + mReturnCode = returnCode; + mPkg = pkg; + mNewUsers = newUsers; mPostInstallRunnable = runnable; } - private static class PackageInstalledInfo { - String mName; - int mUid = -1; - // The set of users that originally had this package installed. - int[] mOrigUsers; - // The set of users that now have this package installed. - int[] mNewUsers; - AndroidPackage mPkg; - int mReturnCode; - String mReturnMsg; - String mInstallerPackageName; - // The set of packages consuming this shared library or null if no consumers exist. - ArrayList<AndroidPackage> mLibraryConsumers; - PackageFreezer mFreezer; - // In some error cases we want to convey more info back to the observer - String mOrigPackage; - String mOrigPermission; - // The ApexInfo returned by ApexManager#installPackage, used by rebootless APEX install - ApexInfo mApexInfo; + // addForInit + InstallRequest(ParsedPackage parsedPackage, int parseFlags, int scanFlags, + @Nullable UserHandle user, ScanResult scanResult) { + if (user != null) { + mUserId = user.getIdentifier(); + } else { + // APEX + mUserId = INVALID_UID; + } + mInstallArgs = null; + mParsedPackage = parsedPackage; + mParseFlags = parseFlags; + mScanFlags = scanFlags; + mScanResult = scanResult; } + @Nullable public String getName() { - return mInstalledInfo.mName; + return mName; } + @Nullable public String getReturnMsg() { - return mInstalledInfo.mReturnMsg; + return mReturnMsg; } + @Nullable public OriginInfo getOriginInfo() { return mInstallArgs == null ? null : mInstallArgs.mOriginInfo; } + @Nullable public PackageRemovedInfo getRemovedInfo() { return mRemovedInfo; } + @Nullable public String getOrigPackage() { - return mInstalledInfo.mOrigPackage; + return mOrigPackage; } + @Nullable public String getOrigPermission() { - return mInstalledInfo.mOrigPermission; + return mOrigPermission; } @Nullable @@ -140,7 +192,7 @@ final class InstallRequest { } public int getReturnCode() { - return mInstalledInfo.mReturnCode; + return mReturnCode; } @Nullable @@ -160,13 +212,13 @@ final class InstallRequest { @Nullable public String getMovePackageName() { - return (mInstallArgs != null && mInstallArgs.mMoveInfo != null) + return (mInstallArgs != null && mInstallArgs.mMoveInfo != null) ? mInstallArgs.mMoveInfo.mPackageName : null; } @Nullable public String getMoveFromCodePath() { - return (mInstallArgs != null && mInstallArgs.mMoveInfo != null) + return (mInstallArgs != null && mInstallArgs.mMoveInfo != null) ? mInstallArgs.mMoveInfo.mFromCodePath : null; } @@ -203,8 +255,9 @@ final class InstallRequest { return mInstallArgs == null ? null : mInstallArgs.mVolumeUuid; } + @Nullable public AndroidPackage getPkg() { - return mInstalledInfo.mPkg; + return mPkg; } @Nullable @@ -256,13 +309,15 @@ final class InstallRequest { @Nullable public Uri getOriginUri() { - return mInstallArgs == null ? null : Uri.fromFile(mInstallArgs.mOriginInfo.mResolvedFile); + return mInstallArgs == null ? null : Uri.fromFile(mInstallArgs.mOriginInfo.mResolvedFile); } + @Nullable public ApexInfo getApexInfo() { - return mInstalledInfo.mApexInfo; + return mApexInfo; } + @Nullable public String getSourceInstallerPackageName() { return mInstallArgs.mInstallSource.installerPackageName; } @@ -272,25 +327,33 @@ final class InstallRequest { && mInstallArgs.mInstallReason == PackageManager.INSTALL_REASON_ROLLBACK; } + @Nullable public int[] getNewUsers() { - return mInstalledInfo.mNewUsers; + return mNewUsers; } + @Nullable public int[] getOriginUsers() { - return mInstalledInfo.mOrigUsers; + return mOrigUsers; } public int getUid() { - return mInstalledInfo.mUid; + return mUid; } @Nullable public String[] getInstallGrantPermissions() { - return mInstallArgs == null ? null : mInstallArgs.mInstallGrantPermissions; + return mInstallArgs == null ? null : mInstallArgs.mInstallGrantPermissions; } + @Nullable public ArrayList<AndroidPackage> getLibraryConsumers() { - return mInstalledInfo.mLibraryConsumers; + return mLibraryConsumers; + } + + @Nullable + public AndroidPackage getExistingPackage() { + return mExistingPackage; } @Nullable @@ -312,13 +375,170 @@ final class InstallRequest { return mInstallArgs == null ? INSTALL_SCENARIO_DEFAULT : mInstallArgs.mInstallScenario; } + @Nullable + public ParsedPackage getParsedPackage() { + return mParsedPackage; + } + + public @ParsingPackageUtils.ParseFlags int getParseFlags() { + return mParseFlags; + } + + public @PackageManagerService.ScanFlags int getScanFlags() { + return mScanFlags; + } + + @Nullable + public String getExistingPackageName() { + if (mExistingPackage != null) { + return mExistingPackage.getPackageName(); + } + return null; + } + + @Nullable + public AndroidPackage getScanRequestOldPackage() { + assertScanResultExists(); + return mScanResult.mRequest.mOldPkg; + } + + public boolean isClearCodeCache() { + return mClearCodeCache; + } + + public boolean isReplace() { + return mReplace; + } + + public boolean isSystem() { + return mSystem; + } + + @Nullable + public PackageSetting getOriginalPackageSetting() { + return mOriginalPs; + } + + @Nullable + public PackageSetting getDisabledPackageSetting() { + return mDisabledPs; + } + + @Nullable + public PackageSetting getScanRequestOldPackageSetting() { + assertScanResultExists(); + return mScanResult.mRequest.mOldPkgSetting; + } + + @Nullable + public PackageSetting getScanRequestOriginalPackageSetting() { + assertScanResultExists(); + return mScanResult.mRequest.mOriginalPkgSetting; + } + + @Nullable + public PackageSetting getScanRequestPackageSetting() { + assertScanResultExists(); + return mScanResult.mRequest.mPkgSetting; + } + + @Nullable + public String getRealPackageName() { + assertScanResultExists(); + return mScanResult.mRequest.mRealPkgName; + } + + @Nullable + public List<String> getChangedAbiCodePath() { + assertScanResultExists(); + return mScanResult.mChangedAbiCodePath; + } + public boolean isForceQueryableOverride() { return mInstallArgs != null && mInstallArgs.mForceQueryableOverride; } + @Nullable + public SharedLibraryInfo getSdkSharedLibraryInfo() { + assertScanResultExists(); + return mScanResult.mSdkSharedLibraryInfo; + } + + @Nullable + public SharedLibraryInfo getStaticSharedLibraryInfo() { + assertScanResultExists(); + return mScanResult.mStaticSharedLibraryInfo; + } + + @Nullable + public List<SharedLibraryInfo> getDynamicSharedLibraryInfos() { + assertScanResultExists(); + return mScanResult.mDynamicSharedLibraryInfos; + } + + @Nullable + public PackageSetting getScannedPackageSetting() { + assertScanResultExists(); + return mScanResult.mPkgSetting; + } + + @Nullable + public PackageSetting getRealPackageSetting() { + // TODO: Fix this to have 1 mutable PackageSetting for scan/install. If the previous + // setting needs to be passed to have a comparison, hide it behind an immutable + // interface. There's no good reason to have 3 different ways to access the real + // PackageSetting object, only one of which is actually correct. + PackageSetting realPkgSetting = isExistingSettingCopied() + ? getScanRequestPackageSetting() : getScannedPackageSetting(); + if (realPkgSetting == null) { + realPkgSetting = getScannedPackageSetting(); + } + return realPkgSetting; + } + + public boolean isExistingSettingCopied() { + assertScanResultExists(); + return mScanResult.mExistingSettingCopied; + } + + /** + * Whether the original PackageSetting needs to be updated with + * a new app ID. Useful when leaving a sharedUserId. + */ + public boolean needsNewAppId() { + assertScanResultExists(); + return mScanResult.mPreviousAppId != Process.INVALID_UID; + } + + public int getPreviousAppId() { + assertScanResultExists(); + return mScanResult.mPreviousAppId; + } + + public boolean isPlatformPackage() { + assertScanResultExists(); + return mScanResult.mRequest.mIsPlatformPackage; + } + + public void assertScanResultExists() { + if (mScanResult == null) { + // Should not happen. This indicates a bug in the installation code flow + if (Build.IS_USERDEBUG || Build.IS_ENG) { + throw new IllegalStateException("ScanResult cannot be null."); + } else { + Slog.e(TAG, "ScanResult is null and it should not happen"); + } + } + + } + + public void setScanFlags(int scanFlags) { + mScanFlags = scanFlags; + } + public void closeFreezer() { - if (mInstalledInfo.mFreezer != null) { - mInstalledInfo.mFreezer.close(); + if (mFreezer != null) { + mFreezer.close(); } } @@ -341,57 +561,53 @@ final class InstallRequest { } public void setError(String msg, PackageManagerException e) { - mInstalledInfo.mReturnCode = e.error; + mReturnCode = e.error; setReturnMessage(ExceptionUtils.getCompleteMessage(msg, e)); Slog.w(TAG, msg, e); } public void setReturnCode(int returnCode) { - mInstalledInfo.mReturnCode = returnCode; + mReturnCode = returnCode; } public void setReturnMessage(String returnMsg) { - mInstalledInfo.mReturnMsg = returnMsg; + mReturnMsg = returnMsg; } public void setApexInfo(ApexInfo apexInfo) { - mInstalledInfo.mApexInfo = apexInfo; + mApexInfo = apexInfo; } public void setPkg(AndroidPackage pkg) { - mInstalledInfo.mPkg = pkg; + mPkg = pkg; } public void setUid(int uid) { - mInstalledInfo.mUid = uid; + mUid = uid; } public void setNewUsers(int[] newUsers) { - mInstalledInfo.mNewUsers = newUsers; + mNewUsers = newUsers; } public void setOriginPackage(String originPackage) { - mInstalledInfo.mOrigPackage = originPackage; + mOrigPackage = originPackage; } public void setOriginPermission(String originPermission) { - mInstalledInfo.mOrigPermission = originPermission; - } - - public void setInstallerPackageName(String installerPackageName) { - mInstalledInfo.mInstallerPackageName = installerPackageName; + mOrigPermission = originPermission; } public void setName(String packageName) { - mInstalledInfo.mName = packageName; + mName = packageName; } public void setOriginUsers(int[] userIds) { - mInstalledInfo.mOrigUsers = userIds; + mOrigUsers = userIds; } public void setFreezer(PackageFreezer freezer) { - mInstalledInfo.mFreezer = freezer; + mFreezer = freezer; } public void setRemovedInfo(PackageRemovedInfo removedInfo) { @@ -399,6 +615,47 @@ final class InstallRequest { } public void setLibraryConsumers(ArrayList<AndroidPackage> libraryConsumers) { - mInstalledInfo.mLibraryConsumers = libraryConsumers; + mLibraryConsumers = libraryConsumers; + } + + public void setPrepareResult(boolean replace, int scanFlags, + int parseFlags, AndroidPackage existingPackage, + ParsedPackage packageToScan, boolean clearCodeCache, boolean system, + PackageSetting originalPs, PackageSetting disabledPs) { + mReplace = replace; + mScanFlags = scanFlags; + mParseFlags = parseFlags; + mExistingPackage = existingPackage; + mParsedPackage = packageToScan; + mClearCodeCache = clearCodeCache; + mSystem = system; + mOriginalPs = originalPs; + mDisabledPs = disabledPs; + } + + public void setScanResult(@NonNull ScanResult scanResult) { + mScanResult = scanResult; + } + + public void setScannedPackageSettingAppId(int appId) { + assertScanResultExists(); + mScanResult.mPkgSetting.setAppId(appId); + } + + public void setScannedPackageSettingFirstInstallTimeFromReplaced( + @Nullable PackageStateInternal replacedPkgSetting, int[] userId) { + assertScanResultExists(); + mScanResult.mPkgSetting.setFirstInstallTimeFromReplaced(replacedPkgSetting, userId); + } + + public void setScannedPackageSettingLastUpdateTime(long lastUpdateTim) { + assertScanResultExists(); + mScanResult.mPkgSetting.setLastUpdateTime(lastUpdateTim); + } + + public void setRemovedAppId(int appId) { + if (mRemovedInfo != null) { + mRemovedInfo.mRemovedAppId = appId; + } } } diff --git a/services/core/java/com/android/server/pm/InstallingSession.java b/services/core/java/com/android/server/pm/InstallingSession.java index 8d5a5e156e71..16b3a815c075 100644 --- a/services/core/java/com/android/server/pm/InstallingSession.java +++ b/services/core/java/com/android/server/pm/InstallingSession.java @@ -42,7 +42,7 @@ import android.content.pm.parsing.PackageLite; import android.os.Environment; import android.os.Trace; import android.os.UserHandle; -import android.util.ArrayMap; +import android.util.ArraySet; import android.util.Pair; import android.util.Slog; @@ -60,7 +60,7 @@ import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Map; +import java.util.Set; class InstallingSession { final OriginInfo mOriginInfo; @@ -599,7 +599,7 @@ class InstallingSession { */ private class MultiPackageInstallingSession { private final List<InstallingSession> mChildInstallingSessions; - private final Map<InstallRequest, Integer> mCurrentState; + private final Set<InstallRequest> mCurrentInstallRequests; @NonNull final PackageManagerService mPm; final UserHandle mUser; @@ -618,7 +618,7 @@ class InstallingSession { final InstallingSession childInstallingSession = childInstallingSessions.get(i); childInstallingSession.mParentInstallingSession = this; } - this.mCurrentState = new ArrayMap<>(mChildInstallingSessions.size()); + mCurrentInstallRequests = new ArraySet<>(mChildInstallingSessions.size()); } public void start() { @@ -636,23 +636,24 @@ class InstallingSession { } public void tryProcessInstallRequest(InstallRequest request) { - mCurrentState.put(request, request.getReturnCode()); - if (mCurrentState.size() != mChildInstallingSessions.size()) { + mCurrentInstallRequests.add(request); + if (mCurrentInstallRequests.size() != mChildInstallingSessions.size()) { return; } int completeStatus = PackageManager.INSTALL_SUCCEEDED; - for (Integer status : mCurrentState.values()) { - if (status == PackageManager.INSTALL_UNKNOWN) { + for (InstallRequest installRequest : mCurrentInstallRequests) { + if (installRequest.getReturnCode() == PackageManager.INSTALL_UNKNOWN) { return; - } else if (status != PackageManager.INSTALL_SUCCEEDED) { - completeStatus = status; + } else if (installRequest.getReturnCode() != PackageManager.INSTALL_SUCCEEDED) { + completeStatus = installRequest.getReturnCode(); break; } } - final List<InstallRequest> installRequests = new ArrayList<>(mCurrentState.size()); - for (Map.Entry<InstallRequest, Integer> entry : mCurrentState.entrySet()) { - entry.getKey().setReturnCode(completeStatus); - installRequests.add(entry.getKey()); + final List<InstallRequest> installRequests = new ArrayList<>( + mCurrentInstallRequests.size()); + for (InstallRequest installRequest : mCurrentInstallRequests) { + installRequest.setReturnCode(completeStatus); + installRequests.add(installRequest); } int finalCompleteStatus = completeStatus; mPm.mHandler.post(() -> processInstallRequests( diff --git a/services/core/java/com/android/server/pm/PrepareResult.java b/services/core/java/com/android/server/pm/PrepareResult.java deleted file mode 100644 index e074f44afff5..000000000000 --- a/services/core/java/com/android/server/pm/PrepareResult.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.pm; - -import android.annotation.Nullable; - -import com.android.server.pm.parsing.pkg.ParsedPackage; -import com.android.server.pm.pkg.AndroidPackage; - -/** - * The set of data needed to successfully install the prepared package. This includes data that - * will be used to scan and reconcile the package. - */ -final class PrepareResult { - public final boolean mReplace; - public final int mScanFlags; - public final int mParseFlags; - @Nullable /* The original Package if it is being replaced, otherwise {@code null} */ - public final AndroidPackage mExistingPackage; - public final ParsedPackage mPackageToScan; - public final boolean mClearCodeCache; - public final boolean mSystem; - public final PackageSetting mOriginalPs; - public final PackageSetting mDisabledPs; - - PrepareResult(boolean replace, int scanFlags, - int parseFlags, AndroidPackage existingPackage, - ParsedPackage packageToScan, boolean clearCodeCache, boolean system, - PackageSetting originalPs, PackageSetting disabledPs) { - mReplace = replace; - mScanFlags = scanFlags; - mParseFlags = parseFlags; - mExistingPackage = existingPackage; - mPackageToScan = packageToScan; - mClearCodeCache = clearCodeCache; - mSystem = system; - mOriginalPs = originalPs; - mDisabledPs = disabledPs; - } -} diff --git a/services/core/java/com/android/server/pm/ReconcilePackageUtils.java b/services/core/java/com/android/server/pm/ReconcilePackageUtils.java index 165b450ce65b..ffce69e00d24 100644 --- a/services/core/java/com/android/server/pm/ReconcilePackageUtils.java +++ b/services/core/java/com/android/server/pm/ReconcilePackageUtils.java @@ -38,34 +38,44 @@ import com.android.server.utils.WatchedLongSparseArray; import java.util.List; import java.util.Map; +/** + * Package scan results and related request details used to reconcile the potential addition of + * one or more packages to the system. + * + * Reconcile will take a set of package details that need to be committed to the system and make + * sure that they are valid in the context of the system and the other installing apps. Any + * invalid state or app will result in a failed reconciliation and thus whatever operation (such + * as install) led to the request. + */ final class ReconcilePackageUtils { public static Map<String, ReconciledPackage> reconcilePackages( - final ReconcileRequest request, SharedLibrariesImpl sharedLibraries, + List<InstallRequest> installRequests, + Map<String, AndroidPackage> allPackages, + Map<String, Settings.VersionInfo> versionInfos, + SharedLibrariesImpl sharedLibraries, KeySetManagerService ksms, Settings settings) throws ReconcileFailure { - final Map<String, ScanResult> scannedPackages = request.mScannedPackages; - - final Map<String, ReconciledPackage> result = new ArrayMap<>(scannedPackages.size()); + final Map<String, ReconciledPackage> result = new ArrayMap<>(installRequests.size()); // make a copy of the existing set of packages so we can combine them with incoming packages final ArrayMap<String, AndroidPackage> combinedPackages = - new ArrayMap<>(request.mAllPackages.size() + scannedPackages.size()); + new ArrayMap<>(allPackages.size() + installRequests.size()); - combinedPackages.putAll(request.mAllPackages); + combinedPackages.putAll(allPackages); final Map<String, WatchedLongSparseArray<SharedLibraryInfo>> incomingSharedLibraries = new ArrayMap<>(); - for (String installPackageName : scannedPackages.keySet()) { - final ScanResult scanResult = scannedPackages.get(installPackageName); + for (InstallRequest installRequest : installRequests) { + final String installPackageName = installRequest.getParsedPackage().getPackageName(); // add / replace existing with incoming packages - combinedPackages.put(scanResult.mPkgSetting.getPackageName(), - scanResult.mRequest.mParsedPackage); + combinedPackages.put(installRequest.getScannedPackageSetting().getPackageName(), + installRequest.getParsedPackage()); // in the first pass, we'll build up the set of incoming shared libraries final List<SharedLibraryInfo> allowedSharedLibInfos = - sharedLibraries.getAllowedSharedLibInfos(scanResult); + sharedLibraries.getAllowedSharedLibInfos(installRequest); if (allowedSharedLibInfos != null) { for (SharedLibraryInfo info : allowedSharedLibInfos) { if (!SharedLibraryUtils.addSharedLibraryToPackageVersionMap( @@ -76,24 +86,18 @@ final class ReconcilePackageUtils { } } - // the following may be null if we're just reconciling on boot (and not during install) - final InstallRequest installRequest = request.mInstallRequests.get(installPackageName); - final PrepareResult prepareResult = request.mPreparedPackages.get(installPackageName); - final boolean isInstall = installRequest != null; - if (isInstall && prepareResult == null) { - throw new ReconcileFailure("Reconcile arguments are not balanced for " - + installPackageName + "!"); - } + final DeletePackageAction deletePackageAction; // we only want to try to delete for non system apps - if (isInstall && prepareResult.mReplace && !prepareResult.mSystem) { - final boolean killApp = (scanResult.mRequest.mScanFlags & SCAN_DONT_KILL_APP) == 0; + if (installRequest.isReplace() && !installRequest.isSystem()) { + final boolean killApp = (installRequest.getScanFlags() & SCAN_DONT_KILL_APP) == 0; final int deleteFlags = PackageManager.DELETE_KEEP_DATA | (killApp ? 0 : PackageManager.DELETE_DONT_KILL_APP); deletePackageAction = DeletePackageHelper.mayDeletePackageLocked( installRequest.getRemovedInfo(), - prepareResult.mOriginalPs, prepareResult.mDisabledPs, + installRequest.getOriginalPackageSetting(), + installRequest.getDisabledPackageSetting(), deleteFlags, null /* all users */); if (deletePackageAction == null) { throw new ReconcileFailure( @@ -104,21 +108,24 @@ final class ReconcilePackageUtils { deletePackageAction = null; } - final int scanFlags = scanResult.mRequest.mScanFlags; - final int parseFlags = scanResult.mRequest.mParseFlags; - final ParsedPackage parsedPackage = scanResult.mRequest.mParsedPackage; - - final PackageSetting disabledPkgSetting = scanResult.mRequest.mDisabledPkgSetting; + final int scanFlags = installRequest.getScanFlags(); + final int parseFlags = installRequest.getParseFlags(); + final ParsedPackage parsedPackage = installRequest.getParsedPackage(); + final PackageSetting disabledPkgSetting = installRequest.getDisabledPackageSetting(); final PackageSetting lastStaticSharedLibSetting = - scanResult.mStaticSharedLibraryInfo == null ? null - : sharedLibraries.getStaticSharedLibLatestVersionSetting(scanResult); + installRequest.getStaticSharedLibraryInfo() == null ? null + : sharedLibraries.getStaticSharedLibLatestVersionSetting( + installRequest); final PackageSetting signatureCheckPs = - (prepareResult != null && lastStaticSharedLibSetting != null) + lastStaticSharedLibSetting != null ? lastStaticSharedLibSetting - : scanResult.mPkgSetting; + : installRequest.getScannedPackageSetting(); boolean removeAppKeySetData = false; boolean sharedUserSignaturesChanged = false; SigningDetails signingDetails = null; + if (parsedPackage != null) { + signingDetails = parsedPackage.getSigningDetails(); + } SharedUserSetting sharedUserSetting = settings.getSharedUserSettingLPr( signatureCheckPs); if (ksms.shouldCheckUpgradeKeySetLocked( @@ -138,28 +145,21 @@ final class ReconcilePackageUtils { PackageManagerService.reportSettingsProblem(Log.WARN, msg); } } - signingDetails = parsedPackage.getSigningDetails(); } else { - try { - final Settings.VersionInfo versionInfo = - request.mVersionInfos.get(installPackageName); + final Settings.VersionInfo versionInfo = versionInfos.get(installPackageName); final boolean compareCompat = isCompatSignatureUpdateNeeded(versionInfo); final boolean compareRecover = isRecoverSignatureUpdateNeeded(versionInfo); - final boolean isRollback = installRequest != null - && installRequest.isRollback(); + final boolean isRollback = installRequest.isRollback(); final boolean compatMatch = PackageManagerServiceUtils.verifySignatures(signatureCheckPs, sharedUserSetting, disabledPkgSetting, - parsedPackage.getSigningDetails(), compareCompat, + signingDetails, compareCompat, compareRecover, isRollback); // The new KeySets will be re-added later in the scanning process. if (compatMatch) { removeAppKeySetData = true; } - // We just determined the app is signed correctly, so bring - // over the latest parsed certs. - signingDetails = parsedPackage.getSigningDetails(); // if this is is a sharedUser, check to see if the new package is signed by a // newer @@ -257,13 +257,12 @@ final class ReconcilePackageUtils { } result.put(installPackageName, - new ReconciledPackage(request, installRequest, scanResult.mPkgSetting, - request.mPreparedPackages.get(installPackageName), scanResult, + new ReconciledPackage(installRequests, allPackages, installRequest, deletePackageAction, allowedSharedLibInfos, signingDetails, sharedUserSignaturesChanged, removeAppKeySetData)); } - for (String installPackageName : scannedPackages.keySet()) { + for (InstallRequest installRequest : installRequests) { // Check all shared libraries and map to their actual file path. // We only do this here for apps not on a system dir, because those // are the only ones that can fail an install due to this. We @@ -271,16 +270,16 @@ final class ReconcilePackageUtils { // library paths after the scan is done. Also during the initial // scan don't update any libs as we do this wholesale after all // apps are scanned to avoid dependency based scanning. - final ScanResult scanResult = scannedPackages.get(installPackageName); - if ((scanResult.mRequest.mScanFlags & SCAN_BOOTING) != 0 - || (scanResult.mRequest.mParseFlags & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR) + if ((installRequest.getScanFlags() & SCAN_BOOTING) != 0 + || (installRequest.getParseFlags() & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR) != 0) { continue; } + final String installPackageName = installRequest.getParsedPackage().getPackageName(); try { result.get(installPackageName).mCollectedSharedLibraryInfos = sharedLibraries.collectSharedLibraryInfos( - scanResult.mRequest.mParsedPackage, combinedPackages, + installRequest.getParsedPackage(), combinedPackages, incomingSharedLibraries); } catch (PackageManagerException e) { throw new ReconcileFailure(e.error, e.getMessage()); diff --git a/services/core/java/com/android/server/pm/ReconcileRequest.java b/services/core/java/com/android/server/pm/ReconcileRequest.java deleted file mode 100644 index 3568c153de91..000000000000 --- a/services/core/java/com/android/server/pm/ReconcileRequest.java +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.android.server.pm; - -import com.android.server.pm.pkg.AndroidPackage; - -import java.util.Collections; -import java.util.Map; - -/** - * Package scan results and related request details used to reconcile the potential addition of - * one or more packages to the system. - * - * Reconcile will take a set of package details that need to be committed to the system and make - * sure that they are valid in the context of the system and the other installing apps. Any - * invalid state or app will result in a failed reconciliation and thus whatever operation (such - * as install) led to the request. - */ -final class ReconcileRequest { - public final Map<String, ScanResult> mScannedPackages; - - public final Map<String, AndroidPackage> mAllPackages; - public final Map<String, InstallRequest> mInstallRequests; - public final Map<String, PrepareResult> mPreparedPackages; - public final Map<String, Settings.VersionInfo> mVersionInfos; - - ReconcileRequest(Map<String, ScanResult> scannedPackages, - Map<String, InstallRequest> installRequests, - Map<String, PrepareResult> preparedPackages, - Map<String, AndroidPackage> allPackages, - Map<String, Settings.VersionInfo> versionInfos) { - mScannedPackages = scannedPackages; - mInstallRequests = installRequests; - mPreparedPackages = preparedPackages; - mAllPackages = allPackages; - mVersionInfos = versionInfos; - } - - ReconcileRequest(Map<String, ScanResult> scannedPackages, - Map<String, AndroidPackage> allPackages, - Map<String, Settings.VersionInfo> versionInfos) { - this(scannedPackages, Collections.emptyMap(), - Collections.emptyMap(), allPackages, versionInfos); - } -} diff --git a/services/core/java/com/android/server/pm/ReconciledPackage.java b/services/core/java/com/android/server/pm/ReconciledPackage.java index d4da6c798b15..701baee085ed 100644 --- a/services/core/java/com/android/server/pm/ReconciledPackage.java +++ b/services/core/java/com/android/server/pm/ReconciledPackage.java @@ -17,7 +17,6 @@ package com.android.server.pm; import android.annotation.NonNull; -import android.annotation.Nullable; import android.content.pm.SharedLibraryInfo; import android.content.pm.SigningDetails; import android.util.ArrayMap; @@ -33,12 +32,9 @@ import java.util.Map; * TODO: move most of the data contained here into a PackageSetting for commit. */ final class ReconciledPackage { - public final ReconcileRequest mRequest; - public final PackageSetting mPkgSetting; - public final ScanResult mScanResult; - // TODO: Remove install-specific details from the reconcile result - @Nullable public final PrepareResult mPrepareResult; - @Nullable public final InstallRequest mInstallRequest; + private final List<InstallRequest> mInstallRequests; + private final Map<String, AndroidPackage> mAllPackages; + @NonNull public final InstallRequest mInstallRequest; public final DeletePackageAction mDeletePackageAction; public final List<SharedLibraryInfo> mAllowedSharedLibraryInfos; public final SigningDetails mSigningDetails; @@ -46,21 +42,17 @@ final class ReconciledPackage { public ArrayList<SharedLibraryInfo> mCollectedSharedLibraryInfos; public final boolean mRemoveAppKeySetData; - ReconciledPackage(ReconcileRequest request, + ReconciledPackage(List<InstallRequest> installRequests, + Map<String, AndroidPackage> allPackages, InstallRequest installRequest, - PackageSetting pkgSetting, - PrepareResult prepareResult, - ScanResult scanResult, DeletePackageAction deletePackageAction, List<SharedLibraryInfo> allowedSharedLibraryInfos, SigningDetails signingDetails, boolean sharedUserSignaturesChanged, boolean removeAppKeySetData) { - mRequest = request; + mInstallRequests = installRequests; + mAllPackages = allPackages; mInstallRequest = installRequest; - mPkgSetting = pkgSetting; - mPrepareResult = prepareResult; - mScanResult = scanResult; mDeletePackageAction = deletePackageAction; mAllowedSharedLibraryInfos = allowedSharedLibraryInfos; mSigningDetails = signingDetails; @@ -75,13 +67,13 @@ final class ReconciledPackage { */ @NonNull Map<String, AndroidPackage> getCombinedAvailablePackages() { final ArrayMap<String, AndroidPackage> combined = - new ArrayMap<>(mRequest.mAllPackages.size() + mRequest.mScannedPackages.size()); + new ArrayMap<>(mAllPackages.size() + mInstallRequests.size()); - combined.putAll(mRequest.mAllPackages); + combined.putAll(mAllPackages); - for (ScanResult scanResult : mRequest.mScannedPackages.values()) { - combined.put(scanResult.mPkgSetting.getPackageName(), - scanResult.mRequest.mParsedPackage); + for (InstallRequest installRequest : mInstallRequests) { + combined.put(installRequest.getScannedPackageSetting().getPackageName(), + installRequest.getParsedPackage()); } return combined; diff --git a/services/core/java/com/android/server/pm/ScanPackageUtils.java b/services/core/java/com/android/server/pm/ScanPackageUtils.java index bd3c7dd0a4b4..a905df98e577 100644 --- a/services/core/java/com/android/server/pm/ScanPackageUtils.java +++ b/services/core/java/com/android/server/pm/ScanPackageUtils.java @@ -462,7 +462,7 @@ final class ScanPackageUtils { } } - return new ScanResult(request, true, pkgSetting, changedAbiCodePath, + return new ScanResult(request, pkgSetting, changedAbiCodePath, !createNewPackage /* existingSettingCopied */, Process.INVALID_UID /* previousAppId */ , sdkLibraryInfo, staticSharedLibraryInfo, dynamicSharedLibraryInfos); diff --git a/services/core/java/com/android/server/pm/ScanResult.java b/services/core/java/com/android/server/pm/ScanResult.java index e2860ca327e7..750e893ebefb 100644 --- a/services/core/java/com/android/server/pm/ScanResult.java +++ b/services/core/java/com/android/server/pm/ScanResult.java @@ -16,6 +16,7 @@ package com.android.server.pm; +import android.annotation.NonNull; import android.annotation.Nullable; import android.content.pm.SharedLibraryInfo; import android.os.Process; @@ -28,9 +29,7 @@ import java.util.List; @VisibleForTesting final class ScanResult { /** The request that initiated the scan that produced this result. */ - public final ScanRequest mRequest; - /** Whether or not the package scan was successful */ - public final boolean mSuccess; + @NonNull public final ScanRequest mRequest; /** * Whether or not the original PackageSetting needs to be updated with this result on * commit. @@ -58,7 +57,7 @@ final class ScanResult { public final List<SharedLibraryInfo> mDynamicSharedLibraryInfos; ScanResult( - ScanRequest request, boolean success, + @NonNull ScanRequest request, @Nullable PackageSetting pkgSetting, @Nullable List<String> changedAbiCodePath, boolean existingSettingCopied, int previousAppId, @@ -66,7 +65,6 @@ final class ScanResult { SharedLibraryInfo staticSharedLibraryInfo, List<SharedLibraryInfo> dynamicSharedLibraryInfos) { mRequest = request; - mSuccess = success; mPkgSetting = pkgSetting; mChangedAbiCodePath = changedAbiCodePath; mExistingSettingCopied = existingSettingCopied; diff --git a/services/core/java/com/android/server/pm/SharedLibrariesImpl.java b/services/core/java/com/android/server/pm/SharedLibrariesImpl.java index 094e748685e5..aa23d8d75c8c 100644 --- a/services/core/java/com/android/server/pm/SharedLibrariesImpl.java +++ b/services/core/java/com/android/server/pm/SharedLibrariesImpl.java @@ -422,15 +422,18 @@ public final class SharedLibrariesImpl implements SharedLibrariesRead, Watchable * Given a package scanned result of a static shared library, returns its package setting of * the latest version * - * @param scanResult The scanned result of a static shared library package. + * @param installRequest The install result of a static shared library package. * @return The package setting that represents the latest version of shared library info. */ @Nullable - PackageSetting getStaticSharedLibLatestVersionSetting(@NonNull ScanResult scanResult) { + PackageSetting getStaticSharedLibLatestVersionSetting(@NonNull InstallRequest installRequest) { + if (installRequest.getParsedPackage() == null) { + return null; + } PackageSetting sharedLibPackage = null; synchronized (mPm.mLock) { final SharedLibraryInfo latestSharedLibraVersionLPr = - getLatestStaticSharedLibraVersionLPr(scanResult.mRequest.mParsedPackage); + getLatestStaticSharedLibraVersionLPr(installRequest.getParsedPackage()); if (latestSharedLibraVersionLPr != null) { sharedLibPackage = mPm.mSettings.getPackageLPr( latestSharedLibraVersionLPr.getPackageName()); @@ -823,34 +826,35 @@ public final class SharedLibrariesImpl implements SharedLibrariesRead, Watchable * Compare the newly scanned package with current system state to see which of its declared * shared libraries should be allowed to be added to the system. */ - List<SharedLibraryInfo> getAllowedSharedLibInfos(ScanResult scanResult) { + List<SharedLibraryInfo> getAllowedSharedLibInfos(InstallRequest installRequest) { // Let's used the parsed package as scanResult.pkgSetting may be null - final ParsedPackage parsedPackage = scanResult.mRequest.mParsedPackage; - if (scanResult.mSdkSharedLibraryInfo == null && scanResult.mStaticSharedLibraryInfo == null - && scanResult.mDynamicSharedLibraryInfos == null) { + final ParsedPackage parsedPackage = installRequest.getParsedPackage(); + if (installRequest.getSdkSharedLibraryInfo() == null + && installRequest.getStaticSharedLibraryInfo() == null + && installRequest.getDynamicSharedLibraryInfos() == null) { return null; } // Any app can add new SDKs and static shared libraries. - if (scanResult.mSdkSharedLibraryInfo != null) { - return Collections.singletonList(scanResult.mSdkSharedLibraryInfo); + if (installRequest.getSdkSharedLibraryInfo() != null) { + return Collections.singletonList(installRequest.getSdkSharedLibraryInfo()); } - if (scanResult.mStaticSharedLibraryInfo != null) { - return Collections.singletonList(scanResult.mStaticSharedLibraryInfo); + if (installRequest.getStaticSharedLibraryInfo() != null) { + return Collections.singletonList(installRequest.getStaticSharedLibraryInfo()); } - final boolean hasDynamicLibraries = parsedPackage.isSystem() - && scanResult.mDynamicSharedLibraryInfos != null; + final boolean hasDynamicLibraries = parsedPackage != null && parsedPackage.isSystem() + && installRequest.getDynamicSharedLibraryInfos() != null; if (!hasDynamicLibraries) { return null; } - final boolean isUpdatedSystemApp = scanResult.mPkgSetting.getPkgState() - .isUpdatedSystemApp(); + final boolean isUpdatedSystemApp = installRequest.getScannedPackageSetting() != null + && installRequest.getScannedPackageSetting().getPkgState().isUpdatedSystemApp(); // We may not yet have disabled the updated package yet, so be sure to grab the // current setting if that's the case. final PackageSetting updatedSystemPs = isUpdatedSystemApp - ? scanResult.mRequest.mDisabledPkgSetting == null - ? scanResult.mRequest.mOldPkgSetting - : scanResult.mRequest.mDisabledPkgSetting + ? installRequest.getDisabledPackageSetting() == null + ? installRequest.getScanRequestOldPackageSetting() + : installRequest.getDisabledPackageSetting() : null; if (isUpdatedSystemApp && (updatedSystemPs.getPkg() == null || updatedSystemPs.getPkg().getLibraryNames() == null)) { @@ -859,8 +863,8 @@ public final class SharedLibrariesImpl implements SharedLibrariesRead, Watchable return null; } final ArrayList<SharedLibraryInfo> infos = - new ArrayList<>(scanResult.mDynamicSharedLibraryInfos.size()); - for (SharedLibraryInfo info : scanResult.mDynamicSharedLibraryInfos) { + new ArrayList<>(installRequest.getDynamicSharedLibraryInfos().size()); + for (SharedLibraryInfo info : installRequest.getDynamicSharedLibraryInfos()) { final String name = info.getName(); if (isUpdatedSystemApp) { // New library entries can only be added through the diff --git a/services/core/java/com/android/server/pm/StorageEventHelper.java b/services/core/java/com/android/server/pm/StorageEventHelper.java index 477e260a4818..aeb11b77f794 100644 --- a/services/core/java/com/android/server/pm/StorageEventHelper.java +++ b/services/core/java/com/android/server/pm/StorageEventHelper.java @@ -158,7 +158,7 @@ public final class StorageEventHelper extends StorageEventListener { final AndroidPackage pkg; try { pkg = installPackageHelper.scanSystemPackageTracedLI( - ps.getPath(), parseFlags, SCAN_INITIAL, null); + ps.getPath(), parseFlags, SCAN_INITIAL); loaded.add(pkg); } catch (PackageManagerException e) { diff --git a/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt b/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt index e28d331b770b..28c78b20aae2 100644 --- a/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt +++ b/services/tests/mockingservicestests/src/com/android/server/pm/SharedLibrariesImplTest.kt @@ -22,6 +22,7 @@ import android.content.pm.SharedLibraryInfo import android.content.pm.VersionedPackage import android.os.Build import android.os.storage.StorageManager +import android.os.UserHandle import android.util.ArrayMap import android.util.PackageUtils import com.android.server.SystemConfig.SharedLibraryEntry @@ -222,10 +223,11 @@ class SharedLibrariesImplTest { val parsedPackage = pair.second as ParsedPackage val scanRequest = ScanRequest(parsedPackage, null, null, null, null, null, null, null, 0, 0, false, null, null) - val scanResult = ScanResult(scanRequest, true, null, null, false, 0, null, null, null) + val scanResult = ScanResult(scanRequest, null, null, false, 0, null, null, null) + var installRequest = InstallRequest(parsedPackage, 0, 0, UserHandle(0), scanResult) val latestInfoSetting = - mSharedLibrariesImpl.getStaticSharedLibLatestVersionSetting(scanResult)!! + mSharedLibrariesImpl.getStaticSharedLibLatestVersionSetting(installRequest)!! assertThat(latestInfoSetting).isNotNull() assertThat(latestInfoSetting.packageName).isEqualTo(STATIC_LIB_PACKAGE_NAME) @@ -305,10 +307,11 @@ class SharedLibrariesImplTest { @Test fun getAllowedSharedLibInfos_withStaticSharedLibInfo() { val testInfo = libOfStatic(TEST_LIB_PACKAGE_NAME, TEST_LIB_NAME, 1L) - val scanResult = ScanResult(mock(), true, null, null, + val scanResult = ScanResult(mock(), null, null, false, 0, null, testInfo, null) + var installRequest = InstallRequest(mock(), 0, 0, UserHandle(0), scanResult) - val allowedInfos = mSharedLibrariesImpl.getAllowedSharedLibInfos(scanResult) + val allowedInfos = mSharedLibrariesImpl.getAllowedSharedLibInfos(installRequest) assertThat(allowedInfos).hasSize(1) assertThat(allowedInfos[0].name).isEqualTo(TEST_LIB_NAME) @@ -327,10 +330,11 @@ class SharedLibrariesImplTest { .setPkgFlags(ApplicationInfo.FLAG_SYSTEM).build() val scanRequest = ScanRequest(parsedPackage, null, null, null, null, null, null, null, 0, 0, false, null, null) - val scanResult = ScanResult(scanRequest, true, packageSetting, null, + val scanResult = ScanResult(scanRequest, packageSetting, null, false, 0, null, null, listOf(testInfo)) + var installRequest = InstallRequest(parsedPackage, 0, 0, UserHandle(0), scanResult) - val allowedInfos = mSharedLibrariesImpl.getAllowedSharedLibInfos(scanResult) + val allowedInfos = mSharedLibrariesImpl.getAllowedSharedLibInfos(installRequest) assertThat(allowedInfos).hasSize(1) assertThat(allowedInfos[0].name).isEqualTo(TEST_LIB_NAME) diff --git a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java index 4d03749d2759..48d6d9037e95 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ScanTests.java +++ b/services/tests/servicestests/src/com/android/server/pm/ScanTests.java @@ -568,7 +568,6 @@ public class ScanTests { private static void assertBasicPackageScanResult( ScanResult scanResult, String packageName, boolean isInstant) { - assertThat(scanResult.mSuccess, is(true)); final PackageSetting pkgSetting = scanResult.mPkgSetting; assertBasicPackageSetting(scanResult, packageName, isInstant, pkgSetting); |