1 /*
2  * Copyright (C) 2023 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.role.controller.util;
18 
19 import android.annotation.TargetApi;
20 import android.content.Context;
21 import android.content.SharedPreferences;
22 import android.content.pm.PackageManager;
23 import android.os.Build;
24 import android.os.UserHandle;
25 
26 import androidx.annotation.NonNull;
27 
28 import java.util.ArrayList;
29 import java.util.List;
30 
31 public class LegacyRoleFallbackEnabledUtils {
32     /**
33      * Name of generic shared preferences file.
34      */
35     private static final String PREFERENCES_FILE = "preferences";
36 
37     /**
38      * Key in the generic shared preferences that stores if the user manually selected the "none"
39      * role holder for a role.
40      */
41     private static final String IS_NONE_ROLE_HOLDER_SELECTED_KEY = "is_none_role_holder_selected:";
42 
43     /**
44      * Get a device protected storage based shared preferences. Avoid storing sensitive data in it.
45      *
46      * @param context the context to get the shared preferences
47      * @return a device protected storage based shared preferences
48      */
49     @NonNull
50     @TargetApi(Build.VERSION_CODES.VANILLA_ICE_CREAM)
getSharedPreferences(@onNull UserHandle user, @NonNull Context context)51     private static SharedPreferences getSharedPreferences(@NonNull UserHandle user,
52             @NonNull Context context) {
53         String packageName = context.getPackageManager().getPermissionControllerPackageName();
54         try {
55             context = context.createPackageContextAsUser(packageName, 0, user);
56         } catch (PackageManager.NameNotFoundException e) {
57             throw new RuntimeException(e);
58         }
59         if (!context.isDeviceProtectedStorage()) {
60             context = context.createDeviceProtectedStorageContext();
61         }
62         return context.getSharedPreferences(PREFERENCES_FILE, Context.MODE_PRIVATE);
63     }
64 
65     /**
66      * Get all role names with fallback disabled, which means their "none" are set to true.
67      *
68      * @return A list of role names with fallback disabled.
69      */
getFallbackDisabledRoles(@onNull UserHandle user, @NonNull Context context)70     public static List<String> getFallbackDisabledRoles(@NonNull UserHandle user,
71             @NonNull Context context) {
72         List<String> fallbackDisabledRoles = new ArrayList<>();
73         SharedPreferences sharedPreferences = getSharedPreferences(user, context);
74         for (String key : sharedPreferences.getAll().keySet()) {
75             if (key.startsWith(IS_NONE_ROLE_HOLDER_SELECTED_KEY)
76                     && sharedPreferences.getBoolean(key, false)) {
77                 String roleName = key.substring(IS_NONE_ROLE_HOLDER_SELECTED_KEY.length());
78                 fallbackDisabledRoles.add(roleName);
79             }
80         }
81         return fallbackDisabledRoles;
82     }
83 
84     /**
85      * Check whether the role has the fallback holder enabled.
86      *
87      * @return whether the "none" role holder is not selected
88      */
isRoleFallbackEnabledAsUser(@onNull String roleName, @NonNull UserHandle user, @NonNull Context context)89     public static boolean isRoleFallbackEnabledAsUser(@NonNull String roleName,
90             @NonNull UserHandle user, @NonNull Context context) {
91         return !getSharedPreferences(user, context)
92                 .getBoolean(IS_NONE_ROLE_HOLDER_SELECTED_KEY + roleName, false);
93     }
94 
95     /**
96      * Set whether the role has fallback holder enabled.
97      */
setRoleFallbackEnabledAsUser(@onNull String roleName, boolean fallbackEnabled, @NonNull UserHandle user, @NonNull Context context)98     public static void setRoleFallbackEnabledAsUser(@NonNull String roleName,
99             boolean fallbackEnabled, @NonNull UserHandle user, @NonNull Context context) {
100         String key = IS_NONE_ROLE_HOLDER_SELECTED_KEY + roleName;
101         if (fallbackEnabled) {
102             getSharedPreferences(user, context).edit().remove(key).apply();
103         } else {
104             getSharedPreferences(user, context).edit().putBoolean(key, true).apply();
105         }
106     }
107 }
108