Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1b2bd1e8 authored by Nikita Ioffe's avatar Nikita Ioffe Committed by Android (Google) Code Review
Browse files

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
parents e460207e 72f47a3f
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -144,6 +144,20 @@ public abstract class PackageManager {
    public static final String PROPERTY_MEDIA_CAPABILITIES =
            "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>
+20 −0
Original line number Diff line number Diff line
@@ -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 */);
+33 −3
Original line number Diff line number Diff line
@@ -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();
    }
}
+26 −0
Original line number Diff line number Diff line
@@ -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()));
@@ -1039,6 +1049,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 {