From aae60473e198e81387c83efd439a8ab3ea7045f1 Mon Sep 17 00:00:00 2001 From: Charles He Date: Fri, 27 Jan 2017 16:14:52 +0000 Subject: [PATCH] Fingerprint: get auth id for non-current user. Previously, getAuthenticatorId() simply returns the authenticator id corresponding to the currently active user in FingerprintService. However, this can cause bugs when, for example, KeyStore calls the method before storing a fingerprint-bound key for a non-current user. In such cases, the authenticator id of the calling user is desired, which is not necessarily the same as the "current user" in FingerprintService. This CL ensures the FingerprintService always returns the authenticator id of the calling user. Bug: 33459191 Test: manual Change-Id: Ia9d6b869d16bd37f45358ba839cd12901ebc1076 Merged-In: I35c5a3a7082cffb8941eeaa219c8e20948ad41a9 --- .../hardware/fingerprint/FingerprintManager.java | 2 +- .../server/fingerprint/FingerprintService.java | 64 ++++++++++++++++++---- 2 files changed, 53 insertions(+), 13 deletions(-) diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java index f17fd55bd22a..c5ae1f54aed6 100644 --- a/core/java/android/hardware/fingerprint/FingerprintManager.java +++ b/core/java/android/hardware/fingerprint/FingerprintManager.java @@ -710,7 +710,7 @@ public class FingerprintManager { /** * Retrieves the authenticator token for binding keys to the lifecycle - * of the current set of fingerprints. Used only by internal clients. + * of the calling user's fingerprints. Used only by internal clients. * * @hide */ diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java index 6c11794b189d..e6408238e4c2 100644 --- a/services/core/java/com/android/server/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java @@ -74,6 +74,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.List; +import java.util.Map; /** * A service to manage multiple clients that want to access the fingerprint HAL API. @@ -101,6 +102,8 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe private final ArrayList mLockoutMonitors = new ArrayList<>(); + private final Map mAuthenticatorIds = + Collections.synchronizedMap(new HashMap<>()); private final AppOpsManager mAppOps; private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30*1000; private static final int MAX_FAILED_ATTEMPTS = 5; @@ -117,7 +120,6 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe private final UserManager mUserManager; private ClientMonitor mCurrentClient; private ClientMonitor mPendingClient; - private long mCurrentAuthenticatorId; private PerformanceStats mPerformanceStats; // Normal fingerprint authentications are tracked by mPerformanceMap. @@ -209,6 +211,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe mDaemon.init(mDaemonCallback); mHalDeviceId = mDaemon.openHal(); if (mHalDeviceId != 0) { + loadAuthenticatorIds(); updateActiveGroup(ActivityManager.getCurrentUser(), null); } else { Slog.w(TAG, "Failed to open Fingerprint HAL!"); @@ -226,6 +229,26 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe return mDaemon; } + /** Populates existing authenticator ids. To be used only during the start of the service. */ + private void loadAuthenticatorIds() { + // This operation can be expensive, so keep track of the elapsed time. Might need to move to + // background if it takes too long. + long t = System.currentTimeMillis(); + + mAuthenticatorIds.clear(); + for (UserInfo user : UserManager.get(mContext).getUsers(true /* excludeDying */)) { + int userId = getUserOrWorkProfileId(null, user.id); + if (!mAuthenticatorIds.containsKey(userId)) { + updateActiveGroup(userId, null); + } + } + + t = System.currentTimeMillis() - t; + if (t > 1000) { + Slog.w(TAG, "loadAuthenticatorIds() taking too long: " + t + "ms"); + } + } + protected void handleEnumerate(long deviceId, int[] fingerIds, int[] groupIds) { if (fingerIds.length != groupIds.length) { Slog.w(TAG, "fingerIds and groupIds differ in length: f[]=" @@ -443,14 +466,23 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe boolean isCurrentUserOrProfile(int userId) { UserManager um = UserManager.get(mContext); + if (um == null) { + Slog.e(TAG, "Unable to acquire UserManager"); + return false; + } - // Allow current user or profiles of the current user... - for (int profileId : um.getEnabledProfileIds(userId)) { - if (profileId == userId) { - return true; + final long token = Binder.clearCallingIdentity(); + try { + // Allow current user or profiles of the current user... + for (int profileId : um.getEnabledProfileIds(mCurrentUserId)) { + if (profileId == userId) { + return true; + } } + return false; + } finally { + Binder.restoreCallingIdentity(token); } - return false; } private boolean isForegroundActivity(int uid, int pid) { @@ -1035,7 +1067,7 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe daemon.setActiveGroup(userId, fpDir.getAbsolutePath().getBytes()); mCurrentUserId = userId; } - mCurrentAuthenticatorId = daemon.getAuthenticatorId(); + mAuthenticatorIds.put(userId, daemon.getAuthenticatorId()); } catch (RemoteException e) { Slog.e(TAG, "Failed to setActiveGroup():", e); } @@ -1058,8 +1090,14 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe * @return true if this is a work profile */ private boolean isWorkProfile(int userId) { - UserInfo info = mUserManager.getUserInfo(userId); - return info != null && info.isManagedProfile(); + UserInfo userInfo = null; + final long token = Binder.clearCallingIdentity(); + try { + userInfo = mUserManager.getUserInfo(userId); + } finally { + Binder.restoreCallingIdentity(token); + } + return userInfo != null && userInfo.isManagedProfile(); } private void listenForUserSwitches() { @@ -1085,12 +1123,14 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe } } - /*** + /** * @param opPackageName the name of the calling package - * @return authenticator id for the current user + * @return authenticator id for the calling user */ public long getAuthenticatorId(String opPackageName) { - return mCurrentAuthenticatorId; + final int userId = getUserOrWorkProfileId(opPackageName, UserHandle.getCallingUserId()); + Long authenticatorId = mAuthenticatorIds.get(userId); + return authenticatorId != null ? authenticatorId : 0; } } -- 2.11.0