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