Delete Directory access Settings.
Bug: 111892460 Test: m RunSettingsRoboTests Change-Id: I6ffa5a4b69fa7b3ee9d9a058fa075b60fbd2b0a3
This commit is contained in:
@@ -2962,16 +2962,6 @@
|
||||
android:value="true" />
|
||||
</activity>
|
||||
|
||||
<activity android:name="Settings$DirectoryAccessSettingsActivity"
|
||||
android:label="@string/directory_access">
|
||||
<intent-filter>
|
||||
<action android:name="android.settings.STORAGE_VOLUME_ACCESS_SETTINGS" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
|
||||
android:value="com.android.settings.applications.manageapplications.ManageApplications" />
|
||||
</activity>
|
||||
|
||||
<provider android:name=".slices.SettingsSliceProvider"
|
||||
android:authorities="com.android.settings.slices;android.settings.slices"
|
||||
android:exported="true"
|
||||
|
@@ -9962,15 +9962,6 @@
|
||||
<!-- UI debug setting: ANGLE enabled app has been set [CHAR LIMIT=NONE] -->
|
||||
<string name="angle_enabled_app_set">ANGLE enabled application: <xliff:g id="app_name" example="com.company.app">%1$s</xliff:g></string>
|
||||
|
||||
<!-- Title for Directory Access settings -->
|
||||
<string name="directory_access">Directory access</string>
|
||||
<!-- 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>
|
||||
|
||||
<!-- Slices Strings -->
|
||||
|
||||
<!-- Summary text on a card explaining that a setting does not exist / is not supported on the device [CHAR_LIMIT=NONE]-->
|
||||
|
@@ -1,20 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Copyright (C) 2018 The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:settings="http://schemas.android.com/apk/res-auto"
|
||||
android:key="directory_access_details"
|
||||
android:title="@string/directory_access"/>
|
@@ -120,16 +120,6 @@
|
||||
android:value="com.android.settings.Settings$VrListenersSettingsActivity" />
|
||||
</Preference>
|
||||
|
||||
<Preference
|
||||
android:key="special_app_directory_access"
|
||||
android:title="@string/directory_access"
|
||||
android:fragment="com.android.settings.applications.manageapplications.ManageApplications"
|
||||
settings:keywords="@string/keywords_directory_access">
|
||||
<extra
|
||||
android:name="classname"
|
||||
android:value="com.android.settings.Settings$DirectoryAccessSettingsActivity" />
|
||||
</Preference>
|
||||
|
||||
<Preference
|
||||
android:key="change_wifi_state"
|
||||
android:title="@string/change_wifi_state_title"
|
||||
|
@@ -120,7 +120,6 @@ public class Settings extends SettingsActivity {
|
||||
public static class PhotosStorageActivity extends SettingsActivity {
|
||||
/* empty */
|
||||
}
|
||||
public static class DirectoryAccessSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
|
||||
public static class ApnSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
public static class WifiCallingSettingsActivity extends SettingsActivity { /* empty */ }
|
||||
|
@@ -1,99 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.settings.applications;
|
||||
|
||||
import static android.os.storage.StorageVolume.ScopedAccessProviderContract.AUTHORITY;
|
||||
import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PACKAGES;
|
||||
import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PACKAGES_COLUMNS;
|
||||
import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PACKAGES_COL_PACKAGE;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.settingslib.applications.ApplicationsState;
|
||||
import com.android.settingslib.applications.ApplicationsState.AppEntry;
|
||||
import com.android.settingslib.applications.ApplicationsState.AppFilter;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
// TODO(b/72055774): add unit tests
|
||||
public class AppStateDirectoryAccessBridge extends AppStateBaseBridge {
|
||||
|
||||
private static final String TAG = "DirectoryAccessBridge";
|
||||
|
||||
// TODO(b/72055774): set to false once feature is ready (or use Log.isLoggable)
|
||||
static final boolean DEBUG = true;
|
||||
static final boolean VERBOSE = true;
|
||||
|
||||
public AppStateDirectoryAccessBridge(ApplicationsState appState, Callback callback) {
|
||||
super(appState, callback);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadAllExtraInfo() { }
|
||||
|
||||
@Override
|
||||
protected void updateExtraInfo(AppEntry app, String pkg, int uid) { }
|
||||
|
||||
public static final AppFilter FILTER_APP_HAS_DIRECTORY_ACCESS = new AppFilter() {
|
||||
|
||||
private Set<String> mPackages;
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
throw new UnsupportedOperationException("Need to call constructor that takes context");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(Context context) {
|
||||
mPackages = null;
|
||||
final Uri providerUri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
|
||||
.authority(AUTHORITY).appendPath(TABLE_PACKAGES).appendPath("*")
|
||||
.build();
|
||||
try (Cursor cursor = context.getContentResolver().query(providerUri,
|
||||
TABLE_PACKAGES_COLUMNS, null, null)) {
|
||||
if (cursor == null) {
|
||||
Log.w(TAG, "Didn't get cursor for " + providerUri);
|
||||
return;
|
||||
}
|
||||
final int count = cursor.getCount();
|
||||
if (count == 0) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "No packages anymore (was " + mPackages + ")");
|
||||
}
|
||||
return;
|
||||
}
|
||||
mPackages = new ArraySet<>(count);
|
||||
while (cursor.moveToNext()) {
|
||||
mPackages.add(cursor.getString(TABLE_PACKAGES_COL_PACKAGE));
|
||||
}
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "init(): " + mPackages);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean filterApp(AppEntry info) {
|
||||
return mPackages != null && mPackages.contains(info.info.packageName);
|
||||
}
|
||||
};
|
||||
}
|
@@ -18,13 +18,10 @@ package com.android.settings.applications;
|
||||
|
||||
import static android.content.pm.ApplicationInfo.FLAG_ALLOW_CLEAR_USER_DATA;
|
||||
import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
|
||||
import static android.os.storage.StorageVolume.ScopedAccessProviderContract.AUTHORITY;
|
||||
import static android.os.storage.StorageVolume.ScopedAccessProviderContract.TABLE_PERMISSIONS;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.app.AppGlobals;
|
||||
import android.app.GrantedUriPermission;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
@@ -32,7 +29,6 @@ import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.IPackageDataObserver;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ProviderInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
@@ -461,17 +457,6 @@ public class AppStorageSettings extends AppInfoWithHeader
|
||||
Context.ACTIVITY_SERVICE);
|
||||
am.clearGrantedUriPermissions(packageName);
|
||||
|
||||
|
||||
// Also update the Scoped Directory Access UI permissions
|
||||
final Uri providerUri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
|
||||
.authority(AUTHORITY).appendPath(TABLE_PERMISSIONS).appendPath("*")
|
||||
.build();
|
||||
Log.v(TAG, "Asking " + providerUri + " to delete permissions for " + packageName);
|
||||
final int deleted = context.getContentResolver().delete(providerUri, null, new String[] {
|
||||
packageName
|
||||
});
|
||||
Log.d(TAG, "Deleted " + deleted + " entries for package " + packageName);
|
||||
|
||||
// Update UI
|
||||
refreshGrantedUriPermissions();
|
||||
}
|
||||
|
@@ -1,323 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.android.settings.applications;
|
||||
|
||||
import static android.os.storage.StorageVolume.ScopedAccessProviderContract.AUTHORITY;
|
||||
import static android.os.storage.StorageVolume.ScopedAccessProviderContract.COL_GRANTED;
|
||||
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;
|
||||
|
||||
import static com.android.settings.applications.AppStateDirectoryAccessBridge.DEBUG;
|
||||
import static com.android.settings.applications.AppStateDirectoryAccessBridge.VERBOSE;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Activity;
|
||||
import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.storage.StorageManager;
|
||||
import android.os.storage.VolumeInfo;
|
||||
import android.util.IconDrawableFactory;
|
||||
import android.util.Log;
|
||||
import android.util.Pair;
|
||||
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.preference.Preference;
|
||||
import androidx.preference.PreferenceCategory;
|
||||
import androidx.preference.PreferenceScreen;
|
||||
import androidx.preference.SwitchPreference;
|
||||
|
||||
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.widget.EntityHeaderController;
|
||||
import com.android.settings.widget.EntityHeaderController.ActionType;
|
||||
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).
|
||||
*
|
||||
* <p>Currently, it shows the entry for which the user denied access with the "Do not ask again"
|
||||
* flag checked on: the user than can use the settings toggle to reset that deniel.
|
||||
*
|
||||
* <p>This fragments dynamically lists all such permissions, starting with one preference per
|
||||
* directory in the primary storage, then adding additional entries for the external volumes (one
|
||||
* entry for the whole volume).
|
||||
*/
|
||||
// TODO(b/72055774): add unit tests
|
||||
public class DirectoryAccessDetails extends AppInfoBase {
|
||||
|
||||
@SuppressWarnings("hiding")
|
||||
private static final String TAG = "DirectoryAccessDetails";
|
||||
|
||||
private boolean mCreated;
|
||||
|
||||
@Override
|
||||
public void onActivityCreated(Bundle savedInstanceState) {
|
||||
super.onActivityCreated(savedInstanceState);
|
||||
|
||||
if (mCreated) {
|
||||
Log.w(TAG, "onActivityCreated(): ignoring duplicate call");
|
||||
return;
|
||||
}
|
||||
mCreated = true;
|
||||
if (mPackageInfo == null) {
|
||||
Log.w(TAG, "onActivityCreated(): no package info");
|
||||
return;
|
||||
}
|
||||
final Activity activity = getActivity();
|
||||
final Preference pref = EntityHeaderController
|
||||
.newInstance(activity, this, /* header= */ null )
|
||||
.setRecyclerView(getListView(), getSettingsLifecycle())
|
||||
.setIcon(IconDrawableFactory.newInstance(getPrefContext())
|
||||
.getBadgedIcon(mPackageInfo.applicationInfo))
|
||||
.setLabel(mPackageInfo.applicationInfo.loadLabel(mPm))
|
||||
.setIsInstantApp(AppUtils.isInstant(mPackageInfo.applicationInfo))
|
||||
.setPackageName(mPackageName)
|
||||
.setUid(mPackageInfo.applicationInfo.uid)
|
||||
.setHasAppInfoLink(false)
|
||||
.setButtonActions(ActionType.ACTION_NONE, ActionType.ACTION_NONE)
|
||||
.done(activity, getPrefContext());
|
||||
getPreferenceScreen().addPreference(pref);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
addPreferencesFromResource(R.xml.directory_access_details);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean refreshUi() {
|
||||
final Context context = getPrefContext();
|
||||
final PreferenceScreen prefsGroup = getPreferenceScreen();
|
||||
prefsGroup.removeAll();
|
||||
|
||||
final Map<String, ExternalVolume> externalVolumes = new HashMap<>();
|
||||
|
||||
final Uri providerUri = new Uri.Builder().scheme(ContentResolver.SCHEME_CONTENT)
|
||||
.authority(AUTHORITY).appendPath(TABLE_PERMISSIONS).appendPath("*")
|
||||
.build();
|
||||
// Query provider for entries.
|
||||
try (Cursor cursor = context.getContentResolver().query(providerUri,
|
||||
TABLE_PERMISSIONS_COLUMNS, null, new String[] { mPackageName }, null)) {
|
||||
if (cursor == null) {
|
||||
Log.w(TAG, "Didn't get cursor for " + mPackageName);
|
||||
return true;
|
||||
}
|
||||
final int count = cursor.getCount();
|
||||
if (count == 0) {
|
||||
// This setting screen should not be reached if there was no permission, so just
|
||||
// ignore it
|
||||
Log.w(TAG, "No permissions for " + mPackageName);
|
||||
return true;
|
||||
}
|
||||
|
||||
while (cursor.moveToNext()) {
|
||||
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
|
||||
+ " granted:" + granted);
|
||||
}
|
||||
|
||||
if (!mPackageName.equals(pkg)) {
|
||||
// Sanity check, shouldn't happen
|
||||
Log.w(TAG, "Ignoring " + uuid + "/" + dir + " due to package mismatch: "
|
||||
+ "expected " + mPackageName + ", got " + pkg);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (uuid == null) {
|
||||
if (dir == null) {
|
||||
// Sanity check, shouldn't happen
|
||||
Log.wtf(TAG, "Ignoring permission on primary storage root");
|
||||
} else {
|
||||
// Primary storage entry: add right away
|
||||
prefsGroup.addPreference(newPreference(context, dir, providerUri,
|
||||
/* uuid= */ null, dir, granted, /* children= */ null));
|
||||
}
|
||||
} else {
|
||||
// External volume entry: save it for later.
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (VERBOSE) {
|
||||
Log.v(TAG, "external volumes: " + externalVolumes);
|
||||
}
|
||||
|
||||
if (externalVolumes.isEmpty()) {
|
||||
// We're done!
|
||||
return true;
|
||||
}
|
||||
|
||||
// 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();
|
||||
if (volumes.isEmpty()) {
|
||||
Log.w(TAG, "StorageManager returned no secondary volumes");
|
||||
return true;
|
||||
}
|
||||
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);
|
||||
}
|
||||
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...
|
||||
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);
|
||||
final SwitchPreference childPref =
|
||||
newPreference(context, name, providerUri, volume.uuid, dir, pair.second,
|
||||
/* children= */ null);
|
||||
category.addPreference(childPref);
|
||||
children.add(childPref);
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private SwitchPreference newPreference(Context context, String title, Uri providerUri,
|
||||
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) -> {
|
||||
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, boolean newValue, Uri providerUri,
|
||||
@Nullable String uuid, @Nullable String directory) {
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Asking " + providerUri + " to update " + uuid + "/" + directory + " to "
|
||||
+ newValue);
|
||||
}
|
||||
final ContentValues values = new ContentValues(1);
|
||||
values.put(COL_GRANTED, newValue);
|
||||
final int updated = context.getContentResolver().update(providerUri, values,
|
||||
null, new String[] { mPackageName, uuid, directory });
|
||||
if (DEBUG) {
|
||||
Log.d(TAG, "Updated " + updated + " entries for " + uuid + "/" + directory);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected AlertDialog createDialog(int id, int errorCode) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
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 + "]";
|
||||
}
|
||||
}
|
||||
}
|
@@ -19,7 +19,6 @@ package com.android.settings.applications.manageapplications;
|
||||
import androidx.annotation.IntDef;
|
||||
|
||||
import com.android.settings.R;
|
||||
import com.android.settings.applications.AppStateDirectoryAccessBridge;
|
||||
import com.android.settings.applications.AppStateInstallAppsBridge;
|
||||
import com.android.settings.applications.AppStateNotificationBridge;
|
||||
import com.android.settings.applications.AppStateOverlayBridge;
|
||||
@@ -70,7 +69,6 @@ public class AppFilterRegistry {
|
||||
public static final int FILTER_APPS_WITH_OVERLAY = 11;
|
||||
public static final int FILTER_APPS_WRITE_SETTINGS = 12;
|
||||
public static final int FILTER_APPS_INSTALL_SOURCES = 13;
|
||||
public static final int FILTER_APP_HAS_DIRECTORY_ACCESS = 14;
|
||||
public static final int FILTER_APP_CAN_CHANGE_WIFI_STATE = 15;
|
||||
public static final int FILTER_APPS_BLOCKED = 16;
|
||||
// Next id: 17
|
||||
@@ -170,12 +168,6 @@ public class AppFilterRegistry {
|
||||
FILTER_APPS_INSTALL_SOURCES,
|
||||
R.string.filter_install_sources_apps);
|
||||
|
||||
// Apps that interacted with directory access permissions (A.K.A. Scoped Directory Access)
|
||||
mFilters[FILTER_APP_HAS_DIRECTORY_ACCESS] = new AppFilterItem(
|
||||
AppStateDirectoryAccessBridge.FILTER_APP_HAS_DIRECTORY_ACCESS,
|
||||
FILTER_APP_HAS_DIRECTORY_ACCESS,
|
||||
R.string.filter_install_sources_apps);
|
||||
|
||||
mFilters[FILTER_APP_CAN_CHANGE_WIFI_STATE] = new AppFilterItem(
|
||||
AppStateChangeWifiStateBridge.FILTER_CHANGE_WIFI_STATE,
|
||||
FILTER_APP_CAN_CHANGE_WIFI_STATE,
|
||||
@@ -208,8 +200,6 @@ public class AppFilterRegistry {
|
||||
return FILTER_APPS_WRITE_SETTINGS;
|
||||
case ManageApplications.LIST_TYPE_MANAGE_SOURCES:
|
||||
return FILTER_APPS_INSTALL_SOURCES;
|
||||
case ManageApplications.LIST_TYPE_DIRECTORY_ACCESS:
|
||||
return FILTER_APP_HAS_DIRECTORY_ACCESS;
|
||||
case ManageApplications.LIST_TYPE_WIFI_ACCESS:
|
||||
return FILTER_APP_CAN_CHANGE_WIFI_STATE;
|
||||
case ManageApplications.LIST_TYPE_NOTIFICATION:
|
||||
|
@@ -90,7 +90,6 @@ import com.android.settings.SettingsActivity;
|
||||
import com.android.settings.applications.AppInfoBase;
|
||||
import com.android.settings.applications.AppStateAppOpsBridge.PermissionState;
|
||||
import com.android.settings.applications.AppStateBaseBridge;
|
||||
import com.android.settings.applications.AppStateDirectoryAccessBridge;
|
||||
import com.android.settings.applications.AppStateInstallAppsBridge;
|
||||
import com.android.settings.applications.AppStateNotificationBridge;
|
||||
import com.android.settings.applications.AppStateNotificationBridge.NotificationsSentState;
|
||||
@@ -101,7 +100,6 @@ import com.android.settings.applications.AppStateUsageBridge.UsageState;
|
||||
import com.android.settings.applications.AppStateWriteSettingsBridge;
|
||||
import com.android.settings.applications.AppStorageSettings;
|
||||
import com.android.settings.applications.DefaultAppSettings;
|
||||
import com.android.settings.applications.DirectoryAccessDetails;
|
||||
import com.android.settings.applications.InstalledAppCounter;
|
||||
import com.android.settings.applications.UsageAccessDetails;
|
||||
import com.android.settings.applications.appinfo.AppInfoDashboardFragment;
|
||||
@@ -218,7 +216,6 @@ public class ManageApplications extends InstrumentedFragment
|
||||
public static final int LIST_TYPE_GAMES = 9;
|
||||
public static final int LIST_TYPE_MOVIES = 10;
|
||||
public static final int LIST_TYPE_PHOTOGRAPHY = 11;
|
||||
public static final int LIST_TYPE_DIRECTORY_ACCESS = 12;
|
||||
public static final int LIST_TYPE_WIFI_ACCESS = 13;
|
||||
|
||||
// List types that should show instant apps.
|
||||
@@ -293,9 +290,6 @@ public class ManageApplications extends InstrumentedFragment
|
||||
mListType = LIST_TYPE_PHOTOGRAPHY;
|
||||
mSortOrder = R.id.sort_order_size;
|
||||
mStorageType = args.getInt(EXTRA_STORAGE_TYPE, STORAGE_TYPE_DEFAULT);
|
||||
} else if (className.equals(Settings.DirectoryAccessSettingsActivity.class.getName())) {
|
||||
mListType = LIST_TYPE_DIRECTORY_ACCESS;
|
||||
screenTitle = R.string.directory_access;
|
||||
} else if (className.equals(Settings.ChangeWifiStateActivity.class.getName())) {
|
||||
mListType = LIST_TYPE_WIFI_ACCESS;
|
||||
screenTitle = R.string.change_wifi_state_title;
|
||||
@@ -479,8 +473,6 @@ public class ManageApplications extends InstrumentedFragment
|
||||
return MetricsEvent.SYSTEM_ALERT_WINDOW_APPS;
|
||||
case LIST_TYPE_MANAGE_SOURCES:
|
||||
return MetricsEvent.MANAGE_EXTERNAL_SOURCES;
|
||||
case LIST_TYPE_DIRECTORY_ACCESS:
|
||||
return MetricsEvent.DIRECTORY_ACCESS;
|
||||
case LIST_TYPE_WIFI_ACCESS:
|
||||
return MetricsEvent.CONFIGURE_WIFI;
|
||||
default:
|
||||
@@ -578,9 +570,6 @@ public class ManageApplications extends InstrumentedFragment
|
||||
case LIST_TYPE_PHOTOGRAPHY:
|
||||
startAppInfoFragment(AppStorageSettings.class, R.string.storage_photos_videos);
|
||||
break;
|
||||
case LIST_TYPE_DIRECTORY_ACCESS:
|
||||
startAppInfoFragment(DirectoryAccessDetails.class, R.string.directory_access);
|
||||
break;
|
||||
case LIST_TYPE_WIFI_ACCESS:
|
||||
startAppInfoFragment(ChangeWifiStateDetails.class,
|
||||
R.string.change_wifi_state_title);
|
||||
@@ -916,8 +905,6 @@ public class ManageApplications extends InstrumentedFragment
|
||||
mExtraInfoBridge = new AppStateWriteSettingsBridge(mContext, mState, this);
|
||||
} else if (mManageApplications.mListType == LIST_TYPE_MANAGE_SOURCES) {
|
||||
mExtraInfoBridge = new AppStateInstallAppsBridge(mContext, mState, this);
|
||||
} else if (mManageApplications.mListType == LIST_TYPE_DIRECTORY_ACCESS) {
|
||||
mExtraInfoBridge = new AppStateDirectoryAccessBridge(mState, this);
|
||||
} else if (mManageApplications.mListType == LIST_TYPE_WIFI_ACCESS) {
|
||||
mExtraInfoBridge = new AppStateChangeWifiStateBridge(mContext, mState, this);
|
||||
} else {
|
||||
@@ -1360,9 +1347,6 @@ public class ManageApplications extends InstrumentedFragment
|
||||
case LIST_TYPE_MANAGE_SOURCES:
|
||||
holder.setSummary(ExternalSourcesDetails.getPreferenceSummary(mContext, entry));
|
||||
break;
|
||||
case LIST_TYPE_DIRECTORY_ACCESS:
|
||||
holder.setSummary(null);
|
||||
break;
|
||||
case LIST_TYPE_WIFI_ACCESS:
|
||||
holder.setSummary(ChangeWifiStateDetails.getSummary(mContext, entry));
|
||||
break;
|
||||
|
@@ -34,7 +34,6 @@ import com.android.settings.accounts.ChooseAccountFragment;
|
||||
import com.android.settings.accounts.ManagedProfileSettings;
|
||||
import com.android.settings.applications.AppAndNotificationDashboardFragment;
|
||||
import com.android.settings.applications.DefaultAppSettings;
|
||||
import com.android.settings.applications.DirectoryAccessDetails;
|
||||
import com.android.settings.applications.ProcessStatsSummary;
|
||||
import com.android.settings.applications.ProcessStatsUi;
|
||||
import com.android.settings.applications.UsageAccessDetails;
|
||||
@@ -258,7 +257,6 @@ public class SettingsGateway {
|
||||
LockscreenDashboardFragment.class.getName(),
|
||||
BluetoothDeviceDetailsFragment.class.getName(),
|
||||
DataUsageList.class.getName(),
|
||||
DirectoryAccessDetails.class.getName(),
|
||||
ToggleBackupSettingFragment.class.getName(),
|
||||
PreviouslyConnectedDeviceDashboardFragment.class.getName(),
|
||||
};
|
||||
|
@@ -15,7 +15,6 @@ com.android.settings.applications.appinfo.WriteSettingsDetails
|
||||
com.android.settings.applications.AppLaunchSettings
|
||||
com.android.settings.applications.AppStorageSettings
|
||||
com.android.settings.applications.ConfirmConvertToFbe
|
||||
com.android.settings.applications.DirectoryAccessDetails
|
||||
com.android.settings.applications.ProcessStatsDetail
|
||||
com.android.settings.applications.ProcessStatsSummary
|
||||
com.android.settings.applications.ProcessStatsUi
|
||||
|
@@ -166,7 +166,6 @@ Device name;device_name
|
||||
Device security;security_category
|
||||
Device theme;theme
|
||||
Dial pad tones;dial_pad_tones
|
||||
Directory access;special_app_directory_access
|
||||
Disable Bluetooth A2DP hardware offload;bluetooth_disable_a2dp_hw_offload
|
||||
Disable HW overlays;disable_overlays
|
||||
Disable USB audio routing;usb_audio
|
||||
@@ -620,4 +619,4 @@ Your access to this device;device_access_category
|
||||
;auto_brightness_video
|
||||
;battery_header
|
||||
;battery_tip
|
||||
;feature_flag_category
|
||||
;feature_flag_category
|
||||
|
Reference in New Issue
Block a user