summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/pm/InstallPackageHelper.java136
-rw-r--r--services/core/java/com/android/server/pm/InstallRequest.java102
-rw-r--r--services/core/java/com/android/server/pm/PackageSetting.java18
3 files changed, 158 insertions, 98 deletions
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 468b3a705bf1..2ee070653a07 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -56,7 +56,6 @@ 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.DEBUG_UPGRADE;
import static com.android.server.pm.PackageManagerService.DEBUG_VERIFY;
-import static com.android.server.pm.PackageManagerService.EMPTY_INT_ARRAY;
import static com.android.server.pm.PackageManagerService.MIN_INSTALLABLE_TARGET_SDK;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
import static com.android.server.pm.PackageManagerService.POST_INSTALL;
@@ -180,7 +179,6 @@ import com.android.server.pm.parsing.pkg.ParsedPackage;
import com.android.server.pm.permission.Permission;
import com.android.server.pm.permission.PermissionManagerServiceInternal;
import com.android.server.pm.pkg.AndroidPackage;
-import com.android.server.pm.pkg.PackageState;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.pm.pkg.SharedLibraryWrapper;
import com.android.server.pm.pkg.component.ComponentMutateUtils;
@@ -1245,6 +1243,7 @@ final class InstallPackageHelper {
boolean systemApp = false;
boolean replace = false;
synchronized (mPm.mLock) {
+ final PackageSetting ps = mPm.mSettings.getPackageLPr(pkgName);
// Check if installing already existing package
if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
String oldName = mPm.mSettings.getRenamedPackageLPr(pkgName);
@@ -1261,16 +1260,15 @@ final class InstallPackageHelper {
Slog.d(TAG, "Replacing existing renamed package: oldName="
+ oldName + " pkgName=" + pkgName);
}
- } else if (mPm.mPackages.containsKey(pkgName)) {
+ } else if (ps != null) {
// This package, under its official name, already exists
// on the device; we should replace it.
replace = true;
if (DEBUG_INSTALL) Slog.d(TAG, "Replace existing package: " + pkgName);
}
-
- if (replace) {
+ final AndroidPackage oldPackage = mPm.mPackages.get(pkgName);
+ if (replace && oldPackage != null) {
// Prevent apps opting out from runtime permissions
- AndroidPackage oldPackage = mPm.mPackages.get(pkgName);
final int oldTargetSdk = oldPackage.getTargetSdkVersion();
final int newTargetSdk = parsedPackage.getTargetSdkVersion();
if (oldTargetSdk > Build.VERSION_CODES.LOLLIPOP_MR1
@@ -1292,7 +1290,6 @@ final class InstallPackageHelper {
}
}
- PackageSetting ps = mPm.mSettings.getPackageLPr(pkgName);
PackageSetting signatureCheckPs = ps;
// SDK libs can have other major versions with different package names.
@@ -1368,8 +1365,8 @@ final class InstallPackageHelper {
if (DEBUG_INSTALL) Slog.d(TAG, "Existing package: " + ps);
systemApp = ps.isSystem();
- request.setOriginUsers(
- ps.queryInstalledUsers(mPm.mUserManager.getUserIds(), true));
+ request.setOriginUsers(ps.queryUsersInstalledOrHasData(
+ mPm.mUserManager.getUserIds()));
}
final int numGroups = ArrayUtils.size(parsedPackage.getPermissionGroups());
@@ -1595,7 +1592,7 @@ final class InstallPackageHelper {
boolean shouldCloseFreezerBeforeReturn = true;
try {
- final PackageState oldPackageState;
+ final PackageSetting oldPackageState;
final AndroidPackage oldPackage;
String renamedPackage;
boolean sysPkg = false;
@@ -1648,7 +1645,7 @@ final class InstallPackageHelper {
}
} else {
SigningDetails parsedPkgSigningDetails = parsedPackage.getSigningDetails();
- SigningDetails oldPkgSigningDetails = oldPackage.getSigningDetails();
+ SigningDetails oldPkgSigningDetails = oldPackageState.getSigningDetails();
// default to original signature matching
if (!parsedPkgSigningDetails.checkCapability(oldPkgSigningDetails,
SigningDetails.CertCapabilities.INSTALLED_DATA)
@@ -1668,7 +1665,8 @@ final class InstallPackageHelper {
}
// don't allow a system upgrade unless the upgrade hash matches
- if (oldPackage.getRestrictUpdateHash() != null && oldPackageState.isSystem()) {
+ if (oldPackage != null && oldPackage.getRestrictUpdateHash() != null
+ && oldPackageState.isSystem()) {
final byte[] digestBytes;
try {
final MessageDigest digest = MessageDigest.getInstance("SHA-512");
@@ -1691,23 +1689,26 @@ final class InstallPackageHelper {
parsedPackage.setRestrictUpdateHash(oldPackage.getRestrictUpdateHash());
}
- // APK should not change its sharedUserId declarations
- final var oldSharedUid = oldPackage.getSharedUserId() != null
- ? oldPackage.getSharedUserId() : "<nothing>";
- final var newSharedUid = parsedPackage.getSharedUserId() != null
- ? parsedPackage.getSharedUserId() : "<nothing>";
- if (!oldSharedUid.equals(newSharedUid)) {
- throw new PrepareFailure(INSTALL_FAILED_UID_CHANGED,
- "Package " + parsedPackage.getPackageName()
- + " shared user changed from "
- + oldSharedUid + " to " + newSharedUid);
- }
+ if (oldPackage != null) {
+ // APK should not change its sharedUserId declarations
+ final var oldSharedUid = oldPackage.getSharedUserId() != null
+ ? oldPackage.getSharedUserId() : "<nothing>";
+ final var newSharedUid = parsedPackage.getSharedUserId() != null
+ ? parsedPackage.getSharedUserId() : "<nothing>";
+ if (!oldSharedUid.equals(newSharedUid)) {
+ throw new PrepareFailure(INSTALL_FAILED_UID_CHANGED,
+ "Package " + parsedPackage.getPackageName()
+ + " shared user changed from "
+ + oldSharedUid + " to " + newSharedUid);
+ }
- // APK should not re-join shared UID
- if (oldPackage.isLeavingSharedUser() && !parsedPackage.isLeavingSharedUser()) {
- throw new PrepareFailure(INSTALL_FAILED_UID_CHANGED,
- "Package " + parsedPackage.getPackageName()
- + " attempting to rejoin " + newSharedUid);
+ // APK should not re-join shared UID
+ if (oldPackage.isLeavingSharedUser()
+ && !parsedPackage.isLeavingSharedUser()) {
+ throw new PrepareFailure(INSTALL_FAILED_UID_CHANGED,
+ "Package " + parsedPackage.getPackageName()
+ + " attempting to rejoin " + newSharedUid);
+ }
}
// In case of rollback, remember per-user/profile install state
@@ -1740,8 +1741,8 @@ final class InstallPackageHelper {
// Update what is removed
PackageRemovedInfo removedInfo = new PackageRemovedInfo(mPm);
- removedInfo.mUid = oldPackage.getUid();
- removedInfo.mRemovedPackage = oldPackage.getPackageName();
+ removedInfo.mUid = ps.getAppId();
+ removedInfo.mRemovedPackage = ps.getPackageName();
removedInfo.mInstallerPackageName =
ps.getInstallSource().mInstallerPackageName;
removedInfo.mIsStaticSharedLib =
@@ -1760,8 +1761,8 @@ final class InstallPackageHelper {
removedInfo.mUninstallReasons.put(userId,
ps.getUninstallReason(userId));
}
- removedInfo.mIsExternal = oldPackage.isExternalStorage();
- removedInfo.mRemovedPackageVersionCode = oldPackage.getLongVersionCode();
+ removedInfo.mIsExternal = oldPackageState.isExternalStorage();
+ removedInfo.mRemovedPackageVersionCode = oldPackageState.getVersionCode();
request.setRemovedInfo(removedInfo);
sysPkg = oldPackageState.isSystem();
@@ -1801,7 +1802,7 @@ final class InstallPackageHelper {
} else { // new package install
ps = null;
disabledPs = null;
- oldPackage = null;
+ oldPackageState = null;
// Remember this for later, in case we need to rollback this install
String pkgName1 = parsedPackage.getPackageName();
@@ -1832,8 +1833,8 @@ final class InstallPackageHelper {
shouldCloseFreezerBeforeReturn = false;
request.setPrepareResult(replace, targetScanFlags, targetParseFlags,
- oldPackage, parsedPackage, replace /* clearCodeCache */, sysPkg,
- ps, disabledPs);
+ oldPackageState, parsedPackage,
+ replace /* clearCodeCache */, sysPkg, ps, disabledPs);
} finally {
request.setFreezer(freezer);
if (shouldCloseFreezerBeforeReturn) {
@@ -2077,7 +2078,7 @@ final class InstallPackageHelper {
// Set the update and install times
PackageStateInternal deletedPkgSetting = mPm.snapshotComputer()
- .getPackageStateInternal(oldPackage.getPackageName());
+ .getPackageStateInternal(packageName);
// TODO(b/225756739): For rebootless APEX, consider using lastUpdateMillis provided
// by apexd to be more accurate.
installRequest.setScannedPackageSettingFirstInstallTimeFromReplaced(
@@ -2126,8 +2127,10 @@ final class InstallPackageHelper {
if (oldCodePaths == null) {
oldCodePaths = new ArraySet<>();
}
- Collections.addAll(oldCodePaths, oldPackage.getBaseApkPath());
- Collections.addAll(oldCodePaths, oldPackage.getSplitCodePaths());
+ if (oldPackage != null) {
+ Collections.addAll(oldCodePaths, oldPackage.getBaseApkPath());
+ Collections.addAll(oldCodePaths, oldPackage.getSplitCodePaths());
+ }
ps1.setOldCodePaths(oldCodePaths);
} else {
ps1.setOldCodePaths(null);
@@ -2852,46 +2855,11 @@ final class InstallPackageHelper {
mPm.notifyInstantAppPackageInstalled(request.getPkg().getPackageName(),
request.getNewUsers());
- // 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 = request.getOriginUsers() == null
- || request.getOriginUsers().length == 0;
- for (int newUser : request.getNewUsers()) {
- final boolean isInstantApp = pkgSetting.getUserStateOrDefault(newUser)
- .isInstantApp();
- if (allNewUsers) {
- if (isInstantApp) {
- firstInstantUserIds = ArrayUtils.appendInt(firstInstantUserIds, newUser);
- } else {
- firstUserIds = ArrayUtils.appendInt(firstUserIds, newUser);
- }
- continue;
- }
- boolean isNew = true;
- for (int origUser : request.getOriginUsers()) {
- 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);
- }
- }
- }
+ request.populateBroadcastUsers();
+ final int[] firstUserIds = request.getFirstTimeBroadcastUserIds();
+ final int[] firstInstantUserIds = request.getFirstTimeBroadcastInstantUserIds();
+ final int[] updateUserIds = request.getUpdateBroadcastUserIds();
+ final int[] instantUserIds = request.getUpdateBroadcastInstantUserIds();
Bundle extras = new Bundle();
extras.putInt(Intent.EXTRA_UID, request.getAppId());
@@ -2969,12 +2937,10 @@ final class InstallPackageHelper {
}
// 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);
- }
+ 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) {
@@ -3070,7 +3036,7 @@ final class InstallPackageHelper {
}
}
- if (allNewUsers && !update) {
+ if (request.isAllNewUsers() && !update) {
mPm.notifyPackageAdded(packageName, request.getAppId());
} else {
mPm.notifyPackageChanged(packageName, request.getAppId());
diff --git a/services/core/java/com/android/server/pm/InstallRequest.java b/services/core/java/com/android/server/pm/InstallRequest.java
index e1cfc418bfe5..3a6d423a574b 100644
--- a/services/core/java/com/android/server/pm/InstallRequest.java
+++ b/services/core/java/com/android/server/pm/InstallRequest.java
@@ -21,6 +21,7 @@ import static android.content.pm.PackageManager.INSTALL_REASON_UNKNOWN;
import static android.content.pm.PackageManager.INSTALL_SCENARIO_DEFAULT;
import static android.content.pm.PackageManager.INSTALL_SUCCEEDED;
import static android.os.Process.INVALID_UID;
+import static com.android.server.pm.PackageManagerService.EMPTY_INT_ARRAY;
import static com.android.server.pm.PackageManagerService.SCAN_AS_INSTANT_APP;
import static com.android.server.pm.PackageManagerService.TAG;
@@ -43,6 +44,7 @@ import android.util.ArrayMap;
import android.util.ExceptionUtils;
import android.util.Slog;
+import com.android.internal.util.ArrayUtils;
import com.android.server.art.model.DexoptResult;
import com.android.server.pm.parsing.pkg.ParsedPackage;
import com.android.server.pm.pkg.AndroidPackage;
@@ -52,6 +54,7 @@ import com.android.server.pm.pkg.parsing.ParsingPackageUtils;
import java.io.File;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.List;
final class InstallRequest {
@@ -69,8 +72,8 @@ final class InstallRequest {
private int mParseFlags;
private boolean mReplace;
- @Nullable /* The original Package if it is being replaced, otherwise {@code null} */
- private AndroidPackage mExistingPackage;
+ @Nullable /* The original package's name if it is being replaced, otherwise {@code null} */
+ private String mExistingPackageName;
/** parsed package to be scanned */
@Nullable
private ParsedPackage mParsedPackage;
@@ -132,6 +135,15 @@ final class InstallRequest {
private int mDexoptStatus;
+ @NonNull
+ private int[] mFirstTimeBroadcastUserIds = EMPTY_INT_ARRAY;
+ @NonNull
+ private int[] mFirstTimeBroadcastInstantUserIds = EMPTY_INT_ARRAY;
+ @NonNull
+ private int[] mUpdateBroadcastUserIds = EMPTY_INT_ARRAY;
+ @NonNull
+ private int[] mUpdateBroadcastInstantUserIds = EMPTY_INT_ARRAY;
+
// New install
InstallRequest(InstallingSession params) {
mUserId = params.getUser().getIdentifier();
@@ -413,11 +425,6 @@ final class InstallRequest {
}
@Nullable
- public AndroidPackage getExistingPackage() {
- return mExistingPackage;
- }
-
- @Nullable
public List<String> getAllowlistedRestrictedPermissions() {
return mInstallArgs == null ? null : mInstallArgs.mAllowlistedRestrictedPermissions;
}
@@ -453,10 +460,7 @@ final class InstallRequest {
@Nullable
public String getExistingPackageName() {
- if (mExistingPackage != null) {
- return mExistingPackage.getPackageName();
- }
- return null;
+ return mExistingPackageName;
}
@Nullable
@@ -627,6 +631,25 @@ final class InstallRequest {
return mDexoptStatus;
}
+ public boolean isAllNewUsers() {
+ return mOrigUsers == null || mOrigUsers.length == 0;
+ }
+ public int[] getFirstTimeBroadcastUserIds() {
+ return mFirstTimeBroadcastUserIds;
+ }
+
+ public int[] getFirstTimeBroadcastInstantUserIds() {
+ return mFirstTimeBroadcastInstantUserIds;
+ }
+
+ public int[] getUpdateBroadcastUserIds() {
+ return mUpdateBroadcastUserIds;
+ }
+
+ public int[] getUpdateBroadcastInstantUserIds() {
+ return mUpdateBroadcastInstantUserIds;
+ }
+
public void setScanFlags(int scanFlags) {
mScanFlags = scanFlags;
}
@@ -729,13 +752,14 @@ final class InstallRequest {
}
public void setPrepareResult(boolean replace, int scanFlags,
- int parseFlags, AndroidPackage existingPackage,
+ int parseFlags, PackageState existingPackageState,
ParsedPackage packageToScan, boolean clearCodeCache, boolean system,
PackageSetting originalPs, PackageSetting disabledPs) {
mReplace = replace;
mScanFlags = scanFlags;
mParseFlags = parseFlags;
- mExistingPackage = existingPackage;
+ mExistingPackageName =
+ existingPackageState != null ? existingPackageState.getPackageName() : null;
mParsedPackage = packageToScan;
mClearCodeCache = clearCodeCache;
mSystem = system;
@@ -769,6 +793,58 @@ final class InstallRequest {
}
}
+ /**
+ * Determine the set of users who are adding this package for the first time vs. those who are
+ * seeing an update.
+ */
+ public void populateBroadcastUsers() {
+ assertScanResultExists();
+ mFirstTimeBroadcastUserIds = EMPTY_INT_ARRAY;
+ mFirstTimeBroadcastInstantUserIds = EMPTY_INT_ARRAY;
+ mUpdateBroadcastUserIds = EMPTY_INT_ARRAY;
+ mUpdateBroadcastInstantUserIds = EMPTY_INT_ARRAY;
+
+ final boolean allNewUsers = isAllNewUsers();
+ if (allNewUsers) {
+ // App was not currently installed on any user
+ for (int newUser : mNewUsers) {
+ final boolean isInstantApp =
+ mScanResult.mPkgSetting.getUserStateOrDefault(newUser).isInstantApp();
+ if (isInstantApp) {
+ mFirstTimeBroadcastInstantUserIds =
+ ArrayUtils.appendInt(mFirstTimeBroadcastInstantUserIds, newUser);
+ } else {
+ mFirstTimeBroadcastUserIds =
+ ArrayUtils.appendInt(mFirstTimeBroadcastUserIds, newUser);
+ }
+ }
+ return;
+ }
+ // App was already installed on some users, but is new to some other users
+ for (int newUser : mNewUsers) {
+ boolean isFirstTimeUser = !ArrayUtils.contains(mOrigUsers, newUser);
+ final boolean isInstantApp =
+ mScanResult.mPkgSetting.getUserStateOrDefault(newUser).isInstantApp();
+ if (isFirstTimeUser) {
+ if (isInstantApp) {
+ mFirstTimeBroadcastInstantUserIds =
+ ArrayUtils.appendInt(mFirstTimeBroadcastInstantUserIds, newUser);
+ } else {
+ mFirstTimeBroadcastUserIds =
+ ArrayUtils.appendInt(mFirstTimeBroadcastUserIds, newUser);
+ }
+ } else {
+ if (isInstantApp) {
+ mUpdateBroadcastInstantUserIds =
+ ArrayUtils.appendInt(mUpdateBroadcastInstantUserIds, newUser);
+ } else {
+ mUpdateBroadcastUserIds =
+ ArrayUtils.appendInt(mUpdateBroadcastUserIds, newUser);
+ }
+ }
+ }
+ }
+
public void onPrepareStarted() {
if (mPackageMetrics != null) {
mPackageMetrics.onStepStarted(PackageMetrics.STEP_PREPARE);
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index 924021b76af7..1884caf6da8b 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -844,6 +844,24 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
return res;
}
+ int[] queryUsersInstalledOrHasData(int[] users) {
+ int num = 0;
+ for (int user : users) {
+ if (getInstalled(user) || readUserState(user).dataExists()) {
+ num++;
+ }
+ }
+ int[] res = new int[num];
+ num = 0;
+ for (int user : users) {
+ if (getInstalled(user) || readUserState(user).dataExists()) {
+ res[num] = user;
+ num++;
+ }
+ }
+ return res;
+ }
+
long getCeDataInode(int userId) {
return readUserState(userId).getCeDataInode();
}