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

Commit 025883da authored by Felipe Leme's avatar Felipe Leme
Browse files

Changed DirectoryAccessDetails to handle children directory on external volumes.

Test: manual verification

Bug: 63720392

Change-Id: Ief4ee0fe271212e2eccbdcedea8ebb3374c4e69b
parent 7c80b5ed
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -9230,6 +9230,10 @@
    <!-- Keywords for Directory Access settings -->
    <string name="keywords_directory_access">directory access</string>
    <!-- String used to describe the name of a directory in a volume; it must
         show both names, with the directory name wrapped in parenthesis -->
    <string name="directory_on_volume"><xliff:g id="volume" example="SD Card">%1$s</xliff:g> (<xliff:g id="directory" example="Movies">%2$s</xliff:g>)</string>
    <!-- Account type associated with the backup account. Empty for AOSP. [DO NOT TRANSLATE] -->
    <string name="account_type" translatable="false"></string>
    <!-- Package to target for Account credential confirmation. This will allow users to
+4 −3
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.AppGlobals;
import android.app.GrantedUriPermission;
import android.app.LoaderManager;
import android.content.Context;
import android.content.DialogInterface;
@@ -399,7 +400,7 @@ public class AppStorageSettings extends AppInfoWithHeader
        // Gets all URI permissions from am.
        ActivityManager am = (ActivityManager) getActivity().getSystemService(
                Context.ACTIVITY_SERVICE);
        List<UriPermission> perms =
        List<GrantedUriPermission> perms =
                am.getGrantedUriPermissions(mAppEntry.info.packageName).getList();

        if (perms.isEmpty()) {
@@ -411,8 +412,8 @@ public class AppStorageSettings extends AppInfoWithHeader

        // Group number of URIs by app.
        Map<CharSequence, MutableInt> uriCounters = new TreeMap<>();
        for (UriPermission perm : perms) {
            String authority = perm.getUri().getAuthority();
        for (GrantedUriPermission perm : perms) {
            String authority = perm.uri.getAuthority();
            ProviderInfo provider = pm.resolveContentProvider(authority, 0);
            CharSequence app = provider.applicationInfo.loadLabel(pm);
            MutableInt count = uriCounters.get(app);
+87 −41
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import static android.os.storage.StorageVolume.ScopedAccessProviderContract.COL_
import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PERMISSIONS;
import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PERMISSIONS_COLUMNS;
import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PERMISSIONS_COL_DIRECTORY;
import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PERMISSIONS_COL_GRANTED;
import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PERMISSIONS_COL_PACKAGE;
import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PERMISSIONS_COL_VOLUME_UUID;

@@ -120,8 +121,7 @@ public class DirectoryAccessDetails extends AppInfoBase {
        addPreferencesFromResource(R.xml.directory_access_details);
        final PreferenceScreen prefsGroup = getPreferenceScreen();

        // Set external directory UUIDs.
        ArraySet<String> externalDirectoryUuids = null;
        final Map<String, ExternalVolume> externalVolumes = new HashMap<>();

        final Uri providerUri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
                .authority(AUTHORITY).appendPath(TABLE_PERMISSIONS).appendPath("*")
@@ -146,8 +146,10 @@ public class DirectoryAccessDetails extends AppInfoBase {
                final String pkg = cursor.getString(TABLE_PERMISSIONS_COL_PACKAGE);
                final String uuid = cursor.getString(TABLE_PERMISSIONS_COL_VOLUME_UUID);
                final String dir = cursor.getString(TABLE_PERMISSIONS_COL_DIRECTORY);
                final boolean granted = cursor.getInt(TABLE_PERMISSIONS_COL_GRANTED) == 1;
                if (VERBOSE) {
                    Log.v(TAG, "Pkg:"  + pkg + " uuid: " + uuid + " dir: " + dir);
                    Log.v(TAG, "Pkg:"  + pkg + " uuid: " + uuid + " dir: " + dir
                            + " granted:" + granted);
                }

                if (!mPackageName.equals(pkg)) {
@@ -159,24 +161,37 @@ public class DirectoryAccessDetails extends AppInfoBase {

                if (uuid == null) {
                    // Primary storage entry: add right away
                    prefsGroup.addPreference(
                            newPreference(context, dir, providerUri, /* uuid= */ null, dir));
                    prefsGroup.addPreference(newPreference(context, dir, providerUri,
                            /* uuid= */ null, dir, granted));
                } else {
                    // External volume entry: save it for later.
                    if (externalDirectoryUuids == null) {
                        externalDirectoryUuids = new ArraySet<>(1);
                    ExternalVolume externalVolume = externalVolumes.get(uuid);
                    if (externalVolume == null) {
                        externalVolume = new ExternalVolume(uuid);
                        externalVolumes.put(uuid, externalVolume);
                    }
                    if (dir == null) {
                        // Whole volume
                        externalVolume.granted = granted;
                    } else {
                        // Directory only
                        externalVolume.children.add(new Pair<>(dir, granted));
                    }
                    externalDirectoryUuids.add(uuid);
                }
            }
        }

        // Add entries from external volumes
        if (externalDirectoryUuids != null) {
        if (VERBOSE) {
                Log.v(TAG, "adding external directories: " + externalDirectoryUuids);
            Log.v(TAG, "external volumes: " + externalVolumes);
        }

        if (externalVolumes.isEmpty()) {
            // We're done!
            return;
        }

        // Add entries from external volumes

        // Query StorageManager to get the user-friendly volume names.
        final StorageManager sm = context.getSystemService(StorageManager.class);
        final List<VolumeInfo> volumes = sm.getVolumes();
@@ -200,23 +215,38 @@ public class DirectoryAccessDetails extends AppInfoBase {
            Log.v(TAG, "UUID -> name mapping: " + volumeNames);
        }

            externalDirectoryUuids.forEach((uuid) ->{
                final String name = volumeNames.get(uuid);
        for (ExternalVolume volume : externalVolumes.values()) {
            final String volumeName = volumeNames.get(volume.uuid);
            if (volumeName == null) {
                Log.w(TAG, "Ignoring entry for invalid UUID: " + volume.uuid);
                continue;
            }
            // First add the pref for the whole volume...
            // TODO(b/72055774): add separator
                prefsGroup.addPreference(
                        newPreference(context, name, providerUri, uuid, /* dir= */ null));
            prefsGroup.addPreference(newPreference(context, volumeName, providerUri, volume.uuid,
                    /* dir= */ null, volume.granted));
            // TODO(b/72055774): make sure children are gone when parent is toggled on - should be
            // handled automatically if we're refreshing the activity on change, otherwise we'll
            // need to explicitly remove them

            // ... then the children prefs
            volume.children.forEach((pair) -> {
                final String dir = pair.first;
                final String name = context.getResources()
                        .getString(R.string.directory_on_volume, volumeName, dir);
                prefsGroup
                        .addPreference(newPreference(context, name, providerUri, volume.uuid,
                                dir, pair.second));
            });
        }
        return;
    }


    private SwitchPreference newPreference(Context context, String title, Uri providerUri,
            String uuid, String dir) {
            String uuid, String dir, boolean granted) {
        final SwitchPreference pref = new SwitchPreference(context);
        pref.setKey(String.format("%s:%s", uuid, dir));
        pref.setTitle(title);
        pref.setChecked(false);
        pref.setChecked(granted);
        pref.setOnPreferenceChangeListener((unused, value) -> {
            resetDoNotAskAgain(context, value, providerUri, uuid, dir);
            return true;
@@ -259,4 +289,20 @@ public class DirectoryAccessDetails extends AppInfoBase {
    public int getMetricsCategory() {
        return MetricsEvent.APPLICATIONS_DIRECTORY_ACCESS_DETAIL;
    }

    private static class ExternalVolume {
        final String uuid;
        final List<Pair<String, Boolean>> children = new ArrayList<>();
        boolean granted;

        ExternalVolume(String uuid) {
            this.uuid = uuid;
        }

        @Override
        public String toString() {
            return "ExternalVolume: [uuid=" + uuid + ", granted=" + granted +
                    ", children=" + children + "]";
        }
    }
}