diff options
| author | Kevin Chyn <kchyn@google.com> | 2018-11-21 16:35:04 -0800 |
|---|---|---|
| committer | Kevin Chyn <kchyn@google.com> | 2018-11-27 16:26:19 -0800 |
| commit | e92cdae2773ff29502781670e35eaf882d5e36c6 (patch) | |
| tree | 2d64b9e0adcede8551f063470b49ecfa3fb7f68d /core/java/android | |
| parent | 2ca566b525dba8b9da8a917ca999c2df0caa0de0 (diff) | |
1/n: Move BiometricDialog management to BiometricService
The BiometricDialog management was done in AuthenticationClient, but
this is not great for the following reasons
1) The dialog lifecycle should not be 1:1 tied to the client monitor,
since this restricts flexibility
2) Devices with multiple biometrics implemented on BiometricDialog
will require extra work. Moving the dialog management up one layer
should solve this limitation
BiometricService now sends both its own receiver and the client's receiver
to the appropriate <Biometric>Service. When the client is actually started
by the <Biometric>Service, it will forward the client's (BiometricPrompt's)
receiver to BiometricService. Lifecycle management is currently still in
<Biometric>Service since the platform still uses <Biometric>Service
directly. AuthenticationClient for BP is now started with the wrapper
receiver, which allows BiometricService to handle messages before deciding
if it should forward the message to the client.
Moving lifecycle management to BiometricService is currently not a great
idea since framework doesn't always go through BiometricService.
Also merged IBiometricPromptReceiver with IBiometricServiceReceiver
Bug: 111461540
Test: Negative button works (error received by demo app)
Test: Cancelling via back or tapping gray area works (error received
by demo app), and hardware is no longer authenticating
Test: Dismissing BP via negative button or gray area returns only a single
error and is not followed by ERROR_CANCELED (as expected)
Test: Error messages are delayed when BP is showing, not delayed
when BP is not showing (pre-auth check errors e.g. no hardware)
Test: Lockout works
Test: Lockout counter resets upon successful auth
Test: Keys are unlocked properly for both implicit and explicit modes
TODO: Figure out multi-modal BiometricService / <Biometric>Service
synchronization. Likely we keep the bundle in BiometricService
and send random numbers (identifier) to <Biometric>Service. When
each <Biometric>Service is ready, it should return the number. Once
BiometricService receives all identifiers, it can then notify
all <Biometric>Service to start authenticating.
Change-Id: I2b6fa57ed3c3cbccc7b0be30279f80fa46a8e917
Diffstat (limited to 'core/java/android')
7 files changed, 64 insertions, 69 deletions
diff --git a/core/java/android/hardware/biometrics/BiometricAuthenticator.java b/core/java/android/hardware/biometrics/BiometricAuthenticator.java index 79e15a7a9a2d..d09819876cd1 100644 --- a/core/java/android/hardware/biometrics/BiometricAuthenticator.java +++ b/core/java/android/hardware/biometrics/BiometricAuthenticator.java @@ -32,17 +32,17 @@ public interface BiometricAuthenticator { /** * @hide */ - int TYPE_FINGERPRINT = 1; + int TYPE_FINGERPRINT = 1 << 0; /** * @hide */ - int TYPE_IRIS = 2; + int TYPE_IRIS = 1 << 1; /** * @hide */ - int TYPE_FACE = 3; + int TYPE_FACE = 1 << 2; /** * Container for biometric data diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java index bd149fd05f59..1eb98c77fbd5 100644 --- a/core/java/android/hardware/biometrics/BiometricPrompt.java +++ b/core/java/android/hardware/biometrics/BiometricPrompt.java @@ -251,27 +251,11 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan private Executor mExecutor; private AuthenticationCallback mAuthenticationCallback; - IBiometricPromptReceiver mDialogReceiver = new IBiometricPromptReceiver.Stub() { - @Override - public void onDialogDismissed(int reason) { - // Check the reason and invoke OnClickListener(s) if necessary - if (reason == DISMISSED_REASON_POSITIVE) { - mPositiveButtonInfo.executor.execute(() -> { - mPositiveButtonInfo.listener.onClick(null, DialogInterface.BUTTON_POSITIVE); - }); - } else if (reason == DISMISSED_REASON_NEGATIVE) { - mNegativeButtonInfo.executor.execute(() -> { - mNegativeButtonInfo.listener.onClick(null, DialogInterface.BUTTON_NEGATIVE); - }); - } - } - }; - - IBiometricServiceReceiver mBiometricServiceReceiver = + private final IBiometricServiceReceiver mBiometricServiceReceiver = new IBiometricServiceReceiver.Stub() { @Override - public void onAuthenticationSucceeded(long deviceId) throws RemoteException { + public void onAuthenticationSucceeded() throws RemoteException { mExecutor.execute(() -> { final AuthenticationResult result = new AuthenticationResult(mCryptoObject); mAuthenticationCallback.onAuthenticationSucceeded(result); @@ -279,14 +263,20 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan } @Override - public void onAuthenticationFailed(long deviceId) throws RemoteException { + public void onAuthenticationSucceededInternal(boolean requireConfirmation, byte[] bytes) + throws RemoteException { + throw new UnsupportedOperationException("Operation not supported!"); + } + + @Override + public void onAuthenticationFailed() throws RemoteException { mExecutor.execute(() -> { mAuthenticationCallback.onAuthenticationFailed(); }); } @Override - public void onError(long deviceId, int error, String message) + public void onError(int error, String message) throws RemoteException { mExecutor.execute(() -> { mAuthenticationCallback.onAuthenticationError(error, message); @@ -294,11 +284,25 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan } @Override - public void onAcquired(long deviceId, int acquireInfo, String message) { + public void onAcquired(int acquireInfo, String message) { mExecutor.execute(() -> { mAuthenticationCallback.onAuthenticationHelp(acquireInfo, message); }); } + + @Override + public void onDialogDismissed(int reason) { + // Check the reason and invoke OnClickListener(s) if necessary + if (reason == DISMISSED_REASON_POSITIVE) { + mPositiveButtonInfo.executor.execute(() -> { + mPositiveButtonInfo.listener.onClick(null, DialogInterface.BUTTON_POSITIVE); + }); + } else if (reason == DISMISSED_REASON_NEGATIVE) { + mNegativeButtonInfo.executor.execute(() -> { + mNegativeButtonInfo.listener.onClick(null, DialogInterface.BUTTON_NEGATIVE); + }); + } + } }; private BiometricPrompt(Context context, Bundle bundle, @@ -557,9 +561,8 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan mExecutor = executor; mAuthenticationCallback = callback; final long sessionId = crypto != null ? crypto.getOpId() : 0; - mService.authenticate(mToken, sessionId, userId, - mBiometricServiceReceiver, 0 /* flags */, mContext.getOpPackageName(), - mBundle, mDialogReceiver); + mService.authenticate(mToken, sessionId, userId, mBiometricServiceReceiver, + 0 /* flags */, mContext.getOpPackageName(), mBundle); } catch (RemoteException e) { Log.e(TAG, "Remote exception while authenticating", e); mExecutor.execute(() -> { diff --git a/core/java/android/hardware/biometrics/IBiometricPromptReceiver.aidl b/core/java/android/hardware/biometrics/IBiometricPromptReceiver.aidl deleted file mode 100644 index 27d25b86b859..000000000000 --- a/core/java/android/hardware/biometrics/IBiometricPromptReceiver.aidl +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (C) 2018 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package android.hardware.biometrics; - -/** - * Communication channel from the BiometricPrompt (SysUI) back to AuthenticationClient. - * @hide - */ -oneway interface IBiometricPromptReceiver { - void onDialogDismissed(int reason); -} diff --git a/core/java/android/hardware/biometrics/IBiometricService.aidl b/core/java/android/hardware/biometrics/IBiometricService.aidl index e17feff0160a..6b2a53fd9b20 100644 --- a/core/java/android/hardware/biometrics/IBiometricService.aidl +++ b/core/java/android/hardware/biometrics/IBiometricService.aidl @@ -18,7 +18,6 @@ package android.hardware.biometrics; import android.os.Bundle; import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback; -import android.hardware.biometrics.IBiometricPromptReceiver; import android.hardware.biometrics.IBiometricServiceReceiver; /** @@ -32,8 +31,7 @@ interface IBiometricService { // Requests authentication. The service choose the appropriate biometric to use, and show // the corresponding BiometricDialog. void authenticate(IBinder token, long sessionId, int userId, - IBiometricServiceReceiver receiver, int flags, String opPackageName, - in Bundle bundle, IBiometricPromptReceiver dialogReceiver); + IBiometricServiceReceiver receiver, int flags, String opPackageName, in Bundle bundle); // Cancel authentication for the given sessionId void cancelAuthentication(IBinder token, String opPackageName); @@ -46,4 +44,9 @@ interface IBiometricService { // Explicitly set the active user. void setActiveUser(int userId); + + // Notify BiometricService when <Biometric>Service starts a new client. Client lifecycle + // is still managed in <Biometric>Service. + void onAuthenticationStarted(in Bundle bundle, IBiometricServiceReceiver receiver, int type, + boolean requireConfirmation, int userId); } diff --git a/core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl b/core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl index a6e3696eeb10..3b8067bf11be 100644 --- a/core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl +++ b/core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl @@ -16,12 +16,27 @@ package android.hardware.biometrics; /** - * Communication channel from the BiometricService back to BiometricPrompt. + * Communication channel from + * 1) BiometricDialogImpl (SysUI) back to BiometricService + * 2) <Biometric>Service back to BiometricService + * 3) BiometricService back to BiometricPrompt + * BiometricPrompt sends a receiver to BiometricService, BiometricService contains another + * "trampoline" receiver which intercepts messages from <Biometric>Service and does some + * logic before forwarding results as necessary to BiometricPrompt. * @hide */ oneway interface IBiometricServiceReceiver { - void onAuthenticationSucceeded(long deviceId); - void onAuthenticationFailed(long deviceId); - void onError(long deviceId, int error, String message); - void onAcquired(long deviceId, int acquiredInfo, String message); + // Notify BiometricPrompt that authentication was successful + void onAuthenticationSucceeded(); + // Notify BiometricService that authentication was successful. If user confirmation is required, + // the auth token must be submitted into KeyStore. + void onAuthenticationSucceededInternal(boolean requireConfirmation, in byte[] token); + // Noties that authentication failed. + void onAuthenticationFailed(); + // Notifies that an error has occurred. + void onError(int error, String message); + // Notifies that a biometric has been acquired. + void onAcquired(int acquiredInfo, String message); + // Notifies that the SystemUI dialog has been dismissed. + void onDialogDismissed(int reason); } diff --git a/core/java/android/hardware/face/IFaceService.aidl b/core/java/android/hardware/face/IFaceService.aidl index 47df8e8f9729..2f9e4855eddc 100644 --- a/core/java/android/hardware/face/IFaceService.aidl +++ b/core/java/android/hardware/face/IFaceService.aidl @@ -16,7 +16,6 @@ package android.hardware.face; import android.os.Bundle; -import android.hardware.biometrics.IBiometricPromptReceiver; import android.hardware.biometrics.IBiometricServiceReceiver; import android.hardware.biometrics.IBiometricServiceLockoutResetCallback; import android.hardware.face.IFaceServiceReceiver; @@ -35,16 +34,16 @@ interface IFaceService { // This method invokes the BiometricDialog. The arguments are almost the same as above, // but should only be called from (BiometricPromptService). void authenticateFromService(boolean requireConfirmation, IBinder token, long sessionId, - int userId, IBiometricServiceReceiver receiver, int flags, String opPackageName, - in Bundle bundle, IBiometricPromptReceiver dialogReceiver, - int callingUid, int callingPid, int callingUserId); + int userId, IBiometricServiceReceiver clientRceiver, + IBiometricServiceReceiver wrapperReceiver, int flags, String opPackageName, + in Bundle bundle, int callingUid, int callingPid, int callingUserId); // Cancel authentication for the given sessionId void cancelAuthentication(IBinder token, String opPackageName); // Same as above, with extra arguments. void cancelAuthenticationFromService(IBinder token, String opPackageName, - int callingUid, int callingPid, int callingUserId); + int callingUid, int callingPid, int callingUserId, boolean fromClient); // Start face enrollment void enroll(IBinder token, in byte [] cryptoToken, int userId, IFaceServiceReceiver receiver, diff --git a/core/java/android/hardware/fingerprint/IFingerprintService.aidl b/core/java/android/hardware/fingerprint/IFingerprintService.aidl index 2662a11c2dd4..cfe30b1dc74a 100644 --- a/core/java/android/hardware/fingerprint/IFingerprintService.aidl +++ b/core/java/android/hardware/fingerprint/IFingerprintService.aidl @@ -16,7 +16,6 @@ package android.hardware.fingerprint; import android.os.Bundle; -import android.hardware.biometrics.IBiometricPromptReceiver; import android.hardware.biometrics.IBiometricServiceReceiver; import android.hardware.biometrics.IBiometricServiceLockoutResetCallback; import android.hardware.fingerprint.IFingerprintClientActiveCallback; @@ -40,9 +39,9 @@ interface IFingerprintService { // called from BiometricPromptService. The additional uid, pid, userId arguments should be // determined by BiometricPromptService. void authenticateFromService(IBinder token, long sessionId, int userId, - IBiometricServiceReceiver receiver, int flags, String opPackageName, - in Bundle bundle, IBiometricPromptReceiver dialogReceiver, - int callingUid, int callingPid, int callingUserId); + IBiometricServiceReceiver clientReceiver, IBiometricServiceReceiver wrapperReceiver, + int flags, String opPackageName, in Bundle bundle, int callingUid, int callingPid, + int callingUserId); // Cancel authentication for the given sessionId void cancelAuthentication(IBinder token, String opPackageName); @@ -50,7 +49,7 @@ interface IFingerprintService { // Same as above, except this is protected by the MANAGE_BIOMETRIC signature permission. Takes // an additional uid, pid, userid. void cancelAuthenticationFromService(IBinder token, String opPackageName, - int callingUid, int callingPid, int callingUserId); + int callingUid, int callingPid, int callingUserId, boolean fromClient); // Start fingerprint enrollment void enroll(IBinder token, in byte [] cryptoToken, int groupId, IFingerprintServiceReceiver receiver, |
