summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/pm/InstallPackageHelper.java51
-rw-r--r--services/core/java/com/android/server/pm/Installer.java6
-rw-r--r--services/core/java/com/android/server/pm/PackageSetting.java1
-rw-r--r--services/core/java/com/android/server/pm/RemovePackageHelper.java6
-rw-r--r--services/core/java/com/android/server/pm/ScanPackageUtils.java30
-rw-r--r--services/core/java/com/android/server/pm/ScanResult.java4
-rw-r--r--services/core/java/com/android/server/pm/Settings.java30
-rw-r--r--services/core/java/com/android/server/pm/SharedUidMigration.java105
-rw-r--r--services/core/java/com/android/server/pm/SharedUserSetting.java19
-rw-r--r--services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java8
10 files changed, 208 insertions, 52 deletions
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index c5c39f82a1fd..6e4d19f8d277 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -86,6 +86,7 @@ import static com.android.server.pm.PackageManagerServiceUtils.compareSignatures
import static com.android.server.pm.PackageManagerServiceUtils.compressedFileExists;
import static com.android.server.pm.PackageManagerServiceUtils.deriveAbiOverride;
import static com.android.server.pm.PackageManagerServiceUtils.logCriticalInfo;
+import static com.android.server.pm.SharedUidMigration.BEST_EFFORT;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -287,6 +288,12 @@ final class InstallPackageHelper {
SharedUserSetting sharedUserSetting = mPm.mSettings.getSharedUserSettingLPr(pkgSetting);
if (sharedUserSetting != null) {
sharedUserSetting.addPackage(pkgSetting);
+ if (parsedPackage.isLeavingSharedUid()
+ && SharedUidMigration.applyStrategy(BEST_EFFORT)
+ && sharedUserSetting.isSingleUser()) {
+ // Attempt the transparent shared UID migration
+ mPm.mSettings.convertSharedUserSettingsLPw(sharedUserSetting);
+ }
}
if (reconciledPkg.mInstallArgs != null
&& reconciledPkg.mInstallArgs.mForceQueryableOverride) {
@@ -2216,23 +2223,8 @@ final class InstallPackageHelper {
}
incrementalStorages.add(storage);
}
- int previousAppId = 0;
- if (reconciledPkg.mScanResult.needsNewAppId()) {
- // Only set previousAppId if the app is migrating out of shared UID
- previousAppId = reconciledPkg.mScanResult.mPreviousAppId;
-
- if (pkg.shouldInheritKeyStoreKeys()) {
- // Migrate keystore data
- mAppDataHelper.migrateKeyStoreData(
- previousAppId, reconciledPkg.mPkgSetting.getAppId());
- }
-
- if (reconciledPkg.mInstallResult.mRemovedInfo.mRemovedAppId == previousAppId) {
- // If the previous app ID is removed, clear the keys
- mAppDataHelper.clearKeystoreData(UserHandle.USER_ALL, previousAppId);
- }
- }
- mAppDataHelper.prepareAppDataPostCommitLIF(pkg, previousAppId);
+ // Hardcode previousAppId to 0 to disable any data migration (http://b/221088088)
+ mAppDataHelper.prepareAppDataPostCommitLIF(pkg, 0);
if (reconciledPkg.mPrepareResult.mClearCodeCache) {
mAppDataHelper.clearAppDataLIF(pkg, UserHandle.USER_ALL,
FLAG_STORAGE_DE | FLAG_STORAGE_CE | FLAG_STORAGE_EXTERNAL
@@ -3026,8 +3018,7 @@ final class InstallPackageHelper {
installPackageFromSystemLIF(stubPkg.getPath(),
mPm.mUserManager.getUserIds() /*allUserHandles*/,
null /*origUserHandles*/,
- true /*writeSettings*/,
- Process.INVALID_UID /*previousAppId*/);
+ 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(),
@@ -3154,10 +3145,8 @@ final class InstallPackageHelper {
try {
synchronized (mPm.mInstallLock) {
final int[] origUsers = outInfo == null ? null : outInfo.mOrigUsers;
- final int previousAppId = disabledPs.getAppId() != deletedPs.getAppId()
- ? deletedPs.getAppId() : Process.INVALID_UID;
installPackageFromSystemLIF(disabledPs.getPathString(), allUserHandles,
- origUsers, writeSettings, previousAppId);
+ origUsers, writeSettings);
}
} catch (PackageManagerException e) {
Slog.w(TAG, "Failed to restore system package:" + deletedPs.getPackageName() + ": "
@@ -3200,7 +3189,7 @@ final class InstallPackageHelper {
@GuardedBy("mPm.mInstallLock")
private void installPackageFromSystemLIF(@NonNull String codePathString,
@NonNull int[] allUserHandles, @Nullable int[] origUserHandles,
- boolean writeSettings, int previousAppId)
+ boolean writeSettings)
throws PackageManagerException {
final File codePath = new File(codePathString);
@ParsingPackageUtils.ParseFlags int parseFlags =
@@ -3223,13 +3212,12 @@ final class InstallPackageHelper {
mAppDataHelper.prepareAppDataAfterInstallLIF(pkg);
- setPackageInstalledForSystemPackage(pkg, allUserHandles,
- origUserHandles, writeSettings, previousAppId);
+ setPackageInstalledForSystemPackage(pkg, allUserHandles, origUserHandles, writeSettings);
}
private void setPackageInstalledForSystemPackage(@NonNull AndroidPackage pkg,
@NonNull int[] allUserHandles, @Nullable int[] origUserHandles,
- boolean writeSettings, int previousAppId) {
+ boolean writeSettings) {
// writer
synchronized (mPm.mLock) {
PackageSetting ps = mPm.mSettings.getPackageLPr(pkg.getPackageName());
@@ -3263,7 +3251,7 @@ final class InstallPackageHelper {
// The method below will take care of removing obsolete permissions and granting
// install permissions.
- mPm.mPermissionManager.onPackageInstalled(pkg, previousAppId,
+ mPm.mPermissionManager.onPackageInstalled(pkg, Process.INVALID_UID,
PermissionManagerServiceInternal.PackageInstalledParams.DEFAULT,
UserHandle.USER_ALL);
for (final int userId : allUserHandles) {
@@ -3701,7 +3689,14 @@ final class InstallPackageHelper {
}
disabledPkgSetting = mPm.mSettings.getDisabledSystemPkgLPr(
parsedPackage.getPackageName());
- if (parsedPackage.getSharedUserId() != null && !parsedPackage.isLeavingSharedUid()) {
+
+ boolean ignoreSharedUserId = false;
+ if (installedPkgSetting == null) {
+ // We can directly ignore sharedUserSetting for new installs
+ ignoreSharedUserId = parsedPackage.isLeavingSharedUid();
+ }
+
+ if (!ignoreSharedUserId && parsedPackage.getSharedUserId() != null) {
sharedUserSetting = mPm.mSettings.getSharedUserLPw(
parsedPackage.getSharedUserId(),
0 /*pkgFlags*/, 0 /*pkgPrivateFlags*/, true /*create*/);
diff --git a/services/core/java/com/android/server/pm/Installer.java b/services/core/java/com/android/server/pm/Installer.java
index 742cc0237cec..6a80852f1bf5 100644
--- a/services/core/java/com/android/server/pm/Installer.java
+++ b/services/core/java/com/android/server/pm/Installer.java
@@ -215,6 +215,8 @@ public class Installer extends SystemService {
if (!checkBeforeRemote()) {
return buildPlaceholderCreateAppDataResult();
}
+ // Hardcode previousAppId to 0 to disable any data migration (http://b/221088088)
+ args.previousAppId = 0;
try {
return mInstalld.createAppData(args);
} catch (Exception e) {
@@ -229,6 +231,10 @@ public class Installer extends SystemService {
Arrays.fill(results, buildPlaceholderCreateAppDataResult());
return results;
}
+ // Hardcode previousAppId to 0 to disable any data migration (http://b/221088088)
+ for (final CreateAppDataArgs arg : args) {
+ arg.previousAppId = 0;
+ }
try {
return mInstalld.createAppDataBatched(args);
} catch (Exception e) {
diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java
index f06ae1e06187..2bae00f91b82 100644
--- a/services/core/java/com/android/server/pm/PackageSetting.java
+++ b/services/core/java/com/android/server/pm/PackageSetting.java
@@ -477,6 +477,7 @@ public class PackageSetting extends SettingBase implements PackageStateInternal
public void setSharedUserAppId(int sharedUserAppId) {
mSharedUserAppId = sharedUserAppId;
+ onChanged();
}
@Override
diff --git a/services/core/java/com/android/server/pm/RemovePackageHelper.java b/services/core/java/com/android/server/pm/RemovePackageHelper.java
index 4d1519c361c9..88df843ec8c5 100644
--- a/services/core/java/com/android/server/pm/RemovePackageHelper.java
+++ b/services/core/java/com/android/server/pm/RemovePackageHelper.java
@@ -284,7 +284,11 @@ final class RemovePackageHelper {
List<AndroidPackage> sharedUserPkgs =
sus != null ? sus.getPackages() : Collections.emptyList();
mPermissionManager.onPackageUninstalled(packageName, deletedPs.getAppId(),
- deletedPs.getPkg(), sharedUserPkgs, UserHandle.USER_ALL);
+ deletedPkg, sharedUserPkgs, UserHandle.USER_ALL);
+ // After permissions are handled, check if the shared user can be migrated
+ if (sus != null) {
+ mPm.mSettings.checkAndConvertSharedUserSettingsLPw(sus);
+ }
}
mPm.clearPackagePreferredActivitiesLPw(
deletedPs.getPackageName(), changedUsers, UserHandle.USER_ALL);
diff --git a/services/core/java/com/android/server/pm/ScanPackageUtils.java b/services/core/java/com/android/server/pm/ScanPackageUtils.java
index 33f0b54fb2de..4e8313bf1891 100644
--- a/services/core/java/com/android/server/pm/ScanPackageUtils.java
+++ b/services/core/java/com/android/server/pm/ScanPackageUtils.java
@@ -165,25 +165,15 @@ final class ScanPackageUtils {
}
}
- int previousAppId = Process.INVALID_UID;
-
if (pkgSetting != null && oldSharedUserSetting != sharedUserSetting) {
- if (oldSharedUserSetting != null && sharedUserSetting == null) {
- previousAppId = pkgSetting.getAppId();
- // Log that something is leaving shareduid and keep going
- Slog.i(TAG,
- "Package " + parsedPackage.getPackageName() + " shared user changed from "
- + oldSharedUserSetting.name + " to " + "<nothing>.");
- } else {
- PackageManagerService.reportSettingsProblem(Log.WARN,
- "Package " + parsedPackage.getPackageName() + " shared user changed from "
- + (oldSharedUserSetting != null
- ? oldSharedUserSetting.name : "<nothing>")
- + " to "
- + (sharedUserSetting != null ? sharedUserSetting.name : "<nothing>")
- + "; replacing with new");
- pkgSetting = null;
- }
+ PackageManagerService.reportSettingsProblem(Log.WARN,
+ "Package " + parsedPackage.getPackageName() + " shared user changed from "
+ + (oldSharedUserSetting != null
+ ? oldSharedUserSetting.name : "<nothing>")
+ + " to "
+ + (sharedUserSetting != null ? sharedUserSetting.name : "<nothing>")
+ + "; replacing with new");
+ pkgSetting = null;
}
String[] usesSdkLibraries = null;
@@ -474,8 +464,8 @@ final class ScanPackageUtils {
return new ScanResult(request, true, pkgSetting, changedAbiCodePath,
!createNewPackage /* existingSettingCopied */,
- previousAppId, sdkLibraryInfo, staticSharedLibraryInfo,
- dynamicSharedLibraryInfos);
+ Process.INVALID_UID /* previousAppId */ , sdkLibraryInfo,
+ staticSharedLibraryInfo, dynamicSharedLibraryInfos);
}
/**
diff --git a/services/core/java/com/android/server/pm/ScanResult.java b/services/core/java/com/android/server/pm/ScanResult.java
index f77be1f9b2d3..e2860ca327e7 100644
--- a/services/core/java/com/android/server/pm/ScanResult.java
+++ b/services/core/java/com/android/server/pm/ScanResult.java
@@ -70,7 +70,9 @@ final class ScanResult {
mPkgSetting = pkgSetting;
mChangedAbiCodePath = changedAbiCodePath;
mExistingSettingCopied = existingSettingCopied;
- mPreviousAppId = previousAppId;
+ // Hardcode mPreviousAppId to INVALID_UID (http://b/221088088)
+ // This will disable all migration code paths in PMS and PermMS
+ mPreviousAppId = Process.INVALID_UID;
mSdkSharedLibraryInfo = sdkSharedLibraryInfo;
mStaticSharedLibraryInfo = staticSharedLibraryInfo;
mDynamicSharedLibraryInfos = dynamicSharedLibraryInfos;
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index d3665749a7f8..e6f23775f615 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -29,6 +29,7 @@ import static android.os.Process.PACKAGE_INFO_GID;
import static android.os.Process.SYSTEM_UID;
import static com.android.server.pm.PackageManagerService.PLATFORM_PACKAGE_NAME;
+import static com.android.server.pm.SharedUidMigration.BEST_EFFORT;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -1424,6 +1425,35 @@ public final class Settings implements Watchable, Snappable {
}
}
+ /**
+ * Transparently convert a SharedUserSetting into PackageSettings without changing appId.
+ * The sharedUser passed to this method has to be {@link SharedUserSetting#isSingleUser()}.
+ */
+ void convertSharedUserSettingsLPw(SharedUserSetting sharedUser) {
+ final PackageSetting ps = sharedUser.getPackageSettings().valueAt(0);
+ replaceAppIdLPw(sharedUser.getAppId(), ps);
+
+ // Unlink the SharedUserSetting
+ ps.setSharedUserAppId(INVALID_UID);
+ if (!sharedUser.getDisabledPackageSettings().isEmpty()) {
+ final PackageSetting disabledPs = sharedUser.getDisabledPackageSettings().valueAt(0);
+ disabledPs.setSharedUserAppId(INVALID_UID);
+ }
+ mSharedUsers.remove(sharedUser.getName());
+ }
+
+ /**
+ * Check and convert eligible SharedUserSettings to PackageSettings.
+ */
+ void checkAndConvertSharedUserSettingsLPw(SharedUserSetting sharedUser) {
+ if (!sharedUser.isSingleUser()) return;
+ final AndroidPackage pkg = sharedUser.getPackageSettings().valueAt(0).getPkg();
+ if (pkg != null && pkg.isLeavingSharedUid()
+ && SharedUidMigration.applyStrategy(BEST_EFFORT)) {
+ convertSharedUserSettingsLPw(sharedUser);
+ }
+ }
+
PreferredIntentResolver editPreferredActivitiesLPw(int userId) {
PreferredIntentResolver pir = mPreferredActivities.get(userId);
if (pir == null) {
diff --git a/services/core/java/com/android/server/pm/SharedUidMigration.java b/services/core/java/com/android/server/pm/SharedUidMigration.java
new file mode 100644
index 000000000000..a7d5e9550149
--- /dev/null
+++ b/services/core/java/com/android/server/pm/SharedUidMigration.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import android.annotation.IntDef;
+import android.os.Build;
+import android.os.SystemProperties;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * A utility class hosting code configuring shared UID migration behavior.
+ */
+public final class SharedUidMigration {
+
+ /**
+ * The system property key used to configure the shared UID migration strategy.
+ */
+ public static final String PROPERTY_KEY = "persist.debug.pm.shared_uid_migration_strategy";
+
+ /**
+ * Only leave shared UID for newly installed packages.
+ */
+ public static final int NEW_INSTALL_ONLY = 1;
+ /**
+ * Opportunistically migrate any single-package shared UID group.
+ */
+ public static final int BEST_EFFORT = 2;
+ /**
+ * Run appId transitions when the device reboots.
+ */
+ public static final int TRANSITION_AT_BOOT = 3;
+ /**
+ * Run appId transitions as soon as the upgrade is installed.
+ */
+ public static final int LIVE_TRANSITION = 4;
+
+ @IntDef({
+ NEW_INSTALL_ONLY,
+ BEST_EFFORT,
+ TRANSITION_AT_BOOT,
+ LIVE_TRANSITION,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface Strategy {}
+
+ private static final int DEFAULT = BEST_EFFORT;
+
+ /**
+ * All shared UID migration is disabled.
+ * This is not a strategy that can be set with system properties.
+ * To disable shared UID migration, change {@link #DEFAULT} to this value.
+ */
+ private static final int DISABLED = 0;
+
+ /**
+ * Whether shared UID migration is fully disabled. Disabled means the sharedUserMaxSdkVersion
+ * attribute will be directly ignored in the parsing phase.
+ */
+ @SuppressWarnings("ConstantConditions")
+ public static boolean isDisabled() {
+ return DEFAULT == DISABLED;
+ }
+
+ /**
+ * If the system is userdebug, returns the strategy to use by getting the system property
+ * {@link #PROPERTY_KEY}, or else returns the default strategy enabled in the build.
+ */
+ public static int getCurrentStrategy() {
+ if (!Build.IS_USERDEBUG) {
+ return DEFAULT;
+ }
+
+ final int s = SystemProperties.getInt(PROPERTY_KEY, DEFAULT);
+ // No transition strategies can be used (http://b/221088088)
+ if (s > BEST_EFFORT || s <= DISABLED) {
+ return DEFAULT;
+ }
+ return s;
+ }
+
+ /**
+ * Should the strategy be used based on the current active strategy.
+ */
+ public static boolean applyStrategy(@Strategy int strategy) {
+ return !isDisabled() && getCurrentStrategy() >= strategy;
+ }
+
+ private SharedUidMigration() {}
+}
diff --git a/services/core/java/com/android/server/pm/SharedUserSetting.java b/services/core/java/com/android/server/pm/SharedUserSetting.java
index 4d0bbc6fe437..23f0de8a5f71 100644
--- a/services/core/java/com/android/server/pm/SharedUserSetting.java
+++ b/services/core/java/com/android/server/pm/SharedUserSetting.java
@@ -221,6 +221,25 @@ public final class SharedUserSetting extends SettingBase implements SharedUserAp
}
/**
+ * A shared user is considered "single user" if there is exactly one single package
+ * currently using it. In the case when that package is also a system app, the APK on
+ * the system partition has to also leave shared UID.
+ */
+ public boolean isSingleUser() {
+ if (mPackages.size() != 1) {
+ return false;
+ }
+ if (mDisabledPackages.size() > 1) {
+ return false;
+ }
+ if (mDisabledPackages.size() == 1) {
+ final AndroidPackage pkg = mDisabledPackages.valueAt(0).getPkg();
+ return pkg != null && pkg.isLeavingSharedUid();
+ }
+ return true;
+ }
+
+ /**
* Determine the targetSdkVersion for a sharedUser and update pkg.applicationInfo.seInfo
* to ensure that all apps within the sharedUser share an SELinux domain. Use the lowest
* targetSdkVersion of all apps within the shared user, which corresponds to the least
diff --git a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
index ed1ab01e1d12..3eaca9dddcc4 100644
--- a/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
+++ b/services/core/java/com/android/server/pm/pkg/parsing/ParsingPackageUtils.java
@@ -91,6 +91,7 @@ import com.android.internal.R;
import com.android.internal.os.ClassLoaderFactory;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.XmlUtils;
+import com.android.server.pm.SharedUidMigration;
import com.android.server.pm.permission.CompatibilityPermissionInfo;
import com.android.server.pm.pkg.component.ComponentMutateUtils;
import com.android.server.pm.pkg.component.ComponentParseUtils;
@@ -1047,8 +1048,11 @@ public class ParsingPackageUtils {
}
}
- int maxSdkVersion = anInteger(0, R.styleable.AndroidManifest_sharedUserMaxSdkVersion, sa);
- boolean leaving = (maxSdkVersion != 0) && (maxSdkVersion < Build.VERSION.RESOURCES_SDK_INT);
+ boolean leaving = false;
+ if (!SharedUidMigration.isDisabled()) {
+ int max = anInteger(0, R.styleable.AndroidManifest_sharedUserMaxSdkVersion, sa);
+ leaving = (max != 0) && (max < Build.VERSION.RESOURCES_SDK_INT);
+ }
return input.success(pkg
.setLeavingSharedUid(leaving)