[pm] merge CommitRequest, PrepareResult, ReconcileRequest into InstallRequest

BUG: 238678399
Test: atest com.android.server.pm.ScanTests
Change-Id: I9f7d17d458318da89a6e47cdf9a0989825b1dbe5
This commit is contained in:
Songchun Fan
2022-10-06 19:45:06 -07:00
parent 4f1033f742
commit 378c481567
15 changed files with 590 additions and 516 deletions

View File

@@ -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;
}
}

View File

@@ -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 {

View File

@@ -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,

View File

@@ -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;
}
}
}

View File

@@ -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(

View File

@@ -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;
}
}

View File

@@ -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());

View File

@@ -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);
}
}

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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

View File

@@ -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) {

View File

@@ -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)

View File

@@ -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);