Merge "Handle cancellation properly for setDeviceCredentialAllowed(true)" into qt-dev

am: 76d5454a86

Change-Id: I1c6d9c51e6af91a79bf34d4d7245f758993a365e
This commit is contained in:
Kevin Chyn
2019-04-10 01:47:21 -07:00
committed by android-build-merger
6 changed files with 296 additions and 58 deletions

View File

@@ -161,6 +161,7 @@ java_defaults {
":libcamera_client_framework_aidl",
"core/java/android/hardware/IConsumerIrService.aidl",
"core/java/android/hardware/ISerialManager.aidl",
"core/java/android/hardware/biometrics/IBiometricConfirmDeviceCredentialCallback.aidl",
"core/java/android/hardware/biometrics/IBiometricEnabledOnKeyguardCallback.aidl",
"core/java/android/hardware/biometrics/IBiometricService.aidl",
"core/java/android/hardware/biometrics/IBiometricServiceReceiver.aidl",

View File

@@ -207,5 +207,22 @@ public class BiometricManager {
Slog.w(TAG, "onConfirmDeviceCredentialError(): Service not connected");
}
}
/**
* TODO(b/123378871): Remove when moved.
* @hide
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
public void registerCancellationCallback(IBiometricConfirmDeviceCredentialCallback callback) {
if (mService != null) {
try {
mService.registerCancellationCallback(callback);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} else {
Slog.w(TAG, "registerCancellationCallback(): Service not connected");
}
}
}

View File

@@ -82,6 +82,11 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
* @hide
*/
public static final String KEY_ALLOW_DEVICE_CREDENTIAL = "allow_device_credential";
/**
* @hide
*/
public static final String KEY_FROM_CONFIRM_DEVICE_CREDENTIAL
= "from_confirm_device_credential";
/**
* Error/help message will show for this amount of time.
@@ -270,6 +275,17 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
return this;
}
/**
* TODO(123378871): Remove when moved.
* @return
* @hide
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
@NonNull public Builder setFromConfirmDeviceCredential() {
mBundle.putBoolean(KEY_FROM_CONFIRM_DEVICE_CREDENTIAL, true);
return this;
}
/**
* Creates a {@link BiometricPrompt}.
* @return a {@link BiometricPrompt}
@@ -494,7 +510,8 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
public void authenticateUser(@NonNull CancellationSignal cancel,
@NonNull @CallbackExecutor Executor executor,
@NonNull AuthenticationCallback callback,
int userId) {
int userId,
IBiometricConfirmDeviceCredentialCallback confirmDeviceCredentialCallback) {
if (cancel == null) {
throw new IllegalArgumentException("Must supply a cancellation signal");
}
@@ -504,7 +521,8 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
if (callback == null) {
throw new IllegalArgumentException("Must supply a callback");
}
authenticateInternal(null /* crypto */, cancel, executor, callback, userId);
authenticateInternal(null /* crypto */, cancel, executor, callback, userId,
confirmDeviceCredentialCallback);
}
/**
@@ -555,7 +573,8 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
if (mBundle.getBoolean(KEY_ALLOW_DEVICE_CREDENTIAL)) {
throw new IllegalArgumentException("Device credential not supported with crypto");
}
authenticateInternal(crypto, cancel, executor, callback, mContext.getUserId());
authenticateInternal(crypto, cancel, executor, callback, mContext.getUserId(),
null /* confirmDeviceCredentialCallback */);
}
/**
@@ -597,7 +616,8 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
if (callback == null) {
throw new IllegalArgumentException("Must supply a callback");
}
authenticateInternal(null /* crypto */, cancel, executor, callback, mContext.getUserId());
authenticateInternal(null /* crypto */, cancel, executor, callback, mContext.getUserId(),
null /* confirmDeviceCredentialCallback */);
}
private void cancelAuthentication() {
@@ -614,7 +634,8 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
@NonNull CancellationSignal cancel,
@NonNull @CallbackExecutor Executor executor,
@NonNull AuthenticationCallback callback,
int userId) {
int userId,
IBiometricConfirmDeviceCredentialCallback confirmDeviceCredentialCallback) {
try {
if (cancel.isCanceled()) {
Log.w(TAG, "Authentication already canceled");
@@ -629,7 +650,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
final long sessionId = crypto != null ? crypto.getOpId() : 0;
if (BiometricManager.hasBiometrics(mContext)) {
mService.authenticate(mToken, sessionId, userId, mBiometricServiceReceiver,
mContext.getOpPackageName(), mBundle);
mContext.getOpPackageName(), mBundle, confirmDeviceCredentialCallback);
} else {
mExecutor.execute(() -> {
callback.onAuthenticationError(BiometricPrompt.BIOMETRIC_ERROR_HW_NOT_PRESENT,

View File

@@ -0,0 +1,26 @@
/*
* Copyright (C) 2019 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 between ConfirmDeviceCredential / ConfirmLock* and BiometricService.
* @hide
*/
interface IBiometricConfirmDeviceCredentialCallback {
// Invoked when authentication should be canceled.
oneway void cancel();
}

View File

@@ -17,6 +17,7 @@
package android.hardware.biometrics;
import android.os.Bundle;
import android.hardware.biometrics.IBiometricConfirmDeviceCredentialCallback;
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
import android.hardware.biometrics.IBiometricServiceReceiver;
@@ -30,8 +31,10 @@ import android.hardware.biometrics.IBiometricServiceReceiver;
interface IBiometricService {
// Requests authentication. The service choose the appropriate biometric to use, and show
// the corresponding BiometricDialog.
// TODO(b/123378871): Remove callback when moved.
void authenticate(IBinder token, long sessionId, int userId,
IBiometricServiceReceiver receiver, String opPackageName, in Bundle bundle);
IBiometricServiceReceiver receiver, String opPackageName, in Bundle bundle,
IBiometricConfirmDeviceCredentialCallback callback);
// Cancel authentication for the given sessionId
void cancelAuthentication(IBinder token, String opPackageName);
@@ -59,4 +62,8 @@ interface IBiometricService {
void onConfirmDeviceCredentialSuccess();
// TODO(b/123378871): Remove when moved.
void onConfirmDeviceCredentialError(int error, String message);
// TODO(b/123378871): Remove when moved.
// When ConfirmLock* is invoked from BiometricPrompt, it needs to register a callback so that
// it can receive the cancellation signal.
void registerCancellationCallback(IBiometricConfirmDeviceCredentialCallback callback);
}

View File

@@ -41,6 +41,7 @@ import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.BiometricSourceType;
import android.hardware.biometrics.BiometricsProtoEnums;
import android.hardware.biometrics.IBiometricConfirmDeviceCredentialCallback;
import android.hardware.biometrics.IBiometricEnabledOnKeyguardCallback;
import android.hardware.biometrics.IBiometricService;
import android.hardware.biometrics.IBiometricServiceReceiver;
@@ -85,6 +86,7 @@ import java.util.Random;
public class BiometricService extends SystemService {
private static final String TAG = "BiometricService";
private static final boolean DEBUG = true;
private static final int MSG_ON_TASK_STACK_CHANGED = 1;
private static final int MSG_ON_AUTHENTICATION_SUCCEEDED = 2;
@@ -96,6 +98,9 @@ public class BiometricService extends SystemService {
private static final int MSG_ON_READY_FOR_AUTHENTICATION = 8;
private static final int MSG_AUTHENTICATE = 9;
private static final int MSG_CANCEL_AUTHENTICATION = 10;
private static final int MSG_ON_CONFIRM_DEVICE_CREDENTIAL_SUCCESS = 11;
private static final int MSG_ON_CONFIRM_DEVICE_CREDENTIAL_ERROR = 12;
private static final int MSG_REGISTER_CANCELLATION_CALLBACK = 13;
private static final int[] FEATURE_ID = {
TYPE_FINGERPRINT,
@@ -128,8 +133,12 @@ public class BiometricService extends SystemService {
* Authentication is successful, but we're waiting for the user to press "confirm" button.
*/
private static final int STATE_AUTH_PENDING_CONFIRM = 5;
/**
* Biometric authentication was canceled, but the device is now showing ConfirmDeviceCredential
*/
private static final int STATE_BIOMETRIC_AUTH_CANCELED_SHOWING_CDC = 6;
private final class AuthSession {
private final class AuthSession implements IBinder.DeathRecipient {
// Map of Authenticator/Cookie pairs. We expect to receive the cookies back from
// <Biometric>Services before we can start authenticating. Pairs that have been returned
// are moved to mModalitiesMatched.
@@ -164,10 +173,14 @@ public class BiometricService extends SystemService {
// Timestamp when hardware authentication occurred
private long mAuthenticatedTimeMs;
// TODO(b/123378871): Remove when moved.
private IBiometricConfirmDeviceCredentialCallback mConfirmDeviceCredentialCallback;
AuthSession(HashMap<Integer, Integer> modalities, IBinder token, long sessionId,
int userId, IBiometricServiceReceiver receiver, String opPackageName,
Bundle bundle, int callingUid, int callingPid, int callingUserId,
int modality, boolean requireConfirmation) {
int modality, boolean requireConfirmation,
IBiometricConfirmDeviceCredentialCallback callback) {
mModalitiesWaiting = modalities;
mToken = token;
mSessionId = sessionId;
@@ -180,12 +193,25 @@ public class BiometricService extends SystemService {
mCallingUserId = callingUserId;
mModality = modality;
mRequireConfirmation = requireConfirmation;
mConfirmDeviceCredentialCallback = callback;
if (isFromConfirmDeviceCredential()) {
try {
token.linkToDeath(this, 0 /* flags */);
} catch (RemoteException e) {
Slog.e(TAG, "Unable to link to death", e);
}
}
}
boolean isCrypto() {
return mSessionId != 0;
}
boolean isFromConfirmDeviceCredential() {
return mBundle.getBoolean(BiometricPrompt.KEY_FROM_CONFIRM_DEVICE_CREDENTIAL, false);
}
boolean containsCookie(int cookie) {
if (mModalitiesWaiting != null && mModalitiesWaiting.containsValue(cookie)) {
return true;
@@ -195,6 +221,25 @@ public class BiometricService extends SystemService {
}
return false;
}
// TODO(b/123378871): Remove when moved.
@Override
public void binderDied() {
mHandler.post(() -> {
Slog.e(TAG, "Binder died, killing ConfirmDeviceCredential");
if (mConfirmDeviceCredentialCallback == null) {
Slog.e(TAG, "Callback is null");
return;
}
try {
mConfirmDeviceCredentialCallback.cancel();
mConfirmDeviceCredentialCallback = null;
} catch (RemoteException e) {
Slog.e(TAG, "Unable to send cancel", e);
}
});
}
}
private final class BiometricTaskStackListener extends TaskStackListener {
@@ -234,6 +279,14 @@ public class BiometricService extends SystemService {
private AuthSession mCurrentAuthSession;
private AuthSession mPendingAuthSession;
// TODO(b/123378871): Remove when moved.
// When BiometricPrompt#setAllowDeviceCredentials is set to true, we need to store the
// client (app) receiver. BiometricService internally launches CDCA which invokes
// BiometricService to start authentication (normal path). When auth is success/rejected,
// CDCA will use an aidl method to poke BiometricService - the result will then be forwarded
// to this receiver.
private IBiometricServiceReceiver mConfirmDeviceCredentialReceiver;
private final Handler mHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
@@ -311,7 +364,8 @@ public class BiometricService extends SystemService {
(Bundle) args.arg5 /* bundle */,
args.argi2 /* callingUid */,
args.argi3 /* callingPid */,
args.argi4 /* callingUserId */);
args.argi4 /* callingUserId */,
(IBiometricConfirmDeviceCredentialCallback) args.arg6 /* callback */);
args.recycle();
break;
}
@@ -325,7 +379,28 @@ public class BiometricService extends SystemService {
break;
}
case MSG_ON_CONFIRM_DEVICE_CREDENTIAL_SUCCESS: {
handleOnConfirmDeviceCredentialSuccess();
break;
}
case MSG_ON_CONFIRM_DEVICE_CREDENTIAL_ERROR: {
SomeArgs args = (SomeArgs) msg.obj;
handleOnConfirmDeviceCredentialError(
args.argi1 /* error */,
(String) args.arg1 /* errorMsg */);
args.recycle();
break;
}
case MSG_REGISTER_CANCELLATION_CALLBACK: {
handleRegisterCancellationCallback(
(IBiometricConfirmDeviceCredentialCallback) msg.obj /* callback */);
break;
}
default:
Slog.e(TAG, "Unknown message: " + msg);
break;
}
}
@@ -533,14 +608,6 @@ public class BiometricService extends SystemService {
* cancelAuthentication() can go to the right place.
*/
private final class BiometricServiceWrapper extends IBiometricService.Stub {
// TODO(b/123378871): Remove when moved.
// When BiometricPrompt#setAllowDeviceCredentials is set to true, we need to store the
// client (app) receiver. BiometricService internally launches CDCA which invokes
// BiometricService to start authentication (normal path). When auth is success/rejected,
// CDCA will use an aidl method to poke BiometricService - the result will then be forwarded
// to this receiver.
private IBiometricServiceReceiver mConfirmDeviceCredentialReceiver;
@Override // Binder call
public void onReadyForAuthentication(int cookie, boolean requireConfirmation, int userId) {
checkInternalPermission();
@@ -554,12 +621,18 @@ public class BiometricService extends SystemService {
@Override // Binder call
public void authenticate(IBinder token, long sessionId, int userId,
IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle)
IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle,
IBiometricConfirmDeviceCredentialCallback callback)
throws RemoteException {
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
final int callingUserId = UserHandle.getCallingUserId();
// TODO(b/123378871): Remove when moved.
if (callback != null) {
checkInternalPermission();
}
// In the BiometricServiceBase, check do the AppOps and foreground check.
if (userId == callingUserId) {
// Check the USE_BIOMETRIC permission here.
@@ -576,6 +649,12 @@ public class BiometricService extends SystemService {
return;
}
final boolean isFromConfirmDeviceCredential =
bundle.getBoolean(BiometricPrompt.KEY_FROM_CONFIRM_DEVICE_CREDENTIAL, false);
if (isFromConfirmDeviceCredential) {
checkInternalPermission();
}
// Check the usage of this in system server. Need to remove this check if it becomes
// a public API.
final boolean useDefaultTitle =
@@ -632,6 +711,7 @@ public class BiometricService extends SystemService {
args.argi2 = callingUid;
args.argi3 = callingPid;
args.argi4 = callingUserId;
args.arg6 = callback;
mHandler.obtainMessage(MSG_AUTHENTICATE, args).sendToTarget();
}
@@ -639,35 +719,30 @@ public class BiometricService extends SystemService {
@Override // Binder call
public void onConfirmDeviceCredentialSuccess() {
checkInternalPermission();
mHandler.post(() -> {
if (mConfirmDeviceCredentialReceiver == null) {
Slog.w(TAG, "onCDCASuccess null!");
return;
}
try {
mConfirmDeviceCredentialReceiver.onAuthenticationSucceeded();
} catch (RemoteException e) {
Slog.e(TAG, "RemoteException", e);
}
mConfirmDeviceCredentialReceiver = null;
});
mHandler.sendEmptyMessage(MSG_ON_CONFIRM_DEVICE_CREDENTIAL_SUCCESS);
}
@Override // Binder call
public void onConfirmDeviceCredentialError(int error, String message) {
checkInternalPermission();
mHandler.post(() -> {
if (mConfirmDeviceCredentialReceiver == null) {
Slog.w(TAG, "onCDCAError null! Error: " + error + " " + message);
return;
}
try {
mConfirmDeviceCredentialReceiver.onError(error, message);
} catch (RemoteException e) {
Slog.e(TAG, "RemoteException", e);
}
mConfirmDeviceCredentialReceiver = null;
});
SomeArgs args = SomeArgs.obtain();
args.argi1 = error;
args.arg1 = message;
mHandler.obtainMessage(MSG_ON_CONFIRM_DEVICE_CREDENTIAL_ERROR, args).sendToTarget();
}
@Override // Binder call
public void registerCancellationCallback(
IBiometricConfirmDeviceCredentialCallback callback) {
// TODO(b/123378871): Remove when moved.
// This callback replaces the one stored in the current session. If the session is null
// we can ignore this, since it means ConfirmDeviceCredential was launched by something
// else (not BiometricPrompt)
checkInternalPermission();
mHandler.obtainMessage(MSG_REGISTER_CANCELLATION_CALLBACK, callback).sendToTarget();
}
@Override // Binder call
@@ -1104,6 +1179,52 @@ public class BiometricService extends SystemService {
}
}
private void handleOnConfirmDeviceCredentialSuccess() {
if (mConfirmDeviceCredentialReceiver == null) {
Slog.w(TAG, "onCDCASuccess null!");
return;
}
try {
mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
mConfirmDeviceCredentialReceiver.onAuthenticationSucceeded();
if (mCurrentAuthSession != null) {
mCurrentAuthSession.mState = STATE_AUTH_IDLE;
mCurrentAuthSession = null;
}
} catch (RemoteException e) {
Slog.e(TAG, "RemoteException", e);
}
mConfirmDeviceCredentialReceiver = null;
}
private void handleOnConfirmDeviceCredentialError(int error, String message) {
if (mConfirmDeviceCredentialReceiver == null) {
Slog.w(TAG, "onCDCAError null! Error: " + error + " " + message);
return;
}
try {
mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
mConfirmDeviceCredentialReceiver.onError(error, message);
if (mCurrentAuthSession != null) {
mCurrentAuthSession.mState = STATE_AUTH_IDLE;
mCurrentAuthSession = null;
}
} catch (RemoteException e) {
Slog.e(TAG, "RemoteException", e);
}
mConfirmDeviceCredentialReceiver = null;
}
private void handleRegisterCancellationCallback(
IBiometricConfirmDeviceCredentialCallback callback) {
if (mCurrentAuthSession == null) {
Slog.d(TAG, "Current auth session null");
return;
}
Slog.d(TAG, "Updating cancel callback");
mCurrentAuthSession.mConfirmDeviceCredentialCallback = callback;
}
private void handleOnError(int cookie, int error, String message) {
Slog.d(TAG, "Error: " + error + " cookie: " + cookie);
// Errors can either be from the current auth session or the pending auth session.
@@ -1114,7 +1235,18 @@ public class BiometricService extends SystemService {
// of their intended receivers.
try {
if (mCurrentAuthSession != null && mCurrentAuthSession.containsCookie(cookie)) {
if (mCurrentAuthSession.mState == STATE_AUTH_STARTED) {
if (mCurrentAuthSession.isFromConfirmDeviceCredential()) {
// If we were invoked by ConfirmDeviceCredential, do not delete the current
// auth session since we still need to respond to cancel signal while
if (DEBUG) Slog.d(TAG, "From CDC, transition to CANCELED_SHOWING_CDC state");
// Send the error to ConfirmDeviceCredential so that it goes to Pin/Pattern/Pass
// screen
mCurrentAuthSession.mClientReceiver.onError(error, message);
mCurrentAuthSession.mState = STATE_BIOMETRIC_AUTH_CANCELED_SHOWING_CDC;
mStatusBarService.hideBiometricDialog();
} else if (mCurrentAuthSession.mState == STATE_AUTH_STARTED) {
mStatusBarService.onBiometricError(message);
if (error == BiometricConstants.BIOMETRIC_ERROR_CANCELED) {
mActivityTaskManager.unregisterTaskStackListener(
@@ -1214,9 +1346,16 @@ public class BiometricService extends SystemService {
KeyStore.getInstance().addAuthToken(mCurrentAuthSession.mTokenEscrow);
mCurrentAuthSession.mClientReceiver.onAuthenticationSucceeded();
}
mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
mCurrentAuthSession.mState = STATE_AUTH_IDLE;
mCurrentAuthSession = null;
// Do not clean up yet if we are from ConfirmDeviceCredential. We should be in the
// STATE_BIOMETRIC_AUTH_CANCELED_SHOWING_CDC. The session should only be removed when
// ConfirmDeviceCredential is confirmed or canceled.
// TODO(b/123378871): Remove when moved
if (!mCurrentAuthSession.isFromConfirmDeviceCredential()) {
mActivityTaskManager.unregisterTaskStackListener(mTaskStackListener);
mCurrentAuthSession.mState = STATE_AUTH_IDLE;
mCurrentAuthSession = null;
}
} catch (RemoteException e) {
Slog.e(TAG, "Remote exception", e);
}
@@ -1235,7 +1374,8 @@ public class BiometricService extends SystemService {
mCurrentAuthSession.mCallingUid,
mCurrentAuthSession.mCallingPid,
mCurrentAuthSession.mCallingUserId,
mCurrentAuthSession.mModality);
mCurrentAuthSession.mModality,
mCurrentAuthSession.mConfirmDeviceCredentialCallback);
}
private void handleOnReadyForAuthentication(int cookie, boolean requireConfirmation,
@@ -1290,7 +1430,8 @@ public class BiometricService extends SystemService {
private void handleAuthenticate(IBinder token, long sessionId, int userId,
IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle,
int callingUid, int callingPid, int callingUserId) {
int callingUid, int callingPid, int callingUserId,
IBiometricConfirmDeviceCredentialCallback callback) {
mHandler.post(() -> {
final Pair<Integer, Integer> result = checkAndGetBiometricModality(userId);
@@ -1328,7 +1469,7 @@ public class BiometricService extends SystemService {
// Start preparing for authentication. Authentication starts when
// all modalities requested have invoked onReadyForAuthentication.
authenticateInternal(token, sessionId, userId, receiver, opPackageName, bundle,
callingUid, callingPid, callingUserId, modality);
callingUid, callingPid, callingUserId, modality, callback);
});
}
@@ -1343,7 +1484,8 @@ public class BiometricService extends SystemService {
*/
private void authenticateInternal(IBinder token, long sessionId, int userId,
IBiometricServiceReceiver receiver, String opPackageName, Bundle bundle,
int callingUid, int callingPid, int callingUserId, int modality) {
int callingUid, int callingPid, int callingUserId, int modality,
IBiometricConfirmDeviceCredentialCallback callback) {
try {
boolean requireConfirmation = bundle.getBoolean(
BiometricPrompt.KEY_REQUIRE_CONFIRMATION, true /* default */);
@@ -1363,7 +1505,7 @@ public class BiometricService extends SystemService {
authenticators.put(modality, cookie);
mPendingAuthSession = new AuthSession(authenticators, token, sessionId, userId,
receiver, opPackageName, bundle, callingUid, callingPid, callingUserId,
modality, requireConfirmation);
modality, requireConfirmation, callback);
mPendingAuthSession.mState = STATE_AUTH_CALLED;
// No polymorphism :(
if ((modality & TYPE_FINGERPRINT) != 0) {
@@ -1390,10 +1532,23 @@ public class BiometricService extends SystemService {
return;
}
// We need to check the current authenticators state. If we're pending confirm
// or idle, we need to dismiss the dialog and send an ERROR_CANCELED to the client,
// since we won't be getting an onError from the driver.
if (mCurrentAuthSession != null && mCurrentAuthSession.mState != STATE_AUTH_STARTED) {
if (mCurrentAuthSession != null
&& mCurrentAuthSession.mState == STATE_BIOMETRIC_AUTH_CANCELED_SHOWING_CDC) {
if (DEBUG) Slog.d(TAG, "Cancel received while ConfirmDeviceCredential showing");
try {
mCurrentAuthSession.mConfirmDeviceCredentialCallback.cancel();
} catch (RemoteException e) {
Slog.e(TAG, "Unable to cancel ConfirmDeviceCredential", e);
}
// TODO(b/123378871): Remove when moved. Piggy back on this for now to clean up.
handleOnConfirmDeviceCredentialError(BiometricConstants.BIOMETRIC_ERROR_CANCELED,
getContext().getString(R.string.biometric_error_canceled));
} else if (mCurrentAuthSession != null
&& mCurrentAuthSession.mState != STATE_AUTH_STARTED) {
// We need to check the current authenticators state. If we're pending confirm
// or idle, we need to dismiss the dialog and send an ERROR_CANCELED to the client,
// since we won't be getting an onError from the driver.
try {
// Send error to client
mCurrentAuthSession.mClientReceiver.onError(
@@ -1409,11 +1564,22 @@ public class BiometricService extends SystemService {
Slog.e(TAG, "Remote exception", e);
}
} else {
cancelInternal(token, opPackageName, true /* fromClient */);
boolean fromCDC = false;
if (mCurrentAuthSession != null) {
fromCDC = mCurrentAuthSession.mBundle.getBoolean(
BiometricPrompt.KEY_FROM_CONFIRM_DEVICE_CREDENTIAL, false);
}
if (fromCDC) {
if (DEBUG) Slog.d(TAG, "Cancelling from CDC");
cancelInternal(token, opPackageName, false /* fromClient */);
} else {
cancelInternal(token, opPackageName, true /* fromClient */);
}
}
}
void cancelInternal(IBinder token, String opPackageName, boolean fromClient) {
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();