1 /* 2 * Copyright (C) 2013 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.documentsui.prefs; 18 19 import static com.android.documentsui.base.State.MODE_UNKNOWN; 20 21 import android.annotation.IntDef; 22 import android.annotation.Nullable; 23 import android.content.Context; 24 import android.content.SharedPreferences; 25 import android.content.SharedPreferences.Editor; 26 import android.os.UserHandle; 27 import android.preference.PreferenceManager; 28 29 import com.android.documentsui.base.RootInfo; 30 import com.android.documentsui.base.State; 31 import com.android.documentsui.base.State.ViewMode; 32 33 import java.lang.annotation.Retention; 34 import java.lang.annotation.RetentionPolicy; 35 36 public class LocalPreferences { 37 private static final String ROOT_VIEW_MODE_PREFIX = "rootViewMode-"; 38 39 public static @ViewMode int getViewMode(Context context, RootInfo root, 40 @ViewMode int fallback) { 41 return getPrefs(context).getInt(createKey(root), fallback); 42 } 43 44 public static void setViewMode(Context context, RootInfo root, @ViewMode int viewMode) { 45 assert(viewMode != MODE_UNKNOWN); 46 getPrefs(context).edit().putInt(createKey(root), viewMode).apply(); 47 } 48 49 private static SharedPreferences getPrefs(Context context) { 50 return PreferenceManager.getDefaultSharedPreferences(context); 51 } 52 53 private static String createKey(RootInfo root) { 54 return ROOT_VIEW_MODE_PREFIX + root.authority + root.rootId; 55 } 56 57 public static final int PERMISSION_ASK = 0; 58 public static final int PERMISSION_ASK_AGAIN = 1; 59 public static final int PERMISSION_NEVER_ASK = -1; 60 61 @IntDef(flag = true, value = { 62 PERMISSION_ASK, 63 PERMISSION_ASK_AGAIN, 64 PERMISSION_NEVER_ASK, 65 }) 66 @Retention(RetentionPolicy.SOURCE) 67 public @interface PermissionStatus {} 68 69 /** 70 * Clears all preferences associated with a given package. 71 * 72 * <p>Typically called when a package is removed or when user asked to clear its data. 73 */ 74 public static void clearPackagePreferences(Context context, String packageName) { 75 clearScopedAccessPreferences(context, packageName); 76 } 77 78 /** 79 * Methods below are used to keep track of denied user requests on scoped directory access so 80 * the dialog is not offered when user checked the 'Do not ask again' box 81 * 82 * <p>It uses a shared preferences, whose key is: 83 * <ol> 84 * <li>{@code USER_ID|PACKAGE_NAME|VOLUME_UUID|DIRECTORY} for storage volumes that have a UUID 85 * (typically physical volumes like SD cards). 86 * <li>{@code USER_ID|PACKAGE_NAME||DIRECTORY} for storage volumes that do not have a UUID 87 * (typically the emulated volume used for primary storage 88 * </ol> 89 */ 90 public static @PermissionStatus int getScopedAccessPermissionStatus(Context context, 91 String packageName, @Nullable String uuid, String directory) { 92 final String key = getScopedAccessDenialsKey(packageName, uuid, directory); 93 return getPrefs(context).getInt(key, PERMISSION_ASK); 94 } 95 96 public static void setScopedAccessPermissionStatus(Context context, String packageName, 97 @Nullable String uuid, String directory, @PermissionStatus int status) { 98 final String key = getScopedAccessDenialsKey(packageName, uuid, directory); 99 getPrefs(context).edit().putInt(key, status).apply(); 100 } 101 102 private static void clearScopedAccessPreferences(Context context, String packageName) { 103 final String keySubstring = "|" + packageName + "|"; 104 final SharedPreferences prefs = getPrefs(context); 105 Editor editor = null; 106 for (final String key : prefs.getAll().keySet()) { 107 if (key.contains(keySubstring)) { 108 if (editor == null) { 109 editor = prefs.edit(); 110 } 111 editor.remove(key); 112 } 113 } 114 if (editor != null) { 115 editor.apply(); 116 } 117 } 118 119 private static String getScopedAccessDenialsKey(String packageName, String uuid, 120 String directory) { 121 final int userId = UserHandle.myUserId(); 122 return uuid == null 123 ? userId + "|" + packageName + "||" + directory 124 : userId + "|" + packageName + "|" + uuid + "|" + directory; 125 } 126 127 public static boolean shouldBackup(String s) { 128 return (s != null) ? s.startsWith(ROOT_VIEW_MODE_PREFIX) : false; 129 } 130 } 131