• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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.devicelockcontroller.storage;
18 
19 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_ALLOW_DEBUGGING;
20 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_DISALLOW_INSTALLING_FROM_UNKNOWN_SOURCES;
21 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_ALLOWLIST;
22 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_APP_PROVIDER_NAME;
23 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_DISABLE_OUTGOING_CALLS;
24 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_ENABLE_NOTIFICATIONS_IN_LOCK_TASK_MODE;
25 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_KIOSK_PACKAGE;
26 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_MANDATORY_PROVISION;
27 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_PROVISIONING_TYPE;
28 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_SUPPORT_URL;
29 import static com.android.devicelockcontroller.common.DeviceLockConstants.EXTRA_TERMS_AND_CONDITIONS_URL;
30 import static com.android.devicelockcontroller.common.DeviceLockConstants.ProvisioningType.TYPE_UNDEFINED;
31 
32 import android.content.Context;
33 import android.content.SharedPreferences;
34 import android.os.Build;
35 import android.os.Bundle;
36 import android.util.ArraySet;
37 
38 import androidx.annotation.Nullable;
39 
40 import com.android.devicelockcontroller.common.DeviceLockConstants.ProvisioningType;
41 import com.android.devicelockcontroller.util.LogUtil;
42 
43 import com.google.common.collect.ImmutableList;
44 
45 import java.util.Locale;
46 import java.util.Set;
47 
48 /**
49  * Stores setup parameters.
50  * <p>
51  * Note that these parameters are created by the system user at the setup time and must not be
52  * written afterwards.
53  * <p>
54  * Also, these parameters are accessed globally by all users and must be accessed all the time via
55  * the {@link SetupParametersClient}.
56  */
57 final class SetupParameters {
58     private static final String TAG = "SetupParameters";
59     private static final String FILENAME = "setup-prefs";
60     private static final String KEY_KIOSK_PACKAGE = "kiosk-package-name";
61     private static final String KEY_KIOSK_ALLOWLIST = "kiosk-allowlist";
62     private static final String KEY_KIOSK_DISABLE_OUTGOING_CALLS =
63             "kiosk-disable-outgoing-calls";
64     private static final String KEY_KIOSK_ENABLE_NOTIFICATIONS_IN_LOCK_TASK_MODE =
65             "kiosk-enable-notifications-in-lock-task-mode";
66     private static final String KEY_ALLOW_DEBUGGING = "allow-debugging";
67     private static final String KEY_PROVISIONING_TYPE = "provisioning-type";
68     private static final String KEY_MANDATORY_PROVISION = "mandatory-provision";
69     private static final String KEY_KIOSK_APP_PROVIDER_NAME = "kiosk-app-provider-name";
70     private static final String KEY_DISALLOW_INSTALLING_FROM_UNKNOWN_SOURCES =
71             "disallow-installing-from-unknown-sources";
72     private static final String KEY_TERMS_AND_CONDITIONS_URL =
73             "terms-and-conditions-url";
74     private static final String KEY_SUPPORT_URL = "support-url";
75 
SetupParameters()76     private SetupParameters() {
77     }
78 
getSharedPreferences(Context context)79     private static SharedPreferences getSharedPreferences(Context context) {
80         Context deviceContext = context.createDeviceProtectedStorageContext();
81         return deviceContext.getSharedPreferences(FILENAME, Context.MODE_PRIVATE);
82     }
83 
84     // Note that this API is only used for debugging purpose and should only be called in
85     // debuggable build.
overridePrefs(Context context, Bundle bundle)86     static synchronized void overridePrefs(Context context, Bundle bundle) {
87         if (!Build.isDebuggable()) {
88             throw new SecurityException(
89                     "Setup parameters is not allowed to be override in non-debuggable build!");
90         }
91         populatePreferencesLocked(getSharedPreferences(context), bundle);
92         dumpParameters(context);
93     }
94 
dumpParameters(Context context)95     static void dumpParameters(Context context) {
96         LogUtil.d(TAG, String.format(Locale.US,
97                 "Dumping SetupParameters ...\n"
98                 + "%s: %s\n"    // kiosk-package-name:
99                 + "%s: %s\n"    // kiosk-allowlist:
100                 + "%s: %s\n"    // kiosk-disable-outgoing-calls:
101                 + "%s: %s\n"    // kiosk-enable-notifications-in-lock-task-mode:
102                 + "%s: %s\n"    // allow-debugging:
103                 + "%s: %d\n"    // provisioning-type:
104                 + "%s: %s\n"    // mandatory-provision:
105                 + "%s: %s\n"    // kiosk-app-provider-name:
106                 + "%s: %s\n"    // disallow-installing-from-unknown-sources:
107                 + "%s: %s\n"    // terms-and-conditions-url:
108                 + "%s: %s\n",   // support-url:
109                 KEY_KIOSK_PACKAGE, getKioskPackage(context),
110                 KEY_KIOSK_ALLOWLIST, getKioskAllowlist(context),
111                 KEY_KIOSK_DISABLE_OUTGOING_CALLS, getOutgoingCallsDisabled(context),
112                 KEY_KIOSK_ENABLE_NOTIFICATIONS_IN_LOCK_TASK_MODE,
113                 isNotificationsInLockTaskModeEnabled(context),
114                 KEY_ALLOW_DEBUGGING, isDebuggingAllowed(context),
115                 KEY_PROVISIONING_TYPE, getProvisioningType(context),
116                 KEY_MANDATORY_PROVISION, isProvisionMandatory(context),
117                 KEY_KIOSK_APP_PROVIDER_NAME, getKioskAppProviderName(context),
118                 KEY_DISALLOW_INSTALLING_FROM_UNKNOWN_SOURCES,
119                 isInstallingFromUnknownSourcesDisallowed(context),
120                 KEY_TERMS_AND_CONDITIONS_URL, getTermsAndConditionsUrl(context),
121                 KEY_SUPPORT_URL, getSupportUrl(context)
122         ));
123     }
124 
125     /**
126      * Parse setup parameters from the extras bundle.
127      *
128      * @param context Application context
129      * @param bundle  Bundle with provisioning parameters.
130      */
createPrefs(Context context, Bundle bundle)131     static synchronized void createPrefs(Context context, Bundle bundle) {
132         SharedPreferences sharedPreferences = getSharedPreferences(context);
133         if (sharedPreferences.contains(KEY_KIOSK_PACKAGE)) {
134             LogUtil.i(TAG, "Setup parameters are already populated");
135 
136             return;
137         }
138         populatePreferencesLocked(sharedPreferences, bundle);
139     }
140 
populatePreferencesLocked(SharedPreferences sharedPreferences, Bundle bundle)141     private static void populatePreferencesLocked(SharedPreferences sharedPreferences,
142             Bundle bundle) {
143 
144         SharedPreferences.Editor editor = sharedPreferences.edit();
145         editor.putString(KEY_KIOSK_PACKAGE, bundle.getString(EXTRA_KIOSK_PACKAGE));
146         editor.putBoolean(KEY_KIOSK_DISABLE_OUTGOING_CALLS,
147                 bundle.getBoolean(EXTRA_KIOSK_DISABLE_OUTGOING_CALLS));
148         editor.putBoolean(KEY_KIOSK_ENABLE_NOTIFICATIONS_IN_LOCK_TASK_MODE,
149                 bundle.getBoolean(EXTRA_KIOSK_ENABLE_NOTIFICATIONS_IN_LOCK_TASK_MODE));
150         editor.putStringSet(KEY_KIOSK_ALLOWLIST,
151                 new ArraySet<>(bundle.getStringArrayList(EXTRA_KIOSK_ALLOWLIST)));
152         editor.putInt(KEY_PROVISIONING_TYPE, bundle.getInt(EXTRA_PROVISIONING_TYPE));
153         editor.putBoolean(KEY_MANDATORY_PROVISION, bundle.getBoolean(EXTRA_MANDATORY_PROVISION));
154         editor.putBoolean(KEY_ALLOW_DEBUGGING, bundle.getBoolean(EXTRA_ALLOW_DEBUGGING));
155         editor.putString(KEY_KIOSK_APP_PROVIDER_NAME,
156                 bundle.getString(EXTRA_KIOSK_APP_PROVIDER_NAME));
157         editor.putBoolean(KEY_DISALLOW_INSTALLING_FROM_UNKNOWN_SOURCES,
158                 bundle.getBoolean(EXTRA_DISALLOW_INSTALLING_FROM_UNKNOWN_SOURCES));
159         editor.putString(KEY_TERMS_AND_CONDITIONS_URL,
160                 bundle.getString(EXTRA_TERMS_AND_CONDITIONS_URL));
161         editor.putString(KEY_SUPPORT_URL, bundle.getString(EXTRA_SUPPORT_URL));
162         editor.apply();
163     }
164 
165     /**
166      * Get the name of the package implementing the kiosk app.
167      *
168      * @param context Context used to get the shared preferences.
169      * @return kiosk app package name.
170      */
171     @Nullable
getKioskPackage(Context context)172     static String getKioskPackage(Context context) {
173         return getSharedPreferences(context).getString(KEY_KIOSK_PACKAGE, null /* defValue */);
174     }
175 
176     /**
177      * Check if the configuration disables outgoing calls.
178      *
179      * @param context Context used to get the shared preferences.
180      * @return True if outgoing calls are disabled.
181      */
getOutgoingCallsDisabled(Context context)182     static boolean getOutgoingCallsDisabled(Context context) {
183         return getSharedPreferences(context)
184                 .getBoolean(KEY_KIOSK_DISABLE_OUTGOING_CALLS, false /* defValue */);
185     }
186 
187     /**
188      * Get package allowlist provisioned by the server.
189      *
190      * @param context Context used to get the shared preferences.
191      * @return List of allowed packages.
192      */
getKioskAllowlist(Context context)193     static ImmutableList<String> getKioskAllowlist(Context context) {
194         SharedPreferences sharedPreferences = getSharedPreferences(context);
195         Set<String> allowlistSet =
196                 sharedPreferences.getStringSet(KEY_KIOSK_ALLOWLIST, null /* defValue */);
197         return allowlistSet == null ? ImmutableList.of() : ImmutableList.copyOf(allowlistSet);
198     }
199 
200     /**
201      * Check if notifications are enabled in lock task mode.
202      *
203      * @param context Context used to get the shared preferences.
204      * @return True if notification are enabled.
205      */
isNotificationsInLockTaskModeEnabled(Context context)206     static boolean isNotificationsInLockTaskModeEnabled(Context context) {
207         return getSharedPreferences(context)
208                 .getBoolean(KEY_KIOSK_ENABLE_NOTIFICATIONS_IN_LOCK_TASK_MODE, false /* defValue */);
209     }
210 
211     /**
212      * Check if adb debugging is allowed even on prod devices.
213      *
214      * @param context Context used to get the shared preferences.
215      * @return True if adb debugging is allowed.
216      */
isDebuggingAllowed(Context context)217     static boolean isDebuggingAllowed(Context context) {
218         return getSharedPreferences(context).getBoolean(KEY_ALLOW_DEBUGGING, false /* defValue */);
219     }
220 
221     /**
222      * Get the provisioning type of this configuration.
223      *
224      * @param context Context used to get the shared preferences.
225      * @return The type of provisioning which could be one of {@link ProvisioningType}.
226      */
227     @ProvisioningType
getProvisioningType(Context context)228     static int getProvisioningType(Context context) {
229         return getSharedPreferences(context).getInt(KEY_PROVISIONING_TYPE, TYPE_UNDEFINED);
230     }
231 
232     /**
233      * Check if provision is mandatory.
234      *
235      * @param context Context used to get the shared preferences.
236      * @return True if the provision should be mandatory.
237      */
isProvisionMandatory(Context context)238     static boolean isProvisionMandatory(Context context) {
239         return getSharedPreferences(context).getBoolean(KEY_MANDATORY_PROVISION, false);
240     }
241 
242     /**
243      * Get the name of the provider of the kiosk app.
244      *
245      * @param context Context used to get the shared preferences.
246      * @return the name of the provider.
247      */
248     @Nullable
getKioskAppProviderName(Context context)249     static String getKioskAppProviderName(Context context) {
250         return getSharedPreferences(context).getString(KEY_KIOSK_APP_PROVIDER_NAME,
251                 null /* defValue */);
252     }
253 
254     /**
255      * Check if installing from unknown sources should be disallowed on this device after provision
256      *
257      * @param context Context used to get the shared preferences.
258      * @return True if installing from unknown sources is disallowed.
259      */
isInstallingFromUnknownSourcesDisallowed(Context context)260     static boolean isInstallingFromUnknownSourcesDisallowed(Context context) {
261         return getSharedPreferences(context).getBoolean(
262                 KEY_DISALLOW_INSTALLING_FROM_UNKNOWN_SOURCES, /* defValue= */ false);
263     }
264 
265     /**
266      * Get the URL to the terms and conditions of the partner for enrolling in a Device Lock
267      * program.
268      *
269      * @param context Context used to get the shared preferences.
270      * @return The URL to the terms and conditions.
271      */
272     @Nullable
getTermsAndConditionsUrl(Context context)273     static String getTermsAndConditionsUrl(Context context) {
274         return getSharedPreferences(context).getString(
275                 KEY_TERMS_AND_CONDITIONS_URL, /* defValue= */ null);
276     }
277 
278     /**
279      * The URL to the support page the user can use to get help.
280      *
281      * @param context Context used to get the shared preferences.
282      * @return The URL to the support page.
283      */
284     @Nullable
getSupportUrl(Context context)285     static String getSupportUrl(Context context) {
286         return getSharedPreferences(context).getString(
287                 KEY_SUPPORT_URL, /* defValue= */ null);
288     }
289 
clear(Context context)290     static void clear(Context context) {
291         if (!Build.isDebuggable()) {
292             throw new SecurityException("Clear is not allowed in non-debuggable build!");
293         }
294         getSharedPreferences(context).edit().clear().commit();
295     }
296 }
297