Merge "Consolidate installation logics from params/args classes"
This commit is contained in:
@@ -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());
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user