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.storage; 18 19 import static com.android.devicelockcontroller.storage.IGlobalParametersService.Stub.asInterface; 20 21 import android.annotation.SuppressLint; 22 import android.content.ComponentName; 23 import android.content.Context; 24 25 import androidx.annotation.GuardedBy; 26 import androidx.annotation.NonNull; 27 import androidx.annotation.Nullable; 28 import androidx.annotation.VisibleForTesting; 29 30 import com.android.devicelockcontroller.DeviceLockControllerApplication; 31 import com.android.devicelockcontroller.common.DeviceLockConstants.DeviceProvisionState; 32 33 import com.google.common.util.concurrent.ListenableFuture; 34 import com.google.common.util.concurrent.ListeningExecutorService; 35 import com.google.common.util.concurrent.MoreExecutors; 36 37 import java.util.List; 38 import java.util.concurrent.Executors; 39 40 /** 41 * A class used to access Global Parameters from any user. 42 */ 43 public final class GlobalParametersClient extends DlcClient { 44 45 private static final Object sInstanceLock = new Object(); 46 47 @SuppressLint("StaticFieldLeak") // Only holds application context. 48 @GuardedBy("sInstanceLock") 49 private static GlobalParametersClient sClient; 50 GlobalParametersClient(@onNull Context context, ListeningExecutorService executorService)51 private GlobalParametersClient(@NonNull Context context, 52 ListeningExecutorService executorService) { 53 super(context, new ComponentName(context, GlobalParametersService.class), executorService); 54 } 55 56 /** 57 * Get the GlobalParametersClient singleton instance. 58 */ getInstance()59 public static GlobalParametersClient getInstance() { 60 return getInstance(DeviceLockControllerApplication.getAppContext(), 61 /* executorService= */ null); 62 } 63 64 /** 65 * Get the GlobalParametersClient singleton instance. 66 */ 67 @VisibleForTesting getInstance(Context appContext, @Nullable ListeningExecutorService executorService)68 public static GlobalParametersClient getInstance(Context appContext, 69 @Nullable ListeningExecutorService executorService) { 70 synchronized (sInstanceLock) { 71 if (sClient == null) { 72 sClient = new GlobalParametersClient( 73 appContext, 74 executorService == null 75 ? MoreExecutors.listeningDecorator(Executors.newCachedThreadPool()) 76 : executorService); 77 } 78 return sClient; 79 } 80 } 81 82 /** 83 * Reset the Client singleton instance 84 */ 85 @VisibleForTesting reset()86 public static void reset() { 87 synchronized (sInstanceLock) { 88 if (sClient != null) { 89 sClient.tearDown(); 90 sClient = null; 91 } 92 } 93 } 94 95 /** 96 * Clear any existing global parameters. 97 * Note that this API can only be called in debuggable build for debugging purpose. 98 */ 99 @SuppressWarnings("GuardedBy") // mLock already held in "call" (error prone). clear()100 public ListenableFuture<Void> clear() { 101 return call(() -> { 102 asInterface(getService()).clear(); 103 return null; 104 }); 105 } 106 107 /** 108 * Gets the list of packages allowlisted in lock task mode. 109 * 110 * @return List of packages that are allowed in lock task mode. 111 */ 112 @SuppressWarnings("GuardedBy") // mLock already held in "call" (error prone). getLockTaskAllowlist()113 public ListenableFuture<List<String>> getLockTaskAllowlist() { 114 return call(() -> asInterface(getService()).getLockTaskAllowlist()); 115 } 116 117 /** 118 * Sets the list of packages allowlisted in lock task mode. 119 * 120 * @param allowlist List of packages that are allowed in lock task mode. 121 */ 122 @SuppressWarnings("GuardedBy") // mLock already held in "call" (error prone). setLockTaskAllowlist(List<String> allowlist)123 public ListenableFuture<Void> setLockTaskAllowlist(List<String> allowlist) { 124 return call(() -> { 125 asInterface(getService()).setLockTaskAllowlist(allowlist); 126 return null; 127 }); 128 } 129 130 /** 131 * Checks if a check-in request needs to be performed. 132 * 133 * @return true if check-in request needs to be performed. 134 */ 135 @SuppressWarnings("GuardedBy") // mLock already held in "call" (error prone). 136 public ListenableFuture<Boolean> needCheckIn() { 137 return call(() -> asInterface(getService()).needCheckIn()); 138 } 139 140 /** 141 * Sets the value of whether this device needs to perform check-in request. 142 * 143 * @param needCheckIn new state of whether the device needs to perform check-in request. 144 */ 145 @SuppressWarnings("GuardedBy") // mLock already held in "call" (error prone). 146 public ListenableFuture<Void> setNeedCheckIn(boolean needCheckIn) { 147 return call(() -> { 148 asInterface(getService()).setNeedCheckIn(needCheckIn); 149 return null; 150 }); 151 } 152 153 /** 154 * Gets the unique identifier that is regisered to DeviceLock backend server. 155 * 156 * @return The registered device unique identifier; null if device has never checked in with 157 * backed server. 158 */ 159 @Nullable 160 @SuppressWarnings("GuardedBy") // mLock already held in "call" (error prone). 161 public ListenableFuture<String> getRegisteredDeviceId() { 162 return call(() -> asInterface(getService()).getRegisteredDeviceId()); 163 } 164 165 /** 166 * Set the unique identifier that is registered to DeviceLock backend server. 167 * 168 * @param registeredDeviceId The registered device unique identifier. 169 */ 170 @SuppressWarnings("GuardedBy") // mLock already held in "call" (error prone). 171 public ListenableFuture<Void> setRegisteredDeviceId(String registeredDeviceId) { 172 return call(() -> { 173 asInterface(getService()).setRegisteredDeviceId(registeredDeviceId); 174 return null; 175 }); 176 } 177 178 /** 179 * Check if provision should be forced. 180 * 181 * @return True if the provision should be forced without any delays. 182 */ 183 @SuppressWarnings("GuardedBy") // mLock already held in "call" (error prone). 184 public ListenableFuture<Boolean> isProvisionForced() { 185 return call(() -> asInterface(getService()).isProvisionForced()); 186 } 187 188 /** 189 * Set provision is forced 190 * 191 * @param isForced The new value of the forced provision flag. 192 */ 193 @SuppressWarnings("GuardedBy") // mLock already held in "call" (error prone). 194 public ListenableFuture<Void> setProvisionForced(boolean isForced) { 195 return call(() -> { 196 asInterface(getService()).setProvisionForced(isForced); 197 return null; 198 }); 199 } 200 201 /** 202 * Get the enrollment token assigned by the Device Lock backend server. 203 * 204 * @return A string value of the enrollment token. 205 */ 206 @Nullable 207 @SuppressWarnings("GuardedBy") // mLock already held in "call" (error prone). 208 public ListenableFuture<String> getEnrollmentToken() { 209 return call(() -> asInterface(getService()).getEnrollmentToken()); 210 } 211 212 /** 213 * Set the enrollment token assigned by the Device Lock backend server. 214 * 215 * @param token The string value of the enrollment token. 216 */ 217 @SuppressWarnings("GuardedBy") // mLock already held in "call" (error prone). 218 public ListenableFuture<Void> setEnrollmentToken(String token) { 219 return call(() -> { 220 asInterface(getService()).setEnrollmentToken(token); 221 return null; 222 }); 223 } 224 225 /** 226 * Get the kiosk app signature. 227 * 228 * @return the kiosk app signature. 229 */ 230 @Nullable 231 @SuppressWarnings("GuardedBy") // mLock already held in "call" (error prone). 232 public ListenableFuture<String> getKioskSignature() { 233 return call(() -> asInterface(getService()).getKioskSignature()); 234 } 235 236 /** 237 * Sets the kiosk app signature. 238 * 239 * @param signature Kiosk app signature. 240 */ 241 @SuppressWarnings("GuardedBy") // mLock already held in "call" (error prone). 242 public ListenableFuture<Void> setKioskSignature(String signature) { 243 return call(() -> { 244 asInterface(getService()).setKioskSignature(signature); 245 return null; 246 }); 247 } 248 249 /** 250 * Get the last received provision state determined by device lock server. 251 * 252 * @return one of {@link DeviceProvisionState}. 253 */ 254 public ListenableFuture<Integer> getLastReceivedProvisionState() { 255 return call(() -> asInterface(getService()).getLastReceivedProvisionState()); 256 } 257 258 /** 259 * Set the last received provision state determined by device lock server. 260 * 261 * @param provisionState The provision state determined by device lock server 262 */ 263 public ListenableFuture<Void> setLastReceivedProvisionState( 264 @DeviceProvisionState int provisionState) { 265 return call(() -> { 266 asInterface(getService()).setLastReceivedProvisionState(provisionState); 267 return null; 268 }); 269 } 270 } 271