blob: 4100a9a5f71c2f76ae36efcf91d3832a705e1dc3 [file] [log] [blame]
Jim Millercb2ce6f2016-04-13 20:28:18 -07001/**
2 * Copyright (C) 2016 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
17package com.android.server.fingerprint;
18
19import android.Manifest;
20import android.content.Context;
Jim Miller40e46452016-12-16 18:38:53 -080021import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
Jim Millercb2ce6f2016-04-13 20:28:18 -070022import android.hardware.fingerprint.FingerprintManager;
Jim Millercb2ce6f2016-04-13 20:28:18 -070023import android.hardware.fingerprint.IFingerprintServiceReceiver;
Beverlyd9ec6df2018-03-20 17:19:07 -040024import android.media.AudioAttributes;
Jim Millercb2ce6f2016-04-13 20:28:18 -070025import android.os.IBinder;
26import android.os.RemoteException;
Michael Wright6726fd52017-06-27 00:41:45 +010027import android.os.VibrationEffect;
28import android.os.Vibrator;
Jim Millercb2ce6f2016-04-13 20:28:18 -070029import android.util.Slog;
30
31import java.util.NoSuchElementException;
32
33/**
Kevin Chyn80e40cc2017-03-14 12:31:17 -070034 * Abstract base class for keeping track and dispatching events from fingerprint HAL to the
Jim Millercb2ce6f2016-04-13 20:28:18 -070035 * the current client. Subclasses are responsible for coordinating the interaction with
Kevin Chyn80e40cc2017-03-14 12:31:17 -070036 * fingerprint HAL for the specific action (e.g. authenticate, enroll, enumerate, etc.).
Jim Millercb2ce6f2016-04-13 20:28:18 -070037 */
38public abstract class ClientMonitor implements IBinder.DeathRecipient {
39 protected static final String TAG = FingerprintService.TAG; // TODO: get specific name
Kevin Chyn80e40cc2017-03-14 12:31:17 -070040 protected static final int ERROR_ESRCH = 3; // Likely fingerprint HAL is dead. See errno.h.
Jim Millercb2ce6f2016-04-13 20:28:18 -070041 protected static final boolean DEBUG = FingerprintService.DEBUG;
Michael Wright6726fd52017-06-27 00:41:45 +010042 private static final long[] DEFAULT_SUCCESS_VIBRATION_PATTERN = new long[] {0, 30};
Beverlyd9ec6df2018-03-20 17:19:07 -040043 private static final AudioAttributes FINGERPRINT_SONFICATION_ATTRIBUTES =
44 new AudioAttributes.Builder()
45 .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
46 .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION)
47 .build();
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;
Jim Millercb2ce6f2016-04-13 20:28:18 -070057 private IBinder mToken;
58 private IFingerprintServiceReceiver mReceiver;
Kevin Chyn37368582017-05-19 17:15:38 -070059 protected boolean mAlreadyCancelled;
Jim Millercb2ce6f2016-04-13 20:28:18 -070060
61 /**
62 * @param context context of FingerprintService
63 * @param halDeviceId the HAL device ID of the associated fingerprint hardware
64 * @param token a unique token for the client
65 * @param receiver recipient of related events (e.g. authentication)
Jim Miller8f2aca02016-04-20 13:34:11 -070066 * @param userId target user id for operation
Jim Millercb2ce6f2016-04-13 20:28:18 -070067 * @param groupId groupId for the fingerprint set
68 * @param restricted whether or not client has the {@link Manifest#MANAGE_FINGERPRINT}
69 * permission
70 * @param owner name of the client that owns this
71 */
72 public ClientMonitor(Context context, long halDeviceId, IBinder token,
Jim Miller8f2aca02016-04-20 13:34:11 -070073 IFingerprintServiceReceiver receiver, int userId, int groupId,boolean restricted,
Jim Millercb2ce6f2016-04-13 20:28:18 -070074 String owner) {
75 mContext = context;
76 mHalDeviceId = halDeviceId;
77 mToken = token;
78 mReceiver = receiver;
Jim Miller8f2aca02016-04-20 13:34:11 -070079 mTargetUserId = userId;
Jim Millercb2ce6f2016-04-13 20:28:18 -070080 mGroupId = groupId;
81 mIsRestricted = restricted;
82 mOwner = owner;
Michael Wright6726fd52017-06-27 00:41:45 +010083 mSuccessVibrationEffect = getSuccessVibrationEffect(context);
84 mErrorVibrationEffect = VibrationEffect.get(VibrationEffect.EFFECT_DOUBLE_CLICK);
Jim Millercb2ce6f2016-04-13 20:28:18 -070085 try {
Jim Miller7e1cb552017-02-27 17:37:32 -080086 if (token != null) {
87 token.linkToDeath(this, 0);
88 }
Jim Millercb2ce6f2016-04-13 20:28:18 -070089 } catch (RemoteException e) {
90 Slog.w(TAG, "caught remote exception in linkToDeath: ", e);
91 }
92 }
93
94 /**
Kevin Chyn80e40cc2017-03-14 12:31:17 -070095 * Contacts fingerprint HAL to start the client.
Michael Wright6726fd52017-06-27 00:41:45 +010096 * @return 0 on success, errno from driver on failure
Jim Millercb2ce6f2016-04-13 20:28:18 -070097 */
98 public abstract int start();
99
100 /**
Kevin Chyn80e40cc2017-03-14 12:31:17 -0700101 * Contacts fingerprint HAL to stop the client.
Jim Millercb2ce6f2016-04-13 20:28:18 -0700102 * @param initiatedByClient whether the operation is at the request of a client
103 */
104 public abstract int stop(boolean initiatedByClient);
105
106 /**
107 * Method to explicitly poke powermanager on events
108 */
109 public abstract void notifyUserActivity();
110
111 /**
112 * Gets the fingerprint daemon from the cached state in the container class.
113 */
Jim Miller40e46452016-12-16 18:38:53 -0800114 public abstract IBiometricsFingerprint getFingerprintDaemon();
Jim Millercb2ce6f2016-04-13 20:28:18 -0700115
116 // Event callbacks from driver. Inappropriate calls is flagged/logged by the
117 // respective client (e.g. enrolling shouldn't get authenticate events).
118 // All of these return 'true' if the operation is completed and it's ok to move
119 // to the next client (e.g. authentication accepts or rejects a fingerprint).
120 public abstract boolean onEnrollResult(int fingerId, int groupId, int rem);
121 public abstract boolean onAuthenticated(int fingerId, int groupId);
Jim Miller40e46452016-12-16 18:38:53 -0800122 public abstract boolean onRemoved(int fingerId, int groupId, int remaining);
123 public abstract boolean onEnumerationResult(int fingerId, int groupId, int remaining);
Jim Millercb2ce6f2016-04-13 20:28:18 -0700124
125 /**
Kevin Chyn80e40cc2017-03-14 12:31:17 -0700126 * Called when we get notification from fingerprint HAL that an image has been acquired.
Jim Millercb2ce6f2016-04-13 20:28:18 -0700127 * Common to authenticate and enroll.
128 * @param acquiredInfo info about the current image acquisition
129 * @return true if client should be removed
130 */
Jim Miller40e46452016-12-16 18:38:53 -0800131 public boolean onAcquired(int acquiredInfo, int vendorCode) {
Jim Millercb2ce6f2016-04-13 20:28:18 -0700132 if (mReceiver == null)
133 return true; // client not connected
134 try {
Jim Miller40e46452016-12-16 18:38:53 -0800135 mReceiver.onAcquired(getHalDeviceId(), acquiredInfo, vendorCode);
Jim Millercb2ce6f2016-04-13 20:28:18 -0700136 return false; // acquisition continues...
137 } catch (RemoteException e) {
138 Slog.w(TAG, "Failed to invoke sendAcquired:", e);
139 return true; // client failed
140 } finally {
141 // Good scans will keep the device awake
142 if (acquiredInfo == FingerprintManager.FINGERPRINT_ACQUIRED_GOOD) {
143 notifyUserActivity();
144 }
145 }
146 }
147
148 /**
Kevin Chyn80e40cc2017-03-14 12:31:17 -0700149 * Called when we get notification from fingerprint HAL that an error has occurred with the
Jim Millercb2ce6f2016-04-13 20:28:18 -0700150 * current operation. Common to authenticate, enroll, enumerate and remove.
151 * @param error
152 * @return true if client should be removed
153 */
Jim Miller40e46452016-12-16 18:38:53 -0800154 public boolean onError(int error, int vendorCode) {
Jim Millercb2ce6f2016-04-13 20:28:18 -0700155 if (mReceiver != null) {
156 try {
Jim Miller40e46452016-12-16 18:38:53 -0800157 mReceiver.onError(getHalDeviceId(), error, vendorCode);
Jim Millercb2ce6f2016-04-13 20:28:18 -0700158 } catch (RemoteException e) {
159 Slog.w(TAG, "Failed to invoke sendError:", e);
160 }
161 }
162 return true; // errors always remove current client
163 }
164
165 public void destroy() {
166 if (mToken != null) {
167 try {
168 mToken.unlinkToDeath(this, 0);
169 } catch (NoSuchElementException e) {
170 // TODO: remove when duplicate call bug is found
171 Slog.e(TAG, "destroy(): " + this + ":", new Exception("here"));
172 }
173 mToken = null;
174 }
175 mReceiver = null;
176 }
177
178 @Override
179 public void binderDied() {
180 mToken = null;
181 mReceiver = null;
Jim Miller40e46452016-12-16 18:38:53 -0800182 onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */);
Jim Millercb2ce6f2016-04-13 20:28:18 -0700183 }
184
185 @Override
186 protected void finalize() throws Throwable {
187 try {
188 if (mToken != null) {
189 if (DEBUG) Slog.w(TAG, "removing leaked reference: " + mToken);
Jim Miller40e46452016-12-16 18:38:53 -0800190 onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE, 0 /* vendorCode */);
Jim Millercb2ce6f2016-04-13 20:28:18 -0700191 }
192 } finally {
193 super.finalize();
194 }
195 }
196
197 public final Context getContext() {
198 return mContext;
199 }
200
201 public final long getHalDeviceId() {
202 return mHalDeviceId;
203 }
204
205 public final String getOwnerString() {
206 return mOwner;
207 }
208
209 public final IFingerprintServiceReceiver getReceiver() {
210 return mReceiver;
211 }
212
213 public final boolean getIsRestricted() {
214 return mIsRestricted;
215 }
216
Jim Miller8f2aca02016-04-20 13:34:11 -0700217 public final int getTargetUserId() {
218 return mTargetUserId;
Jim Millercb2ce6f2016-04-13 20:28:18 -0700219 }
220
221 public final int getGroupId() {
222 return mGroupId;
223 }
224
225 public final IBinder getToken() {
226 return mToken;
227 }
Michael Wright6726fd52017-06-27 00:41:45 +0100228
229 public final void vibrateSuccess() {
230 Vibrator vibrator = mContext.getSystemService(Vibrator.class);
231 if (vibrator != null) {
Beverlyd9ec6df2018-03-20 17:19:07 -0400232 vibrator.vibrate(mSuccessVibrationEffect, FINGERPRINT_SONFICATION_ATTRIBUTES);
Michael Wright6726fd52017-06-27 00:41:45 +0100233 }
234 }
235
236 public final void vibrateError() {
237 Vibrator vibrator = mContext.getSystemService(Vibrator.class);
238 if (vibrator != null) {
Beverlyd9ec6df2018-03-20 17:19:07 -0400239 vibrator.vibrate(mErrorVibrationEffect, FINGERPRINT_SONFICATION_ATTRIBUTES);
Michael Wright6726fd52017-06-27 00:41:45 +0100240 }
241 }
242
243 private static VibrationEffect getSuccessVibrationEffect(Context ctx) {
244 int[] arr = ctx.getResources().getIntArray(
245 com.android.internal.R.array.config_longPressVibePattern);
246 final long[] vibePattern;
247 if (arr == null || arr.length == 0) {
248 vibePattern = DEFAULT_SUCCESS_VIBRATION_PATTERN;
249 } else {
250 vibePattern = new long[arr.length];
251 for (int i = 0; i < arr.length; i++) {
252 vibePattern[i] = arr[i];
253 }
254 }
255 if (vibePattern.length == 1) {
256 return VibrationEffect.createOneShot(
257 vibePattern[0], VibrationEffect.DEFAULT_AMPLITUDE);
258 } else {
259 return VibrationEffect.createWaveform(vibePattern, -1);
260 }
261 }
262
Jim Millercb2ce6f2016-04-13 20:28:18 -0700263}