• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.devicelockcontroller.debug;
18 
19 import static com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState.PROVISION_STATE_UNSPECIFIED;
20 import static com.android.devicelockcontroller.common.DeviceLockConstants.READY_FOR_PROVISION;
21 
22 import android.content.Context;
23 import android.content.SharedPreferences;
24 import android.os.SystemClock;
25 import android.util.ArraySet;
26 
27 import androidx.annotation.Keep;
28 import androidx.annotation.NonNull;
29 import androidx.annotation.Nullable;
30 
31 import com.android.devicelockcontroller.common.DeviceId;
32 import com.android.devicelockcontroller.common.DeviceLockConstants.DeviceCheckInStatus;
33 import com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState;
34 import com.android.devicelockcontroller.common.DeviceLockConstants.ProvisionFailureReason;
35 import com.android.devicelockcontroller.common.DeviceLockConstants.ProvisioningType;
36 import com.android.devicelockcontroller.provision.grpc.DeviceCheckInClient;
37 import com.android.devicelockcontroller.provision.grpc.GetDeviceCheckInStatusGrpcResponse;
38 import com.android.devicelockcontroller.provision.grpc.IsDeviceInApprovedCountryGrpcResponse;
39 import com.android.devicelockcontroller.provision.grpc.PauseDeviceProvisioningGrpcResponse;
40 import com.android.devicelockcontroller.provision.grpc.ProvisioningConfiguration;
41 import com.android.devicelockcontroller.provision.grpc.ReportDeviceProvisionStateGrpcResponse;
42 import com.android.devicelockcontroller.provision.grpc.UpdateFcmTokenGrpcResponse;
43 import com.android.devicelockcontroller.util.LogUtil;
44 import com.android.devicelockcontroller.util.ThreadAsserts;
45 
46 import java.time.Duration;
47 import java.time.Instant;
48 import java.util.List;
49 
50 /**
51  * An implementation of the {@link DeviceCheckInClient} which simulate server responses by
52  * reading it from local storage.
53  */
54 @Keep
55 public final class DeviceCheckInClientDebug extends DeviceCheckInClient {
56 
57     public static final String TAG = "DeviceCheckInClientDebug";
58     public static final String DEBUG_DEVICELOCK_CHECKIN_STATUS = "debug.devicelock.checkin.status";
59     public static final String DEBUG_DEVICELOCK_CHECKIN_RETRY_DELAY =
60             "debug.devicelock.checkin.retry-delay";
61     public static final String DEBUG_DEVICELOCK_CHECKIN_FORCE_PROVISIONING =
62             "debug.devicelock.checkin.force-provisioning";
63     public static final String DEBUG_DEVICELOCK_CHECKIN_APPROVED_COUNTRY =
64             "debug.devicelock.checkin.approved-country";
65     public static final String DEBUG_DEVICELOCK_CHECKIN_NEXT_PROVISION_STATE =
66             "debug.devicelock.checkin.next-provision-state";
67     public static final String DEBUG_DEVICELOCK_CHECKIN_DAYS_LEFT_UNTIL_RESET =
68             "debug.devicelock.checkin.days-left-until-reset";
69 
setDebugClientEnabled(Context context, boolean enabled)70     static void setDebugClientEnabled(Context context, boolean enabled) {
71         getSharedPreferences(context).edit().putBoolean(DEBUG_DEVICELOCK_CHECKIN, enabled).apply();
72     }
73 
setDebugCheckInStatus(Context context, @DeviceCheckInStatus int status)74     static void setDebugCheckInStatus(Context context, @DeviceCheckInStatus int status) {
75         getSharedPreferences(context).edit().putInt(DEBUG_DEVICELOCK_CHECKIN_STATUS,
76                 status).apply();
77     }
78 
setDebugForceProvisioning(Context context, boolean isForced)79     static void setDebugForceProvisioning(Context context, boolean isForced) {
80         getSharedPreferences(context).edit().putBoolean(DEBUG_DEVICELOCK_CHECKIN_FORCE_PROVISIONING,
81                 isForced).apply();
82     }
83 
setDebugCheckInRetryDelay(Context context, int delayMinute)84     static void setDebugCheckInRetryDelay(Context context, int delayMinute) {
85         getSharedPreferences(context).edit().putInt(DEBUG_DEVICELOCK_CHECKIN_RETRY_DELAY,
86                 delayMinute).apply();
87     }
88 
setDebugApprovedCountry(Context context, boolean isInApprovedCountry)89     static void setDebugApprovedCountry(Context context,
90             boolean isInApprovedCountry) {
91         getSharedPreferences(context).edit().putBoolean(DEBUG_DEVICELOCK_CHECKIN_APPROVED_COUNTRY,
92                 isInApprovedCountry).apply();
93     }
94 
setDebugNextProvisionState( Context context, @DeviceProvisionState int provisionState)95     static void setDebugNextProvisionState(
96             Context context, @DeviceProvisionState int provisionState) {
97         getSharedPreferences(context).edit().putInt(DEBUG_DEVICELOCK_CHECKIN_NEXT_PROVISION_STATE,
98                 provisionState).apply();
99     }
100 
setDebugDaysLeftUntilReset(Context context, int daysLeftUntilReset)101     static void setDebugDaysLeftUntilReset(Context context,
102             int daysLeftUntilReset) {
103         getSharedPreferences(context).edit().putInt(DEBUG_DEVICELOCK_CHECKIN_DAYS_LEFT_UNTIL_RESET,
104                 daysLeftUntilReset).apply();
105     }
106 
dumpDebugCheckInClientResponses(Context context)107     static void dumpDebugCheckInClientResponses(Context context) {
108         LogUtil.d(TAG,
109                 "Current Debug Client Responses:\n" + getSharedPreferences(context).getAll());
110     }
111 
clear(Context context)112     static void clear(Context context) {
113         getSharedPreferences(context).edit().clear().apply();
114     }
115 
getSharedPreference(String key, T defValue)116     private static <T> T getSharedPreference(String key, T defValue) {
117         SharedPreferences preferences = getSharedPreferences(/* context= */ null);
118         if (preferences == null) return defValue;
119         T value = (T) preferences.getAll().get(key);
120         return value == null ? defValue : value;
121     }
122 
123     /** Check In with DeviceLock backend server and get the next step for the device. */
124     @Override
getDeviceCheckInStatus( ArraySet<DeviceId> deviceIds, String carrierInfo, String deviceLocale, long deviceLockApexVersion, @Nullable String fcmRegistrationToken)125     public GetDeviceCheckInStatusGrpcResponse getDeviceCheckInStatus(
126             ArraySet<DeviceId> deviceIds,
127             String carrierInfo,
128             String deviceLocale,
129             long deviceLockApexVersion,
130             @Nullable String fcmRegistrationToken) {
131         ThreadAsserts.assertWorkerThread("getDeviceCheckInStatus");
132         return new GetDeviceCheckInStatusGrpcResponse() {
133             @Override
134             @DeviceCheckInStatus
135             public int getDeviceCheckInStatus() {
136                 return DebugLogUtil.logAndReturn(TAG,
137                         getSharedPreference(DEBUG_DEVICELOCK_CHECKIN_STATUS, READY_FOR_PROVISION));
138             }
139 
140             @Nullable
141             @Override
142             public String getRegisteredDeviceIdentifier() {
143                 return DebugLogUtil.logAndReturn(TAG,
144                         !deviceIds.isEmpty() ? deviceIds.valueAt(0).getId() : null);
145             }
146 
147             @Nullable
148             @Override
149             public Instant getNextCheckInTime() {
150                 Duration delay = Duration.ofMinutes(
151                         getSharedPreference(DEBUG_DEVICELOCK_CHECKIN_RETRY_DELAY, /* def= */ 1));
152                 return DebugLogUtil.logAndReturn(TAG,
153                         SystemClock.currentNetworkTimeClock().instant().plus(delay));
154             }
155 
156             @Nullable
157             @Override
158             public ProvisioningConfiguration getProvisioningConfig() {
159                 // This should be overridden using SetupParametersOverrider.
160                 return new ProvisioningConfiguration(
161                         /* kioskAppProviderName= */ "",
162                         /* kioskAppPackageName= */ "",
163                         /* kioskAppAllowlistPackages= */ List.of(""),
164                         /* kioskAppEnableOutgoingCalls= */ false,
165                         /* kioskAppEnableEnableNotifications= */ false,
166                         /* disallowInstallingFromUnknownSources= */ false,
167                         /* termsAndConditionsUrl= */ "",
168                         /* supportUrl= */ "");
169             }
170 
171             @Override
172             public @ProvisioningType int getProvisioningType() {
173                 // This should be overridden using SetupParametersOverrider.
174                 return ProvisioningType.TYPE_UNDEFINED;
175             }
176 
177             @Override
178             public boolean isProvisioningMandatory() {
179                 // This should be overridden using SetupParametersOverrider.
180                 return false;
181             }
182 
183             @Override
184             public boolean isProvisionForced() {
185                 return DebugLogUtil.logAndReturn(TAG,
186                         getSharedPreference(DEBUG_DEVICELOCK_CHECKIN_FORCE_PROVISIONING, false));
187             }
188 
189             @Override
190             public boolean isDeviceInApprovedCountry() {
191                 return DebugLogUtil.logAndReturn(TAG,
192                         getSharedPreference(DEBUG_DEVICELOCK_CHECKIN_APPROVED_COUNTRY, true));
193             }
194 
195             @Override
196             public boolean isDebuggingAllowed() {
197                 // This value should not matter since the device is already on a debug build and
198                 // can use debugging.
199                 return true;
200             }
201         };
202     }
203 
204     /**
205      * Check if the device is in an approved country for the device lock program.
206      */
207     @Override
208     public IsDeviceInApprovedCountryGrpcResponse isDeviceInApprovedCountry(
209             @Nullable String carrierInfo) {
210         ThreadAsserts.assertWorkerThread("isDeviceInApprovedCountry");
211         return new IsDeviceInApprovedCountryGrpcResponse() {
212             @Override
213             public boolean isDeviceInApprovedCountry() {
214                 return DebugLogUtil.logAndReturn(TAG,
215                         getSharedPreference(DEBUG_DEVICELOCK_CHECKIN_APPROVED_COUNTRY, true));
216             }
217         };
218     }
219 
220     /**
221      * Inform the server that device provisioning has been paused for a certain amount of time.
222      */
223     @Override
224     public PauseDeviceProvisioningGrpcResponse pauseDeviceProvisioning(int reason) {
225         ThreadAsserts.assertWorkerThread("pauseDeviceProvisioning");
226         return new PauseDeviceProvisioningGrpcResponse();
227     }
228 
229     /**
230      * Reports the current provision state of the device.
231      */
232     @Override
233     public ReportDeviceProvisionStateGrpcResponse reportDeviceProvisionState(
234             int lastReceivedProvisionState, boolean isSuccessful,
235             @ProvisionFailureReason int reason) {
236         ThreadAsserts.assertWorkerThread("reportDeviceProvisionState");
237         return new ReportDeviceProvisionStateGrpcResponse() {
238             @Override
239             @DeviceProvisionState
240             public int getNextClientProvisionState() {
241                 return DebugLogUtil.logAndReturn(TAG, getSharedPreference(
242                         DEBUG_DEVICELOCK_CHECKIN_NEXT_PROVISION_STATE,
243                         PROVISION_STATE_UNSPECIFIED));
244             }
245 
246             @Override
247             public int getDaysLeftUntilReset() {
248                 return DebugLogUtil.logAndReturn(TAG,
249                         getSharedPreference(
250                                 DEBUG_DEVICELOCK_CHECKIN_DAYS_LEFT_UNTIL_RESET, /* def= */ 1));
251             }
252         };
253     }
254 
255     @Override
256     public UpdateFcmTokenGrpcResponse updateFcmToken(ArraySet<DeviceId> deviceIds,
257             @NonNull String fcmRegistrationToken) {
258         ThreadAsserts.assertWorkerThread("updateFcmToken");
259         return new UpdateFcmTokenGrpcResponse() {
260             @Override
261             public int getFcmTokenResult() {
262                 return FcmTokenResult.RESULT_SUCCESS;
263             }
264         };
265     }
266 }
267