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; 18 19 import static com.android.documentsui.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.State.ActionType; 30 import com.android.documentsui.State.ViewMode; 31 import com.android.documentsui.model.RootInfo; 32 33 import java.lang.annotation.Retention; 34 import java.lang.annotation.RetentionPolicy; 35 36 public class LocalPreferences { 37 private static final String KEY_FILE_SIZE = "fileSize"; 38 private static final String INCLUDE_DEVICE_ROOT = "includeDeviceRoot-"; 39 private static final String ROOT_VIEW_MODE_PREFIX = "rootViewMode-"; 40 getDisplayFileSize(Context context)41 public static boolean getDisplayFileSize(Context context) { 42 return getPrefs(context).getBoolean(KEY_FILE_SIZE, false); 43 } 44 getViewMode(Context context, RootInfo root, @ViewMode int fallback)45 public static @ViewMode int getViewMode(Context context, RootInfo root, 46 @ViewMode int fallback) { 47 return getPrefs(context).getInt(createKey(root), fallback); 48 } 49 setDisplayFileSize(Context context, boolean display)50 public static void setDisplayFileSize(Context context, boolean display) { 51 getPrefs(context).edit().putBoolean(KEY_FILE_SIZE, display).apply(); 52 } 53 getShowDeviceRoot(Context context, @ActionType int action)54 public static boolean getShowDeviceRoot(Context context, @ActionType int action) { 55 return getPrefs(context).getBoolean(INCLUDE_DEVICE_ROOT + action, false); 56 } 57 setShowDeviceRoot( Context context, @ActionType int action, boolean display)58 public static void setShowDeviceRoot( 59 Context context, @ActionType int action, boolean display) { 60 getPrefs(context).edit().putBoolean(INCLUDE_DEVICE_ROOT + action, display).apply(); 61 } 62 setViewMode(Context context, RootInfo root, @ViewMode int viewMode)63 public static void setViewMode(Context context, RootInfo root, @ViewMode int viewMode) { 64 assert(viewMode != MODE_UNKNOWN); 65 getPrefs(context).edit().putInt(createKey(root), viewMode).apply(); 66 } 67 getPrefs(Context context)68 private static SharedPreferences getPrefs(Context context) { 69 return PreferenceManager.getDefaultSharedPreferences(context); 70 } 71 createKey(RootInfo root)72 private static String createKey(RootInfo root) { 73 return ROOT_VIEW_MODE_PREFIX + root.authority + root.rootId; 74 } 75 76 public static final int PERMISSION_ASK = 0; 77 public static final int PERMISSION_ASK_AGAIN = 1; 78 public static final int PERMISSION_NEVER_ASK = -1; 79 80 @IntDef(flag = true, value = { 81 PERMISSION_ASK, 82 PERMISSION_ASK_AGAIN, 83 PERMISSION_NEVER_ASK, 84 }) 85 @Retention(RetentionPolicy.SOURCE) 86 public @interface PermissionStatus {} 87 88 /** 89 * Clears all preferences associated with a given package. 90 * 91 * <p>Typically called when a package is removed or when user asked to clear its data. 92 */ clearPackagePreferences(Context context, String packageName)93 static void clearPackagePreferences(Context context, String packageName) { 94 clearScopedAccessPreferences(context, packageName); 95 } 96 97 /** 98 * Methods below are used to keep track of denied user requests on scoped directory access so 99 * the dialog is not offered when user checked the 'Do not ask again' box 100 * 101 * <p>It uses a shared preferences, whose key is: 102 * <ol> 103 * <li>{@code USER_ID|PACKAGE_NAME|VOLUME_UUID|DIRECTORY} for storage volumes that have a UUID 104 * (typically physical volumes like SD cards). 105 * <li>{@code USER_ID|PACKAGE_NAME||DIRECTORY} for storage volumes that do not have a UUID 106 * (typically the emulated volume used for primary storage 107 * </ol> 108 */ getScopedAccessPermissionStatus(Context context, String packageName, @Nullable String uuid, String directory)109 static @PermissionStatus int getScopedAccessPermissionStatus(Context context, 110 String packageName, @Nullable String uuid, String directory) { 111 final String key = getScopedAccessDenialsKey(packageName, uuid, directory); 112 return getPrefs(context).getInt(key, PERMISSION_ASK); 113 } 114 setScopedAccessPermissionStatus(Context context, String packageName, @Nullable String uuid, String directory, @PermissionStatus int status)115 static void setScopedAccessPermissionStatus(Context context, String packageName, 116 @Nullable String uuid, String directory, @PermissionStatus int status) { 117 final String key = getScopedAccessDenialsKey(packageName, uuid, directory); 118 getPrefs(context).edit().putInt(key, status).apply(); 119 } 120 clearScopedAccessPreferences(Context context, String packageName)121 private static void clearScopedAccessPreferences(Context context, String packageName) { 122 final String keySubstring = "|" + packageName + "|"; 123 final SharedPreferences prefs = getPrefs(context); 124 Editor editor = null; 125 for (final String key : prefs.getAll().keySet()) { 126 if (key.contains(keySubstring)) { 127 if (editor == null) { 128 editor = prefs.edit(); 129 } 130 editor.remove(key); 131 } 132 } 133 if (editor != null) { 134 editor.apply(); 135 } 136 } 137 getScopedAccessDenialsKey(String packageName, String uuid, String directory)138 private static String getScopedAccessDenialsKey(String packageName, String uuid, 139 String directory) { 140 final int userId = UserHandle.myUserId(); 141 return uuid == null 142 ? userId + "|" + packageName + "||" + directory 143 : userId + "|" + packageName + "|" + uuid + "|" + directory; 144 } 145 } 146