Home | History | Annotate | Download | only in fingerprint
      1 /*
      2  * Copyright (C) 2014 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 static android.Manifest.permission.INTERACT_ACROSS_USERS;
     20 import static android.Manifest.permission.MANAGE_FINGERPRINT;
     21 import static android.Manifest.permission.RESET_FINGERPRINT_LOCKOUT;
     22 import static android.Manifest.permission.USE_BIOMETRIC;
     23 import static android.Manifest.permission.USE_FINGERPRINT;
     24 import static android.app.ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE;
     25 
     26 import android.app.ActivityManager;
     27 import android.app.ActivityManager.RunningAppProcessInfo;
     28 import android.app.AlarmManager;
     29 import android.app.AppOpsManager;
     30 import android.app.IActivityManager;
     31 import android.app.PendingIntent;
     32 import android.app.SynchronousUserSwitchObserver;
     33 import android.app.TaskStackListener;
     34 import android.content.BroadcastReceiver;
     35 import android.content.ComponentName;
     36 import android.content.Context;
     37 import android.content.Intent;
     38 import android.content.IntentFilter;
     39 import android.content.pm.PackageManager;
     40 import android.content.pm.UserInfo;
     41 import android.hardware.biometrics.IBiometricPromptReceiver;
     42 import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprint;
     43 import android.hardware.biometrics.fingerprint.V2_1.IBiometricsFingerprintClientCallback;
     44 import android.hardware.fingerprint.Fingerprint;
     45 import android.hardware.fingerprint.FingerprintManager;
     46 import android.hardware.fingerprint.IFingerprintClientActiveCallback;
     47 import android.hardware.fingerprint.IFingerprintService;
     48 import android.hardware.fingerprint.IFingerprintServiceLockoutResetCallback;
     49 import android.hardware.fingerprint.IFingerprintServiceReceiver;
     50 import android.os.Binder;
     51 import android.os.Build;
     52 import android.os.Bundle;
     53 import android.os.DeadObjectException;
     54 import android.os.Environment;
     55 import android.os.Handler;
     56 import android.os.IBinder;
     57 import android.os.IHwBinder;
     58 import android.os.IRemoteCallback;
     59 import android.os.PowerManager;
     60 import android.os.PowerManager.WakeLock;
     61 import android.os.RemoteException;
     62 import android.os.SELinux;
     63 import android.os.ServiceManager;
     64 import android.os.SystemClock;
     65 import android.os.UserHandle;
     66 import android.os.UserManager;
     67 import android.security.KeyStore;
     68 import android.util.Slog;
     69 import android.util.SparseBooleanArray;
     70 import android.util.SparseIntArray;
     71 import android.util.proto.ProtoOutputStream;
     72 
     73 import com.android.internal.annotations.GuardedBy;
     74 import com.android.internal.logging.MetricsLogger;
     75 import com.android.internal.statusbar.IStatusBarService;
     76 import com.android.internal.util.DumpUtils;
     77 import com.android.server.SystemServerInitThreadPool;
     78 import com.android.server.SystemService;
     79 
     80 import org.json.JSONArray;
     81 import org.json.JSONException;
     82 import org.json.JSONObject;
     83 
     84 import java.io.File;
     85 import java.io.FileDescriptor;
     86 import java.io.PrintWriter;
     87 import java.util.ArrayList;
     88 import java.util.Collections;
     89 import java.util.HashMap;
     90 import java.util.List;
     91 import java.util.Map;
     92 import java.util.concurrent.CopyOnWriteArrayList;
     93 
     94 /**
     95  * A service to manage multiple clients that want to access the fingerprint HAL API.
     96  * The service is responsible for maintaining a list of clients and dispatching all
     97  * fingerprint-related events.
     98  *
     99  * @hide
    100  */
    101 public class FingerprintService extends SystemService implements IHwBinder.DeathRecipient {
    102     static final String TAG = "FingerprintService";
    103     static final boolean DEBUG = true;
    104     private static final boolean CLEANUP_UNUSED_FP = true;
    105     private static final String FP_DATA_DIR = "fpdata";
    106     private static final int MSG_USER_SWITCHING = 10;
    107     private static final String ACTION_LOCKOUT_RESET =
    108             "com.android.server.fingerprint.ACTION_LOCKOUT_RESET";
    109     private static final String KEY_LOCKOUT_RESET_USER = "lockout_reset_user";
    110 
    111     private class PerformanceStats {
    112         int accept; // number of accepted fingerprints
    113         int reject; // number of rejected fingerprints
    114         int acquire; // total number of acquisitions. Should be >= accept+reject due to poor image
    115                      // acquisition in some cases (too fast, too slow, dirty sensor, etc.)
    116         int lockout; // total number of lockouts
    117         int permanentLockout; // total number of permanent lockouts
    118     }
    119 
    120     private final ArrayList<FingerprintServiceLockoutResetMonitor> mLockoutMonitors =
    121             new ArrayList<>();
    122     private final CopyOnWriteArrayList<IFingerprintClientActiveCallback> mClientActiveCallbacks =
    123             new CopyOnWriteArrayList<>();
    124     private final Map<Integer, Long> mAuthenticatorIds =
    125             Collections.synchronizedMap(new HashMap<>());
    126     private final AppOpsManager mAppOps;
    127     private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30*1000;
    128     private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_TIMED = 5;
    129     private static final int MAX_FAILED_ATTEMPTS_LOCKOUT_PERMANENT = 20;
    130 
    131     private static final long CANCEL_TIMEOUT_LIMIT = 3000; // max wait for onCancel() from HAL,in ms
    132     private final String mKeyguardPackage;
    133     private int mCurrentUserId = UserHandle.USER_NULL;
    134     private final FingerprintUtils mFingerprintUtils = FingerprintUtils.getInstance();
    135     private Context mContext;
    136     private long mHalDeviceId;
    137     private SparseBooleanArray mTimedLockoutCleared;
    138     private SparseIntArray mFailedAttempts;
    139     @GuardedBy("this")
    140     private IBiometricsFingerprint mDaemon;
    141     private IStatusBarService mStatusBarService;
    142     private final IActivityManager mActivityManager;
    143     private final PowerManager mPowerManager;
    144     private final AlarmManager mAlarmManager;
    145     private final UserManager mUserManager;
    146     private ClientMonitor mCurrentClient;
    147     private ClientMonitor mPendingClient;
    148     private PerformanceStats mPerformanceStats;
    149 
    150     private IBinder mToken = new Binder(); // used for internal FingerprintService enumeration
    151     private ArrayList<UserFingerprint> mUnknownFingerprints = new ArrayList<>(); // hw fingerprints
    152 
    153     private class UserFingerprint {
    154         Fingerprint f;
    155         int userId;
    156         public UserFingerprint(Fingerprint f, int userId) {
    157             this.f = f;
    158             this.userId = userId;
    159         }
    160     }
    161 
    162     // Normal fingerprint authentications are tracked by mPerformanceMap.
    163     private HashMap<Integer, PerformanceStats> mPerformanceMap = new HashMap<>();
    164 
    165     // Transactions that make use of CryptoObjects are tracked by mCryptoPerformaceMap.
    166     private HashMap<Integer, PerformanceStats> mCryptoPerformanceMap = new HashMap<>();
    167 
    168     private Handler mHandler = new Handler() {
    169         @Override
    170         public void handleMessage(android.os.Message msg) {
    171             switch (msg.what) {
    172                 case MSG_USER_SWITCHING:
    173                     handleUserSwitching(msg.arg1);
    174                     break;
    175 
    176                 default:
    177                     Slog.w(TAG, "Unknown message:" + msg.what);
    178             }
    179         }
    180     };
    181 
    182     private final BroadcastReceiver mLockoutReceiver = new BroadcastReceiver() {
    183         @Override
    184         public void onReceive(Context context, Intent intent) {
    185             if (ACTION_LOCKOUT_RESET.equals(intent.getAction())) {
    186                 final int user = intent.getIntExtra(KEY_LOCKOUT_RESET_USER, 0);
    187                 resetFailedAttemptsForUser(false /* clearAttemptCounter */, user);
    188             }
    189         }
    190     };
    191 
    192     private final Runnable mResetFailedAttemptsForCurrentUserRunnable = new Runnable() {
    193         @Override
    194         public void run() {
    195             resetFailedAttemptsForUser(true /* clearAttemptCounter */,
    196                     ActivityManager.getCurrentUser());
    197         }
    198     };
    199 
    200     private final Runnable mResetClientState = new Runnable() {
    201         @Override
    202         public void run() {
    203             // Warning: if we get here, the driver never confirmed our call to cancel the current
    204             // operation (authenticate, enroll, remove, enumerate, etc), which is
    205             // really bad.  The result will be a 3-second delay in starting each new client.
    206             // If you see this on a device, make certain the driver notifies with
    207             // {@link FingerprintManager#FINGERPRINT_ERROR_CANCEL} in response to cancel()
    208             // once it has successfully switched to the IDLE state in the fingerprint HAL.
    209             // Additionally,{@link FingerprintManager#FINGERPRINT_ERROR_CANCEL} should only be sent
    210             // in response to an actual cancel() call.
    211             Slog.w(TAG, "Client "
    212                     + (mCurrentClient != null ? mCurrentClient.getOwnerString() : "null")
    213                     + " failed to respond to cancel, starting client "
    214                     + (mPendingClient != null ? mPendingClient.getOwnerString() : "null"));
    215 
    216             mCurrentClient = null;
    217             startClient(mPendingClient, false);
    218         }
    219     };
    220 
    221     private final TaskStackListener mTaskStackListener = new TaskStackListener() {
    222         @Override
    223         public void onTaskStackChanged() {
    224             try {
    225                 if (!(mCurrentClient instanceof AuthenticationClient)) {
    226                     return;
    227                 }
    228                 final String currentClient = mCurrentClient.getOwnerString();
    229                 if (isKeyguard(currentClient)) {
    230                     return; // Keyguard is always allowed
    231                 }
    232                 List<ActivityManager.RunningTaskInfo> runningTasks = mActivityManager.getTasks(1);
    233                 if (!runningTasks.isEmpty()) {
    234                     final String topPackage = runningTasks.get(0).topActivity.getPackageName();
    235                     if (!topPackage.contentEquals(currentClient)) {
    236                         Slog.e(TAG, "Stopping background authentication, top: " + topPackage
    237                                 + " currentClient: " + currentClient);
    238                         mCurrentClient.stop(false /* initiatedByClient */);
    239                     }
    240                 }
    241             } catch (RemoteException e) {
    242                 Slog.e(TAG, "Unable to get running tasks", e);
    243             }
    244         }
    245     };
    246 
    247     public FingerprintService(Context context) {
    248         super(context);
    249         mContext = context;
    250         mKeyguardPackage = ComponentName.unflattenFromString(context.getResources().getString(
    251                 com.android.internal.R.string.config_keyguardComponent)).getPackageName();
    252         mAppOps = context.getSystemService(AppOpsManager.class);
    253         mPowerManager = mContext.getSystemService(PowerManager.class);
    254         mAlarmManager = mContext.getSystemService(AlarmManager.class);
    255         mContext.registerReceiver(mLockoutReceiver, new IntentFilter(ACTION_LOCKOUT_RESET),
    256                 RESET_FINGERPRINT_LOCKOUT, null /* handler */);
    257         mUserManager = UserManager.get(mContext);
    258         mTimedLockoutCleared = new SparseBooleanArray();
    259         mFailedAttempts = new SparseIntArray();
    260         mStatusBarService = IStatusBarService.Stub.asInterface(
    261                 ServiceManager.getService(Context.STATUS_BAR_SERVICE));
    262         mActivityManager = ((ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE))
    263                 .getService();
    264     }
    265 
    266     @Override
    267     public void serviceDied(long cookie) {
    268         Slog.v(TAG, "fingerprint HAL died");
    269         MetricsLogger.count(mContext, "fingerprintd_died", 1);
    270         handleError(mHalDeviceId, FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE,
    271                 0 /*vendorCode */);
    272     }
    273 
    274     public synchronized IBiometricsFingerprint getFingerprintDaemon() {
    275         if (mDaemon == null) {
    276             Slog.v(TAG, "mDaemon was null, reconnect to fingerprint");
    277             try {
    278                 mDaemon = IBiometricsFingerprint.getService();
    279             } catch (java.util.NoSuchElementException e) {
    280                 // Service doesn't exist or cannot be opened. Logged below.
    281             } catch (RemoteException e) {
    282                 Slog.e(TAG, "Failed to get biometric interface", e);
    283             }
    284             if (mDaemon == null) {
    285                 Slog.w(TAG, "fingerprint HIDL not available");
    286                 return null;
    287             }
    288 
    289             mDaemon.asBinder().linkToDeath(this, 0);
    290 
    291             try {
    292                 mHalDeviceId = mDaemon.setNotify(mDaemonCallback);
    293             } catch (RemoteException e) {
    294                 Slog.e(TAG, "Failed to open fingerprint HAL", e);
    295                 mDaemon = null; // try again later!
    296             }
    297 
    298             if (DEBUG) Slog.v(TAG, "Fingerprint HAL id: " + mHalDeviceId);
    299             if (mHalDeviceId != 0) {
    300                 loadAuthenticatorIds();
    301                 updateActiveGroup(ActivityManager.getCurrentUser(), null);
    302                 doFingerprintCleanupForUser(ActivityManager.getCurrentUser());
    303             } else {
    304                 Slog.w(TAG, "Failed to open Fingerprint HAL!");
    305                 MetricsLogger.count(mContext, "fingerprintd_openhal_error", 1);
    306                 mDaemon = null;
    307             }
    308         }
    309         return mDaemon;
    310     }
    311 
    312     /** Populates existing authenticator ids. To be used only during the start of the service. */
    313     private void loadAuthenticatorIds() {
    314         // This operation can be expensive, so keep track of the elapsed time. Might need to move to
    315         // background if it takes too long.
    316         long t = System.currentTimeMillis();
    317         mAuthenticatorIds.clear();
    318         for (UserInfo user : UserManager.get(mContext).getUsers(true /* excludeDying */)) {
    319             int userId = getUserOrWorkProfileId(null, user.id);
    320             if (!mAuthenticatorIds.containsKey(userId)) {
    321                 updateActiveGroup(userId, null);
    322             }
    323         }
    324 
    325         t = System.currentTimeMillis() - t;
    326         if (t > 1000) {
    327             Slog.w(TAG, "loadAuthenticatorIds() taking too long: " + t + "ms");
    328         }
    329     }
    330 
    331     /**
    332      * This method should be called upon connection to the daemon, and when user switches.
    333      * @param userId
    334      */
    335     private void doFingerprintCleanupForUser(int userId) {
    336         if (CLEANUP_UNUSED_FP) {
    337             enumerateUser(userId);
    338         }
    339     }
    340 
    341     private void clearEnumerateState() {
    342         if (DEBUG) Slog.v(TAG, "clearEnumerateState()");
    343         mUnknownFingerprints.clear();
    344     }
    345 
    346     private void enumerateUser(int userId) {
    347         if (DEBUG) Slog.v(TAG, "Enumerating user(" + userId + ")");
    348         boolean restricted = !hasPermission(MANAGE_FINGERPRINT);
    349         startEnumerate(mToken, userId, null, restricted, true /* internal */);
    350     }
    351 
    352     // Remove unknown fingerprints from hardware
    353     private void cleanupUnknownFingerprints() {
    354         if (!mUnknownFingerprints.isEmpty()) {
    355             UserFingerprint uf = mUnknownFingerprints.get(0);
    356             mUnknownFingerprints.remove(uf);
    357             boolean restricted = !hasPermission(MANAGE_FINGERPRINT);
    358             startRemove(mToken, uf.f.getFingerId(), uf.f.getGroupId(), uf.userId, null,
    359                     restricted, true /* internal */);
    360         } else {
    361             clearEnumerateState();
    362         }
    363     }
    364 
    365     protected void handleEnumerate(long deviceId, int fingerId, int groupId, int remaining) {
    366         ClientMonitor client = mCurrentClient;
    367 
    368         if ( !(client instanceof InternalRemovalClient) && !(client instanceof EnumerateClient) ) {
    369             return;
    370         }
    371         client.onEnumerationResult(fingerId, groupId, remaining);
    372 
    373         // All fingerprints in hardware for this user were enumerated
    374         if (remaining == 0) {
    375             if (client instanceof InternalEnumerateClient) {
    376                 List<Fingerprint> unknownFingerprints =
    377                         ((InternalEnumerateClient) client).getUnknownFingerprints();
    378 
    379                 if (!unknownFingerprints.isEmpty()) {
    380                     Slog.w(TAG, "Adding " + unknownFingerprints.size() +
    381                             " fingerprints for deletion");
    382                 }
    383                 for (Fingerprint f : unknownFingerprints) {
    384                     mUnknownFingerprints.add(new UserFingerprint(f, client.getTargetUserId()));
    385                 }
    386                 removeClient(client);
    387                 cleanupUnknownFingerprints();
    388             } else {
    389                 removeClient(client);
    390             }
    391         }
    392     }
    393 
    394     protected void handleError(long deviceId, int error, int vendorCode) {
    395         ClientMonitor client = mCurrentClient;
    396         if (client instanceof InternalRemovalClient || client instanceof InternalEnumerateClient) {
    397             clearEnumerateState();
    398         }
    399         if (client != null && client.onError(error, vendorCode)) {
    400             removeClient(client);
    401         }
    402 
    403         if (DEBUG) Slog.v(TAG, "handleError(client="
    404                 + (client != null ? client.getOwnerString() : "null") + ", error = " + error + ")");
    405         // This is the magic code that starts the next client when the old client finishes.
    406         if (error == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
    407             mHandler.removeCallbacks(mResetClientState);
    408             if (mPendingClient != null) {
    409                 if (DEBUG) Slog.v(TAG, "start pending client " + mPendingClient.getOwnerString());
    410                 startClient(mPendingClient, false);
    411                 mPendingClient = null;
    412             }
    413         } else if (error == FingerprintManager.FINGERPRINT_ERROR_HW_UNAVAILABLE) {
    414             // If we get HW_UNAVAILABLE, try to connect again later...
    415             Slog.w(TAG, "Got ERROR_HW_UNAVAILABLE; try reconnecting next client.");
    416             synchronized (this) {
    417                 mDaemon = null;
    418                 mHalDeviceId = 0;
    419                 mCurrentUserId = UserHandle.USER_NULL;
    420             }
    421         }
    422     }
    423 
    424     protected void handleRemoved(long deviceId, int fingerId, int groupId, int remaining) {
    425         if (DEBUG) Slog.w(TAG, "Removed: fid=" + fingerId
    426                 + ", gid=" + groupId
    427                 + ", dev=" + deviceId
    428                 + ", rem=" + remaining);
    429 
    430         ClientMonitor client = mCurrentClient;
    431         if (client != null && client.onRemoved(fingerId, groupId, remaining)) {
    432             removeClient(client);
    433             // When the last fingerprint of a group is removed, update the authenticator id
    434             if (!hasEnrolledFingerprints(groupId)) {
    435                 updateActiveGroup(groupId, null);
    436             }
    437         }
    438         if (client instanceof InternalRemovalClient && !mUnknownFingerprints.isEmpty()) {
    439             cleanupUnknownFingerprints();
    440         } else if (client instanceof InternalRemovalClient){
    441             clearEnumerateState();
    442         }
    443     }
    444 
    445     protected void handleAuthenticated(long deviceId, int fingerId, int groupId,
    446             ArrayList<Byte> token) {
    447         ClientMonitor client = mCurrentClient;
    448         if (fingerId != 0) {
    449             // Ugh...
    450             final byte[] byteToken = new byte[token.size()];
    451             for (int i = 0; i < token.size(); i++) {
    452                 byteToken[i] = token.get(i);
    453             }
    454             // Send to Keystore
    455             KeyStore.getInstance().addAuthToken(byteToken);
    456         }
    457         if (client != null && client.onAuthenticated(fingerId, groupId)) {
    458             removeClient(client);
    459         }
    460         if (fingerId != 0) {
    461             mPerformanceStats.accept++;
    462         } else {
    463             mPerformanceStats.reject++;
    464         }
    465     }
    466 
    467     protected void handleAcquired(long deviceId, int acquiredInfo, int vendorCode) {
    468         ClientMonitor client = mCurrentClient;
    469         if (client != null && client.onAcquired(acquiredInfo, vendorCode)) {
    470             removeClient(client);
    471         }
    472         if (mPerformanceStats != null && getLockoutMode() == AuthenticationClient.LOCKOUT_NONE
    473                 && client instanceof AuthenticationClient) {
    474             // ignore enrollment acquisitions or acquisitions when we're locked out
    475             mPerformanceStats.acquire++;
    476         }
    477     }
    478 
    479     protected void handleEnrollResult(long deviceId, int fingerId, int groupId, int remaining) {
    480         ClientMonitor client = mCurrentClient;
    481         if (client != null && client.onEnrollResult(fingerId, groupId, remaining)) {
    482             removeClient(client);
    483             // When enrollment finishes, update this group's authenticator id, as the HAL has
    484             // already generated a new authenticator id when the new fingerprint is enrolled.
    485             updateActiveGroup(groupId, null);
    486         }
    487     }
    488 
    489     private void userActivity() {
    490         long now = SystemClock.uptimeMillis();
    491         mPowerManager.userActivity(now, PowerManager.USER_ACTIVITY_EVENT_TOUCH, 0);
    492     }
    493 
    494     void handleUserSwitching(int userId) {
    495         if (mCurrentClient instanceof InternalRemovalClient
    496                 || mCurrentClient instanceof InternalEnumerateClient) {
    497             Slog.w(TAG, "User switched while performing cleanup");
    498             removeClient(mCurrentClient);
    499             clearEnumerateState();
    500         }
    501         updateActiveGroup(userId, null);
    502         doFingerprintCleanupForUser(userId);
    503     }
    504 
    505     private void removeClient(ClientMonitor client) {
    506         if (client != null) {
    507             client.destroy();
    508             if (client != mCurrentClient && mCurrentClient != null) {
    509                 Slog.w(TAG, "Unexpected client: " + client.getOwnerString() + "expected: "
    510                         + mCurrentClient != null ? mCurrentClient.getOwnerString() : "null");
    511             }
    512         }
    513         if (mCurrentClient != null) {
    514             if (DEBUG) Slog.v(TAG, "Done with client: " + client.getOwnerString());
    515             mCurrentClient = null;
    516         }
    517         if (mPendingClient == null) {
    518             notifyClientActiveCallbacks(false);
    519         }
    520     }
    521 
    522     private int getLockoutMode() {
    523         final int currentUser = ActivityManager.getCurrentUser();
    524         final int failedAttempts = mFailedAttempts.get(currentUser, 0);
    525         if (failedAttempts >= MAX_FAILED_ATTEMPTS_LOCKOUT_PERMANENT) {
    526             return AuthenticationClient.LOCKOUT_PERMANENT;
    527         } else if (failedAttempts > 0 &&
    528                 mTimedLockoutCleared.get(currentUser, false) == false
    529                 && (failedAttempts % MAX_FAILED_ATTEMPTS_LOCKOUT_TIMED == 0)) {
    530             return AuthenticationClient.LOCKOUT_TIMED;
    531         }
    532         return AuthenticationClient.LOCKOUT_NONE;
    533     }
    534 
    535     private void scheduleLockoutResetForUser(int userId) {
    536         mAlarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP,
    537                 SystemClock.elapsedRealtime() + FAIL_LOCKOUT_TIMEOUT_MS,
    538                 getLockoutResetIntentForUser(userId));
    539     }
    540 
    541     private void cancelLockoutResetForUser(int userId) {
    542         mAlarmManager.cancel(getLockoutResetIntentForUser(userId));
    543     }
    544 
    545     private PendingIntent getLockoutResetIntentForUser(int userId) {
    546         return PendingIntent.getBroadcast(mContext, userId,
    547                 new Intent(ACTION_LOCKOUT_RESET).putExtra(KEY_LOCKOUT_RESET_USER, userId),
    548                 PendingIntent.FLAG_UPDATE_CURRENT);
    549     }
    550 
    551     public long startPreEnroll(IBinder token) {
    552         IBiometricsFingerprint daemon = getFingerprintDaemon();
    553         if (daemon == null) {
    554             Slog.w(TAG, "startPreEnroll: no fingerprint HAL!");
    555             return 0;
    556         }
    557         try {
    558             return daemon.preEnroll();
    559         } catch (RemoteException e) {
    560             Slog.e(TAG, "startPreEnroll failed", e);
    561         }
    562         return 0;
    563     }
    564 
    565     public int startPostEnroll(IBinder token) {
    566         IBiometricsFingerprint daemon = getFingerprintDaemon();
    567         if (daemon == null) {
    568             Slog.w(TAG, "startPostEnroll: no fingerprint HAL!");
    569             return 0;
    570         }
    571         try {
    572             return daemon.postEnroll();
    573         } catch (RemoteException e) {
    574             Slog.e(TAG, "startPostEnroll failed", e);
    575         }
    576         return 0;
    577     }
    578 
    579     /**
    580      * Calls fingerprint HAL to switch states to the new task. If there's already a current task,
    581      * it calls cancel() and sets mPendingClient to begin when the current task finishes
    582      * ({@link FingerprintManager#FINGERPRINT_ERROR_CANCELED}).
    583      * @param newClient the new client that wants to connect
    584      * @param initiatedByClient true for authenticate, remove and enroll
    585      */
    586     private void startClient(ClientMonitor newClient, boolean initiatedByClient) {
    587         ClientMonitor currentClient = mCurrentClient;
    588         if (currentClient != null) {
    589             if (DEBUG) Slog.v(TAG, "request stop current client " + currentClient.getOwnerString());
    590             if (currentClient instanceof InternalEnumerateClient ||
    591                     currentClient instanceof InternalRemovalClient) {
    592                 // This condition means we're currently running internal diagnostics to
    593                 // remove extra fingerprints in the hardware and/or the software
    594                 // TODO: design an escape hatch in case client never finishes
    595                 if (newClient != null) {
    596                     Slog.w(TAG, "Internal cleanup in progress but trying to start client "
    597                             + newClient.getClass().getSuperclass().getSimpleName()
    598                             + "(" + newClient.getOwnerString() + ")"
    599                             + ", initiatedByClient = " + initiatedByClient);
    600                 }
    601             }
    602             else {
    603                 currentClient.stop(initiatedByClient);
    604             }
    605             mPendingClient = newClient;
    606             mHandler.removeCallbacks(mResetClientState);
    607             mHandler.postDelayed(mResetClientState, CANCEL_TIMEOUT_LIMIT);
    608         } else if (newClient != null) {
    609             mCurrentClient = newClient;
    610             if (DEBUG) Slog.v(TAG, "starting client "
    611                     + newClient.getClass().getSuperclass().getSimpleName()
    612                     + "(" + newClient.getOwnerString() + ")"
    613                     + ", initiatedByClient = " + initiatedByClient);
    614             notifyClientActiveCallbacks(true);
    615 
    616             newClient.start();
    617         }
    618     }
    619 
    620     void startRemove(IBinder token, int fingerId, int groupId, int userId,
    621             IFingerprintServiceReceiver receiver, boolean restricted, boolean internal) {
    622         if (token == null) {
    623             Slog.w(TAG, "startRemove: token is null");
    624             return;
    625         }
    626         if (receiver == null) {
    627             Slog.w(TAG, "startRemove: receiver is null");
    628             return;
    629         }
    630 
    631         IBiometricsFingerprint daemon = getFingerprintDaemon();
    632         if (daemon == null) {
    633             Slog.w(TAG, "startRemove: no fingerprint HAL!");
    634             return;
    635         }
    636 
    637         if (internal) {
    638             Context context = getContext();
    639             InternalRemovalClient client = new InternalRemovalClient(context, mHalDeviceId,
    640                     token, receiver, fingerId, groupId, userId, restricted,
    641                     context.getOpPackageName()) {
    642                 @Override
    643                 public void notifyUserActivity() {
    644 
    645                 }
    646                 @Override
    647                 public IBiometricsFingerprint getFingerprintDaemon() {
    648                     return FingerprintService.this.getFingerprintDaemon();
    649                 }
    650             };
    651             startClient(client, true);
    652         }
    653         else {
    654             RemovalClient client = new RemovalClient(getContext(), mHalDeviceId, token,
    655                     receiver, fingerId, groupId, userId, restricted, token.toString()) {
    656                 @Override
    657                 public void notifyUserActivity() {
    658                     FingerprintService.this.userActivity();
    659                 }
    660 
    661                 @Override
    662                 public IBiometricsFingerprint getFingerprintDaemon() {
    663                     return FingerprintService.this.getFingerprintDaemon();
    664                 }
    665             };
    666             startClient(client, true);
    667         }
    668     }
    669 
    670     void startEnumerate(IBinder token, int userId,
    671         IFingerprintServiceReceiver receiver, boolean restricted, boolean internal) {
    672         IBiometricsFingerprint daemon = getFingerprintDaemon();
    673         if (daemon == null) {
    674             Slog.w(TAG, "startEnumerate: no fingerprint HAL!");
    675             return;
    676         }
    677         if (internal) {
    678             List<Fingerprint> enrolledList = getEnrolledFingerprints(userId);
    679             Context context = getContext();
    680             InternalEnumerateClient client = new InternalEnumerateClient(context, mHalDeviceId,
    681                     token, receiver, userId, userId, restricted, context.getOpPackageName(),
    682                     enrolledList) {
    683                 @Override
    684                 public void notifyUserActivity() {
    685 
    686                 }
    687 
    688                 @Override
    689                 public IBiometricsFingerprint getFingerprintDaemon() {
    690                     return FingerprintService.this.getFingerprintDaemon();
    691                 }
    692             };
    693             startClient(client, true);
    694         }
    695         else {
    696             EnumerateClient client = new EnumerateClient(getContext(), mHalDeviceId, token,
    697                     receiver, userId, userId, restricted, token.toString()) {
    698                 @Override
    699                 public void notifyUserActivity() {
    700                     FingerprintService.this.userActivity();
    701                 }
    702 
    703                 @Override
    704                 public IBiometricsFingerprint getFingerprintDaemon() {
    705                     return FingerprintService.this.getFingerprintDaemon();
    706                 }
    707             };
    708             startClient(client, true);
    709         }
    710     }
    711 
    712     public List<Fingerprint> getEnrolledFingerprints(int userId) {
    713         return mFingerprintUtils.getFingerprintsForUser(mContext, userId);
    714     }
    715 
    716     public boolean hasEnrolledFingerprints(int userId) {
    717         if (userId != UserHandle.getCallingUserId()) {
    718             checkPermission(INTERACT_ACROSS_USERS);
    719         }
    720         return mFingerprintUtils.getFingerprintsForUser(mContext, userId).size() > 0;
    721     }
    722 
    723     boolean hasPermission(String permission) {
    724         return getContext().checkCallingOrSelfPermission(permission)
    725                 == PackageManager.PERMISSION_GRANTED;
    726     }
    727 
    728     void checkPermission(String permission) {
    729         getContext().enforceCallingOrSelfPermission(permission,
    730                 "Must have " + permission + " permission.");
    731     }
    732 
    733     int getEffectiveUserId(int userId) {
    734         UserManager um = UserManager.get(mContext);
    735         if (um != null) {
    736             final long callingIdentity = Binder.clearCallingIdentity();
    737             userId = um.getCredentialOwnerProfile(userId);
    738             Binder.restoreCallingIdentity(callingIdentity);
    739         } else {
    740             Slog.e(TAG, "Unable to acquire UserManager");
    741         }
    742         return userId;
    743     }
    744 
    745     boolean isCurrentUserOrProfile(int userId) {
    746         UserManager um = UserManager.get(mContext);
    747         if (um == null) {
    748             Slog.e(TAG, "Unable to acquire UserManager");
    749             return false;
    750         }
    751 
    752         final long token = Binder.clearCallingIdentity();
    753         try {
    754             // Allow current user or profiles of the current user...
    755             for (int profileId : um.getEnabledProfileIds(ActivityManager.getCurrentUser())) {
    756                 if (profileId == userId) {
    757                     return true;
    758                 }
    759             }
    760         } finally {
    761             Binder.restoreCallingIdentity(token);
    762         }
    763 
    764         return false;
    765     }
    766 
    767     private boolean isForegroundActivity(int uid, int pid) {
    768         try {
    769             List<RunningAppProcessInfo> procs =
    770                     ActivityManager.getService().getRunningAppProcesses();
    771             int N = procs.size();
    772             for (int i = 0; i < N; i++) {
    773                 RunningAppProcessInfo proc = procs.get(i);
    774                 if (proc.pid == pid && proc.uid == uid
    775                         && proc.importance <= IMPORTANCE_FOREGROUND_SERVICE) {
    776                     return true;
    777                 }
    778             }
    779         } catch (RemoteException e) {
    780             Slog.w(TAG, "am.getRunningAppProcesses() failed");
    781         }
    782         return false;
    783     }
    784 
    785     /**
    786      * @param opPackageName name of package for caller
    787      * @param requireForeground only allow this call while app is in the foreground
    788      * @return true if caller can use fingerprint API
    789      */
    790     private boolean canUseFingerprint(String opPackageName, boolean requireForeground, int uid,
    791             int pid, int userId) {
    792         if (getContext().checkCallingPermission(USE_FINGERPRINT)
    793                 != PackageManager.PERMISSION_GRANTED) {
    794             checkPermission(USE_BIOMETRIC);
    795         }
    796 
    797         if (isKeyguard(opPackageName)) {
    798             return true; // Keyguard is always allowed
    799         }
    800         if (!isCurrentUserOrProfile(userId)) {
    801             Slog.w(TAG,"Rejecting " + opPackageName + " ; not a current user or profile");
    802             return false;
    803         }
    804         if (mAppOps.noteOp(AppOpsManager.OP_USE_FINGERPRINT, uid, opPackageName)
    805                 != AppOpsManager.MODE_ALLOWED) {
    806             Slog.w(TAG, "Rejecting " + opPackageName + " ; permission denied");
    807             return false;
    808         }
    809         if (requireForeground && !(isForegroundActivity(uid, pid) || currentClient(opPackageName))){
    810             Slog.w(TAG, "Rejecting " + opPackageName + " ; not in foreground");
    811             return false;
    812         }
    813         return true;
    814     }
    815 
    816     /**
    817      * @param opPackageName package of the caller
    818      * @return true if this is the same client currently using fingerprint
    819      */
    820     private boolean currentClient(String opPackageName) {
    821         return mCurrentClient != null && mCurrentClient.getOwnerString().equals(opPackageName);
    822     }
    823 
    824     /**
    825      * @param clientPackage
    826      * @return true if this is keyguard package
    827      */
    828     private boolean isKeyguard(String clientPackage) {
    829         return mKeyguardPackage.equals(clientPackage);
    830     }
    831 
    832     private void addLockoutResetMonitor(FingerprintServiceLockoutResetMonitor monitor) {
    833         if (!mLockoutMonitors.contains(monitor)) {
    834             mLockoutMonitors.add(monitor);
    835         }
    836     }
    837 
    838     private void removeLockoutResetCallback(
    839             FingerprintServiceLockoutResetMonitor monitor) {
    840         mLockoutMonitors.remove(monitor);
    841     }
    842 
    843     private void notifyLockoutResetMonitors() {
    844         for (int i = 0; i < mLockoutMonitors.size(); i++) {
    845             mLockoutMonitors.get(i).sendLockoutReset();
    846         }
    847     }
    848 
    849     private void notifyClientActiveCallbacks(boolean isActive) {
    850         List<IFingerprintClientActiveCallback> callbacks = mClientActiveCallbacks;
    851         for (int i = 0; i < callbacks.size(); i++) {
    852             try {
    853                 callbacks.get(i).onClientActiveChanged(isActive);
    854             } catch (RemoteException re) {
    855                 // If the remote is dead, stop notifying it
    856                 mClientActiveCallbacks.remove(callbacks.get(i));
    857             }
    858         }
    859     }
    860 
    861     private void startAuthentication(IBinder token, long opId, int callingUserId, int groupId,
    862                 IFingerprintServiceReceiver receiver, int flags, boolean restricted,
    863                 String opPackageName, Bundle bundle, IBiometricPromptReceiver dialogReceiver) {
    864         updateActiveGroup(groupId, opPackageName);
    865 
    866         if (DEBUG) Slog.v(TAG, "startAuthentication(" + opPackageName + ")");
    867 
    868         AuthenticationClient client = new AuthenticationClient(getContext(), mHalDeviceId, token,
    869                 receiver, mCurrentUserId, groupId, opId, restricted, opPackageName, bundle,
    870                 dialogReceiver, mStatusBarService) {
    871             @Override
    872             public void onStart() {
    873                 try {
    874                     mActivityManager.registerTaskStackListener(mTaskStackListener);
    875                 } catch (RemoteException e) {
    876                     Slog.e(TAG, "Could not register task stack listener", e);
    877                 }
    878             }
    879 
    880             @Override
    881             public void onStop() {
    882                 try {
    883                     mActivityManager.unregisterTaskStackListener(mTaskStackListener);
    884                 } catch (RemoteException e) {
    885                     Slog.e(TAG, "Could not unregister task stack listener", e);
    886                 }
    887             }
    888 
    889             @Override
    890             public int handleFailedAttempt() {
    891                 final int currentUser = ActivityManager.getCurrentUser();
    892                 mFailedAttempts.put(currentUser, mFailedAttempts.get(currentUser, 0) + 1);
    893                 mTimedLockoutCleared.put(ActivityManager.getCurrentUser(), false);
    894                 final int lockoutMode = getLockoutMode();
    895                 if (lockoutMode == AuthenticationClient.LOCKOUT_PERMANENT) {
    896                     mPerformanceStats.permanentLockout++;
    897                 } else if (lockoutMode == AuthenticationClient.LOCKOUT_TIMED) {
    898                     mPerformanceStats.lockout++;
    899                 }
    900 
    901                 // Failing multiple times will continue to push out the lockout time
    902                 if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) {
    903                     scheduleLockoutResetForUser(currentUser);
    904                     return lockoutMode;
    905                 }
    906                 return AuthenticationClient.LOCKOUT_NONE;
    907             }
    908 
    909             @Override
    910             public void resetFailedAttempts() {
    911                 FingerprintService.this.resetFailedAttemptsForUser(true /* clearAttemptCounter */,
    912                         ActivityManager.getCurrentUser());
    913             }
    914 
    915             @Override
    916             public void notifyUserActivity() {
    917                 FingerprintService.this.userActivity();
    918             }
    919 
    920             @Override
    921             public IBiometricsFingerprint getFingerprintDaemon() {
    922                 return FingerprintService.this.getFingerprintDaemon();
    923             }
    924         };
    925 
    926         int lockoutMode = getLockoutMode();
    927         if (lockoutMode != AuthenticationClient.LOCKOUT_NONE) {
    928             Slog.v(TAG, "In lockout mode(" + lockoutMode +
    929                     ") ; disallowing authentication");
    930             int errorCode = lockoutMode == AuthenticationClient.LOCKOUT_TIMED ?
    931                     FingerprintManager.FINGERPRINT_ERROR_LOCKOUT :
    932                     FingerprintManager.FINGERPRINT_ERROR_LOCKOUT_PERMANENT;
    933             if (!client.onError(errorCode, 0 /* vendorCode */)) {
    934                 Slog.w(TAG, "Cannot send permanent lockout message to client");
    935             }
    936             return;
    937         }
    938         startClient(client, true /* initiatedByClient */);
    939     }
    940 
    941     private void startEnrollment(IBinder token, byte [] cryptoToken, int userId,
    942             IFingerprintServiceReceiver receiver, int flags, boolean restricted,
    943             String opPackageName) {
    944         updateActiveGroup(userId, opPackageName);
    945 
    946         final int groupId = userId; // default group for fingerprint enrollment
    947 
    948         EnrollClient client = new EnrollClient(getContext(), mHalDeviceId, token, receiver,
    949                 userId, groupId, cryptoToken, restricted, opPackageName) {
    950 
    951             @Override
    952             public IBiometricsFingerprint getFingerprintDaemon() {
    953                 return FingerprintService.this.getFingerprintDaemon();
    954             }
    955 
    956             @Override
    957             public void notifyUserActivity() {
    958                 FingerprintService.this.userActivity();
    959             }
    960         };
    961         startClient(client, true /* initiatedByClient */);
    962     }
    963 
    964     // attempt counter should only be cleared when Keyguard goes away or when
    965     // a fingerprint is successfully authenticated
    966     protected void resetFailedAttemptsForUser(boolean clearAttemptCounter, int userId) {
    967         if (DEBUG && getLockoutMode() != AuthenticationClient.LOCKOUT_NONE) {
    968             Slog.v(TAG, "Reset fingerprint lockout, clearAttemptCounter=" + clearAttemptCounter);
    969         }
    970         if (clearAttemptCounter) {
    971             mFailedAttempts.put(userId, 0);
    972         }
    973         mTimedLockoutCleared.put(userId, true);
    974         // If we're asked to reset failed attempts externally (i.e. from Keyguard),
    975         // the alarm might still be pending; remove it.
    976         cancelLockoutResetForUser(userId);
    977         notifyLockoutResetMonitors();
    978     }
    979 
    980     private class FingerprintServiceLockoutResetMonitor implements IBinder.DeathRecipient {
    981 
    982         private static final long WAKELOCK_TIMEOUT_MS = 2000;
    983         private final IFingerprintServiceLockoutResetCallback mCallback;
    984         private final WakeLock mWakeLock;
    985 
    986         public FingerprintServiceLockoutResetMonitor(
    987                 IFingerprintServiceLockoutResetCallback callback) {
    988             mCallback = callback;
    989             mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
    990                     "lockout reset callback");
    991             try {
    992                 mCallback.asBinder().linkToDeath(FingerprintServiceLockoutResetMonitor.this, 0);
    993             } catch (RemoteException e) {
    994                 Slog.w(TAG, "caught remote exception in linkToDeath", e);
    995             }
    996         }
    997 
    998         public void sendLockoutReset() {
    999             if (mCallback != null) {
   1000                 try {
   1001                     mWakeLock.acquire(WAKELOCK_TIMEOUT_MS);
   1002                     mCallback.onLockoutReset(mHalDeviceId, new IRemoteCallback.Stub() {
   1003 
   1004                         @Override
   1005                         public void sendResult(Bundle data) throws RemoteException {
   1006                             releaseWakelock();
   1007                         }
   1008                     });
   1009                 } catch (DeadObjectException e) {
   1010                     Slog.w(TAG, "Death object while invoking onLockoutReset: ", e);
   1011                     mHandler.post(mRemoveCallbackRunnable);
   1012                 } catch (RemoteException e) {
   1013                     Slog.w(TAG, "Failed to invoke onLockoutReset: ", e);
   1014                     releaseWakelock();
   1015                 }
   1016             }
   1017         }
   1018 
   1019         private final Runnable mRemoveCallbackRunnable = new Runnable() {
   1020             @Override
   1021             public void run() {
   1022                 releaseWakelock();
   1023                 removeLockoutResetCallback(FingerprintServiceLockoutResetMonitor.this);
   1024             }
   1025         };
   1026 
   1027         @Override
   1028         public void binderDied() {
   1029             Slog.e(TAG, "Lockout reset callback binder died");
   1030             mHandler.post(mRemoveCallbackRunnable);
   1031         }
   1032 
   1033         private void releaseWakelock() {
   1034             if (mWakeLock.isHeld()) {
   1035                 mWakeLock.release();
   1036             }
   1037         }
   1038     }
   1039 
   1040     private IBiometricsFingerprintClientCallback mDaemonCallback =
   1041             new IBiometricsFingerprintClientCallback.Stub() {
   1042 
   1043         @Override
   1044         public void onEnrollResult(final long deviceId, final int fingerId, final int groupId,
   1045                 final int remaining) {
   1046             mHandler.post(new Runnable() {
   1047                 @Override
   1048                 public void run() {
   1049                     handleEnrollResult(deviceId, fingerId, groupId, remaining);
   1050                 }
   1051             });
   1052         }
   1053 
   1054         @Override
   1055         public void onAcquired(final long deviceId, final int acquiredInfo, final int vendorCode) {
   1056             mHandler.post(new Runnable() {
   1057                 @Override
   1058                 public void run() {
   1059                     handleAcquired(deviceId, acquiredInfo, vendorCode);
   1060                 }
   1061             });
   1062         }
   1063 
   1064         @Override
   1065         public void onAuthenticated(final long deviceId, final int fingerId, final int groupId,
   1066                 ArrayList<Byte> token) {
   1067             mHandler.post(new Runnable() {
   1068                 @Override
   1069                 public void run() {
   1070                     handleAuthenticated(deviceId, fingerId, groupId, token);
   1071                 }
   1072             });
   1073         }
   1074 
   1075         @Override
   1076         public void onError(final long deviceId, final int error, final int vendorCode) {
   1077             mHandler.post(new Runnable() {
   1078                 @Override
   1079                 public void run() {
   1080                     handleError(deviceId, error, vendorCode);
   1081                 }
   1082             });
   1083         }
   1084 
   1085         @Override
   1086         public void onRemoved(final long deviceId, final int fingerId, final int groupId, final int remaining) {
   1087             mHandler.post(new Runnable() {
   1088                 @Override
   1089                 public void run() {
   1090                     handleRemoved(deviceId, fingerId, groupId, remaining);
   1091                 }
   1092             });
   1093         }
   1094 
   1095         @Override
   1096         public void onEnumerate(final long deviceId, final int fingerId, final int groupId,
   1097                 final int remaining) {
   1098             mHandler.post(new Runnable() {
   1099                 @Override
   1100                 public void run() {
   1101                     handleEnumerate(deviceId, fingerId, groupId, remaining);
   1102                 }
   1103             });
   1104         }
   1105     };
   1106 
   1107     private final class FingerprintServiceWrapper extends IFingerprintService.Stub {
   1108         @Override // Binder call
   1109         public long preEnroll(IBinder token) {
   1110             checkPermission(MANAGE_FINGERPRINT);
   1111             return startPreEnroll(token);
   1112         }
   1113 
   1114         @Override // Binder call
   1115         public int postEnroll(IBinder token) {
   1116             checkPermission(MANAGE_FINGERPRINT);
   1117             return startPostEnroll(token);
   1118         }
   1119 
   1120         @Override // Binder call
   1121         public void enroll(final IBinder token, final byte[] cryptoToken, final int userId,
   1122                 final IFingerprintServiceReceiver receiver, final int flags,
   1123                 final String opPackageName) {
   1124             checkPermission(MANAGE_FINGERPRINT);
   1125             final int limit = mContext.getResources().getInteger(
   1126                     com.android.internal.R.integer.config_fingerprintMaxTemplatesPerUser);
   1127 
   1128             final int enrolled = FingerprintService.this.getEnrolledFingerprints(userId).size();
   1129             if (enrolled >= limit) {
   1130                 Slog.w(TAG, "Too many fingerprints registered");
   1131                 return;
   1132             }
   1133 
   1134             // Group ID is arbitrarily set to parent profile user ID. It just represents
   1135             // the default fingerprints for the user.
   1136             if (!isCurrentUserOrProfile(userId)) {
   1137                 return;
   1138             }
   1139 
   1140             final boolean restricted = isRestricted();
   1141             mHandler.post(new Runnable() {
   1142                 @Override
   1143                 public void run() {
   1144                     startEnrollment(token, cryptoToken, userId, receiver, flags,
   1145                             restricted, opPackageName);
   1146                 }
   1147             });
   1148         }
   1149 
   1150         private boolean isRestricted() {
   1151             // Only give privileged apps (like Settings) access to fingerprint info
   1152             final boolean restricted = !hasPermission(MANAGE_FINGERPRINT);
   1153             return restricted;
   1154         }
   1155 
   1156         @Override // Binder call
   1157         public void cancelEnrollment(final IBinder token) {
   1158             checkPermission(MANAGE_FINGERPRINT);
   1159             mHandler.post(new Runnable() {
   1160                 @Override
   1161                 public void run() {
   1162                     ClientMonitor client = mCurrentClient;
   1163                     if (client instanceof EnrollClient && client.getToken() == token) {
   1164                         client.stop(client.getToken() == token);
   1165                     }
   1166                 }
   1167             });
   1168         }
   1169 
   1170         @Override // Binder call
   1171         public void authenticate(final IBinder token, final long opId, final int groupId,
   1172                 final IFingerprintServiceReceiver receiver, final int flags,
   1173                 final String opPackageName, final Bundle bundle,
   1174                 final IBiometricPromptReceiver dialogReceiver) {
   1175             final int callingUid = Binder.getCallingUid();
   1176             final int callingPid = Binder.getCallingPid();
   1177             final int callingUserId = UserHandle.getCallingUserId();
   1178             final boolean restricted = isRestricted();
   1179 
   1180             if (!canUseFingerprint(opPackageName, true /* foregroundOnly */, callingUid, callingPid,
   1181                     callingUserId)) {
   1182                 if (DEBUG) Slog.v(TAG, "authenticate(): reject " + opPackageName);
   1183                 return;
   1184             }
   1185 
   1186             mHandler.post(new Runnable() {
   1187                 @Override
   1188                 public void run() {
   1189                     MetricsLogger.histogram(mContext, "fingerprint_token", opId != 0L ? 1 : 0);
   1190 
   1191                     // Get performance stats object for this user.
   1192                     HashMap<Integer, PerformanceStats> pmap
   1193                             = (opId == 0) ? mPerformanceMap : mCryptoPerformanceMap;
   1194                     PerformanceStats stats = pmap.get(mCurrentUserId);
   1195                     if (stats == null) {
   1196                         stats = new PerformanceStats();
   1197                         pmap.put(mCurrentUserId, stats);
   1198                     }
   1199                     mPerformanceStats = stats;
   1200 
   1201                     startAuthentication(token, opId, callingUserId, groupId, receiver,
   1202                             flags, restricted, opPackageName, bundle, dialogReceiver);
   1203                 }
   1204             });
   1205         }
   1206 
   1207         @Override // Binder call
   1208         public void cancelAuthentication(final IBinder token, final String opPackageName) {
   1209             final int callingUid = Binder.getCallingUid();
   1210             final int callingPid = Binder.getCallingPid();
   1211             final int callingUserId = UserHandle.getCallingUserId();
   1212 
   1213             if (!canUseFingerprint(opPackageName, true /* foregroundOnly */, callingUid, callingPid,
   1214                     callingUserId)) {
   1215                 if (DEBUG) Slog.v(TAG, "cancelAuthentication(): reject " + opPackageName);
   1216                 return;
   1217             }
   1218 
   1219             mHandler.post(new Runnable() {
   1220                 @Override
   1221                 public void run() {
   1222                     ClientMonitor client = mCurrentClient;
   1223                     if (client instanceof AuthenticationClient) {
   1224                         if (client.getToken() == token) {
   1225                             if (DEBUG) Slog.v(TAG, "stop client " + client.getOwnerString());
   1226                             client.stop(client.getToken() == token);
   1227                         } else {
   1228                             if (DEBUG) Slog.v(TAG, "can't stop client "
   1229                                     + client.getOwnerString() + " since tokens don't match");
   1230                         }
   1231                     } else if (client != null) {
   1232                         if (DEBUG) Slog.v(TAG, "can't cancel non-authenticating client "
   1233                                 + client.getOwnerString());
   1234                     }
   1235                 }
   1236             });
   1237         }
   1238 
   1239         @Override // Binder call
   1240         public void setActiveUser(final int userId) {
   1241             checkPermission(MANAGE_FINGERPRINT);
   1242             mHandler.post(new Runnable() {
   1243                 @Override
   1244                 public void run() {
   1245                     updateActiveGroup(userId, null);
   1246                 }
   1247             });
   1248         }
   1249 
   1250         @Override // Binder call
   1251         public void remove(final IBinder token, final int fingerId, final int groupId,
   1252                 final int userId, final IFingerprintServiceReceiver receiver) {
   1253             checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission
   1254             final boolean restricted = isRestricted();
   1255             mHandler.post(new Runnable() {
   1256                 @Override
   1257                 public void run() {
   1258                     startRemove(token, fingerId, groupId, userId, receiver,
   1259                             restricted, false /* internal */);
   1260                 }
   1261             });
   1262         }
   1263 
   1264         @Override // Binder call
   1265         public void enumerate(final IBinder token, final int userId,
   1266             final IFingerprintServiceReceiver receiver) {
   1267             checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission
   1268             final boolean restricted = isRestricted();
   1269             mHandler.post(new Runnable() {
   1270                 @Override
   1271                 public void run() {
   1272                     startEnumerate(token, userId, receiver, restricted, false /* internal */);
   1273                 }
   1274             });
   1275         }
   1276 
   1277         @Override // Binder call
   1278         public boolean isHardwareDetected(long deviceId, String opPackageName) {
   1279             if (!canUseFingerprint(opPackageName, false /* foregroundOnly */,
   1280                     Binder.getCallingUid(), Binder.getCallingPid(),
   1281                     UserHandle.getCallingUserId())) {
   1282                 return false;
   1283             }
   1284 
   1285             final long token = Binder.clearCallingIdentity();
   1286             try {
   1287                 IBiometricsFingerprint daemon = getFingerprintDaemon();
   1288                 return daemon != null && mHalDeviceId != 0;
   1289             } finally {
   1290                 Binder.restoreCallingIdentity(token);
   1291             }
   1292         }
   1293 
   1294         @Override // Binder call
   1295         public void rename(final int fingerId, final int groupId, final String name) {
   1296             checkPermission(MANAGE_FINGERPRINT);
   1297             if (!isCurrentUserOrProfile(groupId)) {
   1298                 return;
   1299             }
   1300             mHandler.post(new Runnable() {
   1301                 @Override
   1302                 public void run() {
   1303                     mFingerprintUtils.renameFingerprintForUser(mContext, fingerId,
   1304                             groupId, name);
   1305                 }
   1306             });
   1307         }
   1308 
   1309         @Override // Binder call
   1310         public List<Fingerprint> getEnrolledFingerprints(int userId, String opPackageName) {
   1311             if (!canUseFingerprint(opPackageName, false /* foregroundOnly */,
   1312                     Binder.getCallingUid(), Binder.getCallingPid(),
   1313                     UserHandle.getCallingUserId())) {
   1314                 return Collections.emptyList();
   1315             }
   1316 
   1317             return FingerprintService.this.getEnrolledFingerprints(userId);
   1318         }
   1319 
   1320         @Override // Binder call
   1321         public boolean hasEnrolledFingerprints(int userId, String opPackageName) {
   1322             if (!canUseFingerprint(opPackageName, false /* foregroundOnly */,
   1323                     Binder.getCallingUid(), Binder.getCallingPid(),
   1324                     UserHandle.getCallingUserId())) {
   1325                 return false;
   1326             }
   1327 
   1328             return FingerprintService.this.hasEnrolledFingerprints(userId);
   1329         }
   1330 
   1331         @Override // Binder call
   1332         public long getAuthenticatorId(String opPackageName) {
   1333             // In this method, we're not checking whether the caller is permitted to use fingerprint
   1334             // API because current authenticator ID is leaked (in a more contrived way) via Android
   1335             // Keystore (android.security.keystore package): the user of that API can create a key
   1336             // which requires fingerprint authentication for its use, and then query the key's
   1337             // characteristics (hidden API) which returns, among other things, fingerprint
   1338             // authenticator ID which was active at key creation time.
   1339             //
   1340             // Reason: The part of Android Keystore which runs inside an app's process invokes this
   1341             // method in certain cases. Those cases are not always where the developer demonstrates
   1342             // explicit intent to use fingerprint functionality. Thus, to avoiding throwing an
   1343             // unexpected SecurityException this method does not check whether its caller is
   1344             // permitted to use fingerprint API.
   1345             //
   1346             // The permission check should be restored once Android Keystore no longer invokes this
   1347             // method from inside app processes.
   1348 
   1349             return FingerprintService.this.getAuthenticatorId(opPackageName);
   1350         }
   1351 
   1352         @Override // Binder call
   1353         protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
   1354             if (!DumpUtils.checkDumpPermission(mContext, TAG, pw)) return;
   1355 
   1356             final long ident = Binder.clearCallingIdentity();
   1357             try {
   1358                 if (args.length > 0 && "--proto".equals(args[0])) {
   1359                     dumpProto(fd);
   1360                 } else {
   1361                     dumpInternal(pw);
   1362                 }
   1363             } finally {
   1364                 Binder.restoreCallingIdentity(ident);
   1365             }
   1366         }
   1367 
   1368         @Override // Binder call
   1369         public void resetTimeout(byte [] token) {
   1370             checkPermission(RESET_FINGERPRINT_LOCKOUT);
   1371             // TODO: confirm security token when we move timeout management into the HAL layer.
   1372             mHandler.post(mResetFailedAttemptsForCurrentUserRunnable);
   1373         }
   1374 
   1375         @Override
   1376         public void addLockoutResetCallback(final IFingerprintServiceLockoutResetCallback callback)
   1377                 throws RemoteException {
   1378             mHandler.post(new Runnable() {
   1379                 @Override
   1380                 public void run() {
   1381                     addLockoutResetMonitor(
   1382                             new FingerprintServiceLockoutResetMonitor(callback));
   1383                 }
   1384             });
   1385         }
   1386 
   1387         @Override
   1388         public boolean isClientActive() {
   1389             checkPermission(MANAGE_FINGERPRINT);
   1390             synchronized(FingerprintService.this) {
   1391                 return (mCurrentClient != null) || (mPendingClient != null);
   1392             }
   1393         }
   1394 
   1395         @Override
   1396         public void addClientActiveCallback(IFingerprintClientActiveCallback callback) {
   1397             checkPermission(MANAGE_FINGERPRINT);
   1398             mClientActiveCallbacks.add(callback);
   1399         }
   1400 
   1401         @Override
   1402         public void removeClientActiveCallback(IFingerprintClientActiveCallback callback) {
   1403             checkPermission(MANAGE_FINGERPRINT);
   1404             mClientActiveCallbacks.remove(callback);
   1405         }
   1406     }
   1407 
   1408     private void dumpInternal(PrintWriter pw) {
   1409         JSONObject dump = new JSONObject();
   1410         try {
   1411             dump.put("service", "Fingerprint Manager");
   1412 
   1413             JSONArray sets = new JSONArray();
   1414             for (UserInfo user : UserManager.get(getContext()).getUsers()) {
   1415                 final int userId = user.getUserHandle().getIdentifier();
   1416                 final int N = mFingerprintUtils.getFingerprintsForUser(mContext, userId).size();
   1417                 PerformanceStats stats = mPerformanceMap.get(userId);
   1418                 PerformanceStats cryptoStats = mCryptoPerformanceMap.get(userId);
   1419                 JSONObject set = new JSONObject();
   1420                 set.put("id", userId);
   1421                 set.put("count", N);
   1422                 set.put("accept", (stats != null) ? stats.accept : 0);
   1423                 set.put("reject", (stats != null) ? stats.reject : 0);
   1424                 set.put("acquire", (stats != null) ? stats.acquire : 0);
   1425                 set.put("lockout", (stats != null) ? stats.lockout : 0);
   1426                 set.put("permanentLockout", (stats != null) ? stats.permanentLockout : 0);
   1427                 // cryptoStats measures statistics about secure fingerprint transactions
   1428                 // (e.g. to unlock password storage, make secure purchases, etc.)
   1429                 set.put("acceptCrypto", (cryptoStats != null) ? cryptoStats.accept : 0);
   1430                 set.put("rejectCrypto", (cryptoStats != null) ? cryptoStats.reject : 0);
   1431                 set.put("acquireCrypto", (cryptoStats != null) ? cryptoStats.acquire : 0);
   1432                 set.put("lockoutCrypto", (cryptoStats != null) ? cryptoStats.lockout : 0);
   1433                 set.put("permanentLockoutCrypto",
   1434                     (cryptoStats != null) ? cryptoStats.permanentLockout : 0);
   1435                 sets.put(set);
   1436             }
   1437 
   1438             dump.put("prints", sets);
   1439         } catch (JSONException e) {
   1440             Slog.e(TAG, "dump formatting failure", e);
   1441         }
   1442         pw.println(dump);
   1443     }
   1444 
   1445     private void dumpProto(FileDescriptor fd) {
   1446         final ProtoOutputStream proto = new ProtoOutputStream(fd);
   1447         for (UserInfo user : UserManager.get(getContext()).getUsers()) {
   1448             final int userId = user.getUserHandle().getIdentifier();
   1449 
   1450             final long userToken = proto.start(FingerprintServiceDumpProto.USERS);
   1451 
   1452             proto.write(FingerprintUserStatsProto.USER_ID, userId);
   1453             proto.write(FingerprintUserStatsProto.NUM_FINGERPRINTS,
   1454                     mFingerprintUtils.getFingerprintsForUser(mContext, userId).size());
   1455 
   1456             // Normal fingerprint authentications (e.g. lockscreen)
   1457             final PerformanceStats normal = mPerformanceMap.get(userId);
   1458             if (normal != null) {
   1459                 final long countsToken = proto.start(FingerprintUserStatsProto.NORMAL);
   1460                 proto.write(PerformanceStatsProto.ACCEPT, normal.accept);
   1461                 proto.write(PerformanceStatsProto.REJECT, normal.reject);
   1462                 proto.write(PerformanceStatsProto.ACQUIRE, normal.acquire);
   1463                 proto.write(PerformanceStatsProto.LOCKOUT, normal.lockout);
   1464                 proto.write(PerformanceStatsProto.PERMANENT_LOCKOUT, normal.permanentLockout);
   1465                 proto.end(countsToken);
   1466             }
   1467 
   1468             // Statistics about secure fingerprint transactions (e.g. to unlock password
   1469             // storage, make secure purchases, etc.)
   1470             final PerformanceStats crypto = mCryptoPerformanceMap.get(userId);
   1471             if (crypto != null) {
   1472                 final long countsToken = proto.start(FingerprintUserStatsProto.CRYPTO);
   1473                 proto.write(PerformanceStatsProto.ACCEPT, crypto.accept);
   1474                 proto.write(PerformanceStatsProto.REJECT, crypto.reject);
   1475                 proto.write(PerformanceStatsProto.ACQUIRE, crypto.acquire);
   1476                 proto.write(PerformanceStatsProto.LOCKOUT, crypto.lockout);
   1477                 proto.write(PerformanceStatsProto.PERMANENT_LOCKOUT, crypto.permanentLockout);
   1478                 proto.end(countsToken);
   1479             }
   1480 
   1481             proto.end(userToken);
   1482         }
   1483         proto.flush();
   1484         mPerformanceMap.clear();
   1485         mCryptoPerformanceMap.clear();
   1486     }
   1487 
   1488     @Override
   1489     public void onStart() {
   1490         publishBinderService(Context.FINGERPRINT_SERVICE, new FingerprintServiceWrapper());
   1491         SystemServerInitThreadPool.get().submit(this::getFingerprintDaemon, TAG + ".onStart");
   1492         listenForUserSwitches();
   1493     }
   1494 
   1495     private void updateActiveGroup(int userId, String clientPackage) {
   1496         IBiometricsFingerprint daemon = getFingerprintDaemon();
   1497 
   1498         if (daemon != null) {
   1499             try {
   1500                 userId = getUserOrWorkProfileId(clientPackage, userId);
   1501                 if (userId != mCurrentUserId) {
   1502                     int firstSdkInt = Build.VERSION.FIRST_SDK_INT;
   1503                     if (firstSdkInt < Build.VERSION_CODES.BASE) {
   1504                         Slog.e(TAG, "First SDK version " + firstSdkInt + " is invalid; must be " +
   1505                                 "at least VERSION_CODES.BASE");
   1506                     }
   1507                     File baseDir;
   1508                     if (firstSdkInt <= Build.VERSION_CODES.O_MR1) {
   1509                         baseDir = Environment.getUserSystemDirectory(userId);
   1510                     } else {
   1511                         baseDir = Environment.getDataVendorDeDirectory(userId);
   1512                     }
   1513 
   1514                     File fpDir = new File(baseDir, FP_DATA_DIR);
   1515                     if (!fpDir.exists()) {
   1516                         if (!fpDir.mkdir()) {
   1517                             Slog.v(TAG, "Cannot make directory: " + fpDir.getAbsolutePath());
   1518                             return;
   1519                         }
   1520                         // Calling mkdir() from this process will create a directory with our
   1521                         // permissions (inherited from the containing dir). This command fixes
   1522                         // the label.
   1523                         if (!SELinux.restorecon(fpDir)) {
   1524                             Slog.w(TAG, "Restorecons failed. Directory will have wrong label.");
   1525                             return;
   1526                         }
   1527                     }
   1528 
   1529                     daemon.setActiveGroup(userId, fpDir.getAbsolutePath());
   1530                     mCurrentUserId = userId;
   1531                 }
   1532                 mAuthenticatorIds.put(userId,
   1533                         hasEnrolledFingerprints(userId) ? daemon.getAuthenticatorId() : 0L);
   1534             } catch (RemoteException e) {
   1535                 Slog.e(TAG, "Failed to setActiveGroup():", e);
   1536             }
   1537         }
   1538     }
   1539 
   1540     /**
   1541      * @param clientPackage the package of the caller
   1542      * @return the profile id
   1543      */
   1544     private int getUserOrWorkProfileId(String clientPackage, int userId) {
   1545         if (!isKeyguard(clientPackage) && isWorkProfile(userId)) {
   1546             return userId;
   1547         }
   1548         return getEffectiveUserId(userId);
   1549     }
   1550 
   1551     /**
   1552      * @param userId
   1553      * @return true if this is a work profile
   1554      */
   1555     private boolean isWorkProfile(int userId) {
   1556         UserInfo userInfo = null;
   1557         final long token = Binder.clearCallingIdentity();
   1558         try {
   1559             userInfo = mUserManager.getUserInfo(userId);
   1560         } finally {
   1561             Binder.restoreCallingIdentity(token);
   1562         }
   1563         return userInfo != null && userInfo.isManagedProfile();
   1564     }
   1565 
   1566     private void listenForUserSwitches() {
   1567         try {
   1568             ActivityManager.getService().registerUserSwitchObserver(
   1569                 new SynchronousUserSwitchObserver() {
   1570                     @Override
   1571                     public void onUserSwitching(int newUserId) throws RemoteException {
   1572                         mHandler.obtainMessage(MSG_USER_SWITCHING, newUserId, 0 /* unused */)
   1573                                 .sendToTarget();
   1574                     }
   1575                 }, TAG);
   1576         } catch (RemoteException e) {
   1577             Slog.w(TAG, "Failed to listen for user switching event" ,e);
   1578         }
   1579     }
   1580 
   1581     /***
   1582      * @param opPackageName the name of the calling package
   1583      * @return authenticator id for the calling user
   1584      */
   1585     public long getAuthenticatorId(String opPackageName) {
   1586         final int userId = getUserOrWorkProfileId(opPackageName, UserHandle.getCallingUserId());
   1587         return mAuthenticatorIds.getOrDefault(userId, 0L);
   1588     }
   1589 }
   1590