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