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.policy; 18 19 import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.CLEARED; 20 import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.LOCKED; 21 import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.UNDEFINED; 22 import static com.android.devicelockcontroller.policy.DeviceStateController.DeviceState.UNLOCKED; 23 import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionEvent.PROVISION_SUCCESS; 24 import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.KIOSK_PROVISIONED; 25 import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.PROVISION_SUCCEEDED; 26 import static com.android.devicelockcontroller.policy.ProvisionStateController.ProvisionState.UNPROVISIONED; 27 28 import com.android.devicelockcontroller.storage.GlobalParametersClient; 29 30 import com.google.common.util.concurrent.Futures; 31 import com.google.common.util.concurrent.ListenableFuture; 32 import com.google.common.util.concurrent.MoreExecutors; 33 34 import java.util.concurrent.Executor; 35 36 /** An implementation of the {@link DeviceStateController} */ 37 public final class DeviceStateControllerImpl implements DeviceStateController { 38 private final ProvisionStateController mProvisionStateController; 39 private final DevicePolicyController mPolicyController; 40 private final GlobalParametersClient mGlobalParametersClient; 41 private final Executor mExecutor; 42 // Used to exercising APIs under CTS without actually applying any policies. 43 // This is not persistent across controller restarts, but should be good enough for the 44 // intended purpose. 45 private volatile @DeviceState int mPseudoDeviceState; 46 DeviceStateControllerImpl(DevicePolicyController policyController, ProvisionStateController provisionStateController, Executor executor)47 public DeviceStateControllerImpl(DevicePolicyController policyController, 48 ProvisionStateController provisionStateController, Executor executor) { 49 mPolicyController = policyController; 50 mProvisionStateController = provisionStateController; 51 mGlobalParametersClient = GlobalParametersClient.getInstance(); 52 mExecutor = executor; 53 mPseudoDeviceState = UNDEFINED; 54 } 55 56 @Override lockDevice()57 public ListenableFuture<Void> lockDevice() { 58 return setDeviceState(LOCKED); 59 } 60 61 @Override unlockDevice()62 public ListenableFuture<Void> unlockDevice() { 63 return setDeviceState(UNLOCKED); 64 } 65 66 @Override clearDevice()67 public ListenableFuture<Void> clearDevice() { 68 return setDeviceState(CLEARED); 69 } 70 71 /** 72 * Set the global device state to be the input {@link DeviceState}. The returned 73 * {@link ListenableFuture} will complete when both the state change and policies enforcement 74 * for new state are done. 75 */ setDeviceState(@eviceState int deviceState)76 private ListenableFuture<Void> setDeviceState(@DeviceState int deviceState) { 77 if (deviceState == UNDEFINED) { 78 throw new IllegalArgumentException("Cannot set device state to UNDEFINED"); 79 } 80 return Futures.transformAsync(mProvisionStateController.getState(), 81 provisionState -> { 82 final ListenableFuture<Void> maybeSetProvisioningSuccess; 83 if (provisionState == KIOSK_PROVISIONED) { 84 maybeSetProvisioningSuccess = 85 mProvisionStateController.setNextStateForEvent(PROVISION_SUCCESS); 86 } else if (provisionState == PROVISION_SUCCEEDED) { 87 maybeSetProvisioningSuccess = Futures.immediateVoidFuture(); 88 } else if (provisionState == UNPROVISIONED && (deviceState == LOCKED 89 || deviceState == UNLOCKED)) { 90 // During normal operation, we should not get lock/unlock requests in 91 // the UNPROVISIONED state. Used for CTS compliance. 92 mPseudoDeviceState = deviceState; 93 // Do not apply any policies 94 return Futures.immediateVoidFuture(); 95 } else { 96 throw new RuntimeException( 97 "User has not been provisioned! Current state " + provisionState); 98 } 99 return Futures.transformAsync(maybeSetProvisioningSuccess, 100 unused -> Futures.transformAsync(isCleared(), 101 isCleared -> { 102 if (isCleared) { 103 throw new IllegalStateException("Device has been " 104 + "cleared!"); 105 } 106 return Futures.transformAsync( 107 mGlobalParametersClient.setDeviceState(deviceState), 108 state -> mPolicyController.enforceCurrentPolicies(), 109 mExecutor); 110 }, mExecutor), 111 mExecutor); 112 }, mExecutor); 113 } 114 115 @Override 116 public ListenableFuture<Boolean> isLocked() { 117 return Futures.transformAsync(mProvisionStateController.getState(), 118 provisionState -> { 119 if (provisionState == UNPROVISIONED) { 120 // Used for CTS compliance. 121 return Futures.immediateFuture(mPseudoDeviceState == LOCKED); 122 } else { 123 return Futures.transform(mGlobalParametersClient.getDeviceState(), 124 s -> { 125 if (s == UNDEFINED) { 126 throw new IllegalStateException("isLocked called before " 127 + "setting the locked state " 128 + "(lockDevice/unlockDevice)"); 129 } 130 return s == LOCKED; 131 }, mExecutor); 132 } 133 }, mExecutor); 134 } 135 136 @Override 137 public ListenableFuture<Integer> getDeviceState() { 138 return mGlobalParametersClient.getDeviceState(); 139 } 140 141 @Override 142 public ListenableFuture<Boolean> isCleared() { 143 return Futures.transform(mGlobalParametersClient.getDeviceState(), 144 s -> s == CLEARED, MoreExecutors.directExecutor()); 145 } 146 } 147