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