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, long requestId, int cookie, boolean allowBackgroundAuthentication)109 void goToStateWaitingForCookie(boolean requireConfirmation, IBinder token, long sessionId, 110 int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName, 111 long requestId, int cookie, boolean allowBackgroundAuthentication) 112 throws RemoteException { 113 mCookie = cookie; 114 impl.prepareForAuthentication(requireConfirmation, token, 115 sessionId, userId, sensorReceiver, opPackageName, requestId, 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, long requestId)132 void goToStateCancelling(IBinder token, String opPackageName, long requestId) 133 throws RemoteException { 134 impl.cancelAuthenticationFromService(token, opPackageName, requestId); 135 mSensorState = STATE_CANCELING; 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 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(" + toString() + ")"; 171 mUpdatedStrength = newStrength; 172 log += " After(" + toString() + ")"; 173 Slog.d(TAG, log); 174 } 175 176 @Override toString()177 public String toString() { 178 SensorPropertiesInternal properties = null; 179 try { 180 properties = impl.getSensorProperties(mContext.getOpPackageName()); 181 } catch (RemoteException e) { 182 Slog.e(TAG, "Remote exception", e); 183 } 184 185 return "ID(" + id + ")" 186 + ", oemStrength: " + oemStrength 187 + ", updatedStrength: " + mUpdatedStrength 188 + ", modality " + modality 189 + ", state: " + mSensorState 190 + ", cookie: " + mCookie 191 + ", props: " + properties; 192 } 193 } 194