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.server.biometrics.log; 18 19 import android.annotation.NonNull; 20 import android.annotation.Nullable; 21 import android.content.Intent; 22 import android.hardware.biometrics.AuthenticateOptions; 23 import android.hardware.biometrics.BiometricAuthenticator; 24 import android.hardware.biometrics.IBiometricContextListener; 25 import android.hardware.biometrics.common.AuthenticateReason; 26 import android.hardware.biometrics.common.DisplayState; 27 import android.hardware.biometrics.common.FoldState; 28 import android.hardware.biometrics.common.OperationContext; 29 import android.hardware.biometrics.common.OperationReason; 30 import android.hardware.biometrics.common.OperationState; 31 import android.hardware.biometrics.common.WakeReason; 32 import android.hardware.face.FaceAuthenticateOptions; 33 import android.hardware.fingerprint.FingerprintAuthenticateOptions; 34 import android.os.PowerManager; 35 import android.view.Surface; 36 37 /** 38 * Wrapper around {@link OperationContext} to include properties that are not 39 * shared with the HAL. 40 * 41 * When useful, these properties should move to the wrapped object for use by HAL in 42 * future releases. 43 */ 44 public class OperationContextExt { 45 46 @NonNull private final OperationContext mAidlContext; 47 @Nullable private BiometricContextSessionInfo mSessionInfo; 48 private boolean mIsDisplayOn = false; 49 private int mDockState = Intent.EXTRA_DOCK_STATE_UNDOCKED; 50 @Surface.Rotation private int mOrientation = Surface.ROTATION_0; 51 private int mFoldState = IBiometricContextListener.FoldState.UNKNOWN; 52 private final boolean mIsBP; 53 private final boolean mIsMandatoryBiometrics; 54 55 /** Create a context. */ OperationContextExt(boolean isBP)56 public OperationContextExt(boolean isBP) { 57 this(new OperationContext(), isBP, BiometricAuthenticator.TYPE_NONE); 58 } 59 OperationContextExt(boolean isBP, boolean isMandatoryBiometrics)60 public OperationContextExt(boolean isBP, boolean isMandatoryBiometrics) { 61 this(new OperationContext(), isBP, BiometricAuthenticator.TYPE_NONE, isMandatoryBiometrics); 62 } 63 OperationContextExt(boolean isBP, @BiometricAuthenticator.Modality int modality, boolean isMandatoryBiometrics)64 public OperationContextExt(boolean isBP, @BiometricAuthenticator.Modality int modality, 65 boolean isMandatoryBiometrics) { 66 this(new OperationContext(), isBP, modality, isMandatoryBiometrics); 67 } 68 69 /** Create a wrapped context. */ OperationContextExt(@onNull OperationContext context, boolean isBP, @BiometricAuthenticator.Modality int modality)70 public OperationContextExt(@NonNull OperationContext context, boolean isBP, 71 @BiometricAuthenticator.Modality int modality) { 72 this(context, isBP, modality, false /* isMandatoryBiometrics */); 73 } 74 OperationContextExt(@onNull OperationContext context, boolean isBP, @BiometricAuthenticator.Modality int modality, boolean isMandatoryBiometrics)75 public OperationContextExt(@NonNull OperationContext context, boolean isBP, 76 @BiometricAuthenticator.Modality int modality, boolean isMandatoryBiometrics) { 77 mAidlContext = context; 78 mIsBP = isBP; 79 mIsMandatoryBiometrics = isMandatoryBiometrics; 80 81 if (modality == BiometricAuthenticator.TYPE_FINGERPRINT) { 82 mAidlContext.operationState = OperationState.fingerprintOperationState( 83 new OperationState.FingerprintOperationState()); 84 } else if (modality == BiometricAuthenticator.TYPE_FACE) { 85 mAidlContext.operationState = OperationState.faceOperationState( 86 new OperationState.FaceOperationState()); 87 } 88 } 89 90 /** 91 * Gets the subset of the context that can be shared with the HAL. 92 * 93 * When starting a new operation use methods like to update & fetch the context: 94 * <ul> 95 * <li>{@link #toAidlContext(FaceAuthenticateOptions)} 96 * <li>{@link #toAidlContext(FingerprintAuthenticateOptions)} 97 * </ul> 98 * 99 * Use this method for any subsequent calls to the HAL or for operations that do 100 * not accept any options. 101 * 102 * @return the underlying AIDL context 103 */ 104 @NonNull toAidlContext()105 public OperationContext toAidlContext() { 106 return mAidlContext; 107 } 108 109 /** 110 * Gets the subset of the context that can be shared with the HAL and updates 111 * it with the given options. 112 * 113 * @param options authenticate options 114 * @return the underlying AIDL context 115 */ 116 @NonNull toAidlContext(@onNull AuthenticateOptions options)117 public OperationContext toAidlContext(@NonNull AuthenticateOptions options) { 118 if (options instanceof FaceAuthenticateOptions) { 119 return toAidlContext((FaceAuthenticateOptions) options); 120 } 121 if (options instanceof FingerprintAuthenticateOptions) { 122 return toAidlContext((FingerprintAuthenticateOptions) options); 123 } 124 throw new IllegalStateException("Authenticate options are invalid."); 125 } 126 127 /** 128 * Gets the subset of the context that can be shared with the HAL and updates 129 * it with the given options. 130 * 131 * @param options authenticate options 132 * @return the underlying AIDL context 133 */ 134 @NonNull toAidlContext(@onNull FaceAuthenticateOptions options)135 public OperationContext toAidlContext(@NonNull FaceAuthenticateOptions options) { 136 mAidlContext.authenticateReason = AuthenticateReason 137 .faceAuthenticateReason(getAuthReason(options)); 138 mAidlContext.wakeReason = getWakeReason(options); 139 140 return mAidlContext; 141 } 142 143 /** 144 * Gets the subset of the context that can be shared with the HAL and updates 145 * it with the given options. 146 * 147 * @param options authenticate options 148 * @return the underlying AIDL context 149 */ 150 @NonNull toAidlContext(@onNull FingerprintAuthenticateOptions options)151 public OperationContext toAidlContext(@NonNull FingerprintAuthenticateOptions options) { 152 if (options.getVendorReason() != null) { 153 mAidlContext.authenticateReason = AuthenticateReason 154 .vendorAuthenticateReason(options.getVendorReason()); 155 156 } else { 157 mAidlContext.authenticateReason = AuthenticateReason 158 .fingerprintAuthenticateReason(getAuthReason(options)); 159 } 160 mAidlContext.wakeReason = getWakeReason(options); 161 162 return mAidlContext; 163 } 164 165 @AuthenticateReason.Face getAuthReason(@onNull FaceAuthenticateOptions options)166 private int getAuthReason(@NonNull FaceAuthenticateOptions options) { 167 switch (options.getAuthenticateReason()) { 168 case FaceAuthenticateOptions.AUTHENTICATE_REASON_STARTED_WAKING_UP: 169 return AuthenticateReason.Face.STARTED_WAKING_UP; 170 case FaceAuthenticateOptions.AUTHENTICATE_REASON_PRIMARY_BOUNCER_SHOWN: 171 return AuthenticateReason.Face.PRIMARY_BOUNCER_SHOWN; 172 case FaceAuthenticateOptions.AUTHENTICATE_REASON_ASSISTANT_VISIBLE: 173 return AuthenticateReason.Face.ASSISTANT_VISIBLE; 174 case FaceAuthenticateOptions.AUTHENTICATE_REASON_ALTERNATE_BIOMETRIC_BOUNCER_SHOWN: 175 return AuthenticateReason.Face.ALTERNATE_BIOMETRIC_BOUNCER_SHOWN; 176 case FaceAuthenticateOptions.AUTHENTICATE_REASON_NOTIFICATION_PANEL_CLICKED: 177 return AuthenticateReason.Face.NOTIFICATION_PANEL_CLICKED; 178 case FaceAuthenticateOptions.AUTHENTICATE_REASON_OCCLUDING_APP_REQUESTED: 179 return AuthenticateReason.Face.OCCLUDING_APP_REQUESTED; 180 case FaceAuthenticateOptions.AUTHENTICATE_REASON_PICK_UP_GESTURE_TRIGGERED: 181 return AuthenticateReason.Face.PICK_UP_GESTURE_TRIGGERED; 182 case FaceAuthenticateOptions.AUTHENTICATE_REASON_QS_EXPANDED: 183 return AuthenticateReason.Face.QS_EXPANDED; 184 case FaceAuthenticateOptions.AUTHENTICATE_REASON_SWIPE_UP_ON_BOUNCER: 185 return AuthenticateReason.Face.SWIPE_UP_ON_BOUNCER; 186 case FaceAuthenticateOptions.AUTHENTICATE_REASON_UDFPS_POINTER_DOWN: 187 return AuthenticateReason.Face.UDFPS_POINTER_DOWN; 188 default: 189 return AuthenticateReason.Face.UNKNOWN; 190 } 191 } 192 193 @WakeReason getWakeReason(@onNull FaceAuthenticateOptions options)194 private int getWakeReason(@NonNull FaceAuthenticateOptions options) { 195 switch (options.getWakeReason()) { 196 case PowerManager.WAKE_REASON_POWER_BUTTON: 197 return WakeReason.POWER_BUTTON; 198 case PowerManager.WAKE_REASON_GESTURE: 199 return WakeReason.GESTURE; 200 case PowerManager.WAKE_REASON_WAKE_KEY: 201 return WakeReason.WAKE_KEY; 202 case PowerManager.WAKE_REASON_WAKE_MOTION: 203 return WakeReason.WAKE_MOTION; 204 case PowerManager.WAKE_REASON_DISPLAY_GROUP_ADDED: 205 return WakeReason.DISPLAY_GROUP_ADDED; 206 case PowerManager.WAKE_REASON_TAP: 207 return WakeReason.TAP; 208 case PowerManager.WAKE_REASON_LIFT: 209 return WakeReason.LIFT; 210 case PowerManager.WAKE_REASON_BIOMETRIC: 211 return WakeReason.BIOMETRIC; 212 case PowerManager.WAKE_REASON_CAMERA_LAUNCH: 213 case PowerManager.WAKE_REASON_HDMI: 214 case PowerManager.WAKE_REASON_DISPLAY_GROUP_TURNED_ON: 215 case PowerManager.WAKE_REASON_UNFOLD_DEVICE: 216 case PowerManager.WAKE_REASON_DREAM_FINISHED: 217 case PowerManager.WAKE_REASON_TILT: 218 case PowerManager.WAKE_REASON_APPLICATION: 219 case PowerManager.WAKE_REASON_PLUGGED_IN: 220 default: 221 return WakeReason.UNKNOWN; 222 } 223 } 224 225 @AuthenticateReason.Fingerprint getAuthReason(@onNull FingerprintAuthenticateOptions options)226 private int getAuthReason(@NonNull FingerprintAuthenticateOptions options) { 227 return AuthenticateReason.Fingerprint.UNKNOWN; 228 } 229 230 @WakeReason getWakeReason(@onNull FingerprintAuthenticateOptions options)231 private int getWakeReason(@NonNull FingerprintAuthenticateOptions options) { 232 return WakeReason.UNKNOWN; 233 } 234 235 /** {@link OperationContext#id}. */ getId()236 public int getId() { 237 return mAidlContext.id; 238 } 239 240 /** Gets the current order counter for the session and increment the counter. */ getOrderAndIncrement()241 public int getOrderAndIncrement() { 242 final BiometricContextSessionInfo info = mSessionInfo; 243 return info != null ? info.getOrderAndIncrement() : -1; 244 } 245 246 /** {@link OperationContext#reason}. */ 247 @OperationReason getReason()248 public byte getReason() { 249 return mAidlContext.reason; 250 } 251 252 /** {@link OperationContext#wakeReason}. */ 253 @WakeReason getWakeReason()254 public int getWakeReason() { 255 return mAidlContext.wakeReason; 256 } 257 258 /** If the screen is currently on. */ isDisplayOn()259 public boolean isDisplayOn() { 260 return mIsDisplayOn; 261 } 262 263 /** @deprecated prefer {@link #getDisplayState()} to {@link OperationContext#isAod}. */ isAod()264 public boolean isAod() { 265 return mAidlContext.isAod; 266 } 267 268 /** {@link OperationContext#displayState}. */ 269 @DisplayState getDisplayState()270 public int getDisplayState() { 271 return mAidlContext.displayState; 272 } 273 274 /** {@link OperationContext#isCrypto}. */ isCrypto()275 public boolean isCrypto() { 276 return mAidlContext.isCrypto; 277 } 278 279 /** The dock state when this event occurred {@see Intent.EXTRA_DOCK_STATE_UNDOCKED}. */ getDockState()280 public int getDockState() { 281 return mDockState; 282 } 283 284 /** The fold state of the device when this event occurred. */ getFoldState()285 public int getFoldState() { 286 return mFoldState; 287 } 288 289 /** The orientation of the device when this event occurred. */ 290 @Surface.Rotation getOrientation()291 public int getOrientation() { 292 return mOrientation; 293 } 294 295 /** The current operation state */ getOperationState()296 public OperationState getOperationState() { 297 return mAidlContext.operationState; 298 } 299 300 /** If mandatory biometrics is active. */ getIsMandatoryBiometrics()301 public boolean getIsMandatoryBiometrics() { 302 return mIsMandatoryBiometrics; 303 } 304 305 /** Update this object with the latest values from the given context. */ update(@onNull BiometricContext biometricContext, boolean isCrypto)306 OperationContextExt update(@NonNull BiometricContext biometricContext, boolean isCrypto) { 307 mAidlContext.isAod = biometricContext.isAod(); 308 mAidlContext.displayState = toAidlDisplayState(biometricContext.getDisplayState()); 309 mAidlContext.foldState = toAidlFoldState(biometricContext.getFoldState()); 310 mAidlContext.isCrypto = isCrypto; 311 312 if (mAidlContext.operationState != null && mAidlContext.operationState.getTag() 313 == OperationState.fingerprintOperationState) { 314 mAidlContext.operationState.getFingerprintOperationState().isHardwareIgnoringTouches = 315 biometricContext.isHardwareIgnoringTouches(); 316 } 317 setFirstSessionId(biometricContext); 318 319 mIsDisplayOn = biometricContext.isDisplayOn(); 320 mDockState = biometricContext.getDockedState(); 321 mFoldState = biometricContext.getFoldState(); 322 mOrientation = biometricContext.getCurrentRotation(); 323 324 return this; 325 } 326 327 @DisplayState toAidlDisplayState(@uthenticateOptions.DisplayState int state)328 private static int toAidlDisplayState(@AuthenticateOptions.DisplayState int state) { 329 switch (state) { 330 case AuthenticateOptions.DISPLAY_STATE_AOD: 331 return DisplayState.AOD; 332 case AuthenticateOptions.DISPLAY_STATE_LOCKSCREEN: 333 return DisplayState.LOCKSCREEN; 334 case AuthenticateOptions.DISPLAY_STATE_NO_UI: 335 return DisplayState.NO_UI; 336 case AuthenticateOptions.DISPLAY_STATE_SCREENSAVER: 337 return DisplayState.SCREENSAVER; 338 } 339 return DisplayState.UNKNOWN; 340 } 341 342 @FoldState toAidlFoldState(@BiometricContextListener.FoldState int state)343 private static int toAidlFoldState(@IBiometricContextListener.FoldState int state) { 344 switch (state) { 345 case IBiometricContextListener.FoldState.FULLY_CLOSED: 346 return FoldState.FULLY_CLOSED; 347 case IBiometricContextListener.FoldState.FULLY_OPENED: 348 return FoldState.FULLY_OPENED; 349 case IBiometricContextListener.FoldState.HALF_OPENED: 350 return FoldState.HALF_OPENED; 351 } 352 return FoldState.UNKNOWN; 353 } 354 setFirstSessionId(@onNull BiometricContext biometricContext)355 private void setFirstSessionId(@NonNull BiometricContext biometricContext) { 356 if (mIsBP) { 357 mSessionInfo = biometricContext.getBiometricPromptSessionInfo(); 358 if (mSessionInfo != null) { 359 mAidlContext.id = mSessionInfo.getId(); 360 mAidlContext.reason = OperationReason.BIOMETRIC_PROMPT; 361 return; 362 } 363 } else { 364 mSessionInfo = biometricContext.getKeyguardEntrySessionInfo(); 365 if (mSessionInfo != null) { 366 mAidlContext.id = mSessionInfo.getId(); 367 mAidlContext.reason = OperationReason.KEYGUARD; 368 return; 369 } 370 } 371 372 // no session 373 mAidlContext.id = 0; 374 mAidlContext.reason = OperationReason.UNKNOWN; 375 } 376 } 377