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

Commit b2550115 authored by Abhijeet Kaur's avatar Abhijeet Kaur Committed by Android (Google) Code Review
Browse files

Merge "Use compat flags to reflect the current status of legacy storage."

parents 906d0719 f8af8204
Loading
Loading
Loading
Loading
+43 −21
Original line number Diff line number Diff line
@@ -16,13 +16,13 @@

package android.os;

import android.Manifest;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.annotation.TestApi;
import android.app.AppGlobals;
import android.app.AppOpsManager;
import android.app.admin.DevicePolicyManager;
import android.compat.Compatibility;
import android.compat.annotation.UnsupportedAppUsage;
import android.content.Context;
import android.content.Intent;
@@ -87,6 +87,16 @@ public class Environment {
    private static final File DIR_APEX_ROOT = getDirectory(ENV_APEX_ROOT,
            "/apex");

    /**
     * See definition in com.android.providers.media.LocalCallingIdentity
     */
    private static final long DEFAULT_SCOPED_STORAGE = 149924527L;

    /**
     * See definition in com.android.providers.media.LocalCallingIdentity
     */
    private static final long FORCE_ENABLE_SCOPED_STORAGE = 132649864L;

    @UnsupportedAppUsage
    private static UserEnvironment sCurrentUser;
    private static boolean sUserRequired;
@@ -1190,12 +1200,13 @@ public class Environment {
    }

    /**
     * Returns whether the primary shared/external storage media is a legacy
     * view that includes files not owned by the app.
     * Returns whether the shared/external storage media is a
     * legacy view that includes files not owned by the app.
     * <p>
     * This value may be different from the value requested by
     * {@code requestLegacyExternalStorage} in the app's manifest, since an app
     * may inherit its legacy state based on when it was first installed.
     * may inherit its legacy state based on when it was first installed, target sdk and other
     * factors.
     * <p>
     * Non-legacy apps can continue to discover and read media belonging to
     * other apps via {@link android.provider.MediaStore}.
@@ -1206,12 +1217,13 @@ public class Environment {
    }

    /**
     * Returns whether the shared/external storage media at the given path is a
     * Returns whether the shared/external storage media is a
     * legacy view that includes files not owned by the app.
     * <p>
     * This value may be different from the value requested by
     * {@code requestLegacyExternalStorage} in the app's manifest, since an app
     * may inherit its legacy state based on when it was first installed.
     * may inherit its legacy state based on when it was first installed, target sdk and other
     * factors.
     * <p>
     * Non-legacy apps can continue to discover and read media belonging to
     * other apps via {@link android.provider.MediaStore}.
@@ -1231,28 +1243,38 @@ public class Environment {
            return false;
        }

        if (packageManager.checkPermission(Manifest.permission.WRITE_MEDIA_STORAGE,
                context.getPackageName()) == PackageManager.PERMISSION_GRANTED) {
            return true;
        // TODO(b/150672994): Compat flags do not override instant app and isolated process's
        //  behavior.
        boolean defaultScopedStorage = Compatibility.isChangeEnabled(DEFAULT_SCOPED_STORAGE);
        boolean forceEnableScopedStorage = Compatibility.isChangeEnabled(
                FORCE_ENABLE_SCOPED_STORAGE);
        // if Scoped Storage is strictly enforced, the app does *not* have legacy storage access
        // Note: does not require packagename/uid as this is directly called from an app process
        if (isScopedStorageEnforced(defaultScopedStorage, forceEnableScopedStorage)) {
            return false;
        }

        if (packageManager.checkPermission(Manifest.permission.INSTALL_PACKAGES,
                context.getPackageName()) == PackageManager.PERMISSION_GRANTED) {
        // if Scoped Storage is strictly disabled, the app has legacy storage access
        // Note: does not require packagename/uid as this is directly called from an app process
        if (isScopedStorageDisabled(defaultScopedStorage, forceEnableScopedStorage)) {
            return true;
        }

        final AppOpsManager appOps = context.getSystemService(AppOpsManager.class);
        final String[] packagesForUid = packageManager.getPackagesForUid(uid);
        for (String packageName : packagesForUid) {
            if (appOps.checkOpNoThrow(AppOpsManager.OP_REQUEST_INSTALL_PACKAGES,
                    uid, packageName) == AppOpsManager.MODE_ALLOWED) {
                return true;
        return appOps.checkOpNoThrow(AppOpsManager.OP_LEGACY_STORAGE,
                uid, context.getOpPackageName()) == AppOpsManager.MODE_ALLOWED;
    }

    private static boolean isScopedStorageEnforced(boolean defaultScopedStorage,
            boolean forceEnableScopedStorage) {
        return defaultScopedStorage && forceEnableScopedStorage;
    }

        return appOps.checkOpNoThrow(AppOpsManager.OP_LEGACY_STORAGE,
                uid, context.getOpPackageName()) == AppOpsManager.MODE_ALLOWED;
    private static boolean isScopedStorageDisabled(boolean defaultScopedStorage,
            boolean forceEnableScopedStorage) {
        return !defaultScopedStorage && !forceEnableScopedStorage;
    }


    static File getDirectory(String variableName, String defaultPath) {
        String path = System.getenv(variableName);
        return path == null ? new File(defaultPath) : new File(path);