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

Commit 163eaee6 authored by Felipe Leme's avatar Felipe Leme
Browse files

Fixed logic that parses URI to handle special case of Documents directory.

Also implemente delete() on provider.

Test: manual verification
Test: modified testResetGranted() to use Documents directory
Test: atest CtsAppSecurityHostTestCases:ScopedDirectoryAccessTest

Fixes: 77356487

Change-Id: Ib568a63902a6c750ccc23f074ca75f2807306fd1
parent 9dad4aef
Loading
Loading
Loading
Loading
+33 −5
Original line number Diff line number Diff line
@@ -34,6 +34,7 @@ import static com.android.documentsui.base.SharedMinimal.getUriPermission;
import static com.android.documentsui.prefs.ScopedAccessLocalPreferences.PERMISSION_ASK_AGAIN;
import static com.android.documentsui.prefs.ScopedAccessLocalPreferences.PERMISSION_GRANTED;
import static com.android.documentsui.prefs.ScopedAccessLocalPreferences.PERMISSION_NEVER_ASK;
import static com.android.documentsui.prefs.ScopedAccessLocalPreferences.clearScopedAccessPreferences;
import static com.android.documentsui.prefs.ScopedAccessLocalPreferences.getAllPackages;
import static com.android.documentsui.prefs.ScopedAccessLocalPreferences.getAllPermissions;
import static com.android.documentsui.prefs.ScopedAccessLocalPreferences.setScopedAccessPermissionStatus;
@@ -351,10 +352,20 @@ public class ScopedAccessProvider extends ContentProvider {
                Log.w(TAG, "could not parse uuid and directory on " + uri);
                continue;
            }
            final String uuid = Providers.ROOT_ID_DEVICE.equals(uuidAndDir[0])
            // TODO(b/72055774): to make things uglier, the Documents directory in the primary
            // storage is a special case as its URI is "$ROOT_ID_HOME", instead of
            // "${ROOT_ID_DEVICE}/Documents. This is another reason to move this logic to the
            // provider...
            final String uuid, dir;
            if (Providers.ROOT_ID_HOME.equals(uuidAndDir[0])) {
                uuid = null;
                dir = Environment.DIRECTORY_DOCUMENTS;
            } else {
                uuid = Providers.ROOT_ID_DEVICE.equals(uuidAndDir[0])
                        ? null // primary
                        : uuidAndDir[0]; // external volume
            final String dir = uuidAndDir.length == 1 ? null : uuidAndDir[1];
                dir = uuidAndDir.length == 1 ? null : uuidAndDir[1];
            }
            permissions
                    .add(new Permission(uriPermission.packageName, uuid, dir, PERMISSION_GRANTED));
        }
@@ -373,9 +384,26 @@ public class ScopedAccessProvider extends ContentProvider {

    @Override
    public int delete(Uri uri, String selection, String[] selectionArgs) {
        if (sMatcher.match(uri) != URI_PERMISSIONS) {
            throw new UnsupportedOperationException("delete(): unsupported " + uri);
        }

        if (DEBUG) {
            Log.v(TAG, "delete(" + uri + "): " + Arrays.toString(selectionArgs));
        }

        // TODO(b/72055774): add unit tests for invalid input
        checkArgument(selectionArgs != null && selectionArgs.length == 1,
                "Must have exactly 1 args: package_name" + Arrays.toString(selectionArgs));
        final String packageName = selectionArgs[0];

        // Delete just our preferences - the URI permissions is handled externally
        // TODO(b/72055774): move logic to revoke permissions here, so AppStorageSettings does
        // not need to call am.clearGrantedUriPermissions(packageName) (then we could remove that
        // method from ActivityManager)
        return clearScopedAccessPreferences(getContext(), packageName);
    }

    @Override
    public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
        if (sMatcher.match(uri) != URI_PERMISSIONS) {
+4 −1
Original line number Diff line number Diff line
@@ -100,21 +100,24 @@ public class ScopedAccessLocalPreferences {
        getPrefs(context).edit().putInt(key, status).apply();
    }

    public static void clearScopedAccessPreferences(Context context, String packageName) {
    public static int clearScopedAccessPreferences(Context context, String packageName) {
        final String keySubstring = "|" + packageName + "|";
        final SharedPreferences prefs = getPrefs(context);
        Editor editor = null;
        int removed = 0;
        for (final String key : prefs.getAll().keySet()) {
            if (key.contains(keySubstring)) {
                if (editor == null) {
                    editor = prefs.edit();
                }
                editor.remove(key);
                removed ++;
            }
        }
        if (editor != null) {
            editor.apply();
        }
        return removed;
    }

    private static String getScopedAccessDenialsKey(String packageName, @Nullable String uuid,