Merge "Consolidate installation logics from params/args classes"

This commit is contained in:
Songchun Fan
2021-11-02 20:08:33 +00:00
committed by Android (Google) Code Review
11 changed files with 2826 additions and 2848 deletions

View File

@@ -83,19 +83,15 @@ final class DeletePackageHelper {
private final UserManagerInternal mUserManagerInternal;
private final PermissionManagerServiceInternal mPermissionManager;
private final RemovePackageHelper mRemovePackageHelper;
// TODO(b/201815903): remove dependency to InitAndSystemPackageHelper
private final InitAndSystemPackageHelper mInitAndSystemPackageHelper;
private final AppDataHelper mAppDataHelper;
// TODO(b/198166813): remove PMS dependency
DeletePackageHelper(PackageManagerService pm, RemovePackageHelper removePackageHelper,
InitAndSystemPackageHelper initAndSystemPackageHelper,
AppDataHelper appDataHelper) {
mPm = pm;
mUserManagerInternal = mPm.mInjector.getUserManagerInternal();
mPermissionManager = mPm.mInjector.getPermissionManagerServiceInternal();
mRemovePackageHelper = removePackageHelper;
mInitAndSystemPackageHelper = initAndSystemPackageHelper;
mAppDataHelper = appDataHelper;
}
@@ -105,7 +101,6 @@ final class DeletePackageHelper {
mUserManagerInternal = mPm.mInjector.getUserManagerInternal();
mPermissionManager = mPm.mInjector.getPermissionManagerServiceInternal();
mRemovePackageHelper = new RemovePackageHelper(mPm, mAppDataHelper);
mInitAndSystemPackageHelper = mPm.getInitAndSystemPackageHelper();
}
/**
@@ -282,7 +277,7 @@ final class DeletePackageHelper {
Slog.i(TAG, "Enabling system stub after removal; pkg: "
+ stubPkg.getPackageName());
}
mInitAndSystemPackageHelper.enableCompressedPackage(stubPkg, stubPs);
new InstallPackageHelper(mPm).enableCompressedPackage(stubPkg, stubPs);
} else if (DEBUG_COMPRESSION) {
Slog.i(TAG, "System stub disabled for all users, leaving uncompressed "
+ "after removal; pkg: " + stubPkg.getPackageName());
@@ -422,7 +417,7 @@ final class DeletePackageHelper {
// as well and fall back to existing code in system partition
PackageSetting disabledPs = deleteInstalledSystemPackage(action, ps, allUserHandles,
flags, outInfo, writeSettings);
mInitAndSystemPackageHelper.restoreDisabledSystemPackageLIF(
new InstallPackageHelper(mPm).restoreDisabledSystemPackageLIF(
action, ps, allUserHandles, outInfo, writeSettings, disabledPs);
} else {
if (DEBUG_REMOVE) Slog.d(TAG, "Removing non-system package: " + ps.getPackageName());

View File

@@ -41,14 +41,12 @@ public final class DomainVerificationConnection implements DomainVerificationSer
final PackageManagerService mPm;
final PackageManagerInternal mPmInternal;
final UserManagerInternal mUmInternal;
final VerificationHelper mVerificationHelper;
// TODO(b/198166813): remove PMS dependency
DomainVerificationConnection(PackageManagerService pm) {
mPm = pm;
mPmInternal = mPm.mInjector.getLocalService(PackageManagerInternal.class);
mUmInternal = mPm.mInjector.getLocalService(UserManagerInternal.class);
mVerificationHelper = new VerificationHelper(mPm.mContext);
}
@Override
@@ -79,7 +77,7 @@ public final class DomainVerificationConnection implements DomainVerificationSer
@Override
public long getPowerSaveTempWhitelistAppDuration() {
return mVerificationHelper.getVerificationTimeout();
return VerificationUtils.getVerificationTimeout(mPm.mContext);
}
@Override

View File

@@ -16,22 +16,12 @@
package com.android.server.pm;
import static android.content.pm.PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE;
import android.annotation.NonNull;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInfoLite;
import android.content.pm.PackageManager;
import android.os.UserHandle;
import android.util.Pair;
import android.util.Slog;
import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
import static com.android.server.pm.PackageManagerService.TAG;
import com.android.internal.util.ArrayUtils;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import android.annotation.NonNull;
import android.os.UserHandle;
import android.util.Slog;
abstract class HandlerParams {
/** User handle for the user requesting the information or installation. */
@@ -40,15 +30,13 @@ abstract class HandlerParams {
int mTraceCookie;
@NonNull
final PackageManagerService mPm;
final VerificationHelper mVerificationHelper;
final BroadcastHelper mBroadcastHelper;
final InstallPackageHelper mInstallPackageHelper;
// TODO(b/198166813): remove PMS dependency
HandlerParams(UserHandle user, PackageManagerService pm) {
mUser = user;
mPm = pm;
mVerificationHelper = new VerificationHelper(mPm.mContext);
mBroadcastHelper = new BroadcastHelper(mPm.mInjector);
mInstallPackageHelper = new InstallPackageHelper(mPm);
}
UserHandle getUser() {
@@ -73,135 +61,4 @@ abstract class HandlerParams {
abstract void handleStartCopy();
abstract void handleReturnCode();
Pair<Integer, String> verifyReplacingVersionCode(PackageInfoLite pkgLite,
long requiredInstalledVersionCode, int installFlags) {
if ((installFlags & PackageManager.INSTALL_APEX) != 0) {
return verifyReplacingVersionCodeForApex(
pkgLite, requiredInstalledVersionCode, installFlags);
}
String packageName = pkgLite.packageName;
synchronized (mPm.mLock) {
// Package which currently owns the data that the new package will own if installed.
// If an app is uninstalled while keeping data (e.g. adb uninstall -k), installedPkg
// will be null whereas dataOwnerPkg will contain information about the package
// which was uninstalled while keeping its data.
AndroidPackage dataOwnerPkg = mPm.mPackages.get(packageName);
if (dataOwnerPkg == null) {
PackageSetting ps = mPm.mSettings.getPackageLPr(packageName);
if (ps != null) {
dataOwnerPkg = ps.getPkg();
}
}
if (requiredInstalledVersionCode != PackageManager.VERSION_CODE_HIGHEST) {
if (dataOwnerPkg == null) {
String errorMsg = "Required installed version code was "
+ requiredInstalledVersionCode
+ " but package is not installed";
Slog.w(TAG, errorMsg);
return Pair.create(
PackageManager.INSTALL_FAILED_WRONG_INSTALLED_VERSION, errorMsg);
}
if (dataOwnerPkg.getLongVersionCode() != requiredInstalledVersionCode) {
String errorMsg = "Required installed version code was "
+ requiredInstalledVersionCode
+ " but actual installed version is "
+ dataOwnerPkg.getLongVersionCode();
Slog.w(TAG, errorMsg);
return Pair.create(
PackageManager.INSTALL_FAILED_WRONG_INSTALLED_VERSION, errorMsg);
}
}
if (dataOwnerPkg != null) {
if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags,
dataOwnerPkg.isDebuggable())) {
try {
checkDowngrade(dataOwnerPkg, pkgLite);
} catch (PackageManagerException e) {
String errorMsg = "Downgrade detected: " + e.getMessage();
Slog.w(TAG, errorMsg);
return Pair.create(
PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE, errorMsg);
}
}
}
}
return Pair.create(PackageManager.INSTALL_SUCCEEDED, null);
}
private Pair<Integer, String> verifyReplacingVersionCodeForApex(PackageInfoLite pkgLite,
long requiredInstalledVersionCode, int installFlags) {
String packageName = pkgLite.packageName;
final PackageInfo activePackage = mPm.mApexManager.getPackageInfo(packageName,
ApexManager.MATCH_ACTIVE_PACKAGE);
if (activePackage == null) {
String errorMsg = "Attempting to install new APEX package " + packageName;
Slog.w(TAG, errorMsg);
return Pair.create(PackageManager.INSTALL_FAILED_PACKAGE_CHANGED, errorMsg);
}
final long activeVersion = activePackage.getLongVersionCode();
if (requiredInstalledVersionCode != PackageManager.VERSION_CODE_HIGHEST
&& activeVersion != requiredInstalledVersionCode) {
String errorMsg = "Installed version of APEX package " + packageName
+ " does not match required. Active version: " + activeVersion
+ " required: " + requiredInstalledVersionCode;
Slog.w(TAG, errorMsg);
return Pair.create(PackageManager.INSTALL_FAILED_WRONG_INSTALLED_VERSION, errorMsg);
}
final boolean isAppDebuggable = (activePackage.applicationInfo.flags
& ApplicationInfo.FLAG_DEBUGGABLE) != 0;
final long newVersionCode = pkgLite.getLongVersionCode();
if (!PackageManagerServiceUtils.isDowngradePermitted(installFlags, isAppDebuggable)
&& newVersionCode < activeVersion) {
String errorMsg = "Downgrade of APEX package " + packageName
+ " is not allowed. Active version: " + activeVersion
+ " attempted: " + newVersionCode;
Slog.w(TAG, errorMsg);
return Pair.create(PackageManager.INSTALL_FAILED_VERSION_DOWNGRADE, errorMsg);
}
return Pair.create(PackageManager.INSTALL_SUCCEEDED, null);
}
/**
* Check and throw if the given before/after packages would be considered a
* downgrade.
*/
private 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]);
}
}
}
}
}
}
}

View File

@@ -16,22 +16,13 @@
package com.android.server.pm;
import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
import static android.content.pm.PackageManager.INSTALL_SUCCEEDED;
import static android.content.pm.PackageManager.UNINSTALL_REASON_UNKNOWN;
import static android.content.pm.parsing.ApkLiteParseUtils.isApkFile;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static android.os.storage.StorageManager.FLAG_STORAGE_CE;
import static android.os.storage.StorageManager.FLAG_STORAGE_DE;
import static android.os.storage.StorageManager.FLAG_STORAGE_EXTERNAL;
import static com.android.internal.content.NativeLibraryHelper.LIB_DIR_NAME;
import static com.android.internal.util.FrameworkStatsLog.BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_DATA_APP_AVG_SCAN_TIME;
import static com.android.internal.util.FrameworkStatsLog.BOOT_TIME_EVENT_DURATION__EVENT__OTA_PACKAGE_MANAGER_SYSTEM_APP_AVG_SCAN_TIME;
import static com.android.server.pm.PackageManagerService.COMPRESSED_EXTENSION;
import static com.android.server.pm.PackageManagerService.DEBUG_COMPRESSION;
import static com.android.server.pm.PackageManagerService.DEBUG_PACKAGE_SCANNING;
import static com.android.server.pm.PackageManagerService.DEBUG_REMOVE;
import static com.android.server.pm.PackageManagerService.SCAN_AS_APK_IN_APEX;
import static com.android.server.pm.PackageManagerService.SCAN_AS_PRIVILEGED;
import static com.android.server.pm.PackageManagerService.SCAN_AS_SYSTEM;
@@ -42,31 +33,21 @@ import static com.android.server.pm.PackageManagerService.SCAN_NO_DEX;
import static com.android.server.pm.PackageManagerService.SCAN_REQUIRE_KNOWN;
import static com.android.server.pm.PackageManagerService.SYSTEM_PARTITIONS;
import static com.android.server.pm.PackageManagerService.TAG;
import static com.android.server.pm.PackageManagerServiceUtils.decompressFile;
import static com.android.server.pm.PackageManagerServiceUtils.getCompressedFiles;
import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo;
import static com.android.server.pm.PackageManagerServiceUtils.makeDirRecursive;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.ContentResolver;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
import android.content.pm.parsing.ParsingPackageUtils;
import android.os.Environment;
import android.os.Process;
import android.os.SystemClock;
import android.os.Trace;
import android.os.UserHandle;
import android.system.ErrnoException;
import android.util.ArrayMap;
import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.content.F2fsUtils;
import com.android.internal.content.NativeLibraryHelper;
import com.android.internal.content.om.OverlayConfig;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FrameworkStatsLog;
@@ -74,15 +55,10 @@ import com.android.server.EventLogTags;
import com.android.server.pm.parsing.PackageCacher;
import com.android.server.pm.parsing.PackageParser2;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.utils.WatchedArrayMap;
import libcore.io.IoUtils;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.ExecutorService;
@@ -270,6 +246,8 @@ final class InitAndSystemPackageHelper {
* If the package is scanned, it's not erased.
*/
final AndroidPackage scannedPkg = mPm.mPackages.get(ps.getPackageName());
final PackageSetting disabledPs =
mPm.mSettings.getDisabledSystemPkgLPr(ps.getPackageName());
if (scannedPkg != null) {
/*
* If the system app is both scanned and in the
@@ -278,7 +256,7 @@ final class InitAndSystemPackageHelper {
* scanned package so the previously user-installed
* application can be scanned.
*/
if (mPm.mSettings.isDisabledSystemPackageLPr(ps.getPackageName())) {
if (disabledPs != null) {
logCriticalInfo(Log.WARN,
"Expecting better updated system app for "
+ ps.getPackageName()
@@ -294,7 +272,7 @@ final class InitAndSystemPackageHelper {
continue;
}
if (!mPm.mSettings.isDisabledSystemPackageLPr(ps.getPackageName())) {
if (disabledPs == null) {
logCriticalInfo(Log.WARN, "System package " + ps.getPackageName()
+ " no longer exists; its data will be wiped");
mRemovePackageHelper.removePackageDataLIF(ps, userIds, null, 0, false);
@@ -303,8 +281,6 @@ final class InitAndSystemPackageHelper {
// been removed. check the code path still exists and check there's
// still a package. the latter can happen if an OTA keeps the same
// code path, but, changes the package name.
final PackageSetting disabledPs =
mPm.mSettings.getDisabledSystemPkgLPr(ps.getPackageName());
if (disabledPs.getPath() == null || !disabledPs.getPath().exists()
|| disabledPs.getPkg() == null) {
possiblyDeletedUpdatedSystemApps.add(ps.getPackageName());
@@ -454,7 +430,7 @@ final class InitAndSystemPackageHelper {
// Uncompress and install any stubbed system applications.
// This must be done last to ensure all stubs are replaced or disabled.
installSystemStubPackages(stubSystemApps, mScanFlags);
new InstallPackageHelper(mPm).installSystemStubPackages(stubSystemApps, mScanFlags);
final int cachedNonSystemApps = PackageCacher.sCachedPackageReadCount.get()
- cachedSystemApps;
@@ -568,403 +544,11 @@ final class InitAndSystemPackageHelper {
}
}
/**
* Uncompress and install stub applications.
* <p>In order to save space on the system partition, some applications are shipped in a
* compressed form. In addition the compressed bits for the full application, the
* system image contains a tiny stub comprised of only the Android manifest.
* <p>During the first boot, attempt to uncompress and install the full application. If
* the application can't be installed for any reason, disable the stub and prevent
* uncompressing the full application during future boots.
* <p>In order to forcefully attempt an installation of a full application, go to app
* settings and enable the application.
*/
@GuardedBy({"mPm.mLock", "mPm.mInstallLock"})
private void installSystemStubPackages(@NonNull List<String> systemStubPackageNames,
@PackageManagerService.ScanFlags int scanFlags) {
for (int i = systemStubPackageNames.size() - 1; i >= 0; --i) {
final String packageName = systemStubPackageNames.get(i);
// skip if the system package is already disabled
if (mPm.mSettings.isDisabledSystemPackageLPr(packageName)) {
systemStubPackageNames.remove(i);
continue;
}
// skip if the package isn't installed (?!); this should never happen
final AndroidPackage pkg = mPm.mPackages.get(packageName);
if (pkg == null) {
systemStubPackageNames.remove(i);
continue;
}
// skip if the package has been disabled by the user
final PackageSetting ps = mPm.mSettings.getPackageLPr(packageName);
if (ps != null) {
final int enabledState = ps.getEnabled(UserHandle.USER_SYSTEM);
if (enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
systemStubPackageNames.remove(i);
continue;
}
}
// install the package to replace the stub on /system
try {
installStubPackageLI(pkg, 0, scanFlags);
ps.setEnabled(PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
UserHandle.USER_SYSTEM, "android");
systemStubPackageNames.remove(i);
} catch (PackageManagerException e) {
Slog.e(TAG, "Failed to parse uncompressed system package: " + e.getMessage());
}
// any failed attempt to install the package will be cleaned up later
}
// disable any stub still left; these failed to install the full application
for (int i = systemStubPackageNames.size() - 1; i >= 0; --i) {
final String pkgName = systemStubPackageNames.get(i);
final PackageSetting ps = mPm.mSettings.getPackageLPr(pkgName);
ps.setEnabled(PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
UserHandle.USER_SYSTEM, "android");
logCriticalInfo(Log.ERROR, "Stub disabled; pkg: " + pkgName);
}
}
/**
* Extract, install and enable a stub package.
* <p>If the compressed file can not be extracted / installed for any reason, the stub
* APK will be installed and the package will be disabled. To recover from this situation,
* the user will need to go into system settings and re-enable the package.
*/
@GuardedBy({"mPm.mLock", "mPm.mInstallLock"})
public boolean enableCompressedPackage(AndroidPackage stubPkg,
@NonNull PackageSetting stubPkgSetting) {
final int parseFlags = mPm.getDefParseFlags() | ParsingPackageUtils.PARSE_CHATTY
| ParsingPackageUtils.PARSE_ENFORCE_CODE;
synchronized (mPm.mInstallLock) {
final AndroidPackage pkg;
try (PackageFreezer freezer =
mPm.freezePackage(stubPkg.getPackageName(), "setEnabledSetting")) {
pkg = installStubPackageLI(stubPkg, parseFlags, 0 /*scanFlags*/);
synchronized (mPm.mLock) {
mAppDataHelper.prepareAppDataAfterInstallLIF(pkg);
try {
mPm.updateSharedLibrariesLocked(pkg, stubPkgSetting, null, null,
Collections.unmodifiableMap(mPm.mPackages));
} catch (PackageManagerException e) {
Slog.w(TAG, "updateAllSharedLibrariesLPw failed: ", e);
}
mPm.mPermissionManager.onPackageInstalled(pkg,
Process.INVALID_UID /* previousAppId */,
PermissionManagerServiceInternal.PackageInstalledParams.DEFAULT,
UserHandle.USER_ALL);
mPm.writeSettingsLPrTEMP();
}
} catch (PackageManagerException e) {
// Whoops! Something went very wrong; roll back to the stub and disable the package
try (PackageFreezer freezer =
mPm.freezePackage(stubPkg.getPackageName(), "setEnabledSetting")) {
synchronized (mPm.mLock) {
// NOTE: Ensure the system package is enabled; even for a compressed stub.
// If we don't, installing the system package fails during scan
enableSystemPackageLPw(stubPkg);
}
installPackageFromSystemLIF(stubPkg.getPath(),
mPm.mUserManager.getUserIds() /*allUserHandles*/,
null /*origUserHandles*/,
true /*writeSettings*/);
} catch (PackageManagerException pme) {
// Serious WTF; we have to be able to install the stub
Slog.wtf(TAG, "Failed to restore system package:" + stubPkg.getPackageName(),
pme);
} finally {
// Disable the package; the stub by itself is not runnable
synchronized (mPm.mLock) {
final PackageSetting stubPs = mPm.mSettings.getPackageLPr(
stubPkg.getPackageName());
if (stubPs != null) {
stubPs.setEnabled(COMPONENT_ENABLED_STATE_DISABLED,
UserHandle.USER_SYSTEM, "android");
}
mPm.writeSettingsLPrTEMP();
}
}
return false;
}
mAppDataHelper.clearAppDataLIF(pkg, UserHandle.USER_ALL,
FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL
| Installer.FLAG_CLEAR_CODE_CACHE_ONLY);
mPm.getDexManager().notifyPackageUpdated(pkg.getPackageName(),
pkg.getBaseApkPath(), pkg.getSplitCodePaths());
}
return true;
}
@GuardedBy({"mPm.mLock", "mPm.mInstallLock"})
private AndroidPackage installStubPackageLI(AndroidPackage stubPkg,
@ParsingPackageUtils.ParseFlags int parseFlags,
@PackageManagerService.ScanFlags int scanFlags)
throws PackageManagerException {
if (DEBUG_COMPRESSION) {
Slog.i(TAG, "Uncompressing system stub; pkg: " + stubPkg.getPackageName());
}
// uncompress the binary to its eventual destination on /data
final File scanFile = decompressPackage(stubPkg.getPackageName(), stubPkg.getPath());
if (scanFile == null) {
throw new PackageManagerException(
"Unable to decompress stub at " + stubPkg.getPath());
}
synchronized (mPm.mLock) {
mPm.mSettings.disableSystemPackageLPw(stubPkg.getPackageName(), true /*replaced*/);
}
mRemovePackageHelper.removePackageLI(stubPkg, true /*chatty*/);
final ScanPackageHelper scanPackageHelper = new ScanPackageHelper(mPm);
try {
return scanPackageHelper.scanPackageTracedLI(scanFile, parseFlags, scanFlags, 0, null);
} catch (PackageManagerException e) {
Slog.w(TAG, "Failed to install compressed system package:" + stubPkg.getPackageName(),
e);
// Remove the failed install
mRemovePackageHelper.removeCodePathLI(scanFile);
throw e;
}
}
/**
* Decompresses the given package on the system image onto
* the /data partition.
* @return The directory the package was decompressed into. Otherwise, {@code null}.
*/
@GuardedBy("mPm.mInstallLock")
private File decompressPackage(String packageName, String codePath) {
final File[] compressedFiles = getCompressedFiles(codePath);
if (compressedFiles == null || compressedFiles.length == 0) {
if (DEBUG_COMPRESSION) {
Slog.i(TAG, "No files to decompress: " + codePath);
}
return null;
}
final File dstCodePath =
PackageManagerServiceUtils.getNextCodePath(Environment.getDataAppDirectory(null),
packageName);
int ret = PackageManager.INSTALL_SUCCEEDED;
try {
makeDirRecursive(dstCodePath, 0755);
for (File srcFile : compressedFiles) {
final String srcFileName = srcFile.getName();
final String dstFileName = srcFileName.substring(
0, srcFileName.length() - COMPRESSED_EXTENSION.length());
final File dstFile = new File(dstCodePath, dstFileName);
ret = decompressFile(srcFile, dstFile);
if (ret != PackageManager.INSTALL_SUCCEEDED) {
logCriticalInfo(Log.ERROR, "Failed to decompress"
+ "; pkg: " + packageName
+ ", file: " + dstFileName);
break;
}
}
} catch (ErrnoException e) {
logCriticalInfo(Log.ERROR, "Failed to decompress"
+ "; pkg: " + packageName
+ ", err: " + e.errno);
}
if (ret == PackageManager.INSTALL_SUCCEEDED) {
final File libraryRoot = new File(dstCodePath, LIB_DIR_NAME);
NativeLibraryHelper.Handle handle = null;
try {
handle = NativeLibraryHelper.Handle.create(dstCodePath);
ret = NativeLibraryHelper.copyNativeBinariesWithOverride(handle, libraryRoot,
null /*abiOverride*/, false /*isIncremental*/);
} catch (IOException e) {
logCriticalInfo(Log.ERROR, "Failed to extract native libraries"
+ "; pkg: " + packageName);
ret = PackageManager.INSTALL_FAILED_INTERNAL_ERROR;
} finally {
IoUtils.closeQuietly(handle);
}
}
if (ret == PackageManager.INSTALL_SUCCEEDED) {
// NOTE: During boot, we have to delay releasing cblocks for no other reason than
// we cannot retrieve the setting {@link Secure#RELEASE_COMPRESS_BLOCKS_ON_INSTALL}.
// When we no longer need to read that setting, cblock release can occur always
// occur here directly
if (!mPm.isSystemReady()) {
if (mPm.mReleaseOnSystemReady == null) {
mPm.mReleaseOnSystemReady = new ArrayList<>();
}
mPm.mReleaseOnSystemReady.add(dstCodePath);
} else {
final ContentResolver resolver = mPm.mContext.getContentResolver();
F2fsUtils.releaseCompressedBlocks(resolver, dstCodePath);
}
}
if (ret != PackageManager.INSTALL_SUCCEEDED) {
if (!dstCodePath.exists()) {
return null;
}
mRemovePackageHelper.removeCodePathLI(dstCodePath);
return null;
}
return dstCodePath;
}
@GuardedBy("mPm.mLock")
private void enableSystemPackageLPw(AndroidPackage pkg) {
mPm.mSettings.enableSystemPackageLPw(pkg.getPackageName());
}
/**
* Tries to restore the disabled system package after an update has been deleted.
*/
@GuardedBy({"mPm.mLock", "mPm.mInstallLock"})
public void restoreDisabledSystemPackageLIF(DeletePackageAction action,
PackageSetting deletedPs, @NonNull int[] allUserHandles,
@Nullable PackageRemovedInfo outInfo,
boolean writeSettings,
PackageSetting disabledPs)
throws SystemDeleteException {
// writer
synchronized (mPm.mLock) {
// NOTE: The system package always needs to be enabled; even if it's for
// a compressed stub. If we don't, installing the system package fails
// during scan [scanning checks the disabled packages]. We will reverse
// this later, after we've "installed" the stub.
// Reinstate the old system package
enableSystemPackageLPw(disabledPs.getPkg());
// Remove any native libraries from the upgraded package.
removeNativeBinariesLI(deletedPs);
}
// Install the system package
if (DEBUG_REMOVE) Slog.d(TAG, "Re-installing system package: " + disabledPs);
try {
installPackageFromSystemLIF(disabledPs.getPathString(), allUserHandles,
outInfo == null ? null : outInfo.mOrigUsers, writeSettings);
} catch (PackageManagerException e) {
Slog.w(TAG, "Failed to restore system package:" + deletedPs.getPackageName() + ": "
+ e.getMessage());
// TODO(b/194319951): can we avoid this; throw would come from scan...
throw new SystemDeleteException(e);
} finally {
if (disabledPs.getPkg().isStub()) {
// We've re-installed the stub; make sure it's disabled here. If package was
// originally enabled, we'll install the compressed version of the application
// and re-enable it afterward.
final PackageSetting stubPs = mPm.mSettings.getPackageLPr(
deletedPs.getPackageName());
if (stubPs != null) {
int userId = action.mUser == null
? UserHandle.USER_ALL : action.mUser.getIdentifier();
if (userId == UserHandle.USER_ALL) {
for (int aUserId : allUserHandles) {
stubPs.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, aUserId, "android");
}
} else if (userId >= UserHandle.USER_SYSTEM) {
stubPs.setEnabled(COMPONENT_ENABLED_STATE_DISABLED, userId, "android");
}
}
}
}
}
private void removeNativeBinariesLI(PackageSetting ps) {
if (ps != null) {
NativeLibraryHelper.removeNativeBinariesLI(ps.getLegacyNativeLibraryPath());
}
}
/**
* Installs a package that's already on the system partition.
*/
@GuardedBy({"mPm.mLock", "mPm.mInstallLock"})
private void installPackageFromSystemLIF(@NonNull String codePathString,
@NonNull int[] allUserHandles, @Nullable int[] origUserHandles, boolean writeSettings)
throws PackageManagerException {
final File codePath = new File(codePathString);
@ParsingPackageUtils.ParseFlags int parseFlags =
mPm.getDefParseFlags()
| ParsingPackageUtils.PARSE_MUST_BE_APK
| ParsingPackageUtils.PARSE_IS_SYSTEM_DIR;
@PackageManagerService.ScanFlags int scanFlags = SCAN_AS_SYSTEM;
for (int i = mDirsToScanAsSystem.size() - 1; i >= 0; i--) {
ScanPartition partition = mDirsToScanAsSystem.get(i);
if (partition.containsFile(codePath)) {
scanFlags |= partition.scanFlag;
if (partition.containsPrivApp(codePath)) {
scanFlags |= SCAN_AS_PRIVILEGED;
}
break;
}
}
final ScanPackageHelper scanPackageHelper = new ScanPackageHelper(mPm);
final AndroidPackage pkg =
scanPackageHelper.scanPackageTracedLI(
codePath, parseFlags, scanFlags, 0 /*currentTime*/, null);
PackageSetting pkgSetting = mPm.mSettings.getPackageLPr(pkg.getPackageName());
try {
// update shared libraries for the newly re-installed system package
mPm.updateSharedLibrariesLocked(pkg, pkgSetting, null, null,
Collections.unmodifiableMap(mPm.mPackages));
} catch (PackageManagerException e) {
Slog.e(TAG, "updateAllSharedLibrariesLPw failed: " + e.getMessage());
}
mAppDataHelper.prepareAppDataAfterInstallLIF(pkg);
// writer
synchronized (mPm.mLock) {
PackageSetting ps = mPm.mSettings.getPackageLPr(pkg.getPackageName());
final boolean applyUserRestrictions = origUserHandles != null;
if (applyUserRestrictions) {
boolean installedStateChanged = false;
if (DEBUG_REMOVE) {
Slog.d(TAG, "Propagating install state across reinstall");
}
for (int userId : allUserHandles) {
final boolean installed = ArrayUtils.contains(origUserHandles, userId);
if (DEBUG_REMOVE) {
Slog.d(TAG, " user " + userId + " => " + installed);
}
if (installed != ps.getInstalled(userId)) {
installedStateChanged = true;
}
ps.setInstalled(installed, userId);
if (installed) {
ps.setUninstallReason(UNINSTALL_REASON_UNKNOWN, userId);
}
}
// Regardless of writeSettings we need to ensure that this restriction
// state propagation is persisted
mPm.mSettings.writeAllUsersPackageRestrictionsLPr();
if (installedStateChanged) {
mPm.mSettings.writeKernelMappingLPr(ps);
}
}
// The method below will take care of removing obsolete permissions and granting
// install permissions.
mPm.mPermissionManager.onPackageInstalled(pkg,
Process.INVALID_UID /* previousAppId */,
PermissionManagerServiceInternal.PackageInstalledParams.DEFAULT,
UserHandle.USER_ALL);
for (final int userId : allUserHandles) {
if (applyUserRestrictions) {
mPm.mSettings.writePermissionStateForUserLPr(userId, false);
}
}
// can downgrade to reader here
if (writeSettings) {
mPm.writeSettingsLPrTEMP();
}
}
}
public boolean isExpectingBetter(String packageName) {
return mExpectingBetter.containsKey(packageName);
}
public List<ScanPartition> getDirsToScanAsSystem() {
return mDirsToScanAsSystem;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -16,20 +16,15 @@
package com.android.server.pm;
import static android.content.pm.PackageManager.INSTALL_FAILED_PACKAGE_CHANGED;
import static android.os.PowerExemptionManager.REASON_PACKAGE_REPLACED;
import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
import static com.android.server.pm.PackageManagerService.CHECK_PENDING_INTEGRITY_VERIFICATION;
import static com.android.server.pm.PackageManagerService.CHECK_PENDING_VERIFICATION;
import static com.android.server.pm.PackageManagerService.DEBUG_BACKUP;
import static com.android.server.pm.PackageManagerService.DEBUG_INSTALL;
import static com.android.server.pm.PackageManagerService.DEFAULT_VERIFICATION_RESPONSE;
import static com.android.server.pm.PackageManagerService.DEFERRED_NO_KILL_INSTALL_OBSERVER;
import static com.android.server.pm.PackageManagerService.DEFERRED_NO_KILL_POST_DELETE;
import static com.android.server.pm.PackageManagerService.DEFERRED_NO_KILL_POST_DELETE_DELAY_MS;
import static com.android.server.pm.PackageManagerService.DOMAIN_VERIFICATION;
import static com.android.server.pm.PackageManagerService.EMPTY_INT_ARRAY;
import static com.android.server.pm.PackageManagerService.ENABLE_ROLLBACK_STATUS;
import static com.android.server.pm.PackageManagerService.ENABLE_ROLLBACK_TIMEOUT;
import static com.android.server.pm.PackageManagerService.INIT_COPY;
@@ -46,15 +41,11 @@ import static com.android.server.pm.PackageManagerService.WRITE_PACKAGE_RESTRICT
import static com.android.server.pm.PackageManagerService.WRITE_SETTINGS;
import android.content.Intent;
import android.content.pm.IPackageInstallObserver2;
import android.content.pm.InstantAppRequest;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInstaller;
import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.net.Uri;
import android.os.Binder;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
@@ -62,39 +53,20 @@ import android.os.Process;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.os.storage.StorageManager;
import android.os.storage.VolumeInfo;
import android.stats.storage.StorageEnums;
import android.util.ArrayMap;
import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FrameworkStatsLog;
import com.android.server.EventLogTags;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import dalvik.system.VMRuntime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
/**
* Part of PackageManagerService that handles events.
*/
public final class PackageHandler extends Handler {
final class PackageHandler extends Handler {
private final PackageManagerService mPm;
private final VerificationHelper mVerificationHelper;
private final BroadcastHelper mBroadcastHelper;
private final InstallPackageHelper mInstallPackageHelper;
PackageHandler(Looper looper, PackageManagerService pm) {
super(looper);
mPm = pm;
mVerificationHelper = new VerificationHelper(mPm.mContext);
mBroadcastHelper = new BroadcastHelper(mPm.mInjector);
mInstallPackageHelper = new InstallPackageHelper(mPm);
}
@Override
@@ -121,46 +93,7 @@ public final class PackageHandler extends Handler {
break;
}
case SEND_PENDING_BROADCAST: {
String[] packages;
ArrayList<String>[] components;
int size = 0;
int[] uids;
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
synchronized (mPm.mLock) {
size = mPm.mPendingBroadcasts.size();
if (size <= 0) {
// Nothing to be done. Just return
return;
}
packages = new String[size];
components = new ArrayList[size];
uids = new int[size];
int i = 0; // filling out the above arrays
for (int n = 0; n < mPm.mPendingBroadcasts.userIdCount(); n++) {
final int packageUserId = mPm.mPendingBroadcasts.userIdAt(n);
final ArrayMap<String, ArrayList<String>> componentsToBroadcast =
mPm.mPendingBroadcasts.packagesForUserId(packageUserId);
final int numComponents = componentsToBroadcast.size();
for (int index = 0; i < size && index < numComponents; index++) {
packages[i] = componentsToBroadcast.keyAt(index);
components[i] = componentsToBroadcast.valueAt(index);
final PackageSetting ps = mPm.mSettings.getPackageLPr(packages[i]);
uids[i] = (ps != null)
? UserHandle.getUid(packageUserId, ps.getAppId())
: -1;
i++;
}
}
size = i;
mPm.mPendingBroadcasts.clear();
}
// Send broadcasts
for (int i = 0; i < size; i++) {
mPm.sendPackageChangedBroadcast(packages[i], true /* dontKillApp */,
components[i], uids[i], null /* reason */);
}
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
mInstallPackageHelper.sendPendingBroadcasts();
break;
}
case POST_INSTALL: {
@@ -177,23 +110,7 @@ public final class PackageHandler extends Handler {
if (data != null && data.mPostInstallRunnable != null) {
data.mPostInstallRunnable.run();
} else if (data != null && data.args != null) {
InstallArgs args = data.args;
PackageInstalledInfo parentRes = data.res;
final boolean killApp = (args.mInstallFlags
& PackageManager.INSTALL_DONT_KILL_APP) == 0;
final boolean virtualPreload = ((args.mInstallFlags
& PackageManager.INSTALL_VIRTUAL_PRELOAD) != 0);
handlePackagePostInstall(parentRes, killApp, virtualPreload,
didRestore, args.mInstallSource.installerPackageName,
args.mObserver, args.mDataLoaderType);
// Log tracing if needed
if (args.mTraceMethod != null) {
Trace.asyncTraceEnd(TRACE_TAG_PACKAGE_MANAGER, args.mTraceMethod,
args.mTraceCookie);
}
mInstallPackageHelper.handlePackagePostInstall(data.res, data.args, didRestore);
} else if (DEBUG_INSTALL) {
// No post-install when we run restore from installExistingPackageForUser
Slog.i(TAG, "Nothing to do for post-install token " + msg.arg1);
@@ -217,31 +134,17 @@ public final class PackageHandler extends Handler {
} break;
case WRITE_SETTINGS: {
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
synchronized (mPm.mLock) {
removeMessages(WRITE_SETTINGS);
removeMessages(WRITE_PACKAGE_RESTRICTIONS);
mPm.writeSettingsLPrTEMP();
mPm.mDirtyUsers.clear();
}
mPm.writeSettings();
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
} break;
case WRITE_PACKAGE_RESTRICTIONS: {
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
synchronized (mPm.mLock) {
removeMessages(WRITE_PACKAGE_RESTRICTIONS);
for (int userId : mPm.mDirtyUsers) {
mPm.mSettings.writePackageRestrictionsLPr(userId);
}
mPm.mDirtyUsers.clear();
}
mPm.writePendingRestrictions();
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
} break;
case WRITE_PACKAGE_LIST: {
Process.setThreadPriority(Process.THREAD_PRIORITY_DEFAULT);
synchronized (mPm.mLock) {
removeMessages(WRITE_PACKAGE_LIST);
mPm.mSettings.writePackageListLPr(msg.arg1);
}
mPm.writePackageList(msg.arg1);
Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
} break;
case CHECK_PENDING_VERIFICATION: {
@@ -262,13 +165,13 @@ public final class PackageHandler extends Handler {
Slog.i(TAG, "Continuing with installation of " + originUri);
state.setVerifierResponse(Binder.getCallingUid(),
PackageManager.VERIFICATION_ALLOW_WITHOUT_SUFFICIENT);
mVerificationHelper.broadcastPackageVerified(verificationId, originUri,
VerificationUtils.broadcastPackageVerified(verificationId, originUri,
PackageManager.VERIFICATION_ALLOW, null, params.mDataLoaderType,
user);
user, mPm.mContext);
} else {
mVerificationHelper.broadcastPackageVerified(verificationId, originUri,
VerificationUtils.broadcastPackageVerified(verificationId, originUri,
PackageManager.VERIFICATION_REJECT, null,
params.mDataLoaderType, user);
params.mDataLoaderType, user, mPm.mContext);
params.setReturnCode(
PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE, errorMsg);
state.setVerifierResponse(Binder.getCallingUid(),
@@ -343,8 +246,9 @@ public final class PackageHandler extends Handler {
final Uri originUri = Uri.fromFile(params.mOriginInfo.mResolvedFile);
if (state.isInstallAllowed()) {
mVerificationHelper.broadcastPackageVerified(verificationId, originUri,
response.code, null, params.mDataLoaderType, params.getUser());
VerificationUtils.broadcastPackageVerified(verificationId, originUri,
response.code, null, params.mDataLoaderType, params.getUser(),
mPm.mContext);
} else {
params.setReturnCode(
PackageManager.INSTALL_FAILED_VERIFICATION_FAILURE,
@@ -475,285 +379,6 @@ public final class PackageHandler extends Handler {
}
}
private void handlePackagePostInstall(PackageInstalledInfo res, boolean killApp,
boolean virtualPreload, boolean launchedForRestore, String installerPackage,
IPackageInstallObserver2 installObserver, int dataLoaderType) {
boolean succeeded = res.mReturnCode == PackageManager.INSTALL_SUCCEEDED;
final boolean update = res.mRemovedInfo != null && res.mRemovedInfo.mRemovedPackage != null;
final String packageName = res.mName;
final PackageSetting pkgSetting = succeeded ? mPm.getPackageSetting(packageName) : null;
final boolean removedBeforeUpdate = (pkgSetting == null)
|| (pkgSetting.isSystem() && !pkgSetting.getPathString().equals(
res.mPkg.getPath()));
if (succeeded && removedBeforeUpdate) {
Slog.e(TAG, packageName + " was removed before handlePackagePostInstall "
+ "could be executed");
res.mReturnCode = INSTALL_FAILED_PACKAGE_CHANGED;
res.mReturnMsg = "Package was removed before install could complete.";
// Remove the update failed package's older resources safely now
InstallArgs args = res.mRemovedInfo != null ? res.mRemovedInfo.mArgs : null;
if (args != null) {
synchronized (mPm.mInstallLock) {
args.doPostDeleteLI(true);
}
}
mPm.notifyInstallObserver(res, installObserver);
return;
}
if (succeeded) {
// Clear the uid cache after we installed a new package.
mPm.mPerUidReadTimeoutsCache = null;
// Send the removed broadcasts
if (res.mRemovedInfo != null) {
res.mRemovedInfo.sendPackageRemovedBroadcasts(killApp, false /*removedBySystem*/);
}
final String installerPackageName =
res.mInstallerPackageName != null
? res.mInstallerPackageName
: res.mRemovedInfo != null
? res.mRemovedInfo.mInstallerPackageName
: null;
synchronized (mPm.mLock) {
mPm.mInstantAppRegistry.onPackageInstalledLPw(res.mPkg, res.mNewUsers);
}
// Determine the set of users who are adding this package for
// the first time vs. those who are seeing an update.
int[] firstUserIds = EMPTY_INT_ARRAY;
int[] firstInstantUserIds = EMPTY_INT_ARRAY;
int[] updateUserIds = EMPTY_INT_ARRAY;
int[] instantUserIds = EMPTY_INT_ARRAY;
final boolean allNewUsers = res.mOrigUsers == null || res.mOrigUsers.length == 0;
for (int newUser : res.mNewUsers) {
final boolean isInstantApp = pkgSetting.getInstantApp(newUser);
if (allNewUsers) {
if (isInstantApp) {
firstInstantUserIds = ArrayUtils.appendInt(firstInstantUserIds, newUser);
} else {
firstUserIds = ArrayUtils.appendInt(firstUserIds, newUser);
}
continue;
}
boolean isNew = true;
for (int origUser : res.mOrigUsers) {
if (origUser == newUser) {
isNew = false;
break;
}
}
if (isNew) {
if (isInstantApp) {
firstInstantUserIds = ArrayUtils.appendInt(firstInstantUserIds, newUser);
} else {
firstUserIds = ArrayUtils.appendInt(firstUserIds, newUser);
}
} else {
if (isInstantApp) {
instantUserIds = ArrayUtils.appendInt(instantUserIds, newUser);
} else {
updateUserIds = ArrayUtils.appendInt(updateUserIds, newUser);
}
}
}
// Send installed broadcasts if the package is not a static shared lib.
if (res.mPkg.getStaticSharedLibName() == null) {
mPm.mProcessLoggingHandler.invalidateBaseApkHash(res.mPkg.getBaseApkPath());
// Send added for users that see the package for the first time
// sendPackageAddedForNewUsers also deals with system apps
int appId = UserHandle.getAppId(res.mUid);
boolean isSystem = res.mPkg.isSystem();
mPm.sendPackageAddedForNewUsers(packageName, isSystem || virtualPreload,
virtualPreload /*startReceiver*/, appId, firstUserIds, firstInstantUserIds,
dataLoaderType);
// Send added for users that don't see the package for the first time
Bundle extras = new Bundle(1);
extras.putInt(Intent.EXTRA_UID, res.mUid);
if (update) {
extras.putBoolean(Intent.EXTRA_REPLACING, true);
}
extras.putInt(PackageInstaller.EXTRA_DATA_LOADER_TYPE, dataLoaderType);
// Send to all running apps.
final SparseArray<int[]> newBroadcastAllowList;
synchronized (mPm.mLock) {
newBroadcastAllowList = mPm.mAppsFilter.getVisibilityAllowList(
mPm.getPackageSettingInternal(res.mName, Process.SYSTEM_UID),
updateUserIds, mPm.mSettings.getPackagesLocked());
}
mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
extras, 0 /*flags*/,
null /*targetPackage*/, null /*finishedReceiver*/,
updateUserIds, instantUserIds, newBroadcastAllowList, null);
if (installerPackageName != null) {
// Send to the installer, even if it's not running.
mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
extras, 0 /*flags*/,
installerPackageName, null /*finishedReceiver*/,
updateUserIds, instantUserIds, null /* broadcastAllowList */, null);
}
// if the required verifier is defined, but, is not the installer of record
// for the package, it gets notified
final boolean notifyVerifier = mPm.mRequiredVerifierPackage != null
&& !mPm.mRequiredVerifierPackage.equals(installerPackageName);
if (notifyVerifier) {
mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
extras, 0 /*flags*/,
mPm.mRequiredVerifierPackage, null /*finishedReceiver*/,
updateUserIds, instantUserIds, null /* broadcastAllowList */, null);
}
// If package installer is defined, notify package installer about new
// app installed
if (mPm.mRequiredInstallerPackage != null) {
mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_ADDED, packageName,
extras, Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND /*flags*/,
mPm.mRequiredInstallerPackage, null /*finishedReceiver*/,
firstUserIds, instantUserIds, null /* broadcastAllowList */, null);
}
// Send replaced for users that don't see the package for the first time
if (update) {
mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED,
packageName, extras, 0 /*flags*/,
null /*targetPackage*/, null /*finishedReceiver*/,
updateUserIds, instantUserIds, res.mRemovedInfo.mBroadcastAllowList,
null);
if (installerPackageName != null) {
mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
extras, 0 /*flags*/,
installerPackageName, null /*finishedReceiver*/,
updateUserIds, instantUserIds, null /*broadcastAllowList*/, null);
}
if (notifyVerifier) {
mPm.sendPackageBroadcast(Intent.ACTION_PACKAGE_REPLACED, packageName,
extras, 0 /*flags*/,
mPm.mRequiredVerifierPackage, null /*finishedReceiver*/,
updateUserIds, instantUserIds, null /*broadcastAllowList*/, null);
}
mPm.sendPackageBroadcast(Intent.ACTION_MY_PACKAGE_REPLACED,
null /*package*/, null /*extras*/, 0 /*flags*/,
packageName /*targetPackage*/,
null /*finishedReceiver*/, updateUserIds, instantUserIds,
null /*broadcastAllowList*/,
mBroadcastHelper.getTemporaryAppAllowlistBroadcastOptions(
REASON_PACKAGE_REPLACED).toBundle());
} else if (launchedForRestore && !res.mPkg.isSystem()) {
// First-install and we did a restore, so we're responsible for the
// first-launch broadcast.
if (DEBUG_BACKUP) {
Slog.i(TAG, "Post-restore of " + packageName
+ " sending FIRST_LAUNCH in " + Arrays.toString(firstUserIds));
}
mBroadcastHelper.sendFirstLaunchBroadcast(packageName, installerPackage,
firstUserIds, firstInstantUserIds);
}
// Send broadcast package appeared if external for all users
if (res.mPkg.isExternalStorage()) {
if (!update) {
final StorageManager storage = mPm.mInjector.getSystemService(
StorageManager.class);
VolumeInfo volume =
storage.findVolumeByUuid(
StorageManager.convert(
res.mPkg.getVolumeUuid()).toString());
int packageExternalStorageType =
PackageManagerServiceUtils.getPackageExternalStorageType(volume,
res.mPkg.isExternalStorage());
// If the package was installed externally, log it.
if (packageExternalStorageType != StorageEnums.UNKNOWN) {
FrameworkStatsLog.write(
FrameworkStatsLog.APP_INSTALL_ON_EXTERNAL_STORAGE_REPORTED,
packageExternalStorageType, packageName);
}
}
if (DEBUG_INSTALL) {
Slog.i(TAG, "upgrading pkg " + res.mPkg + " is external");
}
final int[] uidArray = new int[]{res.mPkg.getUid()};
ArrayList<String> pkgList = new ArrayList<>(1);
pkgList.add(packageName);
mBroadcastHelper.sendResourcesChangedBroadcast(
true, true, pkgList, uidArray, null);
}
} else if (!ArrayUtils.isEmpty(res.mLibraryConsumers)) { // if static shared lib
for (int i = 0; i < res.mLibraryConsumers.size(); i++) {
AndroidPackage pkg = res.mLibraryConsumers.get(i);
// send broadcast that all consumers of the static shared library have changed
mPm.sendPackageChangedBroadcast(pkg.getPackageName(), false /* dontKillApp */,
new ArrayList<>(Collections.singletonList(pkg.getPackageName())),
pkg.getUid(), null);
}
}
// Work that needs to happen on first install within each user
if (firstUserIds != null && firstUserIds.length > 0) {
for (int userId : firstUserIds) {
mPm.restorePermissionsAndUpdateRolesForNewUserInstall(packageName,
userId);
}
}
if (allNewUsers && !update) {
mPm.notifyPackageAdded(packageName, res.mUid);
} else {
mPm.notifyPackageChanged(packageName, res.mUid);
}
// Log current value of "unknown sources" setting
EventLog.writeEvent(EventLogTags.UNKNOWN_SOURCES_ENABLED,
getUnknownSourcesSettings());
// Remove the replaced package's older resources safely now
InstallArgs args = res.mRemovedInfo != null ? res.mRemovedInfo.mArgs : null;
if (args != null) {
if (!killApp) {
// If we didn't kill the app, defer the deletion of code/resource files, since
// they may still be in use by the running application. This mitigates problems
// in cases where resources or code is loaded by a new Activity before
// ApplicationInfo changes have propagated to all application threads.
scheduleDeferredNoKillPostDelete(args);
} else {
synchronized (mPm.mInstallLock) {
args.doPostDeleteLI(true);
}
}
} else {
// Force a gc to clear up things. Ask for a background one, it's fine to go on
// and not block here.
VMRuntime.getRuntime().requestConcurrentGC();
}
// Notify DexManager that the package was installed for new users.
// The updated users should already be indexed and the package code paths
// should not change.
// Don't notify the manager for ephemeral apps as they are not expected to
// survive long enough to benefit of background optimizations.
for (int userId : firstUserIds) {
PackageInfo info = mPm.getPackageInfo(packageName, /*flags*/ 0, userId);
// There's a race currently where some install events may interleave with an
// uninstall. This can lead to package info being null (b/36642664).
if (info != null) {
mPm.getDexManager().notifyPackageInstalled(info, userId);
}
}
}
final boolean deferInstallObserver = succeeded && update && !killApp;
if (deferInstallObserver) {
mPm.scheduleDeferredNoKillInstallObserver(res, installObserver);
} else {
mPm.notifyInstallObserver(res, installObserver);
}
}
/**
* Get the default verification agent response code.
*
@@ -777,20 +402,4 @@ public final class PackageHandler extends Handler {
// an easy way to get around the integrity check.
return PackageManager.VERIFICATION_REJECT;
}
/**
* Get the "allow unknown sources" setting.
*
* @return the current "allow unknown sources" setting
*/
private int getUnknownSourcesSettings() {
return android.provider.Settings.Secure.getIntForUser(mPm.mContext.getContentResolver(),
android.provider.Settings.Secure.INSTALL_NON_MARKET_APPS,
-1, UserHandle.USER_SYSTEM);
}
private void scheduleDeferredNoKillPostDelete(InstallArgs args) {
Message message = obtainMessage(DEFERRED_NO_KILL_POST_DELETE, args);
sendMessageDelayed(message, DEFERRED_NO_KILL_POST_DELETE_DELAY_MS);
}
}

View File

@@ -1250,6 +1250,11 @@ public class PackageManagerService extends IPackageManager.Stub
mHandler.sendMessageDelayed(message, DEFERRED_NO_KILL_INSTALL_OBSERVER_DELAY_MS);
}
void scheduleDeferredNoKillPostDelete(InstallArgs args) {
Message message = mHandler.obtainMessage(DEFERRED_NO_KILL_POST_DELETE, args);
mHandler.sendMessageDelayed(message, DEFERRED_NO_KILL_POST_DELETE_DELAY_MS);
}
@Override
public void requestChecksums(@NonNull String packageName, boolean includeSplits,
@Checksum.TypeMask int optional,
@@ -1380,6 +1385,38 @@ public class PackageManagerService extends IPackageManager.Stub
}
}
private void writePendingRestrictionsLocked() {
if (mHandler.hasMessages(WRITE_PACKAGE_RESTRICTIONS)) {
mHandler.removeMessages(WRITE_PACKAGE_RESTRICTIONS);
for (int userId : mDirtyUsers) {
mSettings.writePackageRestrictionsLPr(userId);
}
mDirtyUsers.clear();
}
}
void writePendingRestrictions() {
synchronized (mLock) {
writePendingRestrictionsLocked();
}
}
void writeSettings() {
synchronized (mLock) {
mHandler.removeMessages(WRITE_SETTINGS);
mHandler.removeMessages(WRITE_PACKAGE_RESTRICTIONS);
writeSettingsLPrTEMP();
mDirtyUsers.clear();
}
}
void writePackageList(int userId) {
synchronized (mLock) {
mHandler.removeMessages(WRITE_PACKAGE_LIST);
mSettings.writePackageListLPr(userId);
}
}
public static PackageManagerService main(Context context, Installer installer,
@NonNull DomainVerificationService domainVerificationService, boolean factoryTest,
boolean onlyCore) {
@@ -1772,7 +1809,7 @@ public class PackageManagerService extends IPackageManager.Stub
mInitAndSystemPackageHelper = new InitAndSystemPackageHelper(this, mRemovePackageHelper,
mAppDataHelper);
mDeletePackageHelper = new DeletePackageHelper(this, mRemovePackageHelper,
mInitAndSystemPackageHelper, mAppDataHelper);
mAppDataHelper);
mPreferredActivityHelper = new PreferredActivityHelper(this);
mResolveIntentHelper = new ResolveIntentHelper(this, mPreferredActivityHelper);
mDexOptHelper = new DexOptHelper(this);
@@ -5059,13 +5096,7 @@ public class PackageManagerService extends IPackageManager.Stub
mPackageUsage.writeNow(mSettings.getPackagesLocked());
// This is the last chance to write out pending restriction settings
if (mHandler.hasMessages(WRITE_PACKAGE_RESTRICTIONS)) {
mHandler.removeMessages(WRITE_PACKAGE_RESTRICTIONS);
for (int userId : mDirtyUsers) {
mSettings.writePackageRestrictionsLPr(userId);
}
mDirtyUsers.clear();
}
writePendingRestrictionsLocked();
}
}
@@ -7808,7 +7839,8 @@ public class PackageManagerService extends IPackageManager.Stub
if (isSystemStub
&& (newState == PackageManager.COMPONENT_ENABLED_STATE_DEFAULT
|| newState == PackageManager.COMPONENT_ENABLED_STATE_ENABLED)) {
if (!mInitAndSystemPackageHelper.enableCompressedPackage(deletedPkg, pkgSetting)) {
if (!new InstallPackageHelper(this).enableCompressedPackage(deletedPkg,
pkgSetting)) {
Slog.w(TAG, "Failed setApplicationEnabledSetting: failed to enable "
+ "commpressed package " + setting.getPackageName());
updateAllowed[i] = false;
@@ -11083,11 +11115,24 @@ public class PackageManagerService extends IPackageManager.Stub
return mIsPreNMR1Upgrade;
}
InitAndSystemPackageHelper getInitAndSystemPackageHelper() {
return mInitAndSystemPackageHelper;
}
boolean isOverlayMutable(String packageName) {
return mOverlayConfig.isMutable(packageName);
}
@ScanFlags int getSystemPackageScanFlags(File codePath) {
List<ScanPartition> dirsToScanAsSystem =
mInitAndSystemPackageHelper.getDirsToScanAsSystem();
@PackageManagerService.ScanFlags int scanFlags = SCAN_AS_SYSTEM;
for (int i = dirsToScanAsSystem.size() - 1; i >= 0; i--) {
ScanPartition partition = dirsToScanAsSystem.get(i);
if (partition.containsFile(codePath)) {
scanFlags |= partition.scanFlag;
if (partition.containsPrivApp(codePath)) {
scanFlags |= SCAN_AS_PRIVILEGED;
}
break;
}
}
return scanFlags;
}
}

View File

@@ -643,6 +643,35 @@ public class PackageManagerServiceUtils {
return compatMatch;
}
/**
* Decompress files stored in codePath to dstCodePath for a certain package.
*/
public static int decompressFiles(String codePath, File dstCodePath, String packageName) {
final File[] compressedFiles = getCompressedFiles(codePath);
int ret = PackageManager.INSTALL_SUCCEEDED;
try {
makeDirRecursive(dstCodePath, 0755);
for (File srcFile : compressedFiles) {
final String srcFileName = srcFile.getName();
final String dstFileName = srcFileName.substring(
0, srcFileName.length() - COMPRESSED_EXTENSION.length());
final File dstFile = new File(dstCodePath, dstFileName);
ret = decompressFile(srcFile, dstFile);
if (ret != PackageManager.INSTALL_SUCCEEDED) {
logCriticalInfo(Log.ERROR, "Failed to decompress"
+ "; pkg: " + packageName
+ ", file: " + dstFileName);
break;
}
}
} catch (ErrnoException e) {
logCriticalInfo(Log.ERROR, "Failed to decompress"
+ "; pkg: " + packageName
+ ", err: " + e.errno);
}
return ret;
}
public static int decompressFile(File srcFile, File dstFile) throws ErrnoException {
if (DEBUG_COMPRESSION) {
Slog.i(TAG, "Decompress file"

View File

@@ -51,7 +51,6 @@ import android.content.pm.PackageManager;
import android.content.pm.PackageManagerInternal;
import android.content.pm.ParceledListSlice;
import android.content.pm.ResolveInfo;
import android.content.pm.Signature;
import android.content.pm.SigningDetails;
import android.content.pm.VerifierInfo;
import android.content.pm.parsing.PackageLite;
@@ -62,7 +61,6 @@ import android.os.Process;
import android.os.RemoteException;
import android.os.Trace;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.DeviceConfig;
import android.provider.Settings;
import android.util.ArraySet;
@@ -70,13 +68,9 @@ import android.util.Pair;
import android.util.Slog;
import com.android.server.DeviceIdleInternal;
import com.android.server.pm.parsing.pkg.AndroidPackage;
import java.io.File;
import java.security.PublicKey;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
@@ -90,10 +84,6 @@ final class VerificationParams extends HandlerParams {
* milliseconds.
*/
private static final long DEFAULT_INTEGRITY_VERIFICATION_TIMEOUT = 30 * 1000;
/**
* Whether verification is enabled by default.
*/
private static final boolean DEFAULT_VERIFY_ENABLE = true;
/**
* Timeout duration in milliseconds for enabling package rollback. If we fail to enable
* rollback within that period, the install will proceed without rollback enabled.
@@ -166,7 +156,7 @@ final class VerificationParams extends HandlerParams {
PackageInfoLite pkgLite = PackageManagerServiceUtils.getMinimalPackageInfo(mPm.mContext,
mPackageLite, mOriginInfo.mResolvedPath, mInstallFlags, mPackageAbiOverride);
Pair<Integer, String> ret = verifyReplacingVersionCode(
Pair<Integer, String> ret = mInstallPackageHelper.verifyReplacingVersionCode(
pkgLite, mRequiredInstalledVersionCode, mInstallFlags);
setReturnCode(ret.first, ret.second);
if (mRet != INSTALL_SUCCEEDED) {
@@ -186,7 +176,7 @@ final class VerificationParams extends HandlerParams {
}
}
void sendApkVerificationRequest(PackageInfoLite pkgLite) {
private void sendApkVerificationRequest(PackageInfoLite pkgLite) {
final int verificationId = mPm.mPendingVerificationToken++;
PackageVerificationState verificationState =
@@ -332,7 +322,7 @@ final class VerificationParams extends HandlerParams {
/**
* Send a request to verifier(s) to verify the package if necessary.
*/
void sendPackageVerificationRequest(
private void sendPackageVerificationRequest(
int verificationId,
PackageInfoLite pkgLite,
PackageVerificationState verificationState) {
@@ -354,7 +344,7 @@ final class VerificationParams extends HandlerParams {
verificationState.setRequiredVerifierUid(requiredUid);
final int installerUid =
mVerificationInfo == null ? -1 : mVerificationInfo.mInstallerUid;
final boolean isVerificationEnabled = isVerificationEnabled(
final boolean isVerificationEnabled = mInstallPackageHelper.isVerificationEnabled(
pkgLite, verifierUser.getIdentifier(), mInstallFlags, installerUid);
final boolean isV4Signed =
(mSigningDetails.getSignatureSchemeVersion() == SIGNING_BLOCK_V4);
@@ -404,7 +394,7 @@ final class VerificationParams extends HandlerParams {
DeviceIdleInternal idleController =
mPm.mInjector.getLocalService(DeviceIdleInternal.class);
final long idleDuration = mVerificationHelper.getVerificationTimeout();
final long idleDuration = VerificationUtils.getVerificationTimeout(mPm.mContext);
final BroadcastOptions options = BroadcastOptions.makeBasic();
options.setTemporaryAppAllowlist(idleDuration,
TEMPORARY_ALLOWLIST_TYPE_FOREGROUND_SERVICE_ALLOWED,
@@ -461,7 +451,7 @@ final class VerificationParams extends HandlerParams {
.obtainMessage(CHECK_PENDING_VERIFICATION);
msg.arg1 = verificationId;
mPm.mHandler.sendMessageDelayed(msg,
mVerificationHelper.getVerificationTimeout());
VerificationUtils.getVerificationTimeout(mPm.mContext));
}
}, null, 0, null, null);
@@ -498,7 +488,7 @@ final class VerificationParams extends HandlerParams {
continue;
}
final int verifierUid = getUidForVerifier(verifierInfo);
final int verifierUid = mInstallPackageHelper.getUidForVerifier(verifierInfo);
if (verifierUid == -1) {
continue;
}
@@ -514,44 +504,6 @@ final class VerificationParams extends HandlerParams {
return sufficientVerifiers;
}
private int getUidForVerifier(VerifierInfo verifierInfo) {
synchronized (mPm.mLock) {
final AndroidPackage pkg = mPm.mPackages.get(verifierInfo.packageName);
if (pkg == null) {
return -1;
} else if (pkg.getSigningDetails().getSignatures().length != 1) {
Slog.i(TAG, "Verifier package " + verifierInfo.packageName
+ " has more than one signature; ignoring");
return -1;
}
/*
* If the public key of the package's signature does not match
* our expected public key, then this is a different package and
* we should skip.
*/
final byte[] expectedPublicKey;
try {
final Signature verifierSig = pkg.getSigningDetails().getSignatures()[0];
final PublicKey publicKey = verifierSig.getPublicKey();
expectedPublicKey = publicKey.getEncoded();
} catch (CertificateException e) {
return -1;
}
final byte[] actualPublicKey = verifierInfo.publicKey.getEncoded();
if (!Arrays.equals(actualPublicKey, expectedPublicKey)) {
Slog.i(TAG, "Verifier package " + verifierInfo.packageName
+ " does not have the expected public key; ignoring");
return -1;
}
return pkg.getUid();
}
}
private static ComponentName matchComponentForVerifier(String packageName,
List<ResolveInfo> receivers) {
ActivityInfo targetReceiver = null;
@@ -576,56 +528,6 @@ final class VerificationParams extends HandlerParams {
return new ComponentName(targetReceiver.packageName, targetReceiver.name);
}
/**
* Check whether or not package verification has been enabled.
*
* @return true if verification should be performed
*/
private boolean isVerificationEnabled(
PackageInfoLite pkgInfoLite, int userId, int installFlags, int installerUid) {
if (!DEFAULT_VERIFY_ENABLE) {
return false;
}
// Check if installing from ADB
if ((installFlags & PackageManager.INSTALL_FROM_ADB) != 0) {
if (mPm.isUserRestricted(userId, UserManager.ENSURE_VERIFY_APPS)) {
return true;
}
// Check if the developer wants to skip verification for ADB installs
if ((installFlags & PackageManager.INSTALL_DISABLE_VERIFICATION) != 0) {
synchronized (mPm.mLock) {
if (mPm.mSettings.getPackageLPr(pkgInfoLite.packageName) == null) {
// Always verify fresh install
return true;
}
}
// Only skip when apk is debuggable
return !pkgInfoLite.debuggable;
}
return Settings.Global.getInt(mPm.mContext.getContentResolver(),
Settings.Global.PACKAGE_VERIFIER_INCLUDE_ADB, 1) != 0;
}
// only when not installed from ADB, skip verification for instant apps when
// the installer and verifier are the same.
if ((installFlags & PackageManager.INSTALL_INSTANT_APP) != 0) {
if (mPm.mInstantAppInstallerActivity != null
&& mPm.mInstantAppInstallerActivity.packageName.equals(
mPm.mRequiredVerifierPackage)) {
try {
mPm.mInjector.getSystemService(AppOpsManager.class)
.checkPackage(installerUid, mPm.mRequiredVerifierPackage);
if (DEBUG_VERIFY) {
Slog.i(TAG, "disable verification for instant app");
}
return false;
} catch (SecurityException ignore) { }
}
}
return true;
}
void populateInstallerExtras(Intent intent) {
intent.putExtra(PackageManager.EXTRA_VERIFICATION_INSTALLER_PACKAGE,
mInstallSource.initiatingPackageName);

View File

@@ -27,36 +27,30 @@ import android.net.Uri;
import android.os.UserHandle;
import android.provider.Settings;
public final class VerificationHelper {
final class VerificationUtils {
/**
* The default maximum time to wait for the verification agent to return in
* milliseconds.
*/
private static final long DEFAULT_VERIFICATION_TIMEOUT = 10 * 1000;
Context mContext;
public VerificationHelper(Context context) {
mContext = context;
}
/**
* Get the verification agent timeout. Used for both the APK verifier and the
* intent filter verifier.
*
* @return verification timeout in milliseconds
*/
public long getVerificationTimeout() {
long timeout = Settings.Global.getLong(mContext.getContentResolver(),
public static long getVerificationTimeout(Context context) {
long timeout = Settings.Global.getLong(context.getContentResolver(),
Settings.Global.PACKAGE_VERIFIER_TIMEOUT, DEFAULT_VERIFICATION_TIMEOUT);
// The setting can be used to increase the timeout but not decrease it, since that is
// equivalent to disabling the verifier.
return Math.max(timeout, DEFAULT_VERIFICATION_TIMEOUT);
}
public void broadcastPackageVerified(int verificationId, Uri packageUri,
public static void broadcastPackageVerified(int verificationId, Uri packageUri,
int verificationCode, @Nullable String rootHashString, int dataLoaderType,
UserHandle user) {
UserHandle user, Context context) {
final Intent intent = new Intent(Intent.ACTION_PACKAGE_VERIFIED);
intent.setDataAndType(packageUri, PACKAGE_MIME_TYPE);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
@@ -67,7 +61,7 @@ public final class VerificationHelper {
}
intent.putExtra(PackageInstaller.EXTRA_DATA_LOADER_TYPE, dataLoaderType);
mContext.sendBroadcastAsUser(intent, user,
context.sendBroadcastAsUser(intent, user,
android.Manifest.permission.PACKAGE_VERIFICATION_AGENT);
}
}