• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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;
18 
19 import static android.hardware.biometrics.BiometricManager.Authenticators;
20 
21 import android.annotation.IntDef;
22 import android.annotation.NonNull;
23 import android.content.Context;
24 import android.hardware.biometrics.BiometricConstants;
25 import android.hardware.biometrics.IBiometricAuthenticator;
26 import android.hardware.biometrics.IBiometricSensorReceiver;
27 import android.os.IBinder;
28 import android.os.RemoteException;
29 import android.util.Slog;
30 
31 import java.lang.annotation.Retention;
32 import java.lang.annotation.RetentionPolicy;
33 
34 /**
35  * Wraps IBiometricAuthenticator implementation and stores information about the authenticator,
36  * including its current state.
37  * TODO(b/141025588): Consider refactoring the tests to not rely on this implementation detail.
38  */
39 public abstract class BiometricSensor {
40     private static final String TAG = "BiometricService/Sensor";
41 
42     // State is unknown. Usually this means we need the sensor but have not requested for
43     // it to be used yet (cookie not sent yet)
44     static final int STATE_UNKNOWN = 0;
45     // Cookie has been generated, and the relevant sensor service has been asked to prepare
46     // for authentication. Awaiting "ack" from the sensor.
47     static final int STATE_WAITING_FOR_COOKIE = 1;
48     // The appropriate sensor service has "acked" notifying us that it's ready to be
49     // started for authentication.
50     static final int STATE_COOKIE_RETURNED = 2;
51     // The sensor is being used for authentication.
52     static final int STATE_AUTHENTICATING = 3;
53     // Cancel has been requested, waiting for ERROR_CANCELED to be received from the HAL
54     static final int STATE_CANCELING = 4;
55     static final int STATE_STOPPED = 5;
56 
57     @IntDef({STATE_UNKNOWN,
58             STATE_WAITING_FOR_COOKIE,
59             STATE_COOKIE_RETURNED,
60             STATE_AUTHENTICATING,
61             STATE_CANCELING,
62             STATE_STOPPED})
63     @Retention(RetentionPolicy.SOURCE)
64     @interface SensorState {}
65 
66     @NonNull private final Context mContext;
67     public final int id;
68     public final @Authenticators.Types int oemStrength; // strength as configured by the OEM
69     public final int modality;
70     public final IBiometricAuthenticator impl;
71 
72     private @Authenticators.Types int mUpdatedStrength; // updated by BiometricStrengthController
73     private @SensorState int mSensorState;
74     private @BiometricConstants.Errors int mError;
75 
76     private int mCookie; // invalid during STATE_UNKNOWN
77 
78     /**
79      * @return true if the user's system settings specifies that this sensor always requires
80      * confirmation.
81      */
confirmationAlwaysRequired(int userId)82     abstract boolean confirmationAlwaysRequired(int userId);
83 
84     /**
85      * @return true if confirmation is supported by this sensor.
86      */
confirmationSupported()87     abstract boolean confirmationSupported();
88 
BiometricSensor(@onNull Context context, int id, int modality, @Authenticators.Types int strength, IBiometricAuthenticator impl)89     BiometricSensor(@NonNull Context context, int id, int modality,
90             @Authenticators.Types int strength, IBiometricAuthenticator impl) {
91         this.mContext = context;
92         this.id = id;
93         this.modality = modality;
94         this.oemStrength = strength;
95         this.impl = impl;
96 
97         mUpdatedStrength = strength;
98         goToStateUnknown();
99     }
100 
goToStateUnknown()101     void goToStateUnknown() {
102         mSensorState = STATE_UNKNOWN;
103         mCookie = 0;
104         mError = BiometricConstants.BIOMETRIC_SUCCESS;
105     }
106 
goToStateWaitingForCookie(boolean requireConfirmation, IBinder token, long sessionId, int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName, long requestId, int cookie, boolean allowBackgroundAuthentication)107     void goToStateWaitingForCookie(boolean requireConfirmation, IBinder token, long sessionId,
108             int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName,
109             long requestId, int cookie, boolean allowBackgroundAuthentication)
110             throws RemoteException {
111         mCookie = cookie;
112         impl.prepareForAuthentication(requireConfirmation, token,
113                 sessionId, userId, sensorReceiver, opPackageName, requestId, mCookie,
114                 allowBackgroundAuthentication);
115         mSensorState = STATE_WAITING_FOR_COOKIE;
116     }
117 
goToStateCookieReturnedIfCookieMatches(int cookie)118     void goToStateCookieReturnedIfCookieMatches(int cookie) {
119         if (cookie == mCookie) {
120             Slog.d(TAG, "Sensor(" + id + ") matched cookie: " + cookie);
121             mSensorState = STATE_COOKIE_RETURNED;
122         }
123     }
124 
startSensor()125     void startSensor() throws RemoteException {
126         impl.startPreparedClient(mCookie);
127         mSensorState = STATE_AUTHENTICATING;
128     }
129 
goToStateCancelling(IBinder token, String opPackageName, long requestId)130     void goToStateCancelling(IBinder token, String opPackageName, long requestId)
131             throws RemoteException {
132         if (mSensorState != STATE_CANCELING) {
133             impl.cancelAuthenticationFromService(token, opPackageName, requestId);
134             mSensorState = STATE_CANCELING;
135         }
136     }
137 
goToStoppedStateIfCookieMatches(int cookie, int error)138     void goToStoppedStateIfCookieMatches(int cookie, int error) {
139         if (cookie == mCookie) {
140             Slog.d(TAG, "Sensor(" + id + ") now in STATE_STOPPED");
141             mError = error;
142             mSensorState = STATE_STOPPED;
143         }
144     }
145 
146     /**
147      * Returns the actual strength, taking any updated strengths into effect. Since more bits
148      * means lower strength, the resulting strength is never stronger than the OEM's configured
149      * strength.
150      * @return a bitfield, see {@link android.hardware.biometrics.BiometricManager.Authenticators}
151      */
getCurrentStrength()152     @Authenticators.Types int getCurrentStrength() {
153         return oemStrength | mUpdatedStrength;
154     }
155 
getSensorState()156     @SensorState int getSensorState() {
157         return mSensorState;
158     }
159 
getCookie()160     int getCookie() {
161         return mCookie;
162     }
163 
164     /**
165      * Stores the updated strength, which takes effect whenever {@link #getCurrentStrength()}
166      * is checked.
167      * @param newStrength
168      */
updateStrength(@uthenticators.Types int newStrength)169     void updateStrength(@Authenticators.Types int newStrength) {
170         String log = "updateStrength: Before(" + this + ")";
171         mUpdatedStrength = newStrength;
172         log += " After(" + this + ")";
173         Slog.d(TAG, log);
174     }
175 
176     @Override
toString()177     public String toString() {
178         return "ID(" + id + ")"
179                 + ", oemStrength: " + oemStrength
180                 + ", updatedStrength: " + mUpdatedStrength
181                 + ", modality " + modality
182                 + ", state: " + mSensorState
183                 + ", cookie: " + mCookie;
184     }
185 }
186