1 /** 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 17 package com.android.server.fingerprint; 18 19 import android.Manifest; 20 import android.content.Context; 21 import android.hardware.fingerprint.FingerprintManager; 22 import android.hardware.fingerprint.IFingerprintDaemon; 23 import android.hardware.fingerprint.IFingerprintServiceReceiver; 24 import android.os.IBinder; 25 import android.os.RemoteException; 26 import android.util.Slog; 27 28 import java.util.NoSuchElementException; 29 30 /** 31 * Abstract base class for keeping track and dispatching events from fingerprintd to the 32 * the current client. Subclasses are responsible for coordinating the interaction with 33 * fingerprintd for the specific action (e.g. authenticate, enroll, enumerate, etc.). 34 */ 35 public abstract class ClientMonitor implements IBinder.DeathRecipient { 36 protected static final String TAG = FingerprintService.TAG; // TODO: get specific name 37 protected static final int ERROR_ESRCH = 3; // Likely fingerprintd is dead. See errno.h. 38 protected static final boolean DEBUG = FingerprintService.DEBUG; 39 private IBinder mToken; 40 private IFingerprintServiceReceiver mReceiver; 41 private int mTargetUserId; 42 private int mGroupId; 43 private boolean mIsRestricted; // True if client does not have MANAGE_FINGERPRINT permission 44 private String mOwner; 45 private Context mContext; 46 private long mHalDeviceId; 47 48 /** 49 * @param context context of FingerprintService 50 * @param halDeviceId the HAL device ID of the associated fingerprint hardware 51 * @param token a unique token for the client 52 * @param receiver recipient of related events (e.g. authentication) 53 * @param userId target user id for operation 54 * @param groupId groupId for the fingerprint set 55 * @param restricted whether or not client has the {@link Manifest#MANAGE_FINGERPRINT} 56 * permission 57 * @param owner name of the client that owns this 58 */ ClientMonitor(Context context, long halDeviceId, IBinder token, IFingerprintServiceReceiver receiver, int userId, int groupId,boolean restricted, String owner)59 public ClientMonitor(Context context, long halDeviceId, IBinder token, 60 IFingerprintServiceReceiver receiver, int userId, int groupId,boolean restricted, 61 String owner) { 62 mContext = context; 63 mHalDeviceId = halDeviceId; 64 mToken = token; 65 mReceiver = receiver; 66 mTargetUserId = userId; 67 mGroupId = groupId; 68 mIsRestricted = restricted; 69 mOwner = owner; 70 try { 71 token.linkToDeath(this, 0); 72 } catch (RemoteException e) { 73 Slog.w(TAG, "caught remote exception in linkToDeath: ", e); 74 } 75 } 76 77 /** 78 * Contacts fingerprintd to start the client. 79 * @return 0 on succes, errno from driver on failure 80 */ start()81 public abstract int start(); 82 83 /** 84 * Contacts fingerprintd to stop the client. 85 * @param initiatedByClient whether the operation is at the request of a client 86 */ stop(boolean initiatedByClient)87 public abstract int stop(boolean initiatedByClient); 88 89 /** 90 * Method to explicitly poke powermanager on events 91 */ notifyUserActivity()92 public abstract void notifyUserActivity(); 93 94 /** 95 * Gets the fingerprint daemon from the cached state in the container class. 96 */ getFingerprintDaemon()97 public abstract IFingerprintDaemon getFingerprintDaemon(); 98 99 // Event callbacks from driver. Inappropriate calls is flagged/logged by the 100 // respective client (e.g. enrolling shouldn't get authenticate events). 101 // All of these return 'true' if the operation is completed and it's ok to move 102 // to the next client (e.g. authentication accepts or rejects a fingerprint). onEnrollResult(int fingerId, int groupId, int rem)103 public abstract boolean onEnrollResult(int fingerId, int groupId, int rem); onAuthenticated(int fingerId, int groupId)104 public abstract boolean onAuthenticated(int fingerId, int groupId); onRemoved(int fingerId, int groupId)105 public abstract boolean onRemoved(int fingerId, int groupId); onEnumerationResult(int fingerId, int groupId)106 public abstract boolean onEnumerationResult(int fingerId, int groupId); 107 108 /** 109 * Called when we get notification from fingerprintd that an image has been acquired. 110 * Common to authenticate and enroll. 111 * @param acquiredInfo info about the current image acquisition 112 * @return true if client should be removed 113 */ onAcquired(int acquiredInfo)114 public boolean onAcquired(int acquiredInfo) { 115 if (mReceiver == null) 116 return true; // client not connected 117 try { 118 mReceiver.onAcquired(getHalDeviceId(), acquiredInfo); 119 return false; // acquisition continues... 120 } catch (RemoteException e) { 121 Slog.w(TAG, "Failed to invoke sendAcquired:", e); 122 return true; // client failed 123 } finally { 124 // Good scans will keep the device awake 125 if (acquiredInfo == FingerprintManager.FINGERPRINT_ACQUIRED_GOOD) { 126 notifyUserActivity(); 127 } 128 } 129 } 130 131 /** 132 * Called when we get notification from fingerprintd that an error has occurred with the 133 * current operation. Common to authenticate, enroll, enumerate and remove. 134 * @param error 135 * @return true if client should be removed 136 */ onError(int error)137 public boolean onError(int error) { 138 if (mReceiver != null) { 139 try { 140 mReceiver.onError(getHalDeviceId(), error); 141 } catch (RemoteException e) { 142 Slog.w(TAG, "Failed to invoke sendError:", e); 143 } 144 } 145 return true; // errors always remove current client 146 } 147 destroy()148 public void destroy() { 149 if (mToken != null) { 150 try { 151 mToken.unlinkToDeath(this, 0); 152 } catch (NoSuchElementException e) { 153 // TODO: remove when duplicate call bug is found 154 Slog.e(TAG, "destroy(): " + this + ":", new Exception("here")); 155 } 156 mToken = null; 157 } 158 mReceiver = null; 159 } 160 161 @Override binderDied()162 public void binderDied() { 163 mToken = null; 164 mReceiver = null; 165 onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE); 166 } 167 168 @Override finalize()169 protected void finalize() throws Throwable { 170 try { 171 if (mToken != null) { 172 if (DEBUG) Slog.w(TAG, "removing leaked reference: " + mToken); 173 onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE); 174 } 175 } finally { 176 super.finalize(); 177 } 178 } 179 getContext()180 public final Context getContext() { 181 return mContext; 182 } 183 getHalDeviceId()184 public final long getHalDeviceId() { 185 return mHalDeviceId; 186 } 187 getOwnerString()188 public final String getOwnerString() { 189 return mOwner; 190 } 191 getReceiver()192 public final IFingerprintServiceReceiver getReceiver() { 193 return mReceiver; 194 } 195 getIsRestricted()196 public final boolean getIsRestricted() { 197 return mIsRestricted; 198 } 199 getTargetUserId()200 public final int getTargetUserId() { 201 return mTargetUserId; 202 } 203 getGroupId()204 public final int getGroupId() { 205 return mGroupId; 206 } 207 getToken()208 public final IBinder getToken() { 209 return mToken; 210 } 211 } 212