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