Changed DirectoryAccessDetails to handle children directory on external volumes.
Test: manual verification Bug: 63720392 Change-Id: Ief4ee0fe271212e2eccbdcedea8ebb3374c4e69b
This commit is contained in:
@@ -9230,6 +9230,10 @@
|
|||||||
<!-- Keywords for Directory Access settings -->
|
<!-- Keywords for Directory Access settings -->
|
||||||
<string name="keywords_directory_access">directory access</string>
|
<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] -->
|
<!-- Account type associated with the backup account. Empty for AOSP. [DO NOT TRANSLATE] -->
|
||||||
<string name="account_type" translatable="false"></string>
|
<string name="account_type" translatable="false"></string>
|
||||||
<!-- Package to target for Account credential confirmation. This will allow users to
|
<!-- Package to target for Account credential confirmation. This will allow users to
|
||||||
|
@@ -22,6 +22,7 @@ import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
|
|||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
import android.app.AlertDialog;
|
import android.app.AlertDialog;
|
||||||
import android.app.AppGlobals;
|
import android.app.AppGlobals;
|
||||||
|
import android.app.GrantedUriPermission;
|
||||||
import android.app.LoaderManager;
|
import android.app.LoaderManager;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.DialogInterface;
|
import android.content.DialogInterface;
|
||||||
@@ -399,7 +400,7 @@ public class AppStorageSettings extends AppInfoWithHeader
|
|||||||
// Gets all URI permissions from am.
|
// Gets all URI permissions from am.
|
||||||
ActivityManager am = (ActivityManager) getActivity().getSystemService(
|
ActivityManager am = (ActivityManager) getActivity().getSystemService(
|
||||||
Context.ACTIVITY_SERVICE);
|
Context.ACTIVITY_SERVICE);
|
||||||
List<UriPermission> perms =
|
List<GrantedUriPermission> perms =
|
||||||
am.getGrantedUriPermissions(mAppEntry.info.packageName).getList();
|
am.getGrantedUriPermissions(mAppEntry.info.packageName).getList();
|
||||||
|
|
||||||
if (perms.isEmpty()) {
|
if (perms.isEmpty()) {
|
||||||
@@ -411,8 +412,8 @@ public class AppStorageSettings extends AppInfoWithHeader
|
|||||||
|
|
||||||
// Group number of URIs by app.
|
// Group number of URIs by app.
|
||||||
Map<CharSequence, MutableInt> uriCounters = new TreeMap<>();
|
Map<CharSequence, MutableInt> uriCounters = new TreeMap<>();
|
||||||
for (UriPermission perm : perms) {
|
for (GrantedUriPermission perm : perms) {
|
||||||
String authority = perm.getUri().getAuthority();
|
String authority = perm.uri.getAuthority();
|
||||||
ProviderInfo provider = pm.resolveContentProvider(authority, 0);
|
ProviderInfo provider = pm.resolveContentProvider(authority, 0);
|
||||||
CharSequence app = provider.applicationInfo.loadLabel(pm);
|
CharSequence app = provider.applicationInfo.loadLabel(pm);
|
||||||
MutableInt count = uriCounters.get(app);
|
MutableInt count = uriCounters.get(app);
|
||||||
|
@@ -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;
|
||||||
import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PERMISSIONS_COLUMNS;
|
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_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_PACKAGE;
|
||||||
import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PERMISSIONS_COL_VOLUME_UUID;
|
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);
|
addPreferencesFromResource(R.xml.directory_access_details);
|
||||||
final PreferenceScreen prefsGroup = getPreferenceScreen();
|
final PreferenceScreen prefsGroup = getPreferenceScreen();
|
||||||
|
|
||||||
// Set external directory UUIDs.
|
final Map<String, ExternalVolume> externalVolumes = new HashMap<>();
|
||||||
ArraySet<String> externalDirectoryUuids = null;
|
|
||||||
|
|
||||||
final Uri providerUri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
|
final Uri providerUri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
|
||||||
.authority(AUTHORITY).appendPath(TABLE_PERMISSIONS).appendPath("*")
|
.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 pkg = cursor.getString(TABLE_PERMISSIONS_COL_PACKAGE);
|
||||||
final String uuid = cursor.getString(TABLE_PERMISSIONS_COL_VOLUME_UUID);
|
final String uuid = cursor.getString(TABLE_PERMISSIONS_COL_VOLUME_UUID);
|
||||||
final String dir = cursor.getString(TABLE_PERMISSIONS_COL_DIRECTORY);
|
final String dir = cursor.getString(TABLE_PERMISSIONS_COL_DIRECTORY);
|
||||||
|
final boolean granted = cursor.getInt(TABLE_PERMISSIONS_COL_GRANTED) == 1;
|
||||||
if (VERBOSE) {
|
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)) {
|
if (!mPackageName.equals(pkg)) {
|
||||||
@@ -159,24 +161,37 @@ public class DirectoryAccessDetails extends AppInfoBase {
|
|||||||
|
|
||||||
if (uuid == null) {
|
if (uuid == null) {
|
||||||
// Primary storage entry: add right away
|
// Primary storage entry: add right away
|
||||||
prefsGroup.addPreference(
|
prefsGroup.addPreference(newPreference(context, dir, providerUri,
|
||||||
newPreference(context, dir, providerUri, /* uuid= */ null, dir));
|
/* uuid= */ null, dir, granted));
|
||||||
} else {
|
} else {
|
||||||
// External volume entry: save it for later.
|
// External volume entry: save it for later.
|
||||||
if (externalDirectoryUuids == null) {
|
ExternalVolume externalVolume = externalVolumes.get(uuid);
|
||||||
externalDirectoryUuids = new ArraySet<>(1);
|
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) {
|
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.
|
// Query StorageManager to get the user-friendly volume names.
|
||||||
final StorageManager sm = context.getSystemService(StorageManager.class);
|
final StorageManager sm = context.getSystemService(StorageManager.class);
|
||||||
final List<VolumeInfo> volumes = sm.getVolumes();
|
final List<VolumeInfo> volumes = sm.getVolumes();
|
||||||
@@ -200,23 +215,38 @@ public class DirectoryAccessDetails extends AppInfoBase {
|
|||||||
Log.v(TAG, "UUID -> name mapping: " + volumeNames);
|
Log.v(TAG, "UUID -> name mapping: " + volumeNames);
|
||||||
}
|
}
|
||||||
|
|
||||||
externalDirectoryUuids.forEach((uuid) ->{
|
for (ExternalVolume volume : externalVolumes.values()) {
|
||||||
final String name = volumeNames.get(uuid);
|
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
|
// TODO(b/72055774): add separator
|
||||||
prefsGroup.addPreference(
|
prefsGroup.addPreference(newPreference(context, volumeName, providerUri, volume.uuid,
|
||||||
newPreference(context, name, providerUri, uuid, /* dir= */ null));
|
/* 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,
|
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);
|
final SwitchPreference pref = new SwitchPreference(context);
|
||||||
pref.setKey(String.format("%s:%s", uuid, dir));
|
pref.setKey(String.format("%s:%s", uuid, dir));
|
||||||
pref.setTitle(title);
|
pref.setTitle(title);
|
||||||
pref.setChecked(false);
|
pref.setChecked(granted);
|
||||||
pref.setOnPreferenceChangeListener((unused, value) -> {
|
pref.setOnPreferenceChangeListener((unused, value) -> {
|
||||||
resetDoNotAskAgain(context, value, providerUri, uuid, dir);
|
resetDoNotAskAgain(context, value, providerUri, uuid, dir);
|
||||||
return true;
|
return true;
|
||||||
@@ -259,4 +289,20 @@ public class DirectoryAccessDetails extends AppInfoBase {
|
|||||||
public int getMetricsCategory() {
|
public int getMetricsCategory() {
|
||||||
return MetricsEvent.APPLICATIONS_DIRECTORY_ACCESS_DETAIL;
|
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 + "]";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user