[pm] move mPm related code from ScanPackageHelper to InstallPackageHelper
Tried to consolidate some of scanPackageNew and scanSystemPackage but there is some delicate difference that I am not 100% certain to merge. In this CL I moved all the code that requires mLock into InstallPackageHelper, and made ScanPackageHelper a utility class. I will keep doing the same for other helper classes, such as DeletePackageHelper. BUG: 199937291 Test: manual Change-Id: I9f93cc36494e1fff84628026949ca5887bb3e323
This commit is contained in:
@@ -74,13 +74,6 @@ final class AppDataHelper {
|
||||
mArtManagerService = mInjector.getArtManagerService();
|
||||
}
|
||||
|
||||
AppDataHelper(PackageManagerService pm, PackageManagerServiceInjector injector) {
|
||||
mPm = pm;
|
||||
mInjector = injector;
|
||||
mInstaller = injector.getInstaller();
|
||||
mArtManagerService = injector.getArtManagerService();
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare app data for the given app just after it was installed or
|
||||
* upgraded. This method carefully only touches users that it's installed
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -582,13 +582,6 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
|
||||
/** Directory where installed applications are stored */
|
||||
private final File mAppInstallDir;
|
||||
/** Directory where installed application's 32-bit native libraries are copied. */
|
||||
@VisibleForTesting
|
||||
final File mAppLib32InstallDir;
|
||||
|
||||
static File getAppLib32InstallDir() {
|
||||
return new File(Environment.getDataDirectory(), "app-lib");
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
@@ -975,6 +968,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
private final DeletePackageHelper mDeletePackageHelper;
|
||||
private final InitAndSystemPackageHelper mInitAndSystemPackageHelper;
|
||||
private final AppDataHelper mAppDataHelper;
|
||||
private final InstallPackageHelper mInstallPackageHelper;
|
||||
private final PreferredActivityHelper mPreferredActivityHelper;
|
||||
private final ResolveIntentHelper mResolveIntentHelper;
|
||||
private final DexOptHelper mDexOptHelper;
|
||||
@@ -1697,7 +1691,6 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
mEnableFreeCacheV2 = testParams.enableFreeCacheV2;
|
||||
mSdkVersion = testParams.sdkVersion;
|
||||
mAppInstallDir = testParams.appInstallDir;
|
||||
mAppLib32InstallDir = testParams.appLib32InstallDir;
|
||||
mIsEngBuild = testParams.isEngBuild;
|
||||
mIsUserDebugBuild = testParams.isUserDebugBuild;
|
||||
mIncrementalVersion = testParams.incrementalVersion;
|
||||
@@ -1705,6 +1698,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
|
||||
mBroadcastHelper = testParams.broadcastHelper;
|
||||
mAppDataHelper = testParams.appDataHelper;
|
||||
mInstallPackageHelper = testParams.installPackageHelper;
|
||||
mRemovePackageHelper = testParams.removePackageHelper;
|
||||
mInitAndSystemPackageHelper = testParams.initAndSystemPackageHelper;
|
||||
mDeletePackageHelper = testParams.deletePackageHelper;
|
||||
@@ -1837,7 +1831,6 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
mInstantAppRegistry = new InstantAppRegistry(this, mPermissionManager, mPmInternal);
|
||||
|
||||
mAppInstallDir = new File(Environment.getDataDirectory(), "app");
|
||||
mAppLib32InstallDir = getAppLib32InstallDir();
|
||||
|
||||
mDomainVerificationConnection = new DomainVerificationConnection(this);
|
||||
mDomainVerificationManager = injector.getDomainVerificationManagerInternal();
|
||||
@@ -1845,6 +1838,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
|
||||
mBroadcastHelper = new BroadcastHelper(mInjector);
|
||||
mAppDataHelper = new AppDataHelper(this);
|
||||
mInstallPackageHelper = new InstallPackageHelper(this, mAppDataHelper);
|
||||
mRemovePackageHelper = new RemovePackageHelper(this, mAppDataHelper);
|
||||
mInitAndSystemPackageHelper = new InitAndSystemPackageHelper(this);
|
||||
mDeletePackageHelper = new DeletePackageHelper(this, mRemovePackageHelper,
|
||||
@@ -2006,7 +2000,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
// the rest of the commands above) because there's precious little we
|
||||
// can do about it. A settings error is reported, though.
|
||||
final List<String> changedAbiCodePath =
|
||||
ScanPackageHelper.applyAdjustedAbiToSharedUser(
|
||||
ScanPackageUtils.applyAdjustedAbiToSharedUser(
|
||||
setting, null /*scannedPackage*/,
|
||||
mInjector.getAbiHelper().getAdjustedAbiForSharedUser(
|
||||
setting.packages, null /*scannedPackage*/));
|
||||
@@ -4698,35 +4692,10 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
@Override
|
||||
public int installExistingPackageAsUser(String packageName, int userId, int installFlags,
|
||||
int installReason, List<String> whiteListedPermissions) {
|
||||
final InstallPackageHelper installPackageHelper = new InstallPackageHelper(
|
||||
this, mAppDataHelper);
|
||||
return installPackageHelper.installExistingPackageAsUser(packageName, userId, installFlags,
|
||||
return mInstallPackageHelper.installExistingPackageAsUser(packageName, userId, installFlags,
|
||||
installReason, whiteListedPermissions, null);
|
||||
}
|
||||
|
||||
static void setInstantAppForUser(PackageManagerServiceInjector injector,
|
||||
PackageSetting pkgSetting, int userId, boolean instantApp, boolean fullApp) {
|
||||
// no state specified; do nothing
|
||||
if (!instantApp && !fullApp) {
|
||||
return;
|
||||
}
|
||||
if (userId != UserHandle.USER_ALL) {
|
||||
if (instantApp && !pkgSetting.getInstantApp(userId)) {
|
||||
pkgSetting.setInstantApp(true /*instantApp*/, userId);
|
||||
} else if (fullApp && pkgSetting.getInstantApp(userId)) {
|
||||
pkgSetting.setInstantApp(false /*instantApp*/, userId);
|
||||
}
|
||||
} else {
|
||||
for (int currentUserId : injector.getUserManagerInternal().getUserIds()) {
|
||||
if (instantApp && !pkgSetting.getInstantApp(currentUserId)) {
|
||||
pkgSetting.setInstantApp(true /*instantApp*/, currentUserId);
|
||||
} else if (fullApp && pkgSetting.getInstantApp(currentUserId)) {
|
||||
pkgSetting.setInstantApp(false /*instantApp*/, currentUserId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
boolean isUserRestricted(int userId, String restrictionKey) {
|
||||
Bundle restrictions = mUserManager.getUserRestrictions(userId);
|
||||
if (restrictions.getBoolean(restrictionKey, false)) {
|
||||
@@ -6733,8 +6702,7 @@ public class PackageManagerService extends IPackageManager.Stub
|
||||
if (isSystemStub
|
||||
&& (newState == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
|
||||
|| newState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED)) {
|
||||
if (!new InstallPackageHelper(this).enableCompressedPackage(deletedPkg,
|
||||
pkgSetting)) {
|
||||
if (!mInstallPackageHelper.enableCompressedPackage(deletedPkg, pkgSetting)) {
|
||||
Slog.w(TAG, "Failed setApplicationEnabledSetting: failed to enable "
|
||||
+ "commpressed package " + setting.getPackageName());
|
||||
updateAllowed[i] = false;
|
||||
|
||||
@@ -104,6 +104,7 @@ public final class PackageManagerServiceTestParams {
|
||||
public final String incrementalVersion = Build.VERSION.INCREMENTAL;
|
||||
public BroadcastHelper broadcastHelper;
|
||||
public AppDataHelper appDataHelper;
|
||||
public InstallPackageHelper installPackageHelper;
|
||||
public RemovePackageHelper removePackageHelper;
|
||||
public InitAndSystemPackageHelper initAndSystemPackageHelper;
|
||||
public DeletePackageHelper deletePackageHelper;
|
||||
|
||||
@@ -18,9 +18,11 @@ package com.android.server.pm;
|
||||
|
||||
import static android.content.pm.PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
|
||||
import static android.content.pm.PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
|
||||
import static android.content.pm.PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
|
||||
import static android.system.OsConstants.O_CREAT;
|
||||
import static android.system.OsConstants.O_RDWR;
|
||||
|
||||
import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME;
|
||||
import static com.android.server.pm.PackageManagerService.COMPRESSED_EXTENSION;
|
||||
import static com.android.server.pm.PackageManagerService.DEBUG_COMPRESSION;
|
||||
import static com.android.server.pm.PackageManagerService.DEBUG_INTENT_MATCHING;
|
||||
@@ -60,6 +62,7 @@ import android.os.FileUtils;
|
||||
import android.os.Process;
|
||||
import android.os.SystemProperties;
|
||||
import android.os.incremental.IncrementalManager;
|
||||
import android.os.incremental.IncrementalStorage;
|
||||
import android.os.incremental.V4Signature;
|
||||
import android.os.incremental.V4Signature.HashingInfo;
|
||||
import android.os.storage.DiskInfo;
|
||||
@@ -84,6 +87,7 @@ import com.android.internal.util.FastPrintWriter;
|
||||
import com.android.internal.util.HexDump;
|
||||
import com.android.server.EventLogTags;
|
||||
import com.android.server.IntentResolver;
|
||||
import com.android.server.Watchdog;
|
||||
import com.android.server.compat.PlatformCompat;
|
||||
import com.android.server.pm.dex.PackageDexUsage;
|
||||
import com.android.server.pm.parsing.pkg.AndroidPackage;
|
||||
@@ -648,6 +652,58 @@ public class PackageManagerServiceUtils {
|
||||
return compatMatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract native libraries to a target path
|
||||
*/
|
||||
public static int extractNativeBinaries(File dstCodePath, String packageName) {
|
||||
final File libraryRoot = new File(dstCodePath, LIB_DIR_NAME);
|
||||
NativeLibraryHelper.Handle handle = null;
|
||||
try {
|
||||
handle = NativeLibraryHelper.Handle.create(dstCodePath);
|
||||
return NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
|
||||
null /*abiOverride*/, false /*isIncremental*/);
|
||||
} catch (IOException e) {
|
||||
logCriticalInfo(Log.ERROR, "Failed to extract native libraries"
|
||||
+ "; pkg: " + packageName);
|
||||
return PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
|
||||
} finally {
|
||||
IoUtils.closeQuietly(handle);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove native libraries of a given package
|
||||
*/
|
||||
public static void removeNativeBinariesLI(PackageSetting ps) {
|
||||
if (ps != null) {
|
||||
NativeLibraryHelper.removeNativeBinariesLI(ps.getLegacyNativeLibraryPath());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for native library extraction to be done in IncrementalService
|
||||
*/
|
||||
public static void waitForNativeBinariesExtractionForIncremental(
|
||||
ArraySet<IncrementalStorage> incrementalStorages) {
|
||||
if (incrementalStorages.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
// Native library extraction may take very long time: each page could potentially
|
||||
// wait for either 10s or 100ms (adb vs non-adb data loader), and that easily adds
|
||||
// up to a full watchdog timeout of 1 min, killing the system after that. It doesn't
|
||||
// make much sense as blocking here doesn't lock up the framework, but only blocks
|
||||
// the installation session and the following ones.
|
||||
Watchdog.getInstance().pauseWatchingCurrentThread("native_lib_extract");
|
||||
for (int i = 0; i < incrementalStorages.size(); ++i) {
|
||||
IncrementalStorage storage = incrementalStorages.valueAtUnchecked(i);
|
||||
storage.waitForNativeBinariesExtraction();
|
||||
}
|
||||
} finally {
|
||||
Watchdog.getInstance().resumeWatchingCurrentThread("native_lib_extract");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Decompress files stored in codePath to dstCodePath for a certain package.
|
||||
*/
|
||||
@@ -1280,4 +1336,39 @@ public class PackageManagerServiceUtils {
|
||||
|
||||
return cacheDir;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check and throw if the given before/after packages would be considered a
|
||||
* downgrade.
|
||||
*/
|
||||
public static void checkDowngrade(AndroidPackage before, PackageInfoLite after)
|
||||
throws PackageManagerException {
|
||||
if (after.getLongVersionCode() < before.getLongVersionCode()) {
|
||||
throw new PackageManagerException(INSTALL_FAILED_VERSION_DOWNGRADE,
|
||||
"Update version code " + after.versionCode + " is older than current "
|
||||
+ before.getLongVersionCode());
|
||||
} else if (after.getLongVersionCode() == before.getLongVersionCode()) {
|
||||
if (after.baseRevisionCode < before.getBaseRevisionCode()) {
|
||||
throw new PackageManagerException(INSTALL_FAILED_VERSION_DOWNGRADE,
|
||||
"Update base revision code " + after.baseRevisionCode
|
||||
+ " is older than current " + before.getBaseRevisionCode());
|
||||
}
|
||||
|
||||
if (!ArrayUtils.isEmpty(after.splitNames)) {
|
||||
for (int i = 0; i < after.splitNames.length; i++) {
|
||||
final String splitName = after.splitNames[i];
|
||||
final int j = ArrayUtils.indexOf(before.getSplitNames(), splitName);
|
||||
if (j != -1) {
|
||||
if (after.splitRevisionCodes[i] < before.getSplitRevisionCodes()[j]) {
|
||||
throw new PackageManagerException(INSTALL_FAILED_VERSION_DOWNGRADE,
|
||||
"Update split " + splitName + " revision code "
|
||||
+ after.splitRevisionCodes[i]
|
||||
+ " is older than current "
|
||||
+ before.getSplitRevisionCodes()[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,292 @@
|
||||
/*
|
||||
* 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 static android.content.pm.PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
|
||||
import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES;
|
||||
|
||||
import static com.android.server.pm.PackageManagerService.SCAN_BOOTING;
|
||||
import static com.android.server.pm.PackageManagerService.SCAN_DONT_KILL_APP;
|
||||
import static com.android.server.pm.PackageManagerServiceUtils.compareSignatures;
|
||||
import static com.android.server.pm.PackageManagerServiceUtils.verifySignatures;
|
||||
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.SharedLibraryInfo;
|
||||
import android.content.pm.Signature;
|
||||
import android.content.pm.SigningDetails;
|
||||
import android.content.pm.parsing.ParsingPackageUtils;
|
||||
import android.os.SystemProperties;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.server.pm.parsing.pkg.AndroidPackage;
|
||||
import com.android.server.pm.parsing.pkg.ParsedPackage;
|
||||
import com.android.server.utils.WatchedLongSparseArray;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
final class ReconcilePackageUtils {
|
||||
public static Map<String, ReconciledPackage> reconcilePackages(
|
||||
final ReconcileRequest request, KeySetManagerService ksms,
|
||||
PackageManagerServiceInjector injector)
|
||||
throws ReconcileFailure {
|
||||
final Map<String, ScanResult> scannedPackages = request.mScannedPackages;
|
||||
|
||||
final Map<String, ReconciledPackage> result = new ArrayMap<>(scannedPackages.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());
|
||||
|
||||
combinedPackages.putAll(request.mAllPackages);
|
||||
|
||||
final Map<String, WatchedLongSparseArray<SharedLibraryInfo>> incomingSharedLibraries =
|
||||
new ArrayMap<>();
|
||||
|
||||
for (String installPackageName : scannedPackages.keySet()) {
|
||||
final ScanResult scanResult = scannedPackages.get(installPackageName);
|
||||
|
||||
// add / replace existing with incoming packages
|
||||
combinedPackages.put(scanResult.mPkgSetting.getPackageName(),
|
||||
scanResult.mRequest.mParsedPackage);
|
||||
|
||||
// in the first pass, we'll build up the set of incoming shared libraries
|
||||
final List<SharedLibraryInfo> allowedSharedLibInfos =
|
||||
SharedLibraryHelper.getAllowedSharedLibInfos(scanResult,
|
||||
request.mSharedLibrarySource);
|
||||
if (allowedSharedLibInfos != null) {
|
||||
for (SharedLibraryInfo info : allowedSharedLibInfos) {
|
||||
if (!SharedLibraryHelper.addSharedLibraryToPackageVersionMap(
|
||||
incomingSharedLibraries, info)) {
|
||||
throw new ReconcileFailure("Shared Library " + info.getName()
|
||||
+ " is being installed twice in this set!");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the following may be null if we're just reconciling on boot (and not during install)
|
||||
final InstallArgs installArgs = request.mInstallArgs.get(installPackageName);
|
||||
final PackageInstalledInfo res = request.mInstallResults.get(installPackageName);
|
||||
final PrepareResult prepareResult = request.mPreparedPackages.get(installPackageName);
|
||||
final boolean isInstall = installArgs != null;
|
||||
if (isInstall && (res == null || 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;
|
||||
final int deleteFlags = PackageManager.DELETE_KEEP_DATA
|
||||
| (killApp ? 0 : PackageManager.DELETE_DONT_KILL_APP);
|
||||
deletePackageAction = DeletePackageHelper.mayDeletePackageLocked(res.mRemovedInfo,
|
||||
prepareResult.mOriginalPs, prepareResult.mDisabledPs,
|
||||
deleteFlags, null /* all users */);
|
||||
if (deletePackageAction == null) {
|
||||
throw new ReconcileFailure(
|
||||
PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE,
|
||||
"May not delete " + installPackageName + " to replace");
|
||||
}
|
||||
} else {
|
||||
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 PackageSetting lastStaticSharedLibSetting =
|
||||
request.mLastStaticSharedLibSettings.get(installPackageName);
|
||||
final PackageSetting signatureCheckPs =
|
||||
(prepareResult != null && lastStaticSharedLibSetting != null)
|
||||
? lastStaticSharedLibSetting
|
||||
: scanResult.mPkgSetting;
|
||||
boolean removeAppKeySetData = false;
|
||||
boolean sharedUserSignaturesChanged = false;
|
||||
SigningDetails signingDetails = null;
|
||||
if (ksms.shouldCheckUpgradeKeySetLocked(signatureCheckPs, scanFlags)) {
|
||||
if (ksms.checkUpgradeKeySetLocked(signatureCheckPs, parsedPackage)) {
|
||||
// We just determined the app is signed correctly, so bring
|
||||
// over the latest parsed certs.
|
||||
} else {
|
||||
if ((parseFlags & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR) == 0) {
|
||||
throw new ReconcileFailure(INSTALL_FAILED_UPDATE_INCOMPATIBLE,
|
||||
"Package " + parsedPackage.getPackageName()
|
||||
+ " upgrade keys do not match the previously installed"
|
||||
+ " version");
|
||||
} else {
|
||||
String msg = "System package " + parsedPackage.getPackageName()
|
||||
+ " signature changed; retaining data.";
|
||||
PackageManagerService.reportSettingsProblem(Log.WARN, msg);
|
||||
}
|
||||
}
|
||||
signingDetails = parsedPackage.getSigningDetails();
|
||||
} else {
|
||||
try {
|
||||
final Settings.VersionInfo versionInfo =
|
||||
request.mVersionInfos.get(installPackageName);
|
||||
final boolean compareCompat = isCompatSignatureUpdateNeeded(versionInfo);
|
||||
final boolean compareRecover = isRecoverSignatureUpdateNeeded(versionInfo);
|
||||
final boolean isRollback = installArgs != null
|
||||
&& installArgs.mInstallReason == PackageManager.INSTALL_REASON_ROLLBACK;
|
||||
final boolean compatMatch = verifySignatures(signatureCheckPs,
|
||||
disabledPkgSetting, parsedPackage.getSigningDetails(), 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
|
||||
// signing certificate than the existing one, and if so, copy over the new
|
||||
// details
|
||||
if (signatureCheckPs.getSharedUser() != null) {
|
||||
// Attempt to merge the existing lineage for the shared SigningDetails with
|
||||
// the lineage of the new package; if the shared SigningDetails are not
|
||||
// returned this indicates the new package added new signers to the lineage
|
||||
// and/or changed the capabilities of existing signers in the lineage.
|
||||
SigningDetails sharedSigningDetails =
|
||||
signatureCheckPs.getSharedUser().signatures.mSigningDetails;
|
||||
SigningDetails mergedDetails = sharedSigningDetails.mergeLineageWith(
|
||||
signingDetails);
|
||||
if (mergedDetails != sharedSigningDetails) {
|
||||
signatureCheckPs.getSharedUser().signatures.mSigningDetails =
|
||||
mergedDetails;
|
||||
}
|
||||
if (signatureCheckPs.getSharedUser().signaturesChanged == null) {
|
||||
signatureCheckPs.getSharedUser().signaturesChanged = Boolean.FALSE;
|
||||
}
|
||||
}
|
||||
} catch (PackageManagerException e) {
|
||||
if ((parseFlags & ParsingPackageUtils.PARSE_IS_SYSTEM_DIR) == 0) {
|
||||
throw new ReconcileFailure(e);
|
||||
}
|
||||
signingDetails = parsedPackage.getSigningDetails();
|
||||
|
||||
// If the system app is part of a shared user we allow that shared user to
|
||||
// change
|
||||
// signatures as well as part of an OTA. We still need to verify that the
|
||||
// signatures
|
||||
// are consistent within the shared user for a given boot, so only allow
|
||||
// updating
|
||||
// the signatures on the first package scanned for the shared user (i.e. if the
|
||||
// signaturesChanged state hasn't been initialized yet in SharedUserSetting).
|
||||
if (signatureCheckPs.getSharedUser() != null) {
|
||||
final Signature[] sharedUserSignatures = signatureCheckPs.getSharedUser()
|
||||
.signatures.mSigningDetails.getSignatures();
|
||||
if (signatureCheckPs.getSharedUser().signaturesChanged != null
|
||||
&& compareSignatures(sharedUserSignatures,
|
||||
parsedPackage.getSigningDetails().getSignatures())
|
||||
!= PackageManager.SIGNATURE_MATCH) {
|
||||
if (SystemProperties.getInt("ro.product.first_api_level", 0) <= 29) {
|
||||
// Mismatched signatures is an error and silently skipping system
|
||||
// packages will likely break the device in unforeseen ways.
|
||||
// However, we allow the device to boot anyway because, prior to Q,
|
||||
// vendors were not expecting the platform to crash in this
|
||||
// situation.
|
||||
// This WILL be a hard failure on any new API levels after Q.
|
||||
throw new ReconcileFailure(
|
||||
INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES,
|
||||
"Signature mismatch for shared user: "
|
||||
+ scanResult.mPkgSetting.getSharedUser());
|
||||
} else {
|
||||
// Treat mismatched signatures on system packages using a shared
|
||||
// UID as
|
||||
// fatal for the system overall, rather than just failing to install
|
||||
// whichever package happened to be scanned later.
|
||||
throw new IllegalStateException(
|
||||
"Signature mismatch on system package "
|
||||
+ parsedPackage.getPackageName()
|
||||
+ " for shared user "
|
||||
+ scanResult.mPkgSetting.getSharedUser());
|
||||
}
|
||||
}
|
||||
|
||||
sharedUserSignaturesChanged = true;
|
||||
signatureCheckPs.getSharedUser().signatures.mSigningDetails =
|
||||
parsedPackage.getSigningDetails();
|
||||
signatureCheckPs.getSharedUser().signaturesChanged = Boolean.TRUE;
|
||||
}
|
||||
// File a report about this.
|
||||
String msg = "System package " + parsedPackage.getPackageName()
|
||||
+ " signature changed; retaining data.";
|
||||
PackageManagerService.reportSettingsProblem(Log.WARN, msg);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// should never happen: certs matched when checking, but not when comparing
|
||||
// old to new for sharedUser
|
||||
throw new RuntimeException(
|
||||
"Signing certificates comparison made on incomparable signing details"
|
||||
+ " but somehow passed verifySignatures!", e);
|
||||
}
|
||||
}
|
||||
|
||||
result.put(installPackageName,
|
||||
new ReconciledPackage(request, installArgs, scanResult.mPkgSetting,
|
||||
res, request.mPreparedPackages.get(installPackageName), scanResult,
|
||||
deletePackageAction, allowedSharedLibInfos, signingDetails,
|
||||
sharedUserSignaturesChanged, removeAppKeySetData));
|
||||
}
|
||||
|
||||
for (String installPackageName : scannedPackages.keySet()) {
|
||||
// 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
|
||||
// will take care of the system apps by updating all of their
|
||||
// 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)
|
||||
!= 0) {
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
result.get(installPackageName).mCollectedSharedLibraryInfos =
|
||||
SharedLibraryHelper.collectSharedLibraryInfos(
|
||||
scanResult.mRequest.mParsedPackage,
|
||||
combinedPackages, request.mSharedLibrarySource,
|
||||
incomingSharedLibraries, injector.getCompatibility());
|
||||
|
||||
} catch (PackageManagerException e) {
|
||||
throw new ReconcileFailure(e.error, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the database version for this type of package (internal storage or
|
||||
* external storage) is less than the version where package signatures
|
||||
* were updated, return true.
|
||||
*/
|
||||
public static boolean isCompatSignatureUpdateNeeded(Settings.VersionInfo ver) {
|
||||
return ver.databaseVersion < Settings.DatabaseVersion.SIGNATURE_END_ENTITY;
|
||||
}
|
||||
|
||||
public static boolean isRecoverSignatureUpdateNeeded(Settings.VersionInfo ver) {
|
||||
return ver.databaseVersion < Settings.DatabaseVersion.SIGNATURE_MALFORMED_RECOVER;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
1006
services/core/java/com/android/server/pm/ScanPackageUtils.java
Normal file
1006
services/core/java/com/android/server/pm/ScanPackageUtils.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -470,9 +470,7 @@ public class ScanTests {
|
||||
.addUsesPermission(
|
||||
new ParsedUsesPermissionImpl(Manifest.permission.FACTORY_TEST, 0));
|
||||
|
||||
final ScanPackageHelper scanPackageHelper = new ScanPackageHelper(
|
||||
mMockPackageManager, mMockInjector);
|
||||
final ScanResult scanResult = scanPackageHelper.scanPackageOnlyLI(
|
||||
final ScanResult scanResult = ScanPackageUtils.scanPackageOnlyLI(
|
||||
createBasicScanRequestBuilder(basicPackage).build(),
|
||||
mMockInjector,
|
||||
true /*isUnderFactoryTest*/,
|
||||
@@ -520,9 +518,7 @@ public class ScanTests {
|
||||
|
||||
private ScanResult executeScan(
|
||||
ScanRequest scanRequest) throws PackageManagerException {
|
||||
final ScanPackageHelper scanPackageHelper = new ScanPackageHelper(
|
||||
mMockPackageManager, mMockInjector);
|
||||
ScanResult result = scanPackageHelper.scanPackageOnlyLI(
|
||||
ScanResult result = ScanPackageUtils.scanPackageOnlyLI(
|
||||
scanRequest,
|
||||
mMockInjector,
|
||||
false /*isUnderFactoryTest*/,
|
||||
|
||||
Reference in New Issue
Block a user