diff options
8 files changed, 155 insertions, 129 deletions
diff --git a/api/current.txt b/api/current.txt index 8680c49..4c775a4 100644 --- a/api/current.txt +++ b/api/current.txt @@ -13942,16 +13942,8 @@ package android.hardware.display { package android.hardware.fingerprint { - public final class Fingerprint implements android.os.Parcelable { - ctor public Fingerprint(java.lang.CharSequence, int, int, long); - method public int describeContents(); - method public java.lang.CharSequence getName(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.hardware.fingerprint.Fingerprint> CREATOR; - } - public class FingerprintManager { - method public void authenticate(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.os.CancellationSignal, android.hardware.fingerprint.FingerprintManager.AuthenticationCallback, int); + method public void authenticate(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.os.CancellationSignal, int, android.hardware.fingerprint.FingerprintManager.AuthenticationCallback, android.os.Handler); method public boolean hasEnrolledFingerprints(); method public boolean isHardwareDetected(); field public static final int FINGERPRINT_ACQUIRED_GOOD = 0; // 0x0 @@ -13960,14 +13952,12 @@ package android.hardware.fingerprint { field public static final int FINGERPRINT_ACQUIRED_PARTIAL = 1; // 0x1 field public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 5; // 0x5 field public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 4; // 0x4 - field public static final int FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000; // 0x3e8 field public static final int FINGERPRINT_ERROR_CANCELED = 5; // 0x5 field public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1; // 0x1 field public static final int FINGERPRINT_ERROR_LOCKOUT = 7; // 0x7 field public static final int FINGERPRINT_ERROR_NO_SPACE = 4; // 0x4 field public static final int FINGERPRINT_ERROR_TIMEOUT = 3; // 0x3 field public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2; // 0x2 - field public static final int FINGERPRINT_ERROR_VENDOR_BASE = 1000; // 0x3e8 } public static abstract class FingerprintManager.AuthenticationCallback { @@ -13979,11 +13969,10 @@ package android.hardware.fingerprint { } public static final class FingerprintManager.AuthenticationResult { - ctor public FingerprintManager.AuthenticationResult(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.hardware.fingerprint.Fingerprint); method public android.hardware.fingerprint.FingerprintManager.CryptoObject getCryptoObject(); } - public static class FingerprintManager.CryptoObject { + public static final class FingerprintManager.CryptoObject { ctor public FingerprintManager.CryptoObject(java.security.Signature); ctor public FingerprintManager.CryptoObject(javax.crypto.Cipher); ctor public FingerprintManager.CryptoObject(javax.crypto.Mac); diff --git a/api/system-current.txt b/api/system-current.txt index 44baba2..5184825 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -14260,16 +14260,8 @@ package android.hardware.display { package android.hardware.fingerprint { - public final class Fingerprint implements android.os.Parcelable { - ctor public Fingerprint(java.lang.CharSequence, int, int, long); - method public int describeContents(); - method public java.lang.CharSequence getName(); - method public void writeToParcel(android.os.Parcel, int); - field public static final android.os.Parcelable.Creator<android.hardware.fingerprint.Fingerprint> CREATOR; - } - public class FingerprintManager { - method public void authenticate(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.os.CancellationSignal, android.hardware.fingerprint.FingerprintManager.AuthenticationCallback, int); + method public void authenticate(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.os.CancellationSignal, int, android.hardware.fingerprint.FingerprintManager.AuthenticationCallback, android.os.Handler); method public boolean hasEnrolledFingerprints(); method public boolean isHardwareDetected(); field public static final int FINGERPRINT_ACQUIRED_GOOD = 0; // 0x0 @@ -14278,14 +14270,12 @@ package android.hardware.fingerprint { field public static final int FINGERPRINT_ACQUIRED_PARTIAL = 1; // 0x1 field public static final int FINGERPRINT_ACQUIRED_TOO_FAST = 5; // 0x5 field public static final int FINGERPRINT_ACQUIRED_TOO_SLOW = 4; // 0x4 - field public static final int FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000; // 0x3e8 field public static final int FINGERPRINT_ERROR_CANCELED = 5; // 0x5 field public static final int FINGERPRINT_ERROR_HW_UNAVAILABLE = 1; // 0x1 field public static final int FINGERPRINT_ERROR_LOCKOUT = 7; // 0x7 field public static final int FINGERPRINT_ERROR_NO_SPACE = 4; // 0x4 field public static final int FINGERPRINT_ERROR_TIMEOUT = 3; // 0x3 field public static final int FINGERPRINT_ERROR_UNABLE_TO_PROCESS = 2; // 0x2 - field public static final int FINGERPRINT_ERROR_VENDOR_BASE = 1000; // 0x3e8 } public static abstract class FingerprintManager.AuthenticationCallback { @@ -14297,11 +14287,10 @@ package android.hardware.fingerprint { } public static final class FingerprintManager.AuthenticationResult { - ctor public FingerprintManager.AuthenticationResult(android.hardware.fingerprint.FingerprintManager.CryptoObject, android.hardware.fingerprint.Fingerprint); method public android.hardware.fingerprint.FingerprintManager.CryptoObject getCryptoObject(); } - public static class FingerprintManager.CryptoObject { + public static final class FingerprintManager.CryptoObject { ctor public FingerprintManager.CryptoObject(java.security.Signature); ctor public FingerprintManager.CryptoObject(javax.crypto.Cipher); ctor public FingerprintManager.CryptoObject(javax.crypto.Mac); diff --git a/core/java/android/hardware/fingerprint/FingerprintManager.java b/core/java/android/hardware/fingerprint/FingerprintManager.java index caf21d5..e61813c 100644 --- a/core/java/android/hardware/fingerprint/FingerprintManager.java +++ b/core/java/android/hardware/fingerprint/FingerprintManager.java @@ -18,32 +18,30 @@ package android.hardware.fingerprint; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.RequiresPermission; import android.app.ActivityManagerNative; -import android.content.ContentResolver; import android.content.Context; import android.os.Binder; import android.os.CancellationSignal; import android.os.CancellationSignal.OnCancelListener; import android.os.Handler; import android.os.IBinder; -import android.os.Parcel; -import android.os.Parcelable; +import android.os.Looper; import android.os.RemoteException; import android.os.UserHandle; -import android.provider.Settings; -import android.hardware.fingerprint.FingerprintManager.EnrollmentCallback; import android.security.keystore.AndroidKeyStoreProvider; import android.util.Log; import android.util.Slog; import java.security.Signature; -import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import javax.crypto.Cipher; import javax.crypto.Mac; +import static android.Manifest.permission.USE_FINGERPRINT; +import static android.Manifest.permission.MANAGE_FINGERPRINT; + /** * A class that coordinates access to the fingerprint hardware. * <p> @@ -57,9 +55,10 @@ public class FingerprintManager { private static final boolean DEBUG = true; private static final int MSG_ENROLL_RESULT = 100; private static final int MSG_ACQUIRED = 101; - private static final int MSG_AUTHENTICATED = 102; - private static final int MSG_ERROR = 103; - private static final int MSG_REMOVED = 104; + private static final int MSG_AUTHENTICATION_SUCCEEDED = 102; + private static final int MSG_AUTHENTICATION_FAILED = 103; + private static final int MSG_ERROR = 104; + private static final int MSG_REMOVED = 105; // // Error messages from fingerprint hardware during initilization, enrollment, authentication or @@ -112,6 +111,7 @@ public class FingerprintManager { /** * Hardware vendors may extend this list if there are conditions that do not fall under one of * the above categories. Vendors are responsible for providing error strings for these errors. + * @hide */ public static final int FINGERPRINT_ERROR_VENDOR_BASE = 1000; @@ -162,6 +162,7 @@ public class FingerprintManager { /** * Hardware vendors may extend this list if there are conditions that do not fall under one of * the above categories. Vendors are responsible for providing error strings for these errors. + * @hide */ public static final int FINGERPRINT_ACQUIRED_VENDOR_BASE = 1000; @@ -173,6 +174,7 @@ public class FingerprintManager { private RemovalCallback mRemovalCallback; private CryptoObject mCryptoObject; private Fingerprint mRemovalFingerprint; + private Handler mHandler; private class OnEnrollCancelListener implements OnCancelListener { @Override @@ -198,72 +200,71 @@ public class FingerprintManager { * A wrapper class for the crypto objects supported by FingerprintManager. Currently the * framework supports {@link Signature}, {@link Cipher} and {@link Mac} objects. */ - public static class CryptoObject { + public static final class CryptoObject { public CryptoObject(@NonNull Signature signature) { - mSignature = signature; - mCipher = null; - mMac = null; + mCrypto = signature; } public CryptoObject(@NonNull Cipher cipher) { - mCipher = cipher; - mSignature = null; - mMac = null; + mCrypto = cipher; } public CryptoObject(@NonNull Mac mac) { - mMac = mac; - mCipher = null; - mSignature = null; + mCrypto = mac; } /** * Get {@link Signature} object. * @return {@link Signature} object or null if this doesn't contain one. */ - public Signature getSignature() { return mSignature; } + public Signature getSignature() { + return mCrypto instanceof Signature ? (Signature) mCrypto : null; + } /** * Get {@link Cipher} object. * @return {@link Cipher} object or null if this doesn't contain one. */ - public Cipher getCipher() { return mCipher; } + public Cipher getCipher() { + return mCrypto instanceof Cipher ? (Cipher) mCrypto : null; + } /** * Get {@link Mac} object. * @return {@link Mac} object or null if this doesn't contain one. */ - public Mac getMac() { return mMac; } + public Mac getMac() { + return mCrypto instanceof Mac ? (Mac) mCrypto : null; + } /** * @hide * @return the opId associated with this object or 0 if none */ public long getOpId() { - if (mSignature != null) { - return AndroidKeyStoreProvider.getKeyStoreOperationHandle(mSignature); - } else if (mCipher != null) { - return AndroidKeyStoreProvider.getKeyStoreOperationHandle(mCipher); - } else if (mMac != null) { - return AndroidKeyStoreProvider.getKeyStoreOperationHandle(mMac); - } - return 0; + return mCrypto != null ? + AndroidKeyStoreProvider.getKeyStoreOperationHandle(mCrypto) : 0; } - private final Signature mSignature; - private final Cipher mCipher; - private final Mac mMac; + private final Object mCrypto; }; /** * Container for callback data from {@link FingerprintManager#authenticate(CryptoObject, - * CancellationSignal, AuthenticationCallback, int)}. + * CancellationSignal, int, AuthenticationCallback, Handler)}. */ public static final class AuthenticationResult { private Fingerprint mFingerprint; private CryptoObject mCryptoObject; + /** + * Authentication result + * + * @param crypto the crypto object + * @param fingerprint the recognized fingerprint data, if allowed. + * @hide + */ public AuthenticationResult(CryptoObject crypto, Fingerprint fingerprint) { mCryptoObject = crypto; mFingerprint = fingerprint; @@ -272,7 +273,7 @@ public class FingerprintManager { /** * Obtain the crypto object associated with this transaction * @return crypto object provided to {@link FingerprintManager#authenticate(CryptoObject, - * CancellationSignal, AuthenticationCallback, int)}. + * CancellationSignal, int, AuthenticationCallback, Handler)}. */ public CryptoObject getCryptoObject() { return mCryptoObject; } @@ -287,28 +288,28 @@ public class FingerprintManager { /** * Callback structure provided to {@link FingerprintManager#authenticate(CryptoObject, - * CancellationSignal, AuthenticationCallback, int)}. Users of {@link + * CancellationSignal, int, AuthenticationCallback, Handler)}. Users of {@link * FingerprintManager#authenticate(CryptoObject, CancellationSignal, - * AuthenticationCallback, int) } must provide an implementation of this for listening to + * int, AuthenticationCallback, Handler) } must provide an implementation of this for listening to * fingerprint events. */ public static abstract class AuthenticationCallback { /** * Called when an unrecoverable error has been encountered and the operation is complete. * No further callbacks will be made on this object. - * @param errMsgId An integer identifying the error message + * @param errorCode An integer identifying the error message * @param errString A human-readable error string that can be shown in UI */ - public void onAuthenticationError(int errMsgId, CharSequence errString) { } + public void onAuthenticationError(int errorCode, CharSequence errString) { } /** * Called when a recoverable error has been encountered during authentication. The help * string is provided to give the user guidance for what went wrong, such as * "Sensor dirty, please clean it." - * @param helpMsgId An integer identifying the error message + * @param helpCode An integer identifying the error message * @param helpString A human-readable string that can be shown in UI */ - public void onAuthenticationHelp(int helpMsgId, CharSequence helpString) { } + public void onAuthenticationHelp(int helpCode, CharSequence helpString) { } /** * Called when a fingerprint is recognized. @@ -326,7 +327,7 @@ public class FingerprintManager { * Callback structure provided to {@link FingerprintManager#enroll(long, EnrollmentCallback, * CancellationSignal, int). Users of {@link #FingerprintManager()} * must provide an implementation of this to {@link FingerprintManager#enroll(long, - * CancellationSignal, EnrollmentCallback, int) for listening to fingerprint events. + * CancellationSignal, int, EnrollmentCallback) for listening to fingerprint events. * * @hide */ @@ -392,31 +393,35 @@ public class FingerprintManager { * * @param crypto object associated with the call or null if none required. * @param cancel an object that can be used to cancel authentication - * @param callback an object to receive authentication events * @param flags optional flags; should be 0 + * @param callback an object to receive authentication events + * @param handler an optional handler to handle callback events */ + @RequiresPermission(USE_FINGERPRINT) public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, - @NonNull AuthenticationCallback callback, int flags) { - authenticate(crypto, cancel, callback, flags, UserHandle.myUserId()); + int flags, @NonNull AuthenticationCallback callback, @Nullable Handler handler) { + authenticate(crypto, cancel, flags, callback, handler, UserHandle.myUserId()); } /** - * Request authentication of a crypto object. This call warms up the fingerprint hardware - * and starts scanning for a fingerprint. It terminates when - * {@link AuthenticationCallback#onAuthenticationError(int, CharSequence)} or - * {@link AuthenticationCallback#onAuthenticationSucceeded(AuthenticationResult) is called, at - * which point the object is no longer valid. The operation can be canceled by using the - * provided cancel object. - * - * @param crypto object associated with the call or null if none required. - * @param cancel an object that can be used to cancel authentication - * @param callback an object to receive authentication events - * @param flags optional flags; should be 0 - * @param userId the userId the fingerprint belongs to + * Use the provided handler thread for events. + * @param handler + */ + private void useHandler(Handler handler) { + if (handler != null) { + mHandler = new MyHandler(handler.getLooper()); + } else if (mHandler.getLooper() != mContext.getMainLooper()){ + mHandler = new MyHandler(mContext.getMainLooper()); + } + } + + /** + * Per-user version * @hide */ + @RequiresPermission(USE_FINGERPRINT) public void authenticate(@Nullable CryptoObject crypto, @Nullable CancellationSignal cancel, - @NonNull AuthenticationCallback callback, int flags, int userId) { + int flags, @NonNull AuthenticationCallback callback, Handler handler, int userId) { if (callback == null) { throw new IllegalArgumentException("Must supply an authentication callback"); } @@ -431,6 +436,7 @@ public class FingerprintManager { } if (mService != null) try { + useHandler(handler); mAuthenticationCallback = callback; mCryptoObject = crypto; long sessionId = crypto != null ? crypto.getOpId() : 0; @@ -458,12 +464,13 @@ public class FingerprintManager { * @param token a unique token provided by a recent creation or verification of device * credentials (e.g. pin, pattern or password). * @param cancel an object that can be used to cancel enrollment - * @param callback an object to receive enrollment events * @param flags optional flags + * @param callback an object to receive enrollment events * @hide */ - public void enroll(byte [] token, CancellationSignal cancel, EnrollmentCallback callback, - int flags) { + @RequiresPermission(MANAGE_FINGERPRINT) + public void enroll(byte [] token, CancellationSignal cancel, int flags, + EnrollmentCallback callback) { if (callback == null) { throw new IllegalArgumentException("Must supply an enrollment callback"); } @@ -496,6 +503,7 @@ public class FingerprintManager { * existing device credentials (e.g. pin/pattern/password). * @hide */ + @RequiresPermission(MANAGE_FINGERPRINT) public long preEnroll() { long result = 0; if (mService != null) try { @@ -514,6 +522,7 @@ public class FingerprintManager { * * @hide */ + @RequiresPermission(MANAGE_FINGERPRINT) public void remove(Fingerprint fp, RemovalCallback callback) { if (mService != null) try { mRemovalCallback = callback; @@ -535,6 +544,7 @@ public class FingerprintManager { * * @hide */ + @RequiresPermission(MANAGE_FINGERPRINT) public void rename(int fpId, String newName) { // Renames the given fpId if (mService != null) { @@ -554,6 +564,7 @@ public class FingerprintManager { * * @hide */ + @RequiresPermission(USE_FINGERPRINT) public List<Fingerprint> getEnrolledFingerprints(int userId) { if (mService != null) try { return mService.getEnrolledFingerprints(userId, mContext.getOpPackageName()); @@ -569,6 +580,7 @@ public class FingerprintManager { * * @hide */ + @RequiresPermission(USE_FINGERPRINT) public List<Fingerprint> getEnrolledFingerprints() { return getEnrolledFingerprints(UserHandle.myUserId()); } @@ -578,6 +590,7 @@ public class FingerprintManager { * * @return true if at least one fingerprint is enrolled, false otherwise */ + @RequiresPermission(USE_FINGERPRINT) public boolean hasEnrolledFingerprints() { if (mService != null) try { return mService.hasEnrolledFingerprints(UserHandle.myUserId(), @@ -593,6 +606,7 @@ public class FingerprintManager { * * @return true if hardware is present and functional, false otherwise. */ + @RequiresPermission(USE_FINGERPRINT) public boolean isHardwareDetected() { if (mService != null) { try { @@ -626,13 +640,15 @@ public class FingerprintManager { return 0; } - private Handler mHandler; - private class MyHandler extends Handler { private MyHandler(Context context) { super(context.getMainLooper()); } + private MyHandler(Looper looper) { + super(looper); + } + public void handleMessage(android.os.Message msg) { switch(msg.what) { case MSG_ENROLL_RESULT: @@ -641,8 +657,11 @@ public class FingerprintManager { case MSG_ACQUIRED: sendAcquiredResult((Long) msg.obj /* deviceId */, msg.arg1 /* acquire info */); break; - case MSG_AUTHENTICATED: - sendAuthenticatedResult((Fingerprint) msg.obj); + case MSG_AUTHENTICATION_SUCCEEDED: + sendAuthenticatedSucceeded((Fingerprint) msg.obj); + break; + case MSG_AUTHENTICATION_FAILED: + sendAuthenticatedFailed(); break; case MSG_ERROR: sendErrorResult((Long) msg.obj /* deviceId */, msg.arg1 /* errMsgId */); @@ -684,15 +703,16 @@ public class FingerprintManager { } } - private void sendAuthenticatedResult(Fingerprint fp) { + private void sendAuthenticatedSucceeded(Fingerprint fp) { if (mAuthenticationCallback != null) { - if (fp.getFingerId() == 0) { - // Fingerprint template valid but doesn't match one in database - mAuthenticationCallback.onAuthenticationFailed(); - } else { - final AuthenticationResult result = new AuthenticationResult(mCryptoObject, fp); - mAuthenticationCallback.onAuthenticationSucceeded(result); - } + final AuthenticationResult result = new AuthenticationResult(mCryptoObject, fp); + mAuthenticationCallback.onAuthenticationSucceeded(result); + } + } + + private void sendAuthenticatedFailed() { + if (mAuthenticationCallback != null) { + mAuthenticationCallback.onAuthenticationFailed(); } } @@ -809,24 +829,33 @@ public class FingerprintManager { private IFingerprintServiceReceiver mServiceReceiver = new IFingerprintServiceReceiver.Stub() { + @Override // binder call public void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining) { mHandler.obtainMessage(MSG_ENROLL_RESULT, remaining, 0, new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget(); } + @Override // binder call public void onAcquired(long deviceId, int acquireInfo) { mHandler.obtainMessage(MSG_ACQUIRED, acquireInfo, 0, deviceId).sendToTarget(); } - public void onAuthenticated(long deviceId, int fingerId, int groupId) { - mHandler.obtainMessage(MSG_AUTHENTICATED, - new Fingerprint(null, groupId, fingerId, deviceId)).sendToTarget(); + @Override // binder call + public void onAuthenticationSucceeded(long deviceId, Fingerprint fp) { + mHandler.obtainMessage(MSG_AUTHENTICATION_SUCCEEDED, fp).sendToTarget(); + } + + @Override // binder call + public void onAuthenticationFailed(long deviceId) { + mHandler.obtainMessage(MSG_AUTHENTICATION_FAILED).sendToTarget();; } + @Override // binder call public void onError(long deviceId, int error) { mHandler.obtainMessage(MSG_ERROR, error, 0, deviceId).sendToTarget(); } + @Override // binder call public void onRemoved(long deviceId, int fingerId, int groupId) { mHandler.obtainMessage(MSG_REMOVED, fingerId, groupId, deviceId).sendToTarget(); } diff --git a/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl b/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl index a2d74b8..57a429f 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl +++ b/core/java/android/hardware/fingerprint/IFingerprintServiceReceiver.aidl @@ -15,6 +15,7 @@ */ package android.hardware.fingerprint; +import android.hardware.fingerprint.Fingerprint; import android.os.Bundle; import android.os.UserHandle; @@ -25,7 +26,8 @@ import android.os.UserHandle; oneway interface IFingerprintServiceReceiver { void onEnrollResult(long deviceId, int fingerId, int groupId, int remaining); void onAcquired(long deviceId, int acquiredInfo); - void onAuthenticated(long deviceId, int fingerId, int groupId); + void onAuthenticationSucceeded(long deviceId, in Fingerprint fp); + void onAuthenticationFailed(long deviceId); void onError(long deviceId, int error); void onRemoved(long deviceId, int fingerId, int groupId); } diff --git a/docs/html/training/articles/keystore.jd b/docs/html/training/articles/keystore.jd index 20963f5..fca958e 100644 --- a/docs/html/training/articles/keystore.jd +++ b/docs/html/training/articles/keystore.jd @@ -197,7 +197,7 @@ of the two modes: reset (e.g. by a Device Admin).</li> <li>User authentication is required for every use of the key. In this mode, a specific operation involving a specific key is authorized by the user. Currently, the only means of such - authorization is fingerprint authentication: {@link android.hardware.fingerprint.FingerprintManager#authenticate(CryptoObject, CancellationSignal, AuthenticationCallback, int) FingerprintManager.authenticate}. + authorization is fingerprint authentication: {@link android.hardware.fingerprint.FingerprintManager#authenticate(CryptoObject, CancellationSignal, int, AuthenticationCallback, Handler) FingerprintManager.authenticate}. Such keys can only be generated or imported if at least one fingerprint is enrolled (see {@link android.hardware.fingerprint.FingerprintManager#hasEnrolledFingerprints() FingerprintManager.hasEnrolledFingerprints}). These keys become permanently invalidated once all fingerprints are unenrolled.</li> </ul> diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java index 3c30d8c..d889d0c 100644 --- a/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java +++ b/packages/Keyguard/src/com/android/keyguard/KeyguardUpdateMonitor.java @@ -796,7 +796,7 @@ public class KeyguardUpdateMonitor implements TrustManager.TrustListener { mFingerprintCancelSignal.cancel(); } mFingerprintCancelSignal = new CancellationSignal(); - mFpm.authenticate(null, mFingerprintCancelSignal, mAuthenticationCallback, 0, userId); + mFpm.authenticate(null, mFingerprintCancelSignal, 0, mAuthenticationCallback, null, userId); setFingerprintRunningDetectionRunning(true); } } diff --git a/services/core/java/com/android/server/fingerprint/FingerprintService.java b/services/core/java/com/android/server/fingerprint/FingerprintService.java index fd36b7e..b0d5765 100644 --- a/services/core/java/com/android/server/fingerprint/FingerprintService.java +++ b/services/core/java/com/android/server/fingerprint/FingerprintService.java @@ -22,6 +22,7 @@ import android.app.AppOpsManager; import android.app.IUserSwitchObserver; import android.content.ContentResolver; import android.content.Context; +import android.content.pm.PackageManager; import android.os.Binder; import android.os.Environment; import android.os.Handler; @@ -73,13 +74,6 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe private ClientMonitor mRemoveClient = null; private final AppOpsManager mAppOps; - // Message types. Used internally to dispatch messages to the correct callback. - // Must agree with the list in fingerprint.h - private static final int FINGERPRINT_ERROR = -1; - private static final int FINGERPRINT_ACQUIRED = 1; - private static final int FINGERPRINT_TEMPLATE_ENROLLING = 3; - private static final int FINGERPRINT_TEMPLATE_REMOVED = 4; - private static final int FINGERPRINT_AUTHENTICATED = 5; private static final long MS_PER_SEC = 1000; private static final long FAIL_LOCKOUT_TIMEOUT_MS = 30*1000; private static final int MAX_FAILED_ATTEMPTS = 5; @@ -207,7 +201,6 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe if (mEnrollClient != null) { if (mEnrollClient.sendEnrollResult(fingerId, groupId, remaining)) { if (remaining == 0) { - ContentResolver res = mContext.getContentResolver(); addTemplateForUser(mEnrollClient, fingerId); removeClient(mEnrollClient); } @@ -262,14 +255,14 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe } void startEnrollment(IBinder token, byte[] cryptoToken, int groupId, - IFingerprintServiceReceiver receiver, int flags) { + IFingerprintServiceReceiver receiver, int flags, boolean restricted) { IFingerprintDaemon daemon = getFingerprintDaemon(); if (daemon == null) { Slog.w(TAG, "enroll: no fingeprintd!"); return; } stopPendingOperations(); - mEnrollClient = new ClientMonitor(token, receiver, groupId); + mEnrollClient = new ClientMonitor(token, receiver, groupId, restricted); final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC); try { final int result = daemon.enroll(cryptoToken, groupId, timeout); @@ -328,14 +321,14 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe } void startAuthentication(IBinder token, long opId, int groupId, - IFingerprintServiceReceiver receiver, int flags) { + IFingerprintServiceReceiver receiver, int flags, boolean restricted) { IFingerprintDaemon daemon = getFingerprintDaemon(); if (daemon == null) { Slog.w(TAG, "startAuthentication: no fingeprintd!"); return; } stopPendingOperations(); - mAuthClient = new ClientMonitor(token, receiver, groupId); + mAuthClient = new ClientMonitor(token, receiver, groupId, restricted); if (inLockoutMode()) { Slog.v(TAG, "In lockout mode; disallowing authentication"); if (!mAuthClient.sendError(FingerprintManager.FINGERPRINT_ERROR_LOCKOUT)) { @@ -344,7 +337,6 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe mAuthClient = null; return; } - final int timeout = (int) (ENROLLMENT_TIMEOUT_MS / MS_PER_SEC); try { final int result = daemon.authenticate(opId, groupId); if (result != 0) { @@ -378,13 +370,14 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe } void startRemove(IBinder token, int fingerId, int userId, - IFingerprintServiceReceiver receiver) { + IFingerprintServiceReceiver receiver, boolean restricted) { IFingerprintDaemon daemon = getFingerprintDaemon(); if (daemon == null) { Slog.w(TAG, "startRemove: no fingeprintd!"); return; } - mRemoveClient = new ClientMonitor(token, receiver, userId); + + mRemoveClient = new ClientMonitor(token, receiver, userId, restricted); // The fingerprint template ids will be removed when we get confirmation from the HAL try { final int result = daemon.remove(fingerId, userId); @@ -404,6 +397,11 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe return mFingerprintUtils.getFingerprintsForUser(mContext, groupId).size() > 0; } + boolean hasPermission(String permission) { + return getContext().checkCallingOrSelfPermission(permission) + == PackageManager.PERMISSION_GRANTED; + } + void checkPermission(String permission) { getContext().enforceCallingOrSelfPermission(permission, "Must have " + permission + " permission."); @@ -420,11 +418,14 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe IBinder token; IFingerprintServiceReceiver receiver; int userId; + boolean restricted; // True if client does not have MANAGE_FINGERPRINT permission - public ClientMonitor(IBinder token, IFingerprintServiceReceiver receiver, int userId) { + public ClientMonitor(IBinder token, IFingerprintServiceReceiver receiver, int userId, + boolean restricted) { this.token = token; this.receiver = receiver; this.userId = userId; + this.restricted = restricted; try { token.linkToDeath(this, 0); } catch (RemoteException e) { @@ -498,7 +499,13 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe boolean result = false; if (receiver != null) { try { - receiver.onAuthenticated(mHalDeviceId, fpId, groupId); + if (fpId == 0) { + receiver.onAuthenticationFailed(mHalDeviceId); + } else { + Fingerprint fp = !restricted ? + new Fingerprint("" /* TODO */, groupId, fpId, mHalDeviceId) : null; + receiver.onAuthenticationSucceeded(mHalDeviceId, fp); + } } catch (RemoteException e) { Slog.w(TAG, "Failed to notify Authenticated:", e); result = true; // client failed @@ -592,14 +599,22 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe final IFingerprintServiceReceiver receiver, final int flags) { checkPermission(MANAGE_FINGERPRINT); final byte [] cryptoClone = Arrays.copyOf(cryptoToken, cryptoToken.length); + + final boolean restricted = isRestricted(); mHandler.post(new Runnable() { @Override public void run() { - startEnrollment(token, cryptoClone, groupId, receiver, flags); + startEnrollment(token, cryptoClone, groupId, receiver, flags, restricted); } }); } + private boolean isRestricted() { + // Only give privileged apps (like Settings) access to fingerprint info + final boolean restricted = !hasPermission(MANAGE_FINGERPRINT); + return restricted; + } + @Override // Binder call public void cancelEnrollment(final IBinder token) { checkPermission(MANAGE_FINGERPRINT); @@ -614,14 +629,15 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe @Override // Binder call public void authenticate(final IBinder token, final long opId, final int groupId, final IFingerprintServiceReceiver receiver, final int flags, String opPackageName) { - checkPermission(USE_FINGERPRINT); + if (!canUseFingerprint(opPackageName)) { return; } + final boolean restricted = isRestricted(); mHandler.post(new Runnable() { @Override public void run() { - startAuthentication(token, opId, groupId, receiver, flags); + startAuthentication(token, opId, groupId, receiver, flags, restricted); } }); } @@ -643,10 +659,11 @@ public class FingerprintService extends SystemService implements IBinder.DeathRe public void remove(final IBinder token, final int fingerId, final int groupId, final IFingerprintServiceReceiver receiver) { checkPermission(MANAGE_FINGERPRINT); // TODO: Maybe have another permission + final boolean restricted = isRestricted(); mHandler.post(new Runnable() { @Override public void run() { - startRemove(token, fingerId, groupId, receiver); + startRemove(token, fingerId, groupId, receiver, restricted); } }); diff --git a/services/core/java/com/android/server/fingerprint/FingerprintsUserState.java b/services/core/java/com/android/server/fingerprint/FingerprintsUserState.java index 33177b4..902d970 100644 --- a/services/core/java/com/android/server/fingerprint/FingerprintsUserState.java +++ b/services/core/java/com/android/server/fingerprint/FingerprintsUserState.java @@ -57,7 +57,7 @@ class FingerprintsUserState { private final File mFile; @GuardedBy("this") - private final ArrayList<Fingerprint> mFingerprints = new ArrayList<>(); + private final ArrayList<Fingerprint> mFingerprints = new ArrayList<Fingerprint>(); private final Context mCtx; public FingerprintsUserState(Context ctx, int userId) { @@ -127,7 +127,7 @@ class FingerprintsUserState { } private ArrayList<Fingerprint> getCopy(ArrayList<Fingerprint> array) { - ArrayList<Fingerprint> result = new ArrayList<>(array.size()); + ArrayList<Fingerprint> result = new ArrayList<Fingerprint>(array.size()); for (int i = 0; i < array.size(); i++) { Fingerprint fp = array.get(i); result.add(new Fingerprint(fp.getName(), fp.getGroupId(), fp.getFingerId(), |