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 android.content.Context;
20 import android.content.SharedPreferences;
21 import android.os.Build;
22 
23 import androidx.annotation.Nullable;
24 
25 import com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState;
26 import com.android.devicelockcontroller.policy.DeviceStateController.DeviceState;
27 import com.android.devicelockcontroller.policy.FinalizationControllerImpl.FinalizationState;
28 import com.android.devicelockcontroller.util.LogUtil;
29 
30 import java.util.Locale;
31 
32 /**
33  * Stores global parameters.
34  * <p>
35  * Note that, these parameter values are common across all users which means any users can read or
36  * write them. Due to this reason, unlike {@link UserParameters}, they must be accessed all the time
37  * via the {@link GlobalParametersClient}.
38  */
39 final class GlobalParameters {
40     private static final String FILENAME = "global-params";
41     private static final String KEY_REGISTERED_DEVICE_ID = "registered_device_id";
42     private static final String KEY_FORCED_PROVISION = "forced_provision";
43     private static final String KEY_LAST_RECEIVED_PROVISION_STATE = "last-received-provision-state";
44     private static final String TAG = "GlobalParameters";
45     private static final String KEY_DEVICE_STATE = "device_state";
46     private static final String KEY_FINALIZATION_STATE = "finalization_state";
47     public static final String KEY_IS_PROVISION_READY = "key-is-provision-ready";
48 
49 
GlobalParameters()50     private GlobalParameters() {
51     }
52 
getSharedPreferences(Context context)53     private static SharedPreferences getSharedPreferences(Context context) {
54         final Context deviceContext = context.createDeviceProtectedStorageContext();
55 
56         return deviceContext.getSharedPreferences(FILENAME, Context.MODE_PRIVATE);
57     }
58 
isProvisionReady(Context context)59     static boolean isProvisionReady(Context context) {
60         return getSharedPreferences(context).getBoolean(KEY_IS_PROVISION_READY, false);
61     }
62 
setProvisionReady(Context context, boolean isProvisionReady)63     static void setProvisionReady(Context context, boolean isProvisionReady) {
64         getSharedPreferences(context).edit().putBoolean(KEY_IS_PROVISION_READY,
65                 isProvisionReady).apply();
66     }
67 
68     /**
69      * Gets the unique identifier that is regisered to DeviceLock backend server.
70      *
71      * @param context Context used to get the shared preferences.
72      * @return The registered device unique identifier; null if device has never checked in with
73      * backed server.
74      */
75     @Nullable
getRegisteredDeviceId(Context context)76     static String getRegisteredDeviceId(Context context) {
77         SharedPreferences preferences = getSharedPreferences(context);
78         return preferences.getString(KEY_REGISTERED_DEVICE_ID, null);
79     }
80 
81     /**
82      * Set the unique identifier that is registered to DeviceLock backend server.
83      *
84      * @param context            Context used to get the shared preferences.
85      * @param registeredDeviceId The registered device unique identifier.
86      */
setRegisteredDeviceId(Context context, String registeredDeviceId)87     static void setRegisteredDeviceId(Context context, String registeredDeviceId) {
88         getSharedPreferences(context)
89                 .edit()
90                 .putString(KEY_REGISTERED_DEVICE_ID, registeredDeviceId)
91                 .apply();
92     }
93 
94     /**
95      * Check if provision should be forced.
96      *
97      * @param context Context used to get the shared preferences.
98      * @return True if the provision should be forced without any delays.
99      */
isProvisionForced(Context context)100     static boolean isProvisionForced(Context context) {
101         return getSharedPreferences(context).getBoolean(KEY_FORCED_PROVISION, false);
102     }
103 
104     /**
105      * Gets the current device state.
106      */
107     @DeviceState
getDeviceState(Context context)108     static int getDeviceState(Context context) {
109         return getSharedPreferences(context).getInt(KEY_DEVICE_STATE, DeviceState.UNDEFINED);
110     }
111 
112     /**
113      * Sets the current device state.
114      */
setDeviceState(Context context, @DeviceState int state)115     static void setDeviceState(Context context, @DeviceState int state) {
116         getSharedPreferences(context).edit().putInt(KEY_DEVICE_STATE, state).apply();
117     }
118 
119     /**
120      * Gets the current {@link FinalizationState}.
121      */
122     @FinalizationState
getFinalizationState(Context context)123     static int getFinalizationState(Context context) {
124         return getSharedPreferences(context).getInt(
125                 KEY_FINALIZATION_STATE, FinalizationState.UNFINALIZED);
126     }
127 
128     /**
129      * Sets the current {@link FinalizationState}.
130      */
setFinalizationState(Context context, @FinalizationState int state)131     static void setFinalizationState(Context context, @FinalizationState int state) {
132         getSharedPreferences(context).edit().putInt(KEY_FINALIZATION_STATE, state).apply();
133     }
134 
135     /**
136      * Set provision is forced
137      *
138      * @param context  Context used to get the shared preferences.
139      * @param isForced The new value of the forced provision flag.
140      */
setProvisionForced(Context context, boolean isForced)141     static void setProvisionForced(Context context, boolean isForced) {
142         getSharedPreferences(context)
143                 .edit()
144                 .putBoolean(KEY_FORCED_PROVISION, isForced)
145                 .apply();
146     }
147 
148     @DeviceProvisionState
getLastReceivedProvisionState(Context context)149     static int getLastReceivedProvisionState(Context context) {
150         return getSharedPreferences(context).getInt(KEY_LAST_RECEIVED_PROVISION_STATE,
151                 DeviceProvisionState.PROVISION_STATE_UNSPECIFIED);
152     }
153 
setLastReceivedProvisionState(Context context, @DeviceProvisionState int provisionState)154     static void setLastReceivedProvisionState(Context context,
155             @DeviceProvisionState int provisionState) {
156         getSharedPreferences(context)
157                 .edit()
158                 .putInt(KEY_LAST_RECEIVED_PROVISION_STATE, provisionState)
159                 .apply();
160     }
161 
clear(Context context)162     static void clear(Context context) {
163         if (!Build.isDebuggable()) {
164             throw new SecurityException("Clear is not allowed in non-debuggable build!");
165         }
166         getSharedPreferences(context).edit().clear().commit();
167     }
168 
dump(Context context)169     static void dump(Context context) {
170         LogUtil.d(TAG, String.format(Locale.US,
171                 "Dumping GlobalParameters ...\n"
172                         + "%s: %s\n"    // registered_device_id:
173                         + "%s: %s\n"    // forced_provision:
174                         + "%s: %s\n"    // last-received-provision-state:
175                         + "%s: %s\n"    // device_state:
176                         + "%s: %s\n",    // is-provision-ready:
177                 KEY_REGISTERED_DEVICE_ID, getRegisteredDeviceId(context),
178                 KEY_FORCED_PROVISION, isProvisionForced(context),
179                 KEY_LAST_RECEIVED_PROVISION_STATE, getLastReceivedProvisionState(context),
180                 KEY_DEVICE_STATE, getDeviceState(context),
181                 KEY_IS_PROVISION_READY, isProvisionReady(context)
182         ));
183     }
184 }
185