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