summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Nikita Ioffe <ioffe@google.com> 2022-01-06 16:36:01 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2022-01-06 16:36:01 +0000
commit1b2bd1e83a0c51f095dc4fff1a6f523c9150c75a (patch)
tree1bbd13c34cc546be7466fdf1bd6403ef85d3bed7
parente460207ece04c699574fc9b74d087c594770ed23 (diff)
parent72f47a3f9a558e18e62147931be3b205cd2f9edf (diff)
Merge changes from topic "no_app_data_storage"
* changes: Don't bind mount app storage for app with NO_APP_DATA_STORAGE Don't create app data dirs if app requests not to
-rw-r--r--core/java/android/content/pm/PackageManager.java14
-rw-r--r--services/core/java/com/android/server/am/ProcessList.java20
-rw-r--r--services/core/java/com/android/server/pm/AppDataHelper.java36
-rw-r--r--services/core/java/com/android/server/pm/InstallPackageHelper.java26
4 files changed, 93 insertions, 3 deletions
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 9a7aeef69ed3..338dfd62f316 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -145,6 +145,20 @@ public abstract class PackageManager {
"android.media.PROPERTY_MEDIA_CAPABILITIES";
/**
+ * Application level property that an app can specify to opt-out from having private data
+ * directories both on the internal and external storages.
+ *
+ * <p>Changing the value of this property during app update is not supported, and such updates
+ * will be rejected.
+ *
+ * <p>This should only be set by platform apps that know what they are doing.
+ *
+ * @hide
+ */
+ public static final String PROPERTY_NO_APP_DATA_STORAGE =
+ "android.internal.PROPERTY_NO_APP_DATA_STORAGE";
+
+ /**
* A property value set within the manifest.
* <p>
* The value of a property will only have a single type, as defined by
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index 2def50efee60..1ad0bcea711c 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -135,6 +135,7 @@ import com.android.server.Watchdog;
import com.android.server.am.ActivityManagerService.ProcessChangeItem;
import com.android.server.compat.PlatformCompat;
import com.android.server.pm.dex.DexManager;
+import com.android.server.pm.parsing.pkg.AndroidPackage;
import com.android.server.pm.pkg.PackageStateInternal;
import com.android.server.wm.ActivityServiceConnectionsHolder;
import com.android.server.wm.WindowManagerService;
@@ -2379,6 +2380,8 @@ public final class ProcessList {
final String[] targetPackagesList = sharedPackages.length == 0
? new String[]{app.info.packageName} : sharedPackages;
+ final boolean hasAppStorage = hasAppStorage(pmInt, app.info.packageName);
+
pkgDataInfoMap = getPackageAppDataInfoMap(pmInt, targetPackagesList, uid);
if (pkgDataInfoMap == null) {
// TODO(b/152760674): Handle inode == 0 case properly, now we just give it a
@@ -2401,6 +2404,12 @@ public final class ProcessList {
bindMountAppsData = false;
}
+ if (!hasAppStorage) {
+ bindMountAppsData = false;
+ pkgDataInfoMap = null;
+ allowlistedAppDataInfoMap = null;
+ }
+
int userId = UserHandle.getUserId(uid);
StorageManagerInternal storageManagerInternal = LocalServices.getService(
StorageManagerInternal.class);
@@ -2488,6 +2497,17 @@ public final class ProcessList {
}
}
+ private boolean hasAppStorage(PackageManagerInternal pmInt, String packageName) {
+ final AndroidPackage pkg = pmInt.getPackage(packageName);
+ if (pkg == null) {
+ Slog.w(TAG, "Unknown package " + packageName);
+ return false;
+ }
+ final PackageManager.Property noAppStorageProp =
+ pkg.getProperties().get(PackageManager.PROPERTY_NO_APP_DATA_STORAGE);
+ return noAppStorageProp == null || !noAppStorageProp.getBoolean();
+ }
+
@GuardedBy("mService")
void startProcessLocked(ProcessRecord app, HostingRecord hostingRecord, int zygotePolicyFlags) {
startProcessLocked(app, hostingRecord, zygotePolicyFlags, null /* abiOverride */);
diff --git a/services/core/java/com/android/server/pm/AppDataHelper.java b/services/core/java/com/android/server/pm/AppDataHelper.java
index bedb8b9f7a18..22cd06dfd16b 100644
--- a/services/core/java/com/android/server/pm/AppDataHelper.java
+++ b/services/core/java/com/android/server/pm/AppDataHelper.java
@@ -101,6 +101,12 @@ final class AppDataHelper {
mPm.mSettings.writeKernelMappingLPr(ps);
}
+ // TODO(b/211761016): should we still create the profile dirs?
+ if (!shouldHaveAppStorage(pkg)) {
+ Slog.w(TAG, "Skipping preparing app data for " + pkg.getPackageName());
+ return;
+ }
+
Installer.Batch batch = new Installer.Batch();
UserManagerInternal umInternal = mInjector.getUserManagerInternal();
StorageManagerInternal smInternal = mInjector.getLocalService(
@@ -161,6 +167,10 @@ final class AppDataHelper {
Slog.wtf(TAG, "Package was null!", new Throwable());
return CompletableFuture.completedFuture(null);
}
+ if (!shouldHaveAppStorage(pkg)) {
+ Slog.w(TAG, "Skipping preparing app data for " + pkg.getPackageName());
+ return CompletableFuture.completedFuture(null);
+ }
return prepareAppDataLeaf(batch, pkg, previousAppId, userId, flags);
}
@@ -381,7 +391,7 @@ final class AppDataHelper {
for (File file : files) {
final String packageName = file.getName();
try {
- assertPackageKnownAndInstalled(volumeUuid, packageName, userId);
+ assertPackageStorageValid(volumeUuid, packageName, userId);
} catch (PackageManagerException e) {
logCriticalInfo(Log.WARN, "Destroying " + file + " due to: " + e);
try {
@@ -398,7 +408,7 @@ final class AppDataHelper {
for (File file : files) {
final String packageName = file.getName();
try {
- assertPackageKnownAndInstalled(volumeUuid, packageName, userId);
+ assertPackageStorageValid(volumeUuid, packageName, userId);
} catch (PackageManagerException e) {
logCriticalInfo(Log.WARN, "Destroying " + file + " due to: " + e);
try {
@@ -446,7 +456,11 @@ final class AppDataHelper {
return result;
}
- private void assertPackageKnownAndInstalled(String volumeUuid, String packageName, int userId)
+ /**
+ * Asserts that storage path is valid by checking that {@code packageName} is present,
+ * installed for the given {@code userId} and can have app data.
+ */
+ private void assertPackageStorageValid(String volumeUuid, String packageName, int userId)
throws PackageManagerException {
synchronized (mPm.mLock) {
// Normalize package name to handle renamed packages
@@ -462,6 +476,13 @@ final class AppDataHelper {
} else if (!ps.getInstalled(userId)) {
throw new PackageManagerException(
"Package " + packageName + " not installed for user " + userId);
+ } else if (ps.getPkg() == null) {
+ throw new PackageManagerException("Package " + packageName + " is not parsed yet");
+ } else {
+ if (!shouldHaveAppStorage(ps.getPkg())) {
+ throw new PackageManagerException(
+ "Package " + packageName + " shouldn't have storage");
+ }
}
}
}
@@ -603,4 +624,13 @@ final class AppDataHelper {
Slog.w(TAG, String.valueOf(e));
}
}
+
+ /**
+ * Returns {@code true} if app's internal storage should be created for this {@code pkg}.
+ */
+ private boolean shouldHaveAppStorage(AndroidPackage pkg) {
+ PackageManager.Property noAppDataProp =
+ pkg.getProperties().get(PackageManager.PROPERTY_NO_APP_DATA_STORAGE);
+ return noAppDataProp == null || !noAppDataProp.getBoolean();
+ }
}
diff --git a/services/core/java/com/android/server/pm/InstallPackageHelper.java b/services/core/java/com/android/server/pm/InstallPackageHelper.java
index 0f96e8385e8f..805411c6af0e 100644
--- a/services/core/java/com/android/server/pm/InstallPackageHelper.java
+++ b/services/core/java/com/android/server/pm/InstallPackageHelper.java
@@ -942,6 +942,16 @@ final class InstallPackageHelper {
if (result.needsNewAppId()) {
request.mInstallResult.mRemovedInfo.mAppIdChanging = true;
}
+ if (!checkNoAppStorageIsConsistent(
+ result.mRequest.mOldPkg, result.mPkgSetting.getPkg())) {
+ // TODO: INSTALL_FAILED_UPDATE_INCOMPATIBLE is about incomptabible
+ // signatures. Is there a better error code?
+ request.mInstallResult.setError(
+ INSTALL_FAILED_UPDATE_INCOMPATIBLE,
+ "Update attempted to change value of "
+ + PackageManager.PROPERTY_NO_APP_DATA_STORAGE);
+ return;
+ }
createdAppId.put(packageName, optimisticallyRegisterAppId(result));
versionInfos.put(result.mPkgSetting.getPkg().getPackageName(),
mPm.getSettingsVersionForPackage(result.mPkgSetting.getPkg()));
@@ -1040,6 +1050,22 @@ final class InstallPackageHelper {
}
@GuardedBy("mPm.mInstallLock")
+ private boolean checkNoAppStorageIsConsistent(AndroidPackage oldPkg, AndroidPackage newPkg) {
+ if (oldPkg == null) {
+ // New install, nothing to check against.
+ return true;
+ }
+ final PackageManager.Property curProp =
+ oldPkg.getProperties().get(PackageManager.PROPERTY_NO_APP_DATA_STORAGE);
+ final PackageManager.Property newProp =
+ newPkg.getProperties().get(PackageManager.PROPERTY_NO_APP_DATA_STORAGE);
+ if (curProp == null || !curProp.getBoolean()) {
+ return newProp == null || !newProp.getBoolean();
+ }
+ return newProp != null && newProp.getBoolean();
+ }
+
+ @GuardedBy("mPm.mInstallLock")
private PrepareResult preparePackageLI(InstallArgs args, PackageInstalledInfo res)
throws PrepareFailure {
final int installFlags = args.mInstallFlags;