Home | History | Annotate | Download | only in fingerprint
      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      */
     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      */
     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      */
     87     public abstract int stop(boolean initiatedByClient);
     88 
     89     /**
     90      * Method to explicitly poke powermanager on events
     91      */
     92     public abstract void notifyUserActivity();
     93 
     94     /**
     95      * Gets the fingerprint daemon from the cached state in the container class.
     96      */
     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).
    103     public abstract boolean onEnrollResult(int fingerId, int groupId, int rem);
    104     public abstract boolean onAuthenticated(int fingerId, int groupId);
    105     public abstract boolean onRemoved(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      */
    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      */
    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 
    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
    162     public void binderDied() {
    163         mToken = null;
    164         mReceiver = null;
    165         onError(FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE);
    166     }
    167 
    168     @Override
    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 
    180     public final Context getContext() {
    181         return mContext;
    182     }
    183 
    184     public final long getHalDeviceId() {
    185         return mHalDeviceId;
    186     }
    187 
    188     public final String getOwnerString() {
    189         return mOwner;
    190     }
    191 
    192     public final IFingerprintServiceReceiver getReceiver() {
    193         return mReceiver;
    194     }
    195 
    196     public final boolean getIsRestricted() {
    197         return mIsRestricted;
    198     }
    199 
    200     public final int getTargetUserId() {
    201         return mTargetUserId;
    202     }
    203 
    204     public final int getGroupId() {
    205         return mGroupId;
    206     }
    207 
    208     public final IBinder getToken() {
    209         return mToken;
    210     }
    211 }
    212