Merge changes from topic "more-cancel-sc-qpr1-dev" into sc-qpr1-dev am: 16a7d2e7bd

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15727904

Change-Id: Id9964610269328c04806b44d10b9bb555b1f63e0
This commit is contained in:
Joe Bolinger
2021-09-01 22:23:39 +00:00
committed by Automerger Merge Worker
43 changed files with 713 additions and 309 deletions

View File

@@ -438,9 +438,16 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
}
private class OnAuthenticationCancelListener implements CancellationSignal.OnCancelListener {
private final long mAuthRequestId;
OnAuthenticationCancelListener(long id) {
mAuthRequestId = id;
}
@Override
public void onCancel() {
cancelAuthentication();
Log.d(TAG, "Cancel BP authentication requested for: " + mAuthRequestId);
cancelAuthentication(mAuthRequestId);
}
}
@@ -853,10 +860,12 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
* @param userId The user to authenticate
* @param operationId The keystore operation associated with authentication
*
* @return A requestId that can be used to cancel this operation.
*
* @hide
*/
@RequiresPermission(USE_BIOMETRIC_INTERNAL)
public void authenticateUserForOperation(
public long authenticateUserForOperation(
@NonNull CancellationSignal cancel,
@NonNull @CallbackExecutor Executor executor,
@NonNull AuthenticationCallback callback,
@@ -871,7 +880,8 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
if (callback == null) {
throw new IllegalArgumentException("Must supply a callback");
}
authenticateInternal(operationId, cancel, executor, callback, userId);
return authenticateInternal(operationId, cancel, executor, callback, userId);
}
/**
@@ -1002,10 +1012,10 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
authenticateInternal(null /* crypto */, cancel, executor, callback, mContext.getUserId());
}
private void cancelAuthentication() {
private void cancelAuthentication(long requestId) {
if (mService != null) {
try {
mService.cancelAuthentication(mToken, mContext.getOpPackageName());
mService.cancelAuthentication(mToken, mContext.getOpPackageName(), requestId);
} catch (RemoteException e) {
Log.e(TAG, "Unable to cancel authentication", e);
}
@@ -1024,7 +1034,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
authenticateInternal(operationId, cancel, executor, callback, userId);
}
private void authenticateInternal(
private long authenticateInternal(
long operationId,
@NonNull CancellationSignal cancel,
@NonNull @CallbackExecutor Executor executor,
@@ -1040,9 +1050,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
try {
if (cancel.isCanceled()) {
Log.w(TAG, "Authentication already canceled");
return;
} else {
cancel.setOnCancelListener(new OnAuthenticationCancelListener());
return -1;
}
mExecutor = executor;
@@ -1065,14 +1073,16 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
promptInfo = mPromptInfo;
}
mService.authenticate(mToken, operationId, userId, mBiometricServiceReceiver,
mContext.getOpPackageName(), promptInfo);
final long authId = mService.authenticate(mToken, operationId, userId,
mBiometricServiceReceiver, mContext.getOpPackageName(), promptInfo);
cancel.setOnCancelListener(new OnAuthenticationCancelListener(authId));
return authId;
} catch (RemoteException e) {
Log.e(TAG, "Remote exception while authenticating", e);
mExecutor.execute(() -> callback.onAuthenticationError(
BiometricPrompt.BIOMETRIC_ERROR_HW_UNAVAILABLE,
mContext.getString(R.string.biometric_error_hw_unavailable)));
return -1;
}
}

View File

@@ -41,13 +41,14 @@ interface IAuthService {
// Retrieve the package where BIometricOrompt's UI is implemented
String getUiPackage();
// Requests authentication. The service choose the appropriate biometric to use, and show
// the corresponding BiometricDialog.
void authenticate(IBinder token, long sessionId, int userId,
// Requests authentication. The service chooses the appropriate biometric to use, and shows
// the corresponding BiometricDialog. A requestId is returned that can be used to cancel
// this operation.
long authenticate(IBinder token, long sessionId, int userId,
IBiometricServiceReceiver receiver, String opPackageName, in PromptInfo promptInfo);
// Cancel authentication for the given sessionId
void cancelAuthentication(IBinder token, String opPackageName);
// Cancel authentication for the given requestId.
void cancelAuthentication(IBinder token, String opPackageName, long requestId);
// TODO(b/141025588): Make userId the first arg to be consistent with hasEnrolledBiometrics.
// Checks if biometrics can be used.

View File

@@ -48,13 +48,13 @@ interface IBiometricAuthenticator {
// startPreparedClient().
void prepareForAuthentication(boolean requireConfirmation, IBinder token, long operationId,
int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName,
int cookie, boolean allowBackgroundAuthentication);
long requestId, int cookie, boolean allowBackgroundAuthentication);
// Starts authentication with the previously prepared client.
void startPreparedClient(int cookie);
// Cancels authentication.
void cancelAuthenticationFromService(IBinder token, String opPackageName);
// Cancels authentication for the given requestId.
void cancelAuthenticationFromService(IBinder token, String opPackageName, long requestId);
// Determine if HAL is loaded and ready
boolean isHardwareDetected(String opPackageName);

View File

@@ -36,13 +36,14 @@ interface IBiometricService {
// Retrieve static sensor properties for all biometric sensors
List<SensorPropertiesInternal> getSensorProperties(String opPackageName);
// Requests authentication. The service choose the appropriate biometric to use, and show
// the corresponding BiometricDialog.
void authenticate(IBinder token, long operationId, int userId,
// Requests authentication. The service chooses the appropriate biometric to use, and shows
// the corresponding BiometricDialog. A requestId is returned that can be used to cancel
// this operation.
long authenticate(IBinder token, long operationId, int userId,
IBiometricServiceReceiver receiver, String opPackageName, in PromptInfo promptInfo);
// Cancel authentication for the given session.
void cancelAuthentication(IBinder token, String opPackageName);
// Cancel authentication for the given requestId.
void cancelAuthentication(IBinder token, String opPackageName, long requestId);
// Checks if biometrics can be used.
int canAuthenticate(String opPackageName, int userId, int callingUserId, int authenticators);

View File

@@ -58,7 +58,7 @@ import java.util.List;
public class FaceManager implements BiometricAuthenticator, BiometricFaceConstants {
private static final String TAG = "FaceManager";
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_AUTHENTICATION_SUCCEEDED = 102;
@@ -207,13 +207,9 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
throw new IllegalArgumentException("Must supply an authentication callback");
}
if (cancel != null) {
if (cancel.isCanceled()) {
Slog.w(TAG, "authentication already canceled");
return;
} else {
cancel.setOnCancelListener(new OnAuthenticationCancelListener(crypto));
}
if (cancel != null && cancel.isCanceled()) {
Slog.w(TAG, "authentication already canceled");
return;
}
if (mService != null) {
@@ -223,17 +219,18 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
mCryptoObject = crypto;
final long operationId = crypto != null ? crypto.getOpId() : 0;
Trace.beginSection("FaceManager#authenticate");
mService.authenticate(mToken, operationId, userId, mServiceReceiver,
mContext.getOpPackageName(), isKeyguardBypassEnabled);
final long authId = mService.authenticate(mToken, operationId, userId,
mServiceReceiver, mContext.getOpPackageName(), isKeyguardBypassEnabled);
if (cancel != null) {
cancel.setOnCancelListener(new OnAuthenticationCancelListener(authId));
}
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception while authenticating: ", e);
if (callback != null) {
// Though this may not be a hardware issue, it will cause apps to give up or
// try again later.
callback.onAuthenticationError(FACE_ERROR_HW_UNAVAILABLE,
getErrorString(mContext, FACE_ERROR_HW_UNAVAILABLE,
0 /* vendorCode */));
}
// Though this may not be a hardware issue, it will cause apps to give up or
// try again later.
callback.onAuthenticationError(FACE_ERROR_HW_UNAVAILABLE,
getErrorString(mContext, FACE_ERROR_HW_UNAVAILABLE,
0 /* vendorCode */));
} finally {
Trace.endSection();
}
@@ -255,14 +252,14 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
if (cancel.isCanceled()) {
Slog.w(TAG, "Detection already cancelled");
return;
} else {
cancel.setOnCancelListener(new OnFaceDetectionCancelListener());
}
mFaceDetectionCallback = callback;
try {
mService.detectFace(mToken, userId, mServiceReceiver, mContext.getOpPackageName());
final long authId = mService.detectFace(
mToken, userId, mServiceReceiver, mContext.getOpPackageName());
cancel.setOnCancelListener(new OnFaceDetectionCancelListener(authId));
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception when requesting finger detect", e);
}
@@ -726,23 +723,23 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
}
}
private void cancelAuthentication(CryptoObject cryptoObject) {
private void cancelAuthentication(long requestId) {
if (mService != null) {
try {
mService.cancelAuthentication(mToken, mContext.getOpPackageName());
mService.cancelAuthentication(mToken, mContext.getOpPackageName(), requestId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
}
private void cancelFaceDetect() {
private void cancelFaceDetect(long requestId) {
if (mService == null) {
return;
}
try {
mService.cancelFaceDetect(mToken, mContext.getOpPackageName());
mService.cancelFaceDetect(mToken, mContext.getOpPackageName(), requestId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
@@ -1110,22 +1107,30 @@ public class FaceManager implements BiometricAuthenticator, BiometricFaceConstan
}
private class OnAuthenticationCancelListener implements OnCancelListener {
private final CryptoObject mCrypto;
private final long mAuthRequestId;
OnAuthenticationCancelListener(CryptoObject crypto) {
mCrypto = crypto;
OnAuthenticationCancelListener(long id) {
mAuthRequestId = id;
}
@Override
public void onCancel() {
cancelAuthentication(mCrypto);
Slog.d(TAG, "Cancel face authentication requested for: " + mAuthRequestId);
cancelAuthentication(mAuthRequestId);
}
}
private class OnFaceDetectionCancelListener implements OnCancelListener {
private final long mAuthRequestId;
OnFaceDetectionCancelListener(long id) {
mAuthRequestId = id;
}
@Override
public void onCancel() {
cancelFaceDetect();
Slog.d(TAG, "Cancel face detect requested for: " + mAuthRequestId);
cancelFaceDetect(mAuthRequestId);
}
}

View File

@@ -44,34 +44,36 @@ interface IFaceService {
// Retrieve static sensor properties for the specified sensor
FaceSensorPropertiesInternal getSensorProperties(int sensorId, String opPackageName);
// Authenticate the given sessionId with a face
void authenticate(IBinder token, long operationId, int userId, IFaceServiceReceiver receiver,
// Authenticate with a face. A requestId is returned that can be used to cancel this operation.
long authenticate(IBinder token, long operationId, int userId, IFaceServiceReceiver receiver,
String opPackageName, boolean isKeyguardBypassEnabled);
// Uses the face hardware to detect for the presence of a face, without giving details
// about accept/reject/lockout.
void detectFace(IBinder token, int userId, IFaceServiceReceiver receiver, String opPackageName);
// about accept/reject/lockout. A requestId is returned that can be used to cancel this
// operation.
long detectFace(IBinder token, int userId, IFaceServiceReceiver receiver, String opPackageName);
// This method prepares the service to start authenticating, but doesn't start authentication.
// This is protected by the MANAGE_BIOMETRIC signatuer permission. This method should only be
// called from BiometricService. The additional uid, pid, userId arguments should be determined
// by BiometricService. To start authentication after the clients are ready, use
// startPreparedClient().
void prepareForAuthentication(int sensorId, boolean requireConfirmation, IBinder token, long operationId,
int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName,
int cookie, boolean allowBackgroundAuthentication);
void prepareForAuthentication(int sensorId, boolean requireConfirmation, IBinder token,
long operationId, int userId, IBiometricSensorReceiver sensorReceiver,
String opPackageName, long requestId, int cookie,
boolean allowBackgroundAuthentication);
// Starts authentication with the previously prepared client.
void startPreparedClient(int sensorId, int cookie);
// Cancel authentication for the given sessionId
void cancelAuthentication(IBinder token, String opPackageName);
// Cancel authentication for the given requestId.
void cancelAuthentication(IBinder token, String opPackageName, long requestId);
// Cancel face detection
void cancelFaceDetect(IBinder token, String opPackageName);
// Cancel face detection for the given requestId.
void cancelFaceDetect(IBinder token, String opPackageName, long requestId);
// Same as above, with extra arguments.
void cancelAuthenticationFromService(int sensorId, IBinder token, String opPackageName);
void cancelAuthenticationFromService(int sensorId, IBinder token, String opPackageName, long requestId);
// Start face enrollment
void enroll(int userId, IBinder token, in byte [] hardwareAuthToken, IFaceServiceReceiver receiver,

View File

@@ -189,22 +189,30 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
}
private class OnAuthenticationCancelListener implements OnCancelListener {
private android.hardware.biometrics.CryptoObject mCrypto;
private final long mAuthRequestId;
public OnAuthenticationCancelListener(android.hardware.biometrics.CryptoObject crypto) {
mCrypto = crypto;
OnAuthenticationCancelListener(long id) {
mAuthRequestId = id;
}
@Override
public void onCancel() {
cancelAuthentication(mCrypto);
Slog.d(TAG, "Cancel fingerprint authentication requested for: " + mAuthRequestId);
cancelAuthentication(mAuthRequestId);
}
}
private class OnFingerprintDetectionCancelListener implements OnCancelListener {
private final long mAuthRequestId;
OnFingerprintDetectionCancelListener(long id) {
mAuthRequestId = id;
}
@Override
public void onCancel() {
cancelFingerprintDetect();
Slog.d(TAG, "Cancel fingerprint detect requested for: " + mAuthRequestId);
cancelFingerprintDetect(mAuthRequestId);
}
}
@@ -552,13 +560,9 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
throw new IllegalArgumentException("Must supply an authentication callback");
}
if (cancel != null) {
if (cancel.isCanceled()) {
Slog.w(TAG, "authentication already canceled");
return;
} else {
cancel.setOnCancelListener(new OnAuthenticationCancelListener(crypto));
}
if (cancel != null && cancel.isCanceled()) {
Slog.w(TAG, "authentication already canceled");
return;
}
if (mService != null) {
@@ -567,8 +571,11 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
mAuthenticationCallback = callback;
mCryptoObject = crypto;
final long operationId = crypto != null ? crypto.getOpId() : 0;
mService.authenticate(mToken, operationId, sensorId, userId, mServiceReceiver,
mContext.getOpPackageName());
final long authId = mService.authenticate(mToken, operationId, sensorId, userId,
mServiceReceiver, mContext.getOpPackageName());
if (cancel != null) {
cancel.setOnCancelListener(new OnAuthenticationCancelListener(authId));
}
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception while authenticating: ", e);
// Though this may not be a hardware issue, it will cause apps to give up or try
@@ -595,15 +602,14 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
if (cancel.isCanceled()) {
Slog.w(TAG, "Detection already cancelled");
return;
} else {
cancel.setOnCancelListener(new OnFingerprintDetectionCancelListener());
}
mFingerprintDetectionCallback = callback;
try {
mService.detectFingerprint(mToken, userId, mServiceReceiver,
final long authId = mService.detectFingerprint(mToken, userId, mServiceReceiver,
mContext.getOpPackageName());
cancel.setOnCancelListener(new OnFingerprintDetectionCancelListener(authId));
} catch (RemoteException e) {
Slog.w(TAG, "Remote exception when requesting finger detect", e);
}
@@ -1320,21 +1326,21 @@ public class FingerprintManager implements BiometricAuthenticator, BiometricFing
}
}
private void cancelAuthentication(android.hardware.biometrics.CryptoObject cryptoObject) {
private void cancelAuthentication(long requestId) {
if (mService != null) try {
mService.cancelAuthentication(mToken, mContext.getOpPackageName());
mService.cancelAuthentication(mToken, mContext.getOpPackageName(), requestId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
private void cancelFingerprintDetect() {
private void cancelFingerprintDetect(long requestId) {
if (mService == null) {
return;
}
try {
mService.cancelFingerprintDetect(mToken, mContext.getOpPackageName());
mService.cancelFingerprintDetect(mToken, mContext.getOpPackageName(), requestId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}

View File

@@ -48,15 +48,16 @@ interface IFingerprintService {
// Retrieve static sensor properties for the specified sensor
FingerprintSensorPropertiesInternal getSensorProperties(int sensorId, String opPackageName);
// Authenticate the given sessionId with a fingerprint. This is protected by
// USE_FINGERPRINT/USE_BIOMETRIC permission. This is effectively deprecated, since it only comes
// through FingerprintManager now.
void authenticate(IBinder token, long operationId, int sensorId, int userId,
// Authenticate with a fingerprint. This is protected by USE_FINGERPRINT/USE_BIOMETRIC
// permission. This is effectively deprecated, since it only comes through FingerprintManager
// now. A requestId is returned that can be used to cancel this operation.
long authenticate(IBinder token, long operationId, int sensorId, int userId,
IFingerprintServiceReceiver receiver, String opPackageName);
// Uses the fingerprint hardware to detect for the presence of a finger, without giving details
// about accept/reject/lockout.
void detectFingerprint(IBinder token, int userId, IFingerprintServiceReceiver receiver,
// about accept/reject/lockout. A requestId is returned that can be used to cancel this
// operation.
long detectFingerprint(IBinder token, int userId, IFingerprintServiceReceiver receiver,
String opPackageName);
// This method prepares the service to start authenticating, but doesn't start authentication.
@@ -65,21 +66,21 @@ interface IFingerprintService {
// by BiometricService. To start authentication after the clients are ready, use
// startPreparedClient().
void prepareForAuthentication(int sensorId, IBinder token, long operationId, int userId,
IBiometricSensorReceiver sensorReceiver, String opPackageName, int cookie,
boolean allowBackgroundAuthentication);
IBiometricSensorReceiver sensorReceiver, String opPackageName, long requestId,
int cookie, boolean allowBackgroundAuthentication);
// Starts authentication with the previously prepared client.
void startPreparedClient(int sensorId, int cookie);
// Cancel authentication for the given sessionId
void cancelAuthentication(IBinder token, String opPackageName);
// Cancel authentication for the given requestId.
void cancelAuthentication(IBinder token, String opPackageName, long requestId);
// Cancel finger detection
void cancelFingerprintDetect(IBinder token, String opPackageName);
// Cancel finger detection for the given requestId.
void cancelFingerprintDetect(IBinder token, String opPackageName, long requestId);
// Same as above, except this is protected by the MANAGE_BIOMETRIC signature permission. Takes
// an additional uid, pid, userid.
void cancelAuthenticationFromService(int sensorId, IBinder token, String opPackageName);
void cancelAuthenticationFromService(int sensorId, IBinder token, String opPackageName, long requestId);
// Start fingerprint enrollment
void enroll(IBinder token, in byte [] hardwareAuthToken, int userId, IFingerprintServiceReceiver receiver,

View File

@@ -148,7 +148,7 @@ oneway interface IStatusBar
*/
void showAuthenticationDialog(in PromptInfo promptInfo, IBiometricSysuiReceiver sysuiReceiver,
in int[] sensorIds, boolean credentialAllowed, boolean requireConfirmation, int userId,
String opPackageName, long operationId, int multiSensorConfig);
long operationId, String opPackageName, long requestId, int multiSensorConfig);
/**
* Used to notify the authentication dialog that a biometric has been authenticated.
*/

View File

@@ -110,7 +110,8 @@ interface IStatusBarService
// Used to show the authentication dialog (Biometrics, Device Credential)
void showAuthenticationDialog(in PromptInfo promptInfo, IBiometricSysuiReceiver sysuiReceiver,
in int[] sensorIds, boolean credentialAllowed, boolean requireConfirmation,
int userId, String opPackageName, long operationId, int multiSensorConfig);
int userId, long operationId, String opPackageName, long requestId,
int multiSensorConfig);
// Used to notify the authentication dialog that a biometric has been authenticated
void onBiometricAuthenticated();

View File

@@ -126,6 +126,7 @@ public class AuthContainerView extends LinearLayout
boolean mCredentialAllowed;
boolean mSkipIntro;
long mOperationId;
long mRequestId;
@BiometricMultiSensorMode int mMultiSensorConfig;
}
@@ -172,6 +173,12 @@ public class AuthContainerView extends LinearLayout
return this;
}
/** Unique id for this request. */
public Builder setRequestId(long requestId) {
mConfig.mRequestId = requestId;
return this;
}
/** The multi-sensor mode. */
public Builder setMultiSensorConfig(@BiometricMultiSensorMode int multiSensorConfig) {
mConfig.mMultiSensorConfig = multiSensorConfig;

View File

@@ -501,7 +501,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
@Override
public void showAuthenticationDialog(PromptInfo promptInfo, IBiometricSysuiReceiver receiver,
int[] sensorIds, boolean credentialAllowed, boolean requireConfirmation,
int userId, String opPackageName, long operationId,
int userId, long operationId, String opPackageName, long requestId,
@BiometricMultiSensorMode int multiSensorConfig) {
@Authenticators.Types final int authenticators = promptInfo.getAuthenticators();
@@ -515,6 +515,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
+ ", credentialAllowed: " + credentialAllowed
+ ", requireConfirmation: " + requireConfirmation
+ ", operationId: " + operationId
+ ", requestId: " + requestId
+ ", multiSensorConfig: " + multiSensorConfig);
}
SomeArgs args = SomeArgs.obtain();
@@ -526,6 +527,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
args.argi1 = userId;
args.arg6 = opPackageName;
args.arg7 = operationId;
args.arg8 = requestId;
args.argi2 = multiSensorConfig;
boolean skipAnimation = false;
@@ -629,6 +631,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
if (mCurrentDialog == null) {
// Could be possible if the caller canceled authentication after credential success
// but before the client was notified.
if (DEBUG) Log.d(TAG, "dialog already gone");
return;
}
@@ -683,6 +686,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
final int userId = args.argi1;
final String opPackageName = (String) args.arg6;
final long operationId = (long) args.arg7;
final long requestId = (long) args.arg8;
final @BiometricMultiSensorMode int multiSensorConfig = args.argi2;
// Create a new dialog but do not replace the current one yet.
@@ -695,6 +699,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
opPackageName,
skipAnimation,
operationId,
requestId,
multiSensorConfig);
if (newDialog == null) {
@@ -772,7 +777,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
protected AuthDialog buildDialog(PromptInfo promptInfo, boolean requireConfirmation,
int userId, int[] sensorIds, boolean credentialAllowed, String opPackageName,
boolean skipIntro, long operationId,
boolean skipIntro, long operationId, long requestId,
@BiometricMultiSensorMode int multiSensorConfig) {
return new AuthContainerView.Builder(mContext)
.setCallback(this)
@@ -782,6 +787,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
.setOpPackageName(opPackageName)
.setSkipIntro(skipIntro)
.setOperationId(operationId)
.setRequestId(requestId)
.setMultiSensorConfig(multiSensorConfig)
.build(sensorIds, credentialAllowed, mFpProps, mFaceProps);
}

View File

@@ -290,8 +290,8 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
default void showAuthenticationDialog(PromptInfo promptInfo,
IBiometricSysuiReceiver receiver,
int[] sensorIds, boolean credentialAllowed,
boolean requireConfirmation, int userId, String opPackageName,
long operationId, @BiometricMultiSensorMode int multiSensorConfig) {
boolean requireConfirmation, int userId, long operationId, String opPackageName,
long requestId, @BiometricMultiSensorMode int multiSensorConfig) {
}
/** @see IStatusBar#onBiometricAuthenticated() */
@@ -843,7 +843,7 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
@Override
public void showAuthenticationDialog(PromptInfo promptInfo, IBiometricSysuiReceiver receiver,
int[] sensorIds, boolean credentialAllowed, boolean requireConfirmation,
int userId, String opPackageName, long operationId,
int userId, long operationId, String opPackageName, long requestId,
@BiometricMultiSensorMode int multiSensorConfig) {
synchronized (mLock) {
SomeArgs args = SomeArgs.obtain();
@@ -855,6 +855,7 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
args.argi1 = userId;
args.arg6 = opPackageName;
args.arg7 = operationId;
args.arg8 = requestId;
args.argi2 = multiSensorConfig;
mHandler.obtainMessage(MSG_BIOMETRIC_SHOW, args)
.sendToTarget();
@@ -1312,8 +1313,9 @@ public class CommandQueue extends IStatusBar.Stub implements CallbackController<
(boolean) someArgs.arg4 /* credentialAllowed */,
(boolean) someArgs.arg5 /* requireConfirmation */,
someArgs.argi1 /* userId */,
(String) someArgs.arg6 /* opPackageName */,
(long) someArgs.arg7 /* operationId */,
(String) someArgs.arg6 /* opPackageName */,
(long) someArgs.arg8 /* requestId */,
someArgs.argi2 /* multiSensorConfig */);
}
someArgs.recycle();

View File

@@ -565,8 +565,9 @@ public class AuthControllerTest extends SysuiTestCase {
credentialAllowed,
true /* requireConfirmation */,
0 /* userId */,
"testPackage",
0 /* operationId */,
"testPackage",
1 /* requestId */,
BIOMETRIC_MULTI_SENSOR_FACE_THEN_FINGERPRINT);
}
@@ -612,7 +613,7 @@ public class AuthControllerTest extends SysuiTestCase {
@Override
protected AuthDialog buildDialog(PromptInfo promptInfo,
boolean requireConfirmation, int userId, int[] sensorIds, boolean credentialAllowed,
String opPackageName, boolean skipIntro, long operationId,
String opPackageName, boolean skipIntro, long operationId, long requestId,
@BiometricManager.BiometricMultiSensorMode int multiSensorConfig) {
mLastBiometricPromptInfo = promptInfo;

View File

@@ -423,17 +423,18 @@ public class CommandQueueTest extends SysuiTestCase {
final boolean credentialAllowed = true;
final boolean requireConfirmation = true;
final int userId = 10;
final String packageName = "test";
final long operationId = 1;
final String packageName = "test";
final long requestId = 10;
final int multiSensorConfig = BiometricManager.BIOMETRIC_MULTI_SENSOR_DEFAULT;
mCommandQueue.showAuthenticationDialog(promptInfo, receiver, sensorIds,
credentialAllowed, requireConfirmation , userId, packageName, operationId,
credentialAllowed, requireConfirmation, userId, operationId, packageName, requestId,
multiSensorConfig);
waitForIdleSync();
verify(mCallbacks).showAuthenticationDialog(eq(promptInfo), eq(receiver), eq(sensorIds),
eq(credentialAllowed), eq(requireConfirmation), eq(userId), eq(packageName),
eq(operationId), eq(multiSensorConfig));
eq(credentialAllowed), eq(requireConfirmation), eq(userId), eq(operationId),
eq(packageName), eq(requestId), eq(multiSensorConfig));
}
@Test

View File

@@ -206,7 +206,7 @@ public class AuthService extends SystemService {
}
@Override
public void authenticate(IBinder token, long sessionId, int userId,
public long authenticate(IBinder token, long sessionId, int userId,
IBiometricServiceReceiver receiver, String opPackageName, PromptInfo promptInfo)
throws RemoteException {
// Only allow internal clients to authenticate with a different userId.
@@ -223,18 +223,18 @@ public class AuthService extends SystemService {
if (!checkAppOps(callingUid, opPackageName, "authenticate()")) {
authenticateFastFail("Denied by app ops: " + opPackageName, receiver);
return;
return -1;
}
if (token == null || receiver == null || opPackageName == null || promptInfo == null) {
authenticateFastFail(
"Unable to authenticate, one or more null arguments", receiver);
return;
return -1;
}
if (!Utils.isForeground(callingUid, callingPid)) {
authenticateFastFail("Caller is not foreground: " + opPackageName, receiver);
return;
return -1;
}
if (promptInfo.containsTestConfigurations()) {
@@ -251,7 +251,7 @@ public class AuthService extends SystemService {
final long identity = Binder.clearCallingIdentity();
try {
mBiometricService.authenticate(
return mBiometricService.authenticate(
token, sessionId, userId, receiver, opPackageName, promptInfo);
} finally {
Binder.restoreCallingIdentity(identity);
@@ -270,7 +270,7 @@ public class AuthService extends SystemService {
}
@Override
public void cancelAuthentication(IBinder token, String opPackageName)
public void cancelAuthentication(IBinder token, String opPackageName, long requestId)
throws RemoteException {
checkPermission();
@@ -281,7 +281,7 @@ public class AuthService extends SystemService {
final long identity = Binder.clearCallingIdentity();
try {
mBiometricService.cancelAuthentication(token, opPackageName);
mBiometricService.cancelAuthentication(token, opPackageName, requestId);
} finally {
Binder.restoreCallingIdentity(identity);
}

View File

@@ -128,6 +128,7 @@ public final class AuthSession implements IBinder.DeathRecipient {
@VisibleForTesting final IBinder mToken;
// Info to be shown on BiometricDialog when all cookies are returned.
@VisibleForTesting final PromptInfo mPromptInfo;
private final long mRequestId;
private final long mOperationId;
private final int mUserId;
private final IBiometricSensorReceiver mSensorReceiver;
@@ -142,6 +143,8 @@ public final class AuthSession implements IBinder.DeathRecipient {
private @BiometricMultiSensorMode int mMultiSensorMode;
private @MultiSensorState int mMultiSensorState;
private int[] mSensors;
// TODO(b/197265902): merge into state
private boolean mCancelled;
// For explicit confirmation, do not send to keystore until the user has confirmed
// the authentication.
private byte[] mTokenEscrow;
@@ -162,6 +165,7 @@ public final class AuthSession implements IBinder.DeathRecipient {
@NonNull ClientDeathReceiver clientDeathReceiver,
@NonNull PreAuthInfo preAuthInfo,
@NonNull IBinder token,
long requestId,
long operationId,
int userId,
@NonNull IBiometricSensorReceiver sensorReceiver,
@@ -179,6 +183,7 @@ public final class AuthSession implements IBinder.DeathRecipient {
mClientDeathReceiver = clientDeathReceiver;
mPreAuthInfo = preAuthInfo;
mToken = token;
mRequestId = requestId;
mOperationId = operationId;
mUserId = userId;
mSensorReceiver = sensorReceiver;
@@ -187,6 +192,7 @@ public final class AuthSession implements IBinder.DeathRecipient {
mPromptInfo = promptInfo;
mDebugEnabled = debugEnabled;
mFingerprintSensorProperties = fingerprintSensorProperties;
mCancelled = false;
try {
mClientReceiver.asBinder().linkToDeath(this, 0 /* flags */);
@@ -233,7 +239,7 @@ public final class AuthSession implements IBinder.DeathRecipient {
Slog.v(TAG, "waiting for cooking for sensor: " + sensor.id);
}
sensor.goToStateWaitingForCookie(requireConfirmation, mToken, mOperationId,
mUserId, mSensorReceiver, mOpPackageName, cookie,
mUserId, mSensorReceiver, mOpPackageName, mRequestId, cookie,
mPromptInfo.isAllowBackgroundAuthentication());
}
}
@@ -255,8 +261,9 @@ public final class AuthSession implements IBinder.DeathRecipient {
true /* credentialAllowed */,
false /* requireConfirmation */,
mUserId,
mOpPackageName,
mOperationId,
mOpPackageName,
mRequestId,
mMultiSensorMode);
} else if (!mPreAuthInfo.eligibleSensors.isEmpty()) {
// Some combination of biometric or biometric|credential is requested
@@ -270,6 +277,11 @@ public final class AuthSession implements IBinder.DeathRecipient {
}
void onCookieReceived(int cookie) {
if (mCancelled) {
Slog.w(TAG, "Received cookie but already cancelled (ignoring): " + cookie);
return;
}
for (BiometricSensor sensor : mPreAuthInfo.eligibleSensors) {
sensor.goToStateCookieReturnedIfCookieMatches(cookie);
}
@@ -301,8 +313,9 @@ public final class AuthSession implements IBinder.DeathRecipient {
mPreAuthInfo.shouldShowCredential(),
requireConfirmation,
mUserId,
mOpPackageName,
mOperationId,
mOpPackageName,
mRequestId,
mMultiSensorMode);
mState = STATE_AUTH_STARTED;
} catch (RemoteException e) {
@@ -369,7 +382,7 @@ public final class AuthSession implements IBinder.DeathRecipient {
final boolean shouldCancel = filter.apply(sensor);
Slog.d(TAG, "sensorId: " + sensor.id + ", shouldCancel: " + shouldCancel);
if (shouldCancel) {
sensor.goToStateCancelling(mToken, mOpPackageName);
sensor.goToStateCancelling(mToken, mOpPackageName, mRequestId);
}
} catch (RemoteException e) {
Slog.e(TAG, "Unable to cancel authentication");
@@ -425,8 +438,9 @@ public final class AuthSession implements IBinder.DeathRecipient {
true /* credentialAllowed */,
false /* requireConfirmation */,
mUserId,
mOpPackageName,
mOperationId,
mOpPackageName,
mRequestId,
mMultiSensorMode);
} else {
mClientReceiver.onError(modality, error, vendorCode);
@@ -775,6 +789,8 @@ public final class AuthSession implements IBinder.DeathRecipient {
* @return true if this AuthSession is finished, e.g. should be set to null
*/
boolean onCancelAuthSession(boolean force) {
mCancelled = true;
final boolean authStarted = mState == STATE_AUTH_CALLED
|| mState == STATE_AUTH_STARTED
|| mState == STATE_AUTH_STARTED_UI_SHOWING;
@@ -820,6 +836,7 @@ public final class AuthSession implements IBinder.DeathRecipient {
return Utils.isCredentialRequested(mPromptInfo);
}
@VisibleForTesting
boolean allCookiesReceived() {
final int remainingCookies = mPreAuthInfo.numSensorsWaitingForCookie();
Slog.d(TAG, "Remaining cookies: " + remainingCookies);
@@ -839,6 +856,10 @@ public final class AuthSession implements IBinder.DeathRecipient {
return mState;
}
long getRequestId() {
return mRequestId;
}
private int statsModality() {
int modality = 0;
@@ -901,7 +922,9 @@ public final class AuthSession implements IBinder.DeathRecipient {
@Override
public String toString() {
return "State: " + mState
+ ", cancelled: " + mCancelled
+ ", isCrypto: " + isCrypto()
+ ", PreAuthInfo: " + mPreAuthInfo;
+ ", PreAuthInfo: " + mPreAuthInfo
+ ", requestId: " + mRequestId;
}
}

View File

@@ -108,11 +108,11 @@ public abstract class BiometricSensor {
void goToStateWaitingForCookie(boolean requireConfirmation, IBinder token, long sessionId,
int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName,
int cookie, boolean allowBackgroundAuthentication)
long requestId, int cookie, boolean allowBackgroundAuthentication)
throws RemoteException {
mCookie = cookie;
impl.prepareForAuthentication(requireConfirmation, token,
sessionId, userId, sensorReceiver, opPackageName, mCookie,
sessionId, userId, sensorReceiver, opPackageName, requestId, mCookie,
allowBackgroundAuthentication);
mSensorState = STATE_WAITING_FOR_COOKIE;
}
@@ -129,8 +129,9 @@ public abstract class BiometricSensor {
mSensorState = STATE_AUTHENTICATING;
}
void goToStateCancelling(IBinder token, String opPackageName) throws RemoteException {
impl.cancelAuthenticationFromService(token, opPackageName);
void goToStateCancelling(IBinder token, String opPackageName, long requestId)
throws RemoteException {
impl.cancelAuthenticationFromService(token, opPackageName, requestId);
mSensorState = STATE_CANCELING;
}

View File

@@ -83,6 +83,7 @@ import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.atomic.AtomicLong;
/**
* System service that arbitrates the modality for BiometricPrompt to use.
@@ -115,6 +116,7 @@ public class BiometricService extends SystemService {
final SettingObserver mSettingObserver;
private final List<EnabledOnKeyguardCallback> mEnabledOnKeyguardCallbacks;
private final Random mRandom = new Random();
@NonNull private final AtomicLong mRequestCounter;
@VisibleForTesting
IStatusBarService mStatusBarService;
@@ -194,6 +196,7 @@ public class BiometricService extends SystemService {
SomeArgs args = (SomeArgs) msg.obj;
handleAuthenticate(
(IBinder) args.arg1 /* token */,
(long) args.arg6 /* requestId */,
(long) args.arg2 /* operationId */,
args.argi1 /* userid */,
(IBiometricServiceReceiver) args.arg3 /* receiver */,
@@ -204,7 +207,9 @@ public class BiometricService extends SystemService {
}
case MSG_CANCEL_AUTHENTICATION: {
handleCancelAuthentication();
SomeArgs args = (SomeArgs) msg.obj;
handleCancelAuthentication((long) args.arg3 /* requestId */);
args.recycle();
break;
}
@@ -683,13 +688,13 @@ public class BiometricService extends SystemService {
}
@Override // Binder call
public void authenticate(IBinder token, long operationId, int userId,
public long authenticate(IBinder token, long operationId, int userId,
IBiometricServiceReceiver receiver, String opPackageName, PromptInfo promptInfo) {
checkInternalPermission();
if (token == null || receiver == null || opPackageName == null || promptInfo == null) {
Slog.e(TAG, "Unable to authenticate, one or more null arguments");
return;
return -1;
}
if (!Utils.isValidAuthenticatorConfig(promptInfo)) {
@@ -706,6 +711,8 @@ public class BiometricService extends SystemService {
}
}
final long requestId = mRequestCounter.incrementAndGet();
SomeArgs args = SomeArgs.obtain();
args.arg1 = token;
args.arg2 = operationId;
@@ -713,15 +720,23 @@ public class BiometricService extends SystemService {
args.arg3 = receiver;
args.arg4 = opPackageName;
args.arg5 = promptInfo;
args.arg6 = requestId;
mHandler.obtainMessage(MSG_AUTHENTICATE, args).sendToTarget();
return requestId;
}
@Override // Binder call
public void cancelAuthentication(IBinder token, String opPackageName) {
public void cancelAuthentication(IBinder token, String opPackageName, long requestId) {
checkInternalPermission();
mHandler.obtainMessage(MSG_CANCEL_AUTHENTICATION).sendToTarget();
SomeArgs args = SomeArgs.obtain();
args.arg1 = token;
args.arg2 = opPackageName;
args.arg3 = requestId;
mHandler.obtainMessage(MSG_CANCEL_AUTHENTICATION, args).sendToTarget();
}
@Override // Binder call
@@ -1111,6 +1126,10 @@ public class BiometricService extends SystemService {
return Settings.Secure.getInt(context.getContentResolver(),
CoexCoordinator.FACE_HAPTIC_DISABLE, 1) != 0;
}
public AtomicLong getRequestGenerator() {
return new AtomicLong(0);
}
}
/**
@@ -1136,6 +1155,7 @@ public class BiometricService extends SystemService {
mEnabledOnKeyguardCallbacks = new ArrayList<>();
mSettingObserver = mInjector.getSettingObserver(context, mHandler,
mEnabledOnKeyguardCallbacks);
mRequestCounter = mInjector.getRequestGenerator();
// TODO(b/193089985) This logic lives here (outside of CoexCoordinator) so that it doesn't
// need to depend on context. We can remove this code once the advanced logic is enabled
@@ -1349,7 +1369,7 @@ public class BiometricService extends SystemService {
mCurrentAuthSession.onCookieReceived(cookie);
}
private void handleAuthenticate(IBinder token, long operationId, int userId,
private void handleAuthenticate(IBinder token, long requestId, long operationId, int userId,
IBiometricServiceReceiver receiver, String opPackageName, PromptInfo promptInfo) {
mHandler.post(() -> {
try {
@@ -1360,7 +1380,8 @@ public class BiometricService extends SystemService {
final Pair<Integer, Integer> preAuthStatus = preAuthInfo.getPreAuthenticateStatus();
Slog.d(TAG, "handleAuthenticate: modality(" + preAuthStatus.first
+ "), status(" + preAuthStatus.second + "), preAuthInfo: " + preAuthInfo);
+ "), status(" + preAuthStatus.second + "), preAuthInfo: " + preAuthInfo
+ " requestId: " + requestId);
if (preAuthStatus.second == BiometricConstants.BIOMETRIC_SUCCESS) {
// If BIOMETRIC_WEAK or BIOMETRIC_STRONG are allowed, but not enrolled, but
@@ -1372,8 +1393,8 @@ public class BiometricService extends SystemService {
promptInfo.setAuthenticators(Authenticators.DEVICE_CREDENTIAL);
}
authenticateInternal(token, operationId, userId, receiver, opPackageName,
promptInfo, preAuthInfo);
authenticateInternal(token, requestId, operationId, userId, receiver,
opPackageName, promptInfo, preAuthInfo);
} else {
receiver.onError(preAuthStatus.first /* modality */,
preAuthStatus.second /* errorCode */,
@@ -1394,7 +1415,7 @@ public class BiometricService extends SystemService {
* Note that this path is NOT invoked when the BiometricPrompt "Try again" button is pressed.
* In that case, see {@link #handleOnTryAgainPressed()}.
*/
private void authenticateInternal(IBinder token, long operationId, int userId,
private void authenticateInternal(IBinder token, long requestId, long operationId, int userId,
IBiometricServiceReceiver receiver, String opPackageName, PromptInfo promptInfo,
PreAuthInfo preAuthInfo) {
Slog.d(TAG, "Creating authSession with authRequest: " + preAuthInfo);
@@ -1412,9 +1433,9 @@ public class BiometricService extends SystemService {
final boolean debugEnabled = mInjector.isDebugEnabled(getContext(), userId);
mCurrentAuthSession = new AuthSession(getContext(), mStatusBarService, mSysuiReceiver,
mKeyStore, mRandom, mClientDeathReceiver, preAuthInfo, token, operationId, userId,
mBiometricSensorReceiver, receiver, opPackageName, promptInfo, debugEnabled,
mInjector.getFingerprintSensorProperties(getContext()));
mKeyStore, mRandom, mClientDeathReceiver, preAuthInfo, token, requestId,
operationId, userId, mBiometricSensorReceiver, receiver, opPackageName, promptInfo,
debugEnabled, mInjector.getFingerprintSensorProperties(getContext()));
try {
mCurrentAuthSession.goToInitialState();
} catch (RemoteException e) {
@@ -1422,11 +1443,21 @@ public class BiometricService extends SystemService {
}
}
private void handleCancelAuthentication() {
private void handleCancelAuthentication(long requestId) {
if (mCurrentAuthSession == null) {
Slog.e(TAG, "handleCancelAuthentication: AuthSession is null");
return;
}
if (mCurrentAuthSession.getRequestId() != requestId) {
// TODO: actually cancel the operation
// This can happen if the operation has been queued, but is cancelled before
// it reaches the head of the scheduler. Consider it a programming error for now
// and ignore it.
Slog.e(TAG, "handleCancelAuthentication: AuthSession mismatch current requestId: "
+ mCurrentAuthSession.getRequestId() + " cancel for: " + requestId
+ " (ignoring cancellation)");
return;
}
final boolean finished = mCurrentAuthSession.onCancelAuthSession(false /* force */);
if (finished) {

View File

@@ -101,6 +101,7 @@ public abstract class BaseClientMonitor extends LoggableMonitor
private final int mSensorId; // sensorId as configured by the framework
@Nullable private IBinder mToken;
private long mRequestId;
@Nullable private ClientMonitorCallbackConverter mListener;
// Currently only used for authentication client. The cookie generated by BiometricService
// is never 0.
@@ -154,6 +155,7 @@ public abstract class BaseClientMonitor extends LoggableMonitor
mSequentialId = sCount++;
mContext = context;
mToken = token;
mRequestId = -1;
mListener = listener;
mTargetUserId = userId;
mOwner = owner;
@@ -258,6 +260,29 @@ public abstract class BaseClientMonitor extends LoggableMonitor
return mSensorId;
}
/** Unique request id. */
public final long getRequestId() {
return mRequestId;
}
/** If a unique id has been set via {@link #setRequestId(long)} */
public final boolean hasRequestId() {
return mRequestId > 0;
}
/**
* A unique identifier used to tie this operation to a request (i.e an API invocation).
*
* Subclasses should not call this method if this operation does not have a direct
* correspondence to a request and {@link #hasRequestId()} will return false.
*/
protected final void setRequestId(long id) {
if (id <= 0) {
throw new IllegalArgumentException("request id must be positive");
}
mRequestId = id;
}
@VisibleForTesting
public Callback getCallback() {
return mCallback;
@@ -270,6 +295,7 @@ public abstract class BaseClientMonitor extends LoggableMonitor
+ ", proto=" + getProtoEnum()
+ ", owner=" + getOwnerString()
+ ", cookie=" + getCookie()
+ ", requestId=" + getRequestId()
+ ", userId=" + getTargetUserId() + "}";
}
}

View File

@@ -643,22 +643,18 @@ public class BiometricScheduler {
/**
* Requests to cancel authentication or detection.
* @param token from the caller, should match the token passed in when requesting authentication
* @param requestId the id returned when requesting authentication
*/
public void cancelAuthenticationOrDetection(IBinder token) {
if (mCurrentOperation == null) {
Slog.e(getTag(), "Unable to cancel authentication, null operation");
return;
}
final boolean isCorrectClient = isAuthenticationOrDetectionOperation(mCurrentOperation);
final boolean tokenMatches = mCurrentOperation.mClientMonitor.getToken() == token;
public void cancelAuthenticationOrDetection(IBinder token, long requestId) {
Slog.d(getTag(), "cancelAuthenticationOrDetection, requestId: " + requestId
+ " current: " + mCurrentOperation
+ " stack size: " + mPendingOperations.size());
Slog.d(getTag(), "cancelAuthenticationOrDetection, isCorrectClient: " + isCorrectClient
+ ", tokenMatches: " + tokenMatches);
if (isCorrectClient && tokenMatches) {
if (mCurrentOperation != null
&& canCancelAuthOperation(mCurrentOperation, token, requestId)) {
Slog.d(getTag(), "Cancelling: " + mCurrentOperation);
cancelInternal(mCurrentOperation);
} else if (!isCorrectClient) {
} else {
// Look through the current queue for all authentication clients for the specified
// token, and mark them as STATE_WAITING_IN_QUEUE_CANCELING. Note that we're marking
// all of them, instead of just the first one, since the API surface currently doesn't
@@ -666,8 +662,7 @@ public class BiometricScheduler {
// process. However, this generally does not happen anyway, and would be a class of
// bugs on its own.
for (Operation operation : mPendingOperations) {
if (isAuthenticationOrDetectionOperation(operation)
&& operation.mClientMonitor.getToken() == token) {
if (canCancelAuthOperation(operation, token, requestId)) {
Slog.d(getTag(), "Marking " + operation
+ " as STATE_WAITING_IN_QUEUE_CANCELING");
operation.mState = Operation.STATE_WAITING_IN_QUEUE_CANCELING;
@@ -676,10 +671,26 @@ public class BiometricScheduler {
}
}
private boolean isAuthenticationOrDetectionOperation(@NonNull Operation operation) {
final boolean isAuthentication = operation.mClientMonitor
instanceof AuthenticationConsumer;
final boolean isDetection = operation.mClientMonitor instanceof DetectionConsumer;
private static boolean canCancelAuthOperation(Operation operation, IBinder token,
long requestId) {
// TODO: restrict callers that can cancel without requestId (negative value)?
return isAuthenticationOrDetectionOperation(operation)
&& operation.mClientMonitor.getToken() == token
&& isMatchingRequestId(operation, requestId);
}
// By default, monitors are not associated with a request id to retain the original
// behavior (i.e. if no requestId is explicitly set then assume it matches)
private static boolean isMatchingRequestId(Operation operation, long requestId) {
return !operation.mClientMonitor.hasRequestId()
|| operation.mClientMonitor.getRequestId() == requestId;
}
private static boolean isAuthenticationOrDetectionOperation(@NonNull Operation operation) {
final boolean isAuthentication =
operation.mClientMonitor instanceof AuthenticationConsumer;
final boolean isDetection =
operation.mClientMonitor instanceof DetectionConsumer;
return isAuthentication || isDetection;
}

View File

@@ -61,10 +61,11 @@ public final class FaceAuthenticator extends IBiometricAuthenticator.Stub {
@Override
public void prepareForAuthentication(boolean requireConfirmation, IBinder token,
long operationId, int userId, IBiometricSensorReceiver sensorReceiver,
String opPackageName, int cookie, boolean allowBackgroundAuthentication)
String opPackageName, long requestId, int cookie, boolean allowBackgroundAuthentication)
throws RemoteException {
mFaceService.prepareForAuthentication(mSensorId, requireConfirmation, token, operationId,
userId, sensorReceiver, opPackageName, cookie, allowBackgroundAuthentication);
userId, sensorReceiver, opPackageName, requestId, cookie,
allowBackgroundAuthentication);
}
@Override
@@ -73,9 +74,9 @@ public final class FaceAuthenticator extends IBiometricAuthenticator.Stub {
}
@Override
public void cancelAuthenticationFromService(IBinder token, String opPackageName)
public void cancelAuthenticationFromService(IBinder token, String opPackageName, long requestId)
throws RemoteException {
mFaceService.cancelAuthenticationFromService(mSensorId, token, opPackageName);
mFaceService.cancelAuthenticationFromService(mSensorId, token, opPackageName, requestId);
}
@Override

View File

@@ -250,7 +250,7 @@ public class FaceService extends SystemService {
}
@Override // Binder call
public void authenticate(final IBinder token, final long operationId, int userId,
public long authenticate(final IBinder token, final long operationId, int userId,
final IFaceServiceReceiver receiver, final String opPackageName,
boolean isKeyguardBypassEnabled) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
@@ -270,38 +270,38 @@ public class FaceService extends SystemService {
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for authenticate");
return;
return -1;
}
provider.second.scheduleAuthenticate(provider.first, token, operationId, userId,
return provider.second.scheduleAuthenticate(provider.first, token, operationId, userId,
0 /* cookie */,
new ClientMonitorCallbackConverter(receiver), opPackageName, restricted,
statsClient, isKeyguard, isKeyguardBypassEnabled);
}
@Override // Binder call
public void detectFace(final IBinder token, final int userId,
public long detectFace(final IBinder token, final int userId,
final IFaceServiceReceiver receiver, final String opPackageName) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
if (!Utils.isKeyguard(getContext(), opPackageName)) {
Slog.w(TAG, "detectFace called from non-sysui package: " + opPackageName);
return;
return -1;
}
if (!Utils.isUserEncryptedOrLockdown(mLockPatternUtils, userId)) {
// If this happens, something in KeyguardUpdateMonitor is wrong. This should only
// ever be invoked when the user is encrypted or lockdown.
Slog.e(TAG, "detectFace invoked when user is not encrypted or lockdown");
return;
return -1;
}
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for detectFace");
return;
return -1;
}
provider.second.scheduleFaceDetect(provider.first, token, userId,
return provider.second.scheduleFaceDetect(provider.first, token, userId,
new ClientMonitorCallbackConverter(receiver), opPackageName,
BiometricsProtoEnums.CLIENT_KEYGUARD);
}
@@ -309,8 +309,8 @@ public class FaceService extends SystemService {
@Override // Binder call
public void prepareForAuthentication(int sensorId, boolean requireConfirmation,
IBinder token, long operationId, int userId,
IBiometricSensorReceiver sensorReceiver, String opPackageName, int cookie,
boolean allowBackgroundAuthentication) {
IBiometricSensorReceiver sensorReceiver, String opPackageName, long requestId,
int cookie, boolean allowBackgroundAuthentication) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
final ServiceProvider provider = getProviderForSensor(sensorId);
@@ -322,9 +322,9 @@ public class FaceService extends SystemService {
final boolean isKeyguardBypassEnabled = false; // only valid for keyguard clients
final boolean restricted = true; // BiometricPrompt is always restricted
provider.scheduleAuthenticate(sensorId, token, operationId, userId, cookie,
new ClientMonitorCallbackConverter(sensorReceiver), opPackageName, restricted,
BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, allowBackgroundAuthentication,
isKeyguardBypassEnabled);
new ClientMonitorCallbackConverter(sensorReceiver), opPackageName, requestId,
restricted, BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT,
allowBackgroundAuthentication, isKeyguardBypassEnabled);
}
@Override // Binder call
@@ -341,7 +341,8 @@ public class FaceService extends SystemService {
}
@Override // Binder call
public void cancelAuthentication(final IBinder token, final String opPackageName) {
public void cancelAuthentication(final IBinder token, final String opPackageName,
final long requestId) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
@@ -350,11 +351,12 @@ public class FaceService extends SystemService {
return;
}
provider.second.cancelAuthentication(provider.first, token);
provider.second.cancelAuthentication(provider.first, token, requestId);
}
@Override // Binder call
public void cancelFaceDetect(final IBinder token, final String opPackageName) {
public void cancelFaceDetect(final IBinder token, final String opPackageName,
final long requestId) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
if (!Utils.isKeyguard(getContext(), opPackageName)) {
Slog.w(TAG, "cancelFaceDetect called from non-sysui package: "
@@ -368,12 +370,12 @@ public class FaceService extends SystemService {
return;
}
provider.second.cancelFaceDetect(provider.first, token);
provider.second.cancelFaceDetect(provider.first, token, requestId);
}
@Override // Binder call
public void cancelAuthenticationFromService(int sensorId, final IBinder token,
final String opPackageName) {
final String opPackageName, final long requestId) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
final ServiceProvider provider = getProviderForSensor(sensorId);
@@ -382,7 +384,7 @@ public class FaceService extends SystemService {
return;
}
provider.cancelAuthentication(sensorId, token);
provider.cancelAuthentication(sensorId, token, requestId);
}
@Override // Binder call

View File

@@ -101,18 +101,23 @@ public interface ServiceProvider {
void cancelEnrollment(int sensorId, @NonNull IBinder token);
void scheduleFaceDetect(int sensorId, @NonNull IBinder token, int userId,
long scheduleFaceDetect(int sensorId, @NonNull IBinder token, int userId,
@NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName,
int statsClient);
void cancelFaceDetect(int sensorId, @NonNull IBinder token);
void cancelFaceDetect(int sensorId, @NonNull IBinder token, long requestId);
void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId,
long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId,
int cookie, @NonNull ClientMonitorCallbackConverter callback,
@NonNull String opPackageName, boolean restricted, int statsClient,
boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled);
void cancelAuthentication(int sensorId, @NonNull IBinder token);
void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId,
int cookie, @NonNull ClientMonitorCallbackConverter callback,
@NonNull String opPackageName, long requestId, boolean restricted, int statsClient,
boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled);
void cancelAuthentication(int sensorId, @NonNull IBinder token, long requestId);
void scheduleRemove(int sensorId, @NonNull IBinder token, int faceId, int userId,
@NonNull IFaceServiceReceiver receiver, @NonNull String opPackageName);

View File

@@ -65,7 +65,8 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements
@FaceManager.FaceAcquired private int mLastAcquire = FaceManager.FACE_ACQUIRED_UNKNOWN;
FaceAuthenticationClient(@NonNull Context context,
@NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token,
@NonNull LazyDaemon<ISession> lazyDaemon,
@NonNull IBinder token, long requestId,
@NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
boolean restricted, String owner, int cookie, boolean requireConfirmation, int sensorId,
boolean isStrongBiometric, int statsClient, @NonNull UsageStats usageStats,
@@ -76,6 +77,7 @@ class FaceAuthenticationClient extends AuthenticationClient<ISession> implements
BiometricsProtoEnums.MODALITY_FACE, statsClient, null /* taskStackListener */,
lockoutCache, allowBackgroundAuthentication, true /* shouldVibrate */,
isKeyguardBypassEnabled);
setRequestId(requestId);
mUsageStats = usageStats;
mLockoutCache = lockoutCache;
mNotificationManager = context.getSystemService(NotificationManager.class);

View File

@@ -43,11 +43,13 @@ public class FaceDetectClient extends AcquisitionClient<ISession> implements Det
@Nullable private ICancellationSignal mCancellationSignal;
public FaceDetectClient(@NonNull Context context, @NonNull LazyDaemon<ISession> lazyDaemon,
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId,
@NonNull IBinder token, long requestId,
@NonNull ClientMonitorCallbackConverter listener, int userId,
@NonNull String owner, int sensorId, boolean isStrongBiometric, int statsClient) {
super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
true /* shouldVibrate */, BiometricsProtoEnums.MODALITY_FACE,
BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient);
setRequestId(requestId);
mIsStrongBiometric = isStrongBiometric;
}

View File

@@ -65,6 +65,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
/**
* Provider for a single instance of the {@link IFace} HAL.
@@ -83,6 +84,8 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
@NonNull private final UsageStats mUsageStats;
@NonNull private final ActivityTaskManager mActivityTaskManager;
@NonNull private final BiometricTaskStackListener mTaskStackListener;
// for requests that do not use biometric prompt
@NonNull private final AtomicLong mRequestCounter = new AtomicLong(0);
@Nullable private IFace mDaemon;
@@ -110,8 +113,8 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
&& !client.isAlreadyDone()) {
Slog.e(getTag(), "Stopping background authentication, top: "
+ topPackage + " currentClient: " + client);
mSensors.valueAt(i).getScheduler()
.cancelAuthenticationOrDetection(client.getToken());
mSensors.valueAt(i).getScheduler().cancelAuthenticationOrDetection(
client.getToken(), client.getRequestId());
}
}
}
@@ -356,34 +359,39 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
}
@Override
public void scheduleFaceDetect(int sensorId, @NonNull IBinder token,
public long scheduleFaceDetect(int sensorId, @NonNull IBinder token,
int userId, @NonNull ClientMonitorCallbackConverter callback,
@NonNull String opPackageName, int statsClient) {
final long id = mRequestCounter.incrementAndGet();
mHandler.post(() -> {
final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId);
final FaceDetectClient client = new FaceDetectClient(mContext,
mSensors.get(sensorId).getLazySession(), token, callback, userId, opPackageName,
mSensors.get(sensorId).getLazySession(),
token, id, callback, userId, opPackageName,
sensorId, isStrongBiometric, statsClient);
scheduleForSensor(sensorId, client);
});
return id;
}
@Override
public void cancelFaceDetect(int sensorId, @NonNull IBinder token) {
public void cancelFaceDetect(int sensorId, @NonNull IBinder token, long requestId) {
mHandler.post(() -> mSensors.get(sensorId).getScheduler()
.cancelAuthenticationOrDetection(token));
.cancelAuthenticationOrDetection(token, requestId));
}
@Override
public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback,
@NonNull String opPackageName, boolean restricted, int statsClient,
@NonNull String opPackageName, long requestId, boolean restricted, int statsClient,
boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled) {
mHandler.post(() -> {
final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId);
final FaceAuthenticationClient client = new FaceAuthenticationClient(
mContext, mSensors.get(sensorId).getLazySession(), token, callback, userId,
operationId, restricted, opPackageName, cookie,
mContext, mSensors.get(sensorId).getLazySession(), token, requestId, callback,
userId, operationId, restricted, opPackageName, cookie,
false /* requireConfirmation */, sensorId, isStrongBiometric, statsClient,
mUsageStats, mSensors.get(sensorId).getLockoutCache(),
allowBackgroundAuthentication, isKeyguardBypassEnabled);
@@ -392,9 +400,23 @@ public class FaceProvider implements IBinder.DeathRecipient, ServiceProvider {
}
@Override
public void cancelAuthentication(int sensorId, @NonNull IBinder token) {
public long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback,
@NonNull String opPackageName, boolean restricted, int statsClient,
boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled) {
final long id = mRequestCounter.incrementAndGet();
scheduleAuthenticate(sensorId, token, operationId, userId, cookie, callback,
opPackageName, id, restricted, statsClient,
allowBackgroundAuthentication, isKeyguardBypassEnabled);
return id;
}
@Override
public void cancelAuthentication(int sensorId, @NonNull IBinder token, long requestId) {
mHandler.post(() -> mSensors.get(sensorId).getScheduler()
.cancelAuthenticationOrDetection(token));
.cancelAuthenticationOrDetection(token, requestId));
}
@Override

View File

@@ -87,6 +87,7 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
/**
* Supports a single instance of the {@link android.hardware.biometrics.face.V1_0} or its extended
@@ -115,6 +116,8 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
@NonNull private final Map<Integer, Long> mAuthenticatorIds;
@Nullable private IBiometricsFace mDaemon;
@NonNull private final HalResultController mHalResultController;
// for requests that do not use biometric prompt
@NonNull private final AtomicLong mRequestCounter = new AtomicLong(0);
private int mCurrentUserId = UserHandle.USER_NULL;
private final int mSensorId;
private final List<Long> mGeneratedChallengeCount = new ArrayList<>();
@@ -605,7 +608,7 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
}
@Override
public void scheduleFaceDetect(int sensorId, @NonNull IBinder token,
public long scheduleFaceDetect(int sensorId, @NonNull IBinder token,
int userId, @NonNull ClientMonitorCallbackConverter callback,
@NonNull String opPackageName, int statsClient) {
throw new IllegalStateException("Face detect not supported by IBiometricsFace@1.0. Did you"
@@ -613,7 +616,7 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
}
@Override
public void cancelFaceDetect(int sensorId, @NonNull IBinder token) {
public void cancelFaceDetect(int sensorId, @NonNull IBinder token, long requestId) {
throw new IllegalStateException("Face detect not supported by IBiometricsFace@1.0. Did you"
+ "forget to check the supportsFaceDetection flag?");
}
@@ -621,26 +624,38 @@ public class Face10 implements IHwBinder.DeathRecipient, ServiceProvider {
@Override
public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
int userId, int cookie, @NonNull ClientMonitorCallbackConverter receiver,
@NonNull String opPackageName, boolean restricted, int statsClient,
@NonNull String opPackageName, long requestId, boolean restricted, int statsClient,
boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled) {
mHandler.post(() -> {
scheduleUpdateActiveUserWithoutHandler(userId);
final boolean isStrongBiometric = Utils.isStrongBiometric(mSensorId);
final FaceAuthenticationClient client = new FaceAuthenticationClient(mContext,
mLazyDaemon, token, receiver, userId, operationId, restricted, opPackageName,
cookie, false /* requireConfirmation */, mSensorId, isStrongBiometric,
statsClient, mLockoutTracker, mUsageStats, allowBackgroundAuthentication,
isKeyguardBypassEnabled);
mLazyDaemon, token, requestId, receiver, userId, operationId, restricted,
opPackageName, cookie, false /* requireConfirmation */, mSensorId,
isStrongBiometric, statsClient, mLockoutTracker, mUsageStats,
allowBackgroundAuthentication, isKeyguardBypassEnabled);
mScheduler.scheduleClientMonitor(client);
});
}
@Override
public void cancelAuthentication(int sensorId, @NonNull IBinder token) {
mHandler.post(() -> {
mScheduler.cancelAuthenticationOrDetection(token);
});
public long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
int userId, int cookie, @NonNull ClientMonitorCallbackConverter receiver,
@NonNull String opPackageName, boolean restricted, int statsClient,
boolean allowBackgroundAuthentication, boolean isKeyguardBypassEnabled) {
final long id = mRequestCounter.incrementAndGet();
scheduleAuthenticate(sensorId, token, operationId, userId, cookie, receiver,
opPackageName, id, restricted, statsClient,
allowBackgroundAuthentication, isKeyguardBypassEnabled);
return id;
}
@Override
public void cancelAuthentication(int sensorId, @NonNull IBinder token, long requestId) {
mHandler.post(() -> mScheduler.cancelAuthenticationOrDetection(token, requestId));
}
@Override

View File

@@ -57,7 +57,8 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> {
private int mLastAcquire;
FaceAuthenticationClient(@NonNull Context context,
@NonNull LazyDaemon<IBiometricsFace> lazyDaemon, @NonNull IBinder token,
@NonNull LazyDaemon<IBiometricsFace> lazyDaemon,
@NonNull IBinder token, long requestId,
@NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
boolean restricted, String owner, int cookie, boolean requireConfirmation, int sensorId,
boolean isStrongBiometric, int statsClient, @NonNull LockoutTracker lockoutTracker,
@@ -68,6 +69,7 @@ class FaceAuthenticationClient extends AuthenticationClient<IBiometricsFace> {
BiometricsProtoEnums.MODALITY_FACE, statsClient, null /* taskStackListener */,
lockoutTracker, allowBackgroundAuthentication, true /* shouldVibrate */,
isKeyguardBypassEnabled);
setRequestId(requestId);
mUsageStats = usageStats;
final Resources resources = getContext().getResources();

View File

@@ -61,10 +61,10 @@ public final class FingerprintAuthenticator extends IBiometricAuthenticator.Stub
@Override
public void prepareForAuthentication(boolean requireConfirmation, IBinder token,
long operationId, int userId, IBiometricSensorReceiver sensorReceiver,
String opPackageName, int cookie, boolean allowBackgroundAuthentication)
String opPackageName, long requestId, int cookie, boolean allowBackgroundAuthentication)
throws RemoteException {
mFingerprintService.prepareForAuthentication(mSensorId, token, operationId, userId,
sensorReceiver, opPackageName, cookie, allowBackgroundAuthentication);
sensorReceiver, opPackageName, requestId, cookie, allowBackgroundAuthentication);
}
@Override
@@ -73,9 +73,10 @@ public final class FingerprintAuthenticator extends IBiometricAuthenticator.Stub
}
@Override
public void cancelAuthenticationFromService(IBinder token, String opPackageName)
public void cancelAuthenticationFromService(IBinder token, String opPackageName, long requestId)
throws RemoteException {
mFingerprintService.cancelAuthenticationFromService(mSensorId, token, opPackageName);
mFingerprintService.cancelAuthenticationFromService(
mSensorId, token, opPackageName, requestId);
}
@Override

View File

@@ -245,7 +245,7 @@ public class FingerprintService extends SystemService {
@SuppressWarnings("deprecation")
@Override // Binder call
public void authenticate(final IBinder token, final long operationId,
public long authenticate(final IBinder token, final long operationId,
final int sensorId, final int userId, final IFingerprintServiceReceiver receiver,
final String opPackageName) {
final int callingUid = Binder.getCallingUid();
@@ -255,7 +255,7 @@ public class FingerprintService extends SystemService {
if (!canUseFingerprint(opPackageName, true /* requireForeground */, callingUid,
callingPid, callingUserId)) {
Slog.w(TAG, "Authenticate rejecting package: " + opPackageName);
return;
return -1;
}
// Keyguard check must be done on the caller's binder identity, since it also checks
@@ -270,7 +270,7 @@ public class FingerprintService extends SystemService {
// SafetyNet for b/79776455
EventLog.writeEvent(0x534e4554, "79776455");
Slog.e(TAG, "Authenticate invoked when user is encrypted or lockdown");
return;
return -1;
}
} finally {
Binder.restoreCallingIdentity(identity);
@@ -290,7 +290,7 @@ public class FingerprintService extends SystemService {
}
if (provider == null) {
Slog.w(TAG, "Null provider for authenticate");
return;
return -1;
}
final FingerprintSensorPropertiesInternal sensorProps =
@@ -299,18 +299,17 @@ public class FingerprintService extends SystemService {
&& sensorProps != null && sensorProps.isAnyUdfpsType()) {
identity = Binder.clearCallingIdentity();
try {
authenticateWithPrompt(operationId, sensorProps, userId, receiver);
return authenticateWithPrompt(operationId, sensorProps, userId, receiver);
} finally {
Binder.restoreCallingIdentity(identity);
}
} else {
provider.second.scheduleAuthenticate(provider.first, token, operationId, userId,
0 /* cookie */, new ClientMonitorCallbackConverter(receiver), opPackageName,
restricted, statsClient, isKeyguard, mFingerprintStateCallback);
}
return provider.second.scheduleAuthenticate(provider.first, token, operationId, userId,
0 /* cookie */, new ClientMonitorCallbackConverter(receiver), opPackageName,
restricted, statsClient, isKeyguard, mFingerprintStateCallback);
}
private void authenticateWithPrompt(
private long authenticateWithPrompt(
final long operationId,
@NonNull final FingerprintSensorPropertiesInternal props,
final int userId,
@@ -387,33 +386,33 @@ public class FingerprintService extends SystemService {
}
};
biometricPrompt.authenticateUserForOperation(
return biometricPrompt.authenticateUserForOperation(
new CancellationSignal(), executor, promptCallback, userId, operationId);
}
@Override
public void detectFingerprint(final IBinder token, final int userId,
public long detectFingerprint(final IBinder token, final int userId,
final IFingerprintServiceReceiver receiver, final String opPackageName) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
if (!Utils.isKeyguard(getContext(), opPackageName)) {
Slog.w(TAG, "detectFingerprint called from non-sysui package: " + opPackageName);
return;
return -1;
}
if (!Utils.isUserEncryptedOrLockdown(mLockPatternUtils, userId)) {
// If this happens, something in KeyguardUpdateMonitor is wrong. This should only
// ever be invoked when the user is encrypted or lockdown.
Slog.e(TAG, "detectFingerprint invoked when user is not encrypted or lockdown");
return;
return -1;
}
final Pair<Integer, ServiceProvider> provider = getSingleProvider();
if (provider == null) {
Slog.w(TAG, "Null provider for detectFingerprint");
return;
return -1;
}
provider.second.scheduleFingerDetect(provider.first, token, userId,
return provider.second.scheduleFingerDetect(provider.first, token, userId,
new ClientMonitorCallbackConverter(receiver), opPackageName,
BiometricsProtoEnums.CLIENT_KEYGUARD, mFingerprintStateCallback);
}
@@ -421,7 +420,7 @@ public class FingerprintService extends SystemService {
@Override // Binder call
public void prepareForAuthentication(int sensorId, IBinder token, long operationId,
int userId, IBiometricSensorReceiver sensorReceiver, String opPackageName,
int cookie, boolean allowBackgroundAuthentication) {
long requestId, int cookie, boolean allowBackgroundAuthentication) {
Utils.checkPermission(getContext(), MANAGE_BIOMETRIC);
final ServiceProvider provider = getProviderForSensor(sensorId);
@@ -432,9 +431,9 @@ public class FingerprintService extends SystemService {
final boolean restricted = true; // BiometricPrompt is always restricted
provider.scheduleAuthenticate(sensorId, token, operationId, userId, cookie,
new ClientMonitorCallbackConverter(sensorReceiver), opPackageName, restricted,
BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT, allowBackgroundAuthentication,
mFingerprintStateCallback);
new ClientMonitorCallbackConverter(sensorReceiver), opPackageName, requestId,
restricted, BiometricsProtoEnums.CLIENT_BIOMETRIC_PROMPT,
allowBackgroundAuthentication, mFingerprintStateCallback);
}
@Override // Binder call
@@ -452,7 +451,8 @@ public class FingerprintService extends SystemService {
@Override // Binder call
public void cancelAuthentication(final IBinder token, final String opPackageName) {
public void cancelAuthentication(final IBinder token, final String opPackageName,
long requestId) {
final int callingUid = Binder.getCallingUid();
final int callingPid = Binder.getCallingPid();
final int callingUserId = UserHandle.getCallingUserId();
@@ -469,11 +469,12 @@ public class FingerprintService extends SystemService {
return;
}
provider.second.cancelAuthentication(provider.first, token);
provider.second.cancelAuthentication(provider.first, token, requestId);
}
@Override // Binder call
public void cancelFingerprintDetect(final IBinder token, final String opPackageName) {
public void cancelFingerprintDetect(final IBinder token, final String opPackageName,
final long requestId) {
Utils.checkPermission(getContext(), USE_BIOMETRIC_INTERNAL);
if (!Utils.isKeyguard(getContext(), opPackageName)) {
Slog.w(TAG, "cancelFingerprintDetect called from non-sysui package: "
@@ -489,12 +490,12 @@ public class FingerprintService extends SystemService {
return;
}
provider.second.cancelAuthentication(provider.first, token);
provider.second.cancelAuthentication(provider.first, token, requestId);
}
@Override // Binder call
public void cancelAuthenticationFromService(final int sensorId, final IBinder token,
final String opPackageName) {
final String opPackageName, final long requestId) {
Utils.checkPermission(getContext(), MANAGE_BIOMETRIC);
@@ -506,7 +507,7 @@ public class FingerprintService extends SystemService {
return;
}
provider.cancelAuthentication(sensorId, token);
provider.cancelAuthentication(sensorId, token, requestId);
}
@Override // Binder call

View File

@@ -95,12 +95,18 @@ public interface ServiceProvider {
void cancelEnrollment(int sensorId, @NonNull IBinder token);
void scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId,
long scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId,
@NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName,
int statsClient,
@NonNull FingerprintStateCallback fingerprintStateCallback);
void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId,
int cookie, @NonNull ClientMonitorCallbackConverter callback,
@NonNull String opPackageName, long requestId, boolean restricted, int statsClient,
boolean allowBackgroundAuthentication,
@NonNull FingerprintStateCallback fingerprintStateCallback);
long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId, int userId,
int cookie, @NonNull ClientMonitorCallbackConverter callback,
@NonNull String opPackageName, boolean restricted, int statsClient,
boolean allowBackgroundAuthentication,
@@ -108,7 +114,7 @@ public interface ServiceProvider {
void startPreparedClient(int sensorId, int cookie);
void cancelAuthentication(int sensorId, @NonNull IBinder token);
void cancelAuthentication(int sensorId, @NonNull IBinder token, long requestId);
void scheduleRemove(int sensorId, @NonNull IBinder token,
@NonNull IFingerprintServiceReceiver receiver, int fingerId, int userId,

View File

@@ -61,7 +61,8 @@ class FingerprintAuthenticationClient extends AuthenticationClient<ISession> imp
private boolean mIsPointerDown;
FingerprintAuthenticationClient(@NonNull Context context,
@NonNull LazyDaemon<ISession> lazyDaemon, @NonNull IBinder token,
@NonNull LazyDaemon<ISession> lazyDaemon,
@NonNull IBinder token, long requestId,
@NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
boolean restricted, @NonNull String owner, int cookie, boolean requireConfirmation,
int sensorId, boolean isStrongBiometric, int statsClient,
@@ -74,6 +75,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<ISession> imp
BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener,
lockoutCache, allowBackgroundAuthentication, true /* shouldVibrate */,
false /* isKeyguardBypassEnabled */);
setRequestId(requestId);
mLockoutCache = lockoutCache;
mUdfpsOverlayController = udfpsOverlayController;
mSensorProps = sensorProps;

View File

@@ -47,13 +47,15 @@ class FingerprintDetectClient extends AcquisitionClient<ISession> implements Det
@Nullable private ICancellationSignal mCancellationSignal;
FingerprintDetectClient(@NonNull Context context, @NonNull LazyDaemon<ISession> lazyDaemon,
@NonNull IBinder token, @NonNull ClientMonitorCallbackConverter listener, int userId,
@NonNull IBinder token, long requestId,
@NonNull ClientMonitorCallbackConverter listener, int userId,
@NonNull String owner, int sensorId,
@Nullable IUdfpsOverlayController udfpsOverlayController, boolean isStrongBiometric,
int statsClient) {
super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
true /* shouldVibrate */, BiometricsProtoEnums.MODALITY_FINGERPRINT,
BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient);
setRequestId(requestId);
mIsStrongBiometric = isStrongBiometric;
mUdfpsOverlayController = udfpsOverlayController;
}

View File

@@ -71,6 +71,7 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicLong;
/**
* Provider for a single instance of the {@link IFingerprint} HAL.
@@ -88,6 +89,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
@NonNull private final LockoutResetDispatcher mLockoutResetDispatcher;
@NonNull private final ActivityTaskManager mActivityTaskManager;
@NonNull private final BiometricTaskStackListener mTaskStackListener;
// for requests that do not use biometric prompt
@NonNull private final AtomicLong mRequestCounter = new AtomicLong(0);
@Nullable private IFingerprint mDaemon;
@Nullable private IUdfpsOverlayController mUdfpsOverlayController;
@@ -118,8 +121,8 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
&& !client.isAlreadyDone()) {
Slog.e(getTag(), "Stopping background authentication, top: "
+ topPackage + " currentClient: " + client);
mSensors.valueAt(i).getScheduler()
.cancelAuthenticationOrDetection(client.getToken());
mSensors.valueAt(i).getScheduler().cancelAuthenticationOrDetection(
client.getToken(), client.getRequestId());
}
}
}
@@ -369,31 +372,35 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
}
@Override
public void scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId,
public long scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId,
@NonNull ClientMonitorCallbackConverter callback, @NonNull String opPackageName,
int statsClient,
@NonNull FingerprintStateCallback fingerprintStateCallback) {
final long id = mRequestCounter.incrementAndGet();
mHandler.post(() -> {
final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId);
final FingerprintDetectClient client = new FingerprintDetectClient(mContext,
mSensors.get(sensorId).getLazySession(), token, callback, userId,
mSensors.get(sensorId).getLazySession(), token, id, callback, userId,
opPackageName, sensorId, mUdfpsOverlayController, isStrongBiometric,
statsClient);
scheduleForSensor(sensorId, client, fingerprintStateCallback);
});
return id;
}
@Override
public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback,
@NonNull String opPackageName, boolean restricted, int statsClient,
@NonNull String opPackageName, long requestId, boolean restricted, int statsClient,
boolean allowBackgroundAuthentication,
@NonNull FingerprintStateCallback fingerprintStateCallback) {
mHandler.post(() -> {
final boolean isStrongBiometric = Utils.isStrongBiometric(sensorId);
final FingerprintAuthenticationClient client = new FingerprintAuthenticationClient(
mContext, mSensors.get(sensorId).getLazySession(), token, callback, userId,
operationId, restricted, opPackageName, cookie,
mContext, mSensors.get(sensorId).getLazySession(), token, requestId, callback,
userId, operationId, restricted, opPackageName, cookie,
false /* requireConfirmation */, sensorId, isStrongBiometric, statsClient,
mTaskStackListener, mSensors.get(sensorId).getLockoutCache(),
mUdfpsOverlayController, allowBackgroundAuthentication,
@@ -402,15 +409,30 @@ public class FingerprintProvider implements IBinder.DeathRecipient, ServiceProvi
});
}
@Override
public long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
int userId, int cookie, @NonNull ClientMonitorCallbackConverter callback,
@NonNull String opPackageName, boolean restricted, int statsClient,
boolean allowBackgroundAuthentication,
@NonNull FingerprintStateCallback fingerprintStateCallback) {
final long id = mRequestCounter.incrementAndGet();
scheduleAuthenticate(sensorId, token, operationId, userId, cookie, callback,
opPackageName, id, restricted, statsClient, allowBackgroundAuthentication,
fingerprintStateCallback);
return id;
}
@Override
public void startPreparedClient(int sensorId, int cookie) {
mHandler.post(() -> mSensors.get(sensorId).getScheduler().startPreparedClient(cookie));
}
@Override
public void cancelAuthentication(int sensorId, @NonNull IBinder token) {
public void cancelAuthentication(int sensorId, @NonNull IBinder token, long requestId) {
mHandler.post(() -> mSensors.get(sensorId).getScheduler()
.cancelAuthenticationOrDetection(token));
.cancelAuthenticationOrDetection(token, requestId));
}
@Override

View File

@@ -88,6 +88,7 @@ import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicLong;
/**
* Supports a single instance of the {@link android.hardware.biometrics.fingerprint.V2_1} or
@@ -115,6 +116,8 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
@NonNull private final HalResultController mHalResultController;
@Nullable private IUdfpsOverlayController mUdfpsOverlayController;
@Nullable private ISidefpsController mSidefpsController;
// for requests that do not use biometric prompt
@NonNull private final AtomicLong mRequestCounter = new AtomicLong(0);
private int mCurrentUserId = UserHandle.USER_NULL;
private final boolean mIsUdfps;
private final int mSensorId;
@@ -142,7 +145,8 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
&& !client.isAlreadyDone()) {
Slog.e(TAG, "Stopping background authentication, top: "
+ topPackage + " currentClient: " + client);
mScheduler.cancelAuthenticationOrDetection(client.getToken());
mScheduler.cancelAuthenticationOrDetection(
client.getToken(), client.getRequestId());
}
}
});
@@ -591,26 +595,30 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
}
@Override
public void scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId,
public long scheduleFingerDetect(int sensorId, @NonNull IBinder token, int userId,
@NonNull ClientMonitorCallbackConverter listener, @NonNull String opPackageName,
int statsClient,
@NonNull FingerprintStateCallback fingerprintStateCallback) {
final long id = mRequestCounter.incrementAndGet();
mHandler.post(() -> {
scheduleUpdateActiveUserWithoutHandler(userId);
final boolean isStrongBiometric = Utils.isStrongBiometric(mSensorProperties.sensorId);
final FingerprintDetectClient client = new FingerprintDetectClient(mContext,
mLazyDaemon, token, listener, userId, opPackageName,
mLazyDaemon, token, id, listener, userId, opPackageName,
mSensorProperties.sensorId, mUdfpsOverlayController, isStrongBiometric,
statsClient);
mScheduler.scheduleClientMonitor(client, fingerprintStateCallback);
});
return id;
}
@Override
public void scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
int userId, int cookie, @NonNull ClientMonitorCallbackConverter listener,
@NonNull String opPackageName, boolean restricted, int statsClient,
@NonNull String opPackageName, long requestId, boolean restricted, int statsClient,
boolean allowBackgroundAuthentication,
@NonNull FingerprintStateCallback fingerprintStateCallback) {
mHandler.post(() -> {
@@ -618,8 +626,8 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
final boolean isStrongBiometric = Utils.isStrongBiometric(mSensorProperties.sensorId);
final FingerprintAuthenticationClient client = new FingerprintAuthenticationClient(
mContext, mLazyDaemon, token, listener, userId, operationId, restricted,
opPackageName, cookie, false /* requireConfirmation */,
mContext, mLazyDaemon, token, requestId, listener, userId, operationId,
restricted, opPackageName, cookie, false /* requireConfirmation */,
mSensorProperties.sensorId, isStrongBiometric, statsClient,
mTaskStackListener, mLockoutTracker, mUdfpsOverlayController,
allowBackgroundAuthentication, mSensorProperties);
@@ -627,15 +635,30 @@ public class Fingerprint21 implements IHwBinder.DeathRecipient, ServiceProvider
});
}
@Override
public long scheduleAuthenticate(int sensorId, @NonNull IBinder token, long operationId,
int userId, int cookie, @NonNull ClientMonitorCallbackConverter listener,
@NonNull String opPackageName, boolean restricted, int statsClient,
boolean allowBackgroundAuthentication,
@NonNull FingerprintStateCallback fingerprintStateCallback) {
final long id = mRequestCounter.incrementAndGet();
scheduleAuthenticate(sensorId, token, operationId, userId, cookie, listener,
opPackageName, id, restricted, statsClient, allowBackgroundAuthentication,
fingerprintStateCallback);
return id;
}
@Override
public void startPreparedClient(int sensorId, int cookie) {
mHandler.post(() -> mScheduler.startPreparedClient(cookie));
}
@Override
public void cancelAuthentication(int sensorId, @NonNull IBinder token) {
public void cancelAuthentication(int sensorId, @NonNull IBinder token, long requestId) {
Slog.d(TAG, "cancelAuthentication, sensorId: " + sensorId);
mHandler.post(() -> mScheduler.cancelAuthenticationOrDetection(token));
mHandler.post(() -> mScheduler.cancelAuthenticationOrDetection(token, requestId));
}
@Override

View File

@@ -59,7 +59,8 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi
private boolean mIsPointerDown;
FingerprintAuthenticationClient(@NonNull Context context,
@NonNull LazyDaemon<IBiometricsFingerprint> lazyDaemon, @NonNull IBinder token,
@NonNull LazyDaemon<IBiometricsFingerprint> lazyDaemon,
@NonNull IBinder token, long requestId,
@NonNull ClientMonitorCallbackConverter listener, int targetUserId, long operationId,
boolean restricted, @NonNull String owner, int cookie, boolean requireConfirmation,
int sensorId, boolean isStrongBiometric, int statsClient,
@@ -73,6 +74,7 @@ class FingerprintAuthenticationClient extends AuthenticationClient<IBiometricsFi
BiometricsProtoEnums.MODALITY_FINGERPRINT, statsClient, taskStackListener,
lockoutTracker, allowBackgroundAuthentication, true /* shouldVibrate */,
false /* isKeyguardBypassEnabled */);
setRequestId(requestId);
mLockoutFrameworkImpl = lockoutTracker;
mUdfpsOverlayController = udfpsOverlayController;
mSensorProps = sensorProps;

View File

@@ -52,13 +52,15 @@ class FingerprintDetectClient extends AcquisitionClient<IBiometricsFingerprint>
private boolean mIsPointerDown;
public FingerprintDetectClient(@NonNull Context context,
@NonNull LazyDaemon<IBiometricsFingerprint> lazyDaemon, @NonNull IBinder token,
@NonNull LazyDaemon<IBiometricsFingerprint> lazyDaemon,
@NonNull IBinder token, long requestId,
@NonNull ClientMonitorCallbackConverter listener, int userId, @NonNull String owner,
int sensorId, @Nullable IUdfpsOverlayController udfpsOverlayController,
boolean isStrongBiometric, int statsClient) {
super(context, lazyDaemon, token, listener, userId, owner, 0 /* cookie */, sensorId,
true /* shouldVibrate */, BiometricsProtoEnums.MODALITY_FINGERPRINT,
BiometricsProtoEnums.ACTION_AUTHENTICATE, statsClient);
setRequestId(requestId);
mUdfpsOverlayController = udfpsOverlayController;
mIsStrongBiometric = isStrongBiometric;
}

View File

@@ -59,7 +59,7 @@ public final class IrisAuthenticator extends IBiometricAuthenticator.Stub {
@Override
public void prepareForAuthentication(boolean requireConfirmation, IBinder token,
long sessionId, int userId, IBiometricSensorReceiver sensorReceiver,
String opPackageName, int cookie, boolean allowBackgroundAuthentication)
String opPackageName, long requestId, int cookie, boolean allowBackgroundAuthentication)
throws RemoteException {
}
@@ -68,7 +68,7 @@ public final class IrisAuthenticator extends IBiometricAuthenticator.Stub {
}
@Override
public void cancelAuthenticationFromService(IBinder token, String opPackageName)
public void cancelAuthenticationFromService(IBinder token, String opPackageName, long requestId)
throws RemoteException {
}

View File

@@ -783,13 +783,14 @@ public class StatusBarManagerService extends IStatusBarService.Stub implements D
@Override
public void showAuthenticationDialog(PromptInfo promptInfo, IBiometricSysuiReceiver receiver,
int[] sensorIds, boolean credentialAllowed, boolean requireConfirmation,
int userId, String opPackageName, long operationId,
int userId, long operationId, String opPackageName, long requestId,
@BiometricMultiSensorMode int multiSensorConfig) {
enforceBiometricDialog();
if (mBar != null) {
try {
mBar.showAuthenticationDialog(promptInfo, receiver, sensorIds, credentialAllowed,
requireConfirmation, userId, opPackageName, operationId, multiSensorConfig);
requireConfirmation, userId, operationId, opPackageName, requestId,
multiSensorConfig);
} catch (RemoteException ex) {
}
}

View File

@@ -74,6 +74,7 @@ import java.util.function.Consumer;
public class AuthSessionTest {
private static final String TEST_PACKAGE = "test_package";
private static final long TEST_REQUEST_ID = 22;
@Mock private Context mContext;
@Mock private ITrustManager mTrustManager;
@@ -112,6 +113,7 @@ public class AuthSessionTest {
final AuthSession session = createAuthSession(mSensors,
false /* checkDevicePolicyManager */,
Authenticators.BIOMETRIC_STRONG,
TEST_REQUEST_ID,
0 /* operationId */,
0 /* userId */);
@@ -133,6 +135,7 @@ public class AuthSessionTest {
final AuthSession session = createAuthSession(mSensors,
false /* checkDevicePolicyManager */,
Authenticators.BIOMETRIC_STRONG,
TEST_REQUEST_ID,
operationId,
userId);
assertEquals(mSensors.size(), session.mPreAuthInfo.eligibleSensors.size());
@@ -153,6 +156,7 @@ public class AuthSessionTest {
eq(userId),
eq(mSensorReceiver),
eq(TEST_PACKAGE),
eq(TEST_REQUEST_ID),
eq(sensor.getCookie()),
anyBoolean() /* allowBackgroundAuthentication */);
}
@@ -184,6 +188,33 @@ public class AuthSessionTest {
}
}
@Test
public void testCancelReducesAppetiteForCookies() throws Exception {
setupFace(0 /* id */, false /* confirmationAlwaysRequired */,
mock(IBiometricAuthenticator.class));
setupFingerprint(1 /* id */, FingerprintSensorProperties.TYPE_UDFPS_OPTICAL);
final AuthSession session = createAuthSession(mSensors,
false /* checkDevicePolicyManager */,
Authenticators.BIOMETRIC_STRONG,
TEST_REQUEST_ID,
44 /* operationId */,
2 /* userId */);
session.goToInitialState();
for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) {
assertEquals(BiometricSensor.STATE_WAITING_FOR_COOKIE, sensor.getSensorState());
}
session.onCancelAuthSession(false /* force */);
for (BiometricSensor sensor : session.mPreAuthInfo.eligibleSensors) {
session.onCookieReceived(sensor.getCookie());
assertEquals(BiometricSensor.STATE_CANCELING, sensor.getSensorState());
}
}
@Test
public void testMultiAuth_singleSensor_fingerprintSensorStartsAfterDialogAnimationCompletes()
throws Exception {
@@ -212,6 +243,7 @@ public class AuthSessionTest {
final AuthSession session = createAuthSession(mSensors,
false /* checkDevicePolicyManager */,
Authenticators.BIOMETRIC_STRONG,
TEST_REQUEST_ID,
operationId,
userId);
assertEquals(mSensors.size(), session.mPreAuthInfo.eligibleSensors.size());
@@ -238,7 +270,7 @@ public class AuthSessionTest {
// fingerprint sensor does not start even if all cookies are received
assertEquals(STATE_AUTH_STARTED, session.getState());
verify(mStatusBarService).showAuthenticationDialog(any(), any(), any(),
anyBoolean(), anyBoolean(), anyInt(), any(), anyLong(), anyInt());
anyBoolean(), anyBoolean(), anyInt(), anyLong(), any(), anyLong(), anyInt());
// Notify AuthSession that the UI is shown. Then, fingerprint sensor should be started.
session.onDialogAnimatedIn();
@@ -277,6 +309,7 @@ public class AuthSessionTest {
final AuthSession session = createAuthSession(mSensors,
false /* checkDevicePolicyManager */,
Authenticators.BIOMETRIC_STRONG,
TEST_REQUEST_ID,
0 /* operationId */,
0 /* userId */);
@@ -285,7 +318,8 @@ public class AuthSessionTest {
sessionConsumer.accept(session);
verify(faceAuthenticator).cancelAuthenticationFromService(eq(mToken), eq(TEST_PACKAGE));
verify(faceAuthenticator).cancelAuthenticationFromService(
eq(mToken), eq(TEST_PACKAGE), eq(TEST_REQUEST_ID));
}
private PreAuthInfo createPreAuthInfo(List<BiometricSensor> sensors, int userId,
@@ -302,14 +336,14 @@ public class AuthSessionTest {
private AuthSession createAuthSession(List<BiometricSensor> sensors,
boolean checkDevicePolicyManager, @Authenticators.Types int authenticators,
long operationId, int userId) throws RemoteException {
long requestId, long operationId, int userId) throws RemoteException {
final PromptInfo promptInfo = createPromptInfo(authenticators);
final PreAuthInfo preAuthInfo = createPreAuthInfo(sensors, userId, promptInfo,
checkDevicePolicyManager);
return new AuthSession(mContext, mStatusBarService, mSysuiReceiver, mKeyStore,
mRandom, mClientDeathReceiver, preAuthInfo, mToken, operationId, userId,
mRandom, mClientDeathReceiver, preAuthInfo, mToken, requestId, operationId, userId,
mSensorReceiver, mClientReceiver, TEST_PACKAGE, promptInfo,
false /* debugEnabled */, mFingerprintSensorProps);
}

View File

@@ -85,6 +85,7 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;
@Presubmit
@SmallTest
@@ -93,6 +94,7 @@ public class BiometricServiceTest {
private static final String TAG = "BiometricServiceTest";
private static final String TEST_PACKAGE_NAME = "test_package";
private static final long TEST_REQUEST_ID = 44;
private static final String ERROR_HW_UNAVAILABLE = "hw_unavailable";
private static final String ERROR_NOT_RECOGNIZED = "not_recognized";
@@ -151,6 +153,7 @@ public class BiometricServiceTest {
.thenReturn(mock(BiometricStrengthController.class));
when(mInjector.getTrustManager()).thenReturn(mTrustManager);
when(mInjector.getDevicePolicyManager(any())).thenReturn(mDevicePolicyManager);
when(mInjector.getRequestGenerator()).thenReturn(new AtomicLong(TEST_REQUEST_ID - 1));
when(mResources.getString(R.string.biometric_error_hw_unavailable))
.thenReturn(ERROR_HW_UNAVAILABLE);
@@ -215,8 +218,7 @@ public class BiometricServiceTest {
mBiometricService.mCurrentAuthSession.getState());
verify(mBiometricService.mCurrentAuthSession.mPreAuthInfo.eligibleSensors.get(0).impl)
.cancelAuthenticationFromService(any(),
any());
.cancelAuthenticationFromService(any(), any(), anyLong());
// Simulate ERROR_CANCELED received from HAL
mBiometricService.mBiometricSensorReceiver.onError(
@@ -272,8 +274,9 @@ public class BiometricServiceTest {
eq(true) /* credentialAllowed */,
anyBoolean() /* requireConfirmation */,
anyInt() /* userId */,
anyLong() /* operationId */,
eq(TEST_PACKAGE_NAME),
anyLong() /* sessionId */,
eq(TEST_REQUEST_ID),
eq(BIOMETRIC_MULTI_SENSOR_DEFAULT));
}
@@ -357,8 +360,9 @@ public class BiometricServiceTest {
eq(false) /* credentialAllowed */,
eq(false) /* requireConfirmation */,
anyInt() /* userId */,
anyLong() /* operationId */,
eq(TEST_PACKAGE_NAME),
anyLong() /* sessionId */,
eq(TEST_REQUEST_ID),
eq(BIOMETRIC_MULTI_SENSOR_DEFAULT));
}
@@ -467,6 +471,7 @@ public class BiometricServiceTest {
anyInt() /* userId */,
any(IBiometricSensorReceiver.class),
anyString() /* opPackageName */,
eq(TEST_REQUEST_ID),
cookieCaptor.capture() /* cookie */,
anyBoolean() /* allowBackgroundAuthentication */);
@@ -488,8 +493,9 @@ public class BiometricServiceTest {
eq(false) /* credentialAllowed */,
anyBoolean() /* requireConfirmation */,
anyInt() /* userId */,
anyLong() /* operationId */,
eq(TEST_PACKAGE_NAME),
anyLong() /* sessionId */,
eq(TEST_REQUEST_ID),
eq(BIOMETRIC_MULTI_SENSOR_DEFAULT));
// Hardware authenticated
@@ -543,8 +549,9 @@ public class BiometricServiceTest {
eq(true) /* credentialAllowed */,
anyBoolean() /* requireConfirmation */,
anyInt() /* userId */,
anyLong() /* operationId */,
eq(TEST_PACKAGE_NAME),
anyLong() /* sessionId */,
eq(TEST_REQUEST_ID),
eq(BIOMETRIC_MULTI_SENSOR_DEFAULT));
}
@@ -705,8 +712,9 @@ public class BiometricServiceTest {
anyBoolean() /* credentialAllowed */,
anyBoolean() /* requireConfirmation */,
anyInt() /* userId */,
anyLong() /* operationId */,
anyString(),
anyLong() /* sessionId */,
anyLong() /* requestId */,
eq(BIOMETRIC_MULTI_SENSOR_DEFAULT));
}
@@ -805,8 +813,9 @@ public class BiometricServiceTest {
eq(true) /* credentialAllowed */,
anyBoolean() /* requireConfirmation */,
anyInt() /* userId */,
anyLong() /* operationId */,
eq(TEST_PACKAGE_NAME),
anyLong() /* sessionId */,
eq(TEST_REQUEST_ID),
eq(BIOMETRIC_MULTI_SENSOR_DEFAULT));
}
@@ -885,8 +894,9 @@ public class BiometricServiceTest {
eq(true) /* credentialAllowed */,
anyBoolean() /* requireConfirmation */,
anyInt() /* userId */,
anyLong() /* operationId */,
eq(TEST_PACKAGE_NAME),
anyLong() /* sessionId */,
eq(TEST_REQUEST_ID),
eq(BIOMETRIC_MULTI_SENSOR_DEFAULT));
}
@@ -1030,8 +1040,7 @@ public class BiometricServiceTest {
eq(BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED),
eq(0 /* vendorCode */));
verify(mBiometricService.mSensors.get(0).impl).cancelAuthenticationFromService(
any(),
any());
any(), any(), anyLong());
assertNull(mBiometricService.mCurrentAuthSession);
}
@@ -1051,7 +1060,7 @@ public class BiometricServiceTest {
waitForIdle();
verify(mBiometricService.mSensors.get(0).impl)
.cancelAuthenticationFromService(any(), any());
.cancelAuthenticationFromService(any(), any(), anyLong());
}
@Test
@@ -1071,7 +1080,7 @@ public class BiometricServiceTest {
waitForIdle();
verify(mBiometricService.mSensors.get(0).impl)
.cancelAuthenticationFromService(any(), any());
.cancelAuthenticationFromService(any(), any(), anyLong());
}
@Test
@@ -1088,7 +1097,7 @@ public class BiometricServiceTest {
waitForIdle();
verify(mBiometricService.mSensors.get(0).impl)
.cancelAuthenticationFromService(any(), any());
.cancelAuthenticationFromService(any(), any(), anyLong());
verify(mReceiver1).onError(
eq(BiometricAuthenticator.TYPE_FACE),
eq(BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED),
@@ -1126,7 +1135,7 @@ public class BiometricServiceTest {
false /* requireConfirmation */, null /* authenticators */);
mBiometricService.mImpl.cancelAuthentication(mBiometricService.mCurrentAuthSession.mToken,
TEST_PACKAGE_NAME);
TEST_PACKAGE_NAME, TEST_REQUEST_ID);
waitForIdle();
// Pretend that the HAL has responded to cancel with ERROR_CANCELED
@@ -1353,8 +1362,8 @@ public class BiometricServiceTest {
int authenticators = Authenticators.BIOMETRIC_STRONG;
assertEquals(BiometricManager.BIOMETRIC_ERROR_SECURITY_UPDATE_REQUIRED,
invokeCanAuthenticate(mBiometricService, authenticators));
invokeAuthenticate(mBiometricService.mImpl, mReceiver1, false /* requireConfirmation */,
authenticators);
long requestId = invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
false /* requireConfirmation */, authenticators);
waitForIdle();
verify(mReceiver1).onError(
eq(BiometricAuthenticator.TYPE_FINGERPRINT),
@@ -1366,7 +1375,7 @@ public class BiometricServiceTest {
authenticators = Authenticators.BIOMETRIC_WEAK;
assertEquals(BiometricManager.BIOMETRIC_SUCCESS,
invokeCanAuthenticate(mBiometricService, authenticators));
invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
requestId = invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
false /* requireConfirmation */,
authenticators);
waitForIdle();
@@ -1377,8 +1386,9 @@ public class BiometricServiceTest {
eq(false) /* credentialAllowed */,
anyBoolean() /* requireConfirmation */,
anyInt() /* userId */,
anyLong() /* operationId */,
eq(TEST_PACKAGE_NAME),
anyLong() /* sessionId */,
eq(requestId),
eq(BIOMETRIC_MULTI_SENSOR_DEFAULT));
// Requesting strong and credential, when credential is setup
@@ -1387,7 +1397,7 @@ public class BiometricServiceTest {
when(mTrustManager.isDeviceSecure(anyInt())).thenReturn(true);
assertEquals(BiometricManager.BIOMETRIC_SUCCESS,
invokeCanAuthenticate(mBiometricService, authenticators));
invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
requestId = invokeAuthenticate(mBiometricService.mImpl, mReceiver1,
false /* requireConfirmation */,
authenticators);
waitForIdle();
@@ -1399,8 +1409,9 @@ public class BiometricServiceTest {
eq(true) /* credentialAllowed */,
anyBoolean() /* requireConfirmation */,
anyInt() /* userId */,
anyLong() /* operationId */,
eq(TEST_PACKAGE_NAME),
anyLong() /* sessionId */,
eq(requestId),
eq(BIOMETRIC_MULTI_SENSOR_DEFAULT));
// Un-downgrading the authenticator allows successful strong auth
@@ -1414,7 +1425,7 @@ public class BiometricServiceTest {
authenticators = Authenticators.BIOMETRIC_STRONG;
assertEquals(BiometricManager.BIOMETRIC_SUCCESS,
invokeCanAuthenticate(mBiometricService, authenticators));
invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
requestId = invokeAuthenticateAndStart(mBiometricService.mImpl, mReceiver1,
false /* requireConfirmation */, authenticators);
waitForIdle();
verify(mBiometricService.mStatusBarService).showAuthenticationDialog(
@@ -1424,8 +1435,9 @@ public class BiometricServiceTest {
eq(false) /* credentialAllowed */,
anyBoolean() /* requireConfirmation */,
anyInt() /* userId */,
anyLong() /* operationId */,
eq(TEST_PACKAGE_NAME),
anyLong() /* sessionId */,
eq(requestId),
eq(BIOMETRIC_MULTI_SENSOR_DEFAULT));
}
@@ -1617,11 +1629,12 @@ public class BiometricServiceTest {
mBiometricService.mStatusBarService = mock(IStatusBarService.class);
}
private void invokeAuthenticateAndStart(IBiometricService.Stub service,
private long invokeAuthenticateAndStart(IBiometricService.Stub service,
IBiometricServiceReceiver receiver, boolean requireConfirmation,
Integer authenticators) throws Exception {
// Request auth, creates a pending session
invokeAuthenticate(service, receiver, requireConfirmation, authenticators);
final long requestId = invokeAuthenticate(
service, receiver, requireConfirmation, authenticators);
waitForIdle();
startPendingAuthSession(mBiometricService);
@@ -1629,6 +1642,8 @@ public class BiometricServiceTest {
assertNotNull(mBiometricService.mCurrentAuthSession);
assertEquals(STATE_AUTH_STARTED, mBiometricService.mCurrentAuthSession.getState());
return requestId;
}
private static void startPendingAuthSession(BiometricService service) throws Exception {
@@ -1644,10 +1659,10 @@ public class BiometricServiceTest {
service.mImpl.onReadyForAuthentication(cookie);
}
private static void invokeAuthenticate(IBiometricService.Stub service,
private static long invokeAuthenticate(IBiometricService.Stub service,
IBiometricServiceReceiver receiver, boolean requireConfirmation,
Integer authenticators) throws Exception {
service.authenticate(
return service.authenticate(
new Binder() /* token */,
0 /* operationId */,
0 /* userId */,
@@ -1657,9 +1672,9 @@ public class BiometricServiceTest {
false /* checkDevicePolicy */));
}
private static void invokeAuthenticateForWorkApp(IBiometricService.Stub service,
private static long invokeAuthenticateForWorkApp(IBiometricService.Stub service,
IBiometricServiceReceiver receiver, Integer authenticators) throws Exception {
service.authenticate(
return service.authenticate(
new Binder() /* token */,
0 /* operationId */,
0 /* userId */,

View File

@@ -40,6 +40,7 @@ import android.platform.test.annotations.Presubmit;
import android.testing.TestableContext;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -193,7 +194,7 @@ public class BiometricSchedulerTest {
// Request it to be canceled. The operation can be canceled immediately, and the scheduler
// should go back to idle, since in this case the framework has not even requested the HAL
// to authenticate yet.
mScheduler.cancelAuthenticationOrDetection(mToken);
mScheduler.cancelAuthenticationOrDetection(mToken, 1 /* requestId */);
assertNull(mScheduler.mCurrentOperation);
}
@@ -303,7 +304,7 @@ public class BiometricSchedulerTest {
mScheduler.mPendingOperations.getFirst().mState);
// Request cancel before the authentication client has started
mScheduler.cancelAuthenticationOrDetection(mToken);
mScheduler.cancelAuthenticationOrDetection(mToken, 1 /* requestId */);
waitForIdle();
assertEquals(Operation.STATE_WAITING_IN_QUEUE_CANCELING,
mScheduler.mPendingOperations.getFirst().mState);
@@ -317,6 +318,107 @@ public class BiometricSchedulerTest {
assertNull(mScheduler.getCurrentClient());
}
@Test
public void testCancels_whenAuthRequestIdNotSet() {
testCancelsWhenRequestId(null /* requestId */, 2, true /* started */);
}
@Test
public void testCancels_whenAuthRequestIdNotSet_notStarted() {
testCancelsWhenRequestId(null /* requestId */, 2, false /* started */);
}
@Test
public void testCancels_whenAuthRequestIdMatches() {
testCancelsWhenRequestId(200L, 200, true /* started */);
}
@Test
public void testCancels_whenAuthRequestIdMatches_noStarted() {
testCancelsWhenRequestId(200L, 200, false /* started */);
}
@Test
public void testDoesNotCancel_whenAuthRequestIdMismatched() {
testCancelsWhenRequestId(10L, 20, true /* started */);
}
@Test
public void testDoesNotCancel_whenAuthRequestIdMismatched_notStarted() {
testCancelsWhenRequestId(10L, 20, false /* started */);
}
private void testCancelsWhenRequestId(@Nullable Long requestId, long cancelRequestId,
boolean started) {
final boolean matches = requestId == null || requestId == cancelRequestId;
final HalClientMonitor.LazyDaemon<Object> lazyDaemon = () -> mock(Object.class);
final ClientMonitorCallbackConverter callback = mock(ClientMonitorCallbackConverter.class);
final TestAuthenticationClient client = new TestAuthenticationClient(
mContext, lazyDaemon, mToken, callback);
if (requestId != null) {
client.setRequestId(requestId);
}
mScheduler.scheduleClientMonitor(client);
if (started) {
mScheduler.startPreparedClient(client.getCookie());
}
waitForIdle();
mScheduler.cancelAuthenticationOrDetection(mToken, cancelRequestId);
waitForIdle();
assertEquals(matches && started ? 1 : 0, client.mNumCancels);
if (matches) {
if (started) {
assertEquals(Operation.STATE_STARTED_CANCELING,
mScheduler.mCurrentOperation.mState);
}
} else {
if (started) {
assertEquals(Operation.STATE_STARTED,
mScheduler.mCurrentOperation.mState);
} else {
assertEquals(Operation.STATE_WAITING_FOR_COOKIE,
mScheduler.mCurrentOperation.mState);
}
}
}
@Test
public void testCancelsPending_whenAuthRequestIdsSet() {
final long requestId1 = 10;
final long requestId2 = 20;
final HalClientMonitor.LazyDaemon<Object> lazyDaemon = () -> mock(Object.class);
final ClientMonitorCallbackConverter callback = mock(ClientMonitorCallbackConverter.class);
final TestAuthenticationClient client1 = new TestAuthenticationClient(
mContext, lazyDaemon, mToken, callback);
client1.setRequestId(requestId1);
final TestAuthenticationClient client2 = new TestAuthenticationClient(
mContext, lazyDaemon, mToken, callback);
client2.setRequestId(requestId2);
mScheduler.scheduleClientMonitor(client1);
mScheduler.scheduleClientMonitor(client2);
mScheduler.startPreparedClient(client1.getCookie());
waitForIdle();
mScheduler.cancelAuthenticationOrDetection(mToken, 9999);
waitForIdle();
assertEquals(Operation.STATE_STARTED,
mScheduler.mCurrentOperation.mState);
assertEquals(Operation.STATE_WAITING_IN_QUEUE,
mScheduler.mPendingOperations.getFirst().mState);
mScheduler.cancelAuthenticationOrDetection(mToken, requestId2);
waitForIdle();
assertEquals(Operation.STATE_STARTED,
mScheduler.mCurrentOperation.mState);
assertEquals(Operation.STATE_WAITING_IN_QUEUE_CANCELING,
mScheduler.mPendingOperations.getFirst().mState);
}
@Test
public void testInterruptPrecedingClients_whenExpected() {
final BaseClientMonitor interruptableMonitor = mock(BaseClientMonitor.class,
@@ -377,12 +479,10 @@ public class BiometricSchedulerTest {
@Override
protected void stopHalOperation() {
}
@Override
protected void startHalOperation() {
}
@Override
@@ -397,6 +497,7 @@ public class BiometricSchedulerTest {
}
private static class TestAuthenticationClient extends AuthenticationClient<Object> {
int mNumCancels = 0;
public TestAuthenticationClient(@NonNull Context context,
@NonNull LazyDaemon<Object> lazyDaemon, @NonNull IBinder token,
@@ -428,6 +529,11 @@ public class BiometricSchedulerTest {
public boolean wasUserDetected() {
return false;
}
public void cancel() {
mNumCancels++;
super.cancel();
}
}
private static class TestClientMonitor2 extends TestClientMonitor {