Final (?!?!?!?!) Directory Access improvements.
- Hide children items when parent is granted access (and vice versa). - Added dividers in between volumes. Test: manual verification Test: atest CtsAppSecurityHostTestCases:ScopedDirectoryAccessTest#testResetDoNotAskAgain,testResetGranted Bug: 72055774 Change-Id: Ie4ad117d1f8a53bf7dbf7747e768a301b0d03604
This commit is contained in:
@@ -44,8 +44,10 @@ import android.os.storage.StorageManager;
|
||||
import android.os.storage.VolumeInfo;
|
||||
import android.support.v14.preference.SwitchPreference;
|
||||
import android.support.v7.preference.Preference;
|
||||
import android.support.v7.preference.PreferenceGroupAdapter;
|
||||
import android.support.v7.preference.Preference.OnPreferenceChangeListener;
|
||||
import android.support.v7.preference.Preference.OnPreferenceClickListener;
|
||||
import android.support.v7.preference.PreferenceCategory;
|
||||
import android.text.TextUtils;
|
||||
import android.support.v7.preference.PreferenceManager;
|
||||
import android.support.v7.preference.PreferenceScreen;
|
||||
@@ -63,8 +65,10 @@ import com.android.settingslib.applications.AppUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Detailed settings for an app's directory access permissions (A.K.A Scoped Directory Access).
|
||||
@@ -135,10 +139,9 @@ public class DirectoryAccessDetails extends AppInfoBase {
|
||||
}
|
||||
final int count = cursor.getCount();
|
||||
if (count == 0) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "No permissions for " + mPackageName);
|
||||
}
|
||||
// TODO(b/72055774): display empty message
|
||||
// This setting screen should not be reached if there was no permission, so just
|
||||
// ignore it
|
||||
Log.w(TAG, "No permissions for " + mPackageName);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -162,7 +165,7 @@ public class DirectoryAccessDetails extends AppInfoBase {
|
||||
if (uuid == null) {
|
||||
// Primary storage entry: add right away
|
||||
prefsGroup.addPreference(newPreference(context, dir, providerUri,
|
||||
/* uuid= */ null, dir, granted));
|
||||
/* uuid= */ null, dir, granted, /* children= */ null));
|
||||
} else {
|
||||
// External volume entry: save it for later.
|
||||
ExternalVolume externalVolume = externalVolumes.get(uuid);
|
||||
@@ -222,46 +225,55 @@ public class DirectoryAccessDetails extends AppInfoBase {
|
||||
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
|
||||
final PreferenceCategory category = new PreferenceCategory(context);
|
||||
prefsGroup.addPreference(category);
|
||||
final Set<SwitchPreference> children = new HashSet<>(volume.children.size());
|
||||
category.addPreference(newPreference(context, volumeName, providerUri, volume.uuid,
|
||||
/* dir= */ null, volume.granted, children));
|
||||
|
||||
// ... 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));
|
||||
final SwitchPreference childPref =
|
||||
newPreference(context, name, providerUri, volume.uuid, dir, pair.second,
|
||||
/* children= */ null);
|
||||
category.addPreference(childPref);
|
||||
children.add(childPref);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private SwitchPreference newPreference(Context context, String title, Uri providerUri,
|
||||
String uuid, String dir, boolean granted) {
|
||||
String uuid, String dir, boolean granted, @Nullable Set<SwitchPreference> children) {
|
||||
final SwitchPreference pref = new SwitchPreference(context);
|
||||
pref.setKey(String.format("%s:%s", uuid, dir));
|
||||
pref.setTitle(title);
|
||||
pref.setChecked(granted);
|
||||
pref.setOnPreferenceChangeListener((unused, value) -> {
|
||||
resetDoNotAskAgain(context, value, providerUri, uuid, dir);
|
||||
if (!Boolean.class.isInstance(value)) {
|
||||
// Sanity check
|
||||
Log.wtf(TAG, "Invalid value from switch: " + value);
|
||||
return true;
|
||||
}
|
||||
final boolean newValue = ((Boolean) value).booleanValue();
|
||||
|
||||
resetDoNotAskAgain(context, newValue, providerUri, uuid, dir);
|
||||
if (children != null) {
|
||||
// When parent is granted, children should be hidden; and vice versa
|
||||
final boolean newChildValue = !newValue;
|
||||
for (SwitchPreference child : children) {
|
||||
child.setVisible(newChildValue);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
});
|
||||
return pref;
|
||||
}
|
||||
|
||||
private void resetDoNotAskAgain(Context context, Object value, Uri providerUri,
|
||||
private void resetDoNotAskAgain(Context context, boolean newValue, Uri providerUri,
|
||||
@Nullable String uuid, @Nullable String directory) {
|
||||
if (!Boolean.class.isInstance(value)) {
|
||||
// Sanity check
|
||||
Log.wtf(TAG, "Invalid value from switch: " + value);
|
||||
return;
|
||||
}
|
||||
final boolean newValue = ((Boolean) value).booleanValue();
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Asking " + providerUri + " to update " + uuid + "/" + directory + " to "
|
||||
+ newValue);
|
||||
|
Reference in New Issue
Block a user