OSDN Git Service

Changed DirectoryAccessDetails to handle children directory on external volumes.
authorFelipe Leme <felipeal@google.com>
Wed, 24 Jan 2018 20:17:29 +0000 (12:17 -0800)
committerFelipe Leme <felipeal@google.com>
Thu, 25 Jan 2018 18:48:59 +0000 (10:48 -0800)
Test: manual verification

Bug: 63720392

Change-Id: Ief4ee0fe271212e2eccbdcedea8ebb3374c4e69b

res/values/strings.xml
src/com/android/settings/applications/AppStorageSettings.java
src/com/android/settings/applications/DirectoryAccessDetails.java

index c7f46c6..ea3605c 100644 (file)
     <!-- 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
index 78a5050..ff036bb 100644 (file)
@@ -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);
index 43422d0..3e9bf47 100644 (file)
@@ -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,64 +161,92 @@ 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);
                 }
             }
         }
 
+        if (VERBOSE) {
+            Log.v(TAG, "external volumes: " + externalVolumes);
+        }
+
+        if (externalVolumes.isEmpty()) {
+            // We're done!
+            return;
+        }
+
         // Add entries from external volumes
-        if (externalDirectoryUuids != null) {
-            if (VERBOSE) {
-                Log.v(TAG, "adding external directories: " + externalDirectoryUuids);
-            }
 
-            // Query StorageManager to get the user-friendly volume names.
-            final StorageManager sm = context.getSystemService(StorageManager.class);
-            final List<VolumeInfo> volumes = sm.getVolumes();
-            if (volumes.isEmpty()) {
-                Log.w(TAG, "StorageManager returned no secondary volumes");
-                return;
-            }
-            final Map<String, String> volumeNames = new HashMap<>(volumes.size());
-            for (VolumeInfo volume : volumes) {
-                final String uuid = volume.getFsUuid();
-                if (uuid == null) continue; // Primary storage; not used.
-
-                String name = sm.getBestVolumeDescription(volume);
-                if (name == null) {
-                    Log.w(TAG, "No description for " + volume + "; using uuid instead: " + uuid);
-                    name = uuid;
-                }
-                volumeNames.put(uuid, name);
+        // Query StorageManager to get the user-friendly volume names.
+        final StorageManager sm = context.getSystemService(StorageManager.class);
+        final List<VolumeInfo> volumes = sm.getVolumes();
+        if (volumes.isEmpty()) {
+            Log.w(TAG, "StorageManager returned no secondary volumes");
+            return;
+        }
+        final Map<String, String> volumeNames = new HashMap<>(volumes.size());
+        for (VolumeInfo volume : volumes) {
+            final String uuid = volume.getFsUuid();
+            if (uuid == null) continue; // Primary storage; not used.
+
+            String name = sm.getBestVolumeDescription(volume);
+            if (name == null) {
+                Log.w(TAG, "No description for " + volume + "; using uuid instead: " + uuid);
+                name = uuid;
             }
-            if (VERBOSE) {
-                Log.v(TAG, "UUID -> name mapping: " + volumeNames);
+            volumeNames.put(uuid, name);
+        }
+        if (VERBOSE) {
+            Log.v(TAG, "UUID -> name mapping: " + volumeNames);
+        }
+
+        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, 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
 
-            externalDirectoryUuids.forEach((uuid) ->{
-                final String name = volumeNames.get(uuid);
-                // TODO(b/72055774): add separator
-                prefsGroup.addPreference(
-                        newPreference(context, name, providerUri, uuid, /* dir= */ null));
+            // ... 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 + "]";
+        }
+    }
 }