blob: 22b7418b53b7baacb10f36373dece5dd1aadeed2 [file] [log] [blame]
Kevin Chyn037c4d52018-06-11 19:17:32 -07001/*
2 * Copyright (C) 2018 The Android Open Source Project
Jim Millercb2ce6f2016-04-13 20:28:18 -07003 *
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
Kevin Chyn037c4d52018-06-11 19:17:32 -070014 * limitations under the License
Jim Millercb2ce6f2016-04-13 20:28:18 -070015 */
16
Kevin Chyn836f2cf2018-08-27 11:06:39 -070017package com.android.server.biometrics;
Jim Millercb2ce6f2016-04-13 20:28:18 -070018
Jim Millercb2ce6f2016-04-13 20:28:18 -070019import android.content.Context;
Kevin Chyna56dff72018-06-19 18:41:12 -070020import android.hardware.biometrics.BiometricAuthenticator;
Kevin Chyn037c4d52018-06-11 19:17:32 -070021import android.hardware.biometrics.BiometricConstants;
Beverlyd9ec6df2018-03-20 17:19:07 -040022import android.media.AudioAttributes;
Jim Millercb2ce6f2016-04-13 20:28:18 -070023import android.os.IBinder;
24import android.os.RemoteException;
Michael Wright6726fd52017-06-27 00:41:45 +010025import android.os.VibrationEffect;
26import android.os.Vibrator;
Jim Millercb2ce6f2016-04-13 20:28:18 -070027import android.util.Slog;
28
Kevin Chyn037c4d52018-06-11 19:17:32 -070029import com.android.internal.logging.MetricsLogger;
30
Kevin Chyn6cf54e82018-09-18 19:13:27 -070031import java.util.ArrayList;
Jim Millercb2ce6f2016-04-13 20:28:18 -070032import java.util.NoSuchElementException;
33
34/**
Kevin Chyn037c4d52018-06-11 19:17:32 -070035 * Abstract base class for keeping track and dispatching events from the biometric's HAL to the
Jim Millercb2ce6f2016-04-13 20:28:18 -070036 * the current client. Subclasses are responsible for coordinating the interaction with
Kevin Chyn037c4d52018-06-11 19:17:32 -070037 * the biometric's HAL for the specific action (e.g. authenticate, enroll, enumerate, etc.).
Jim Millercb2ce6f2016-04-13 20:28:18 -070038 */
39public abstract class ClientMonitor implements IBinder.DeathRecipient {
Kevin Chyn037c4d52018-06-11 19:17:32 -070040 protected static final int ERROR_ESRCH = 3; // Likely HAL is dead. See errno.h.
Kevin Chyn355c6bf2018-09-20 22:14:19 -070041 protected static final boolean DEBUG = BiometricServiceBase.DEBUG;
Beverlyd9ec6df2018-03-20 17:19:07 -040042 private static final AudioAttributes FINGERPRINT_SONFICATION_ATTRIBUTES =
43 new AudioAttributes.Builder()
44 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
45 .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
46 .build();
Kevin Chyn037c4d52018-06-11 19:17:32 -070047
Michael Wright6726fd52017-06-27 00:41:45 +010048 private final Context mContext;
49 private final long mHalDeviceId;
50 private final int mTargetUserId;
51 private final int mGroupId;
52 // True if client does not have MANAGE_FINGERPRINT permission
53 private final boolean mIsRestricted;
54 private final String mOwner;
55 private final VibrationEffect mSuccessVibrationEffect;
56 private final VibrationEffect mErrorVibrationEffect;
Kevin Chyn355c6bf2018-09-20 22:14:19 -070057 private final BiometricServiceBase.DaemonWrapper mDaemon;
Kevin Chyn037c4d52018-06-11 19:17:32 -070058
Jim Millercb2ce6f2016-04-13 20:28:18 -070059 private IBinder mToken;
Kevin Chyn355c6bf2018-09-20 22:14:19 -070060 private BiometricServiceBase.ServiceListener mListener;
Kevin Chyn037c4d52018-06-11 19:17:32 -070061
62 protected final MetricsLogger mMetricsLogger;
63 protected final Metrics mMetrics;
64
Kevin Chyn37368582017-05-19 17:15:38 -070065 protected boolean mAlreadyCancelled;
Kevin Chync79856b2018-10-05 18:57:35 -070066 protected boolean mAlreadyDone;
Jim Millercb2ce6f2016-04-13 20:28:18 -070067
68 /**
Kevin Chyn037c4d52018-06-11 19:17:32 -070069 * @param context context of BiometricService
70 * @param daemon interface to call back to a specific biometric's daemon
71 * @param halDeviceId the HAL device ID of the associated biometric hardware
Jim Millercb2ce6f2016-04-13 20:28:18 -070072 * @param token a unique token for the client
Kevin Chyn037c4d52018-06-11 19:17:32 -070073 * @param listener recipient of related events (e.g. authentication)
Jim Miller8f2aca02016-04-20 13:34:11 -070074 * @param userId target user id for operation
Jim Millercb2ce6f2016-04-13 20:28:18 -070075 * @param groupId groupId for the fingerprint set
Kevin Chyn037c4d52018-06-11 19:17:32 -070076 * @param restricted whether or not client has the MANAGE_* permission
Jim Millercb2ce6f2016-04-13 20:28:18 -070077 * permission
78 * @param owner name of the client that owns this
79 */
Kevin Chyn355c6bf2018-09-20 22:14:19 -070080 public ClientMonitor(Context context, Metrics metrics,
81 BiometricServiceBase.DaemonWrapper daemon, long halDeviceId, IBinder token,
82 BiometricServiceBase.ServiceListener listener, int userId, int groupId,
83 boolean restricted, String owner) {
Jim Millercb2ce6f2016-04-13 20:28:18 -070084 mContext = context;
Kevin Chyn037c4d52018-06-11 19:17:32 -070085 mMetrics = metrics;
86 mDaemon = daemon;
Jim Millercb2ce6f2016-04-13 20:28:18 -070087 mHalDeviceId = halDeviceId;
88 mToken = token;
Kevin Chyn037c4d52018-06-11 19:17:32 -070089 mListener = listener;
Jim Miller8f2aca02016-04-20 13:34:11 -070090 mTargetUserId = userId;
Jim Millercb2ce6f2016-04-13 20:28:18 -070091 mGroupId = groupId;
92 mIsRestricted = restricted;
93 mOwner = owner;
Ilya Matyukhin21a0d1e2018-04-26 15:57:29 -070094 mSuccessVibrationEffect = VibrationEffect.get(VibrationEffect.EFFECT_CLICK);
Michael Wright6726fd52017-06-27 00:41:45 +010095 mErrorVibrationEffect = VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);
Kevin Chyn037c4d52018-06-11 19:17:32 -070096 mMetricsLogger = new MetricsLogger();
Jim Millercb2ce6f2016-04-13 20:28:18 -070097 try {
Jim Miller7e1cb552017-02-27 17:37:32 -080098 if (token != null) {
99 token.linkToDeath(this, 0);
100 }
Jim Millercb2ce6f2016-04-13 20:28:18 -0700101 } catch (RemoteException e) {
Kevin Chyn037c4d52018-06-11 19:17:32 -0700102 Slog.w(getLogTag(), "caught remote exception in linkToDeath: ", e);
Jim Millercb2ce6f2016-04-13 20:28:18 -0700103 }
104 }
105
Kevin Chyn037c4d52018-06-11 19:17:32 -0700106 protected String getLogTag() {
107 return mMetrics.logTag();
108 }
109
Jim Millercb2ce6f2016-04-13 20:28:18 -0700110 /**
Kevin Chyn037c4d52018-06-11 19:17:32 -0700111 * Contacts the biometric's HAL to start the client.
Michael Wright6726fd52017-06-27 00:41:45 +0100112 * @return 0 on success, errno from driver on failure
Jim Millercb2ce6f2016-04-13 20:28:18 -0700113 */
114 public abstract int start();
115
116 /**
Kevin Chyn037c4d52018-06-11 19:17:32 -0700117 * Contacts the biometric's HAL to stop the client.
Jim Millercb2ce6f2016-04-13 20:28:18 -0700118 * @param initiatedByClient whether the operation is at the request of a client
119 */
120 public abstract int stop(boolean initiatedByClient);
121
122 /**
123 * Method to explicitly poke powermanager on events
124 */
125 public abstract void notifyUserActivity();
126
Jim Millercb2ce6f2016-04-13 20:28:18 -0700127 // Event callbacks from driver. Inappropriate calls is flagged/logged by the
128 // respective client (e.g. enrolling shouldn't get authenticate events).
129 // All of these return 'true' if the operation is completed and it's ok to move
Kevin Chyn037c4d52018-06-11 19:17:32 -0700130 // to the next client (e.g. authentication accepts or rejects a biometric).
Kevin Chyna56dff72018-06-19 18:41:12 -0700131 public abstract boolean onEnrollResult(BiometricAuthenticator.Identifier identifier,
132 int remaining);
Kevin Chynb528d692018-07-20 11:53:14 -0700133 public abstract boolean onAuthenticated(BiometricAuthenticator.Identifier identifier,
Kevin Chyn6cf54e82018-09-18 19:13:27 -0700134 boolean authenticated, ArrayList<Byte> token);
Kevin Chyna56dff72018-06-19 18:41:12 -0700135 public abstract boolean onRemoved(BiometricAuthenticator.Identifier identifier,
136 int remaining);
137 public abstract boolean onEnumerationResult(
138 BiometricAuthenticator.Identifier identifier, int remaining);
Jim Millercb2ce6f2016-04-13 20:28:18 -0700139
Kevin Chync79856b2018-10-05 18:57:35 -0700140
141 public boolean isAlreadyDone() {
142 return mAlreadyDone;
143 }
144
Jim Millercb2ce6f2016-04-13 20:28:18 -0700145 /**
Kevin Chyn037c4d52018-06-11 19:17:32 -0700146 * Called when we get notification from the biometric's HAL that an image has been acquired.
Jim Millercb2ce6f2016-04-13 20:28:18 -0700147 * Common to authenticate and enroll.
148 * @param acquiredInfo info about the current image acquisition
149 * @return true if client should be removed
150 */
Jim Miller40e46452016-12-16 18:38:53 -0800151 public boolean onAcquired(int acquiredInfo, int vendorCode) {
Jim Millercb2ce6f2016-04-13 20:28:18 -0700152 try {
Kevin Chyna56dff72018-06-19 18:41:12 -0700153 if (mListener != null) {
154 mListener.onAcquired(getHalDeviceId(), acquiredInfo, vendorCode);
155 }
Jim Millercb2ce6f2016-04-13 20:28:18 -0700156 return false; // acquisition continues...
157 } catch (RemoteException e) {
Kevin Chyn037c4d52018-06-11 19:17:32 -0700158 Slog.w(getLogTag(), "Failed to invoke sendAcquired", e);
159 return true;
Jim Millercb2ce6f2016-04-13 20:28:18 -0700160 } finally {
161 // Good scans will keep the device awake
Kevin Chyn037c4d52018-06-11 19:17:32 -0700162 if (acquiredInfo == BiometricConstants.BIOMETRIC_ACQUIRED_GOOD) {
Jim Millercb2ce6f2016-04-13 20:28:18 -0700163 notifyUserActivity();
164 }
165 }
166 }
167
168 /**
Kevin Chyn037c4d52018-06-11 19:17:32 -0700169 * Called when we get notification from the biometric's HAL that an error has occurred with the
Jim Millercb2ce6f2016-04-13 20:28:18 -0700170 * current operation. Common to authenticate, enroll, enumerate and remove.
171 * @param error
172 * @return true if client should be removed
173 */
Kevin Chyna56dff72018-06-19 18:41:12 -0700174 public boolean onError(long deviceId, int error, int vendorCode) {
Kevin Chyn037c4d52018-06-11 19:17:32 -0700175 try {
Kevin Chyna56dff72018-06-19 18:41:12 -0700176 if (mListener != null) {
177 mListener.onError(deviceId, error, vendorCode);
178 }
Kevin Chyn037c4d52018-06-11 19:17:32 -0700179 } catch (RemoteException e) {
180 Slog.w(getLogTag(), "Failed to invoke sendError", e);
Jim Millercb2ce6f2016-04-13 20:28:18 -0700181 }
182 return true; // errors always remove current client
183 }
184
185 public void destroy() {
186 if (mToken != null) {
187 try {
188 mToken.unlinkToDeath(this, 0);
189 } catch (NoSuchElementException e) {
190 // TODO: remove when duplicate call bug is found
Kevin Chyn037c4d52018-06-11 19:17:32 -0700191 Slog.e(getLogTag(), "destroy(): " + this + ":", new Exception("here"));
Jim Millercb2ce6f2016-04-13 20:28:18 -0700192 }
193 mToken = null;
194 }
Kevin Chyn037c4d52018-06-11 19:17:32 -0700195 mListener = null;
Jim Millercb2ce6f2016-04-13 20:28:18 -0700196 }
197
198 @Override
199 public void binderDied() {
200 mToken = null;
Kevin Chyn037c4d52018-06-11 19:17:32 -0700201 mListener = null;
Kevin Chyna56dff72018-06-19 18:41:12 -0700202 onError(getHalDeviceId(), BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
203 0 /* vendorCode */);
Jim Millercb2ce6f2016-04-13 20:28:18 -0700204 }
205
206 @Override
207 protected void finalize() throws Throwable {
208 try {
209 if (mToken != null) {
Kevin Chyn037c4d52018-06-11 19:17:32 -0700210 if (DEBUG) Slog.w(getLogTag(), "removing leaked reference: " + mToken);
Kevin Chyna56dff72018-06-19 18:41:12 -0700211 onError(getHalDeviceId(), BiometricConstants.BIOMETRIC_ERROR_HW_UNAVAILABLE,
212 0 /* vendorCode */);
Jim Millercb2ce6f2016-04-13 20:28:18 -0700213 }
214 } finally {
215 super.finalize();
216 }
217 }
218
219 public final Context getContext() {
220 return mContext;
221 }
222
223 public final long getHalDeviceId() {
224 return mHalDeviceId;
225 }
226
227 public final String getOwnerString() {
228 return mOwner;
229 }
230
Kevin Chyn355c6bf2018-09-20 22:14:19 -0700231 public final BiometricServiceBase.ServiceListener getListener() {
Kevin Chyn037c4d52018-06-11 19:17:32 -0700232 return mListener;
233 }
234
Kevin Chyn355c6bf2018-09-20 22:14:19 -0700235 public final BiometricServiceBase.DaemonWrapper getDaemonWrapper() {
Kevin Chyn037c4d52018-06-11 19:17:32 -0700236 return mDaemon;
Jim Millercb2ce6f2016-04-13 20:28:18 -0700237 }
238
239 public final boolean getIsRestricted() {
240 return mIsRestricted;
241 }
242
Jim Miller8f2aca02016-04-20 13:34:11 -0700243 public final int getTargetUserId() {
244 return mTargetUserId;
Jim Millercb2ce6f2016-04-13 20:28:18 -0700245 }
246
247 public final int getGroupId() {
248 return mGroupId;
249 }
250
251 public final IBinder getToken() {
252 return mToken;
253 }
Michael Wright6726fd52017-06-27 00:41:45 +0100254
255 public final void vibrateSuccess() {
256 Vibrator vibrator = mContext.getSystemService(Vibrator.class);
257 if (vibrator != null) {
Beverlyd9ec6df2018-03-20 17:19:07 -0400258 vibrator.vibrate(mSuccessVibrationEffect, FINGERPRINT_SONFICATION_ATTRIBUTES);
Michael Wright6726fd52017-06-27 00:41:45 +0100259 }
260 }
261
262 public final void vibrateError() {
263 Vibrator vibrator = mContext.getSystemService(Vibrator.class);
264 if (vibrator != null) {
Beverlyd9ec6df2018-03-20 17:19:07 -0400265 vibrator.vibrate(mErrorVibrationEffect, FINGERPRINT_SONFICATION_ATTRIBUTES);
Michael Wright6726fd52017-06-27 00:41:45 +0100266 }
267 }
Jim Millercb2ce6f2016-04-13 20:28:18 -0700268}