Merge "Update and cleanup FingerprintManager API to new spec" into mnc-dev
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -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(),
|
||||
|
||||
Reference in New Issue
Block a user