/* * 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_DIRECTORY; import static android.os.storage.StorageVolume.ScopedAccessProviderContract.COL_GRANTED; import static android.os.storage.StorageVolume.ScopedAccessProviderContract.COL_PACKAGE; import static android.os.storage.StorageVolume.ScopedAccessProviderContract.COL_VOLUME_UUID; 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.app.AlertDialog; 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.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; import android.util.ArrayMap; import android.util.ArraySet; import android.util.IconDrawableFactory; import android.util.Log; import android.util.Pair; 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). * *
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. * *
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(), getLifecycle())
.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