• 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, boolean isForLegacyFingerprintManager, boolean isMandatoryBiometrics)107     void goToStateWaitingForCookie(boolean requireConfirmation, IBinder token, long sessionId,
108             int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName,
109             long requestId, int cookie, boolean allowBackgroundAuthentication,
110             boolean isForLegacyFingerprintManager, boolean isMandatoryBiometrics)
111             throws RemoteException {
112         mCookie = cookie;
113         impl.prepareForAuthentication(requireConfirmation, token,
114                 sessionId, userId, sensorReceiver, opPackageName, requestId, mCookie,
115                 allowBackgroundAuthentication, isForLegacyFingerprintManager,
116                 isMandatoryBiometrics);
117         mSensorState = STATE_WAITING_FOR_COOKIE;
118     }
119 
goToStateCookieReturnedIfCookieMatches(int cookie)120     void goToStateCookieReturnedIfCookieMatches(int cookie) {
121         if (cookie == mCookie) {
122             Slog.d(TAG, "Sensor(" + id + ") matched cookie: " + cookie);
123             mSensorState = STATE_COOKIE_RETURNED;
124         }
125     }
126 
startSensor()127     void startSensor() throws RemoteException {
128         impl.startPreparedClient(mCookie);
129         mSensorState = STATE_AUTHENTICATING;
130     }
131 
goToStateCancelling(IBinder token, String opPackageName, long requestId)132     void goToStateCancelling(IBinder token, String opPackageName, long requestId)
133             throws RemoteException {
134         if (mSensorState != STATE_CANCELING) {
135             impl.cancelAuthenticationFromService(token, opPackageName, requestId);
136             mSensorState = STATE_CANCELING;
137         }
138     }
139 
goToStoppedStateIfCookieMatches(int cookie, int error)140     void goToStoppedStateIfCookieMatches(int cookie, int error) {
141         if (cookie == mCookie) {
142             Slog.d(TAG, "Sensor(" + id + ") now in STATE_STOPPED");
143             mError = error;
144             mSensorState = STATE_STOPPED;
145         }
146     }
147 
148     /**
149      * Returns the actual strength, taking any updated strengths into effect. Since more bits
150      * means lower strength, the resulting strength is never stronger than the OEM's configured
151      * strength.
152      * @return a bitfield, see {@link android.hardware.biometrics.BiometricManager.Authenticators}
153      */
getCurrentStrength()154     @Authenticators.Types int getCurrentStrength() {
155         return oemStrength | mUpdatedStrength;
156     }
157 
getSensorState()158     @SensorState int getSensorState() {
159         return mSensorState;
160     }
161 
getCookie()162     int getCookie() {
163         return mCookie;
164     }
165 
166     /**
167      * Stores the updated strength, which takes effect whenever {@link #getCurrentStrength()}
168      * is checked.
169      * @param newStrength
170      */
updateStrength(@uthenticators.Types int newStrength)171     void updateStrength(@Authenticators.Types int newStrength) {
172         String log = "updateStrength: Before(" + this + ")";
173         mUpdatedStrength = newStrength;
174         log += " After(" + this + ")";
175         Slog.d(TAG, log);
176     }
177 
178     @Override
toString()179     public String toString() {
180         return "ID(" + id + ")"
181                 + ", oemStrength: " + oemStrength
182                 + ", updatedStrength: " + mUpdatedStrength
183                 + ", modality " + modality
184                 + ", state: " + mSensorState
185                 + ", cookie: " + mCookie;
186     }
187 }
188