diff options
| author | 2022-01-06 16:36:01 +0000 | |
|---|---|---|
| committer | 2022-01-06 16:36:01 +0000 | |
| commit | 1b2bd1e83a0c51f095dc4fff1a6f523c9150c75a (patch) | |
| tree | 1bbd13c34cc546be7466fdf1bd6403ef85d3bed7 | |
| parent | e460207ece04c699574fc9b74d087c594770ed23 (diff) | |
| parent | 72f47a3f9a558e18e62147931be3b205cd2f9edf (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
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; |