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