summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoe Bolinger <jbolinger@google.com>2022-03-18 23:56:35 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2022-05-16 21:11:25 +0000
commit8a5bbe3094120c9fec151cf952b51a205a8dbed9 (patch)
tree9f64893f06f7b3d6ec03aa406afbc1e6cacee320
parent187187a31441e44c29d13c1a04c932abc420b709 (diff)
downloadbase-8a5bbe3094120c9fec151cf952b51a205a8dbed9.tar.gz
[DO NOT MERGE] Do not clear calling identify when using BiometricPrompt from FingerprintService.
Bug: 214261879 Test: atest AuthControllerTest Test: Manually verify with test apps in bug Change-Id: I8ae9f2b8a970bf7e5d32121dc358f7d0f0d060b8 (cherry picked from commit 2d60fb3647a838c4c7f10c6f98bf98be4508b119) Merged-In: I8ae9f2b8a970bf7e5d32121dc358f7d0f0d060b8
-rw-r--r--core/java/android/hardware/biometrics/BiometricPrompt.java38
-rw-r--r--core/java/android/hardware/biometrics/ITestSessionCallback.aidl2
-rw-r--r--core/java/android/hardware/biometrics/PromptInfo.java22
-rw-r--r--packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java10
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java32
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java81
-rw-r--r--services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java22
7 files changed, 140 insertions, 67 deletions
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index 6b5bec99e674..520234bcf050 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -421,6 +421,18 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
}
/**
+ * Set if BiometricPrompt is being used by the legacy fingerprint manager API.
+ * @param sensorId sensor id
+ * @return This builder.
+ * @hide
+ */
+ @NonNull
+ public Builder setIsForLegacyFingerprintManager(int sensorId) {
+ mPromptInfo.setIsForLegacyFingerprintManager(sensorId);
+ return this;
+ }
+
+ /**
* Creates a {@link BiometricPrompt}.
*
* @return An instance of {@link BiometricPrompt}.
@@ -861,28 +873,36 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
@NonNull @CallbackExecutor Executor executor,
@NonNull AuthenticationCallback callback,
int userId) {
- authenticateUserForOperation(cancel, executor, callback, userId, 0 /* operationId */);
+ if (cancel == null) {
+ throw new IllegalArgumentException("Must supply a cancellation signal");
+ }
+ if (executor == null) {
+ throw new IllegalArgumentException("Must supply an executor");
+ }
+ if (callback == null) {
+ throw new IllegalArgumentException("Must supply a callback");
+ }
+
+ authenticateInternal(0 /* operationId */, cancel, executor, callback, userId);
}
/**
- * Authenticates for the given user and keystore operation.
+ * Authenticates for the given keystore operation.
*
* @param cancel An object that can be used to cancel authentication
* @param executor An executor to handle callback events
* @param callback An object to receive authentication events
- * @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 long authenticateUserForOperation(
+ @RequiresPermission(USE_BIOMETRIC)
+ public long authenticateForOperation(
@NonNull CancellationSignal cancel,
@NonNull @CallbackExecutor Executor executor,
@NonNull AuthenticationCallback callback,
- int userId,
long operationId) {
if (cancel == null) {
throw new IllegalArgumentException("Must supply a cancellation signal");
@@ -894,7 +914,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
throw new IllegalArgumentException("Must supply a callback");
}
- return authenticateInternal(operationId, cancel, executor, callback, userId);
+ return authenticateInternal(operationId, cancel, executor, callback, mContext.getUserId());
}
/**
@@ -1028,7 +1048,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
private void cancelAuthentication(long requestId) {
if (mService != null) {
try {
- mService.cancelAuthentication(mToken, mContext.getOpPackageName(), requestId);
+ mService.cancelAuthentication(mToken, mContext.getPackageName(), requestId);
} catch (RemoteException e) {
Log.e(TAG, "Unable to cancel authentication", e);
}
@@ -1087,7 +1107,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
}
final long authId = mService.authenticate(mToken, operationId, userId,
- mBiometricServiceReceiver, mContext.getOpPackageName(), promptInfo);
+ mBiometricServiceReceiver, mContext.getPackageName(), promptInfo);
cancel.setOnCancelListener(new OnAuthenticationCancelListener(authId));
return authId;
} catch (RemoteException e) {
diff --git a/core/java/android/hardware/biometrics/ITestSessionCallback.aidl b/core/java/android/hardware/biometrics/ITestSessionCallback.aidl
index 3d9517f29548..b336a9f21b60 100644
--- a/core/java/android/hardware/biometrics/ITestSessionCallback.aidl
+++ b/core/java/android/hardware/biometrics/ITestSessionCallback.aidl
@@ -19,7 +19,7 @@ package android.hardware.biometrics;
* ITestSession callback for FingerprintManager and BiometricManager.
* @hide
*/
-interface ITestSessionCallback {
+oneway interface ITestSessionCallback {
void onCleanupStarted(int userId);
void onCleanupFinished(int userId);
}
diff --git a/core/java/android/hardware/biometrics/PromptInfo.java b/core/java/android/hardware/biometrics/PromptInfo.java
index e6b762a64384..2742f0effde6 100644
--- a/core/java/android/hardware/biometrics/PromptInfo.java
+++ b/core/java/android/hardware/biometrics/PromptInfo.java
@@ -46,6 +46,7 @@ public class PromptInfo implements Parcelable {
@NonNull private List<Integer> mAllowedSensorIds = new ArrayList<>();
private boolean mAllowBackgroundAuthentication;
private boolean mIgnoreEnrollmentState;
+ private boolean mIsForLegacyFingerprintManager = false;
public PromptInfo() {
@@ -68,6 +69,7 @@ public class PromptInfo implements Parcelable {
mAllowedSensorIds = in.readArrayList(Integer.class.getClassLoader());
mAllowBackgroundAuthentication = in.readBoolean();
mIgnoreEnrollmentState = in.readBoolean();
+ mIsForLegacyFingerprintManager = in.readBoolean();
}
public static final Creator<PromptInfo> CREATOR = new Creator<PromptInfo>() {
@@ -105,10 +107,15 @@ public class PromptInfo implements Parcelable {
dest.writeList(mAllowedSensorIds);
dest.writeBoolean(mAllowBackgroundAuthentication);
dest.writeBoolean(mIgnoreEnrollmentState);
+ dest.writeBoolean(mIsForLegacyFingerprintManager);
}
public boolean containsTestConfigurations() {
- if (!mAllowedSensorIds.isEmpty()) {
+ if (mIsForLegacyFingerprintManager
+ && mAllowedSensorIds.size() == 1
+ && !mAllowBackgroundAuthentication) {
+ return false;
+ } else if (!mAllowedSensorIds.isEmpty()) {
return true;
} else if (mAllowBackgroundAuthentication) {
return true;
@@ -188,7 +195,8 @@ public class PromptInfo implements Parcelable {
}
public void setAllowedSensorIds(@NonNull List<Integer> sensorIds) {
- mAllowedSensorIds = sensorIds;
+ mAllowedSensorIds.clear();
+ mAllowedSensorIds.addAll(sensorIds);
}
public void setAllowBackgroundAuthentication(boolean allow) {
@@ -199,6 +207,12 @@ public class PromptInfo implements Parcelable {
mIgnoreEnrollmentState = ignoreEnrollmentState;
}
+ public void setIsForLegacyFingerprintManager(int sensorId) {
+ mIsForLegacyFingerprintManager = true;
+ mAllowedSensorIds.clear();
+ mAllowedSensorIds.add(sensorId);
+ }
+
// Getters
public CharSequence getTitle() {
@@ -272,4 +286,8 @@ public class PromptInfo implements Parcelable {
public boolean isIgnoreEnrollmentState() {
return mIgnoreEnrollmentState;
}
+
+ public boolean isForLegacyFingerprintManager() {
+ return mIsForLegacyFingerprintManager;
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
index df20b83a36ca..7ab214e94230 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java
@@ -134,7 +134,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
private class BiometricTaskStackListener extends TaskStackListener {
@Override
public void onTaskStackChanged() {
- mHandler.post(AuthController.this::handleTaskStackChanged);
+ mHandler.post(AuthController.this::cancelIfOwnerIsNotInForeground);
}
}
@@ -181,7 +181,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
}
};
- private void handleTaskStackChanged() {
+ private void cancelIfOwnerIsNotInForeground() {
mExecution.assertIsMainThread();
if (mCurrentDialog != null) {
try {
@@ -193,7 +193,7 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
final String topPackage = runningTasks.get(0).topActivity.getPackageName();
if (!topPackage.contentEquals(clientPackage)
&& !Utils.isSystem(mContext, clientPackage)) {
- Log.w(TAG, "Evicting client due to: " + topPackage);
+ Log.e(TAG, "Evicting client due to: " + topPackage);
mCurrentDialog.dismissWithoutCallback(true /* animate */);
mCurrentDialog = null;
mOrientationListener.disable();
@@ -814,6 +814,10 @@ public class AuthController extends SystemUI implements CommandQueue.Callbacks,
mCurrentDialog = newDialog;
mCurrentDialog.show(mWindowManager, savedState);
mOrientationListener.enable();
+
+ if (!promptInfo.isAllowBackgroundAuthentication()) {
+ mHandler.post(this::cancelIfOwnerIsNotInForeground);
+ }
}
private void onDialogDismissed(@DismissedReason int reason) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
index 08c77146d34c..2b7c984f04b1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java
@@ -555,15 +555,25 @@ public class AuthControllerTest extends SysuiTestCase {
}
@Test
+ public void testClientNotified_whenTaskStackChangesDuringShow() throws Exception {
+ switchTask("other_package");
+ showDialog(new int[] {1} /* sensorIds */, false /* credentialAllowed */);
+
+ mTestableLooper.processAllMessages();
+
+ assertNull(mAuthController.mCurrentDialog);
+ assertNull(mAuthController.mReceiver);
+ verify(mDialog1).dismissWithoutCallback(true /* animate */);
+ verify(mReceiver).onDialogDismissed(
+ eq(BiometricPrompt.DISMISSED_REASON_USER_CANCEL),
+ eq(null) /* credentialAttestation */);
+ }
+
+ @Test
public void testClientNotified_whenTaskStackChangesDuringAuthentication() throws Exception {
showDialog(new int[] {1} /* sensorIds */, false /* credentialAllowed */);
- List<ActivityManager.RunningTaskInfo> tasks = new ArrayList<>();
- ActivityManager.RunningTaskInfo taskInfo = mock(ActivityManager.RunningTaskInfo.class);
- taskInfo.topActivity = mock(ComponentName.class);
- when(taskInfo.topActivity.getPackageName()).thenReturn("other_package");
- tasks.add(taskInfo);
- when(mActivityTaskManager.getTasks(anyInt())).thenReturn(tasks);
+ switchTask("other_package");
mAuthController.mTaskStackListener.onTaskStackChanged();
mTestableLooper.processAllMessages();
@@ -640,6 +650,16 @@ public class AuthControllerTest extends SysuiTestCase {
BIOMETRIC_MULTI_SENSOR_FACE_THEN_FINGERPRINT);
}
+ private void switchTask(String packageName) {
+ final List<ActivityManager.RunningTaskInfo> tasks = new ArrayList<>();
+ final ActivityManager.RunningTaskInfo taskInfo =
+ mock(ActivityManager.RunningTaskInfo.class);
+ taskInfo.topActivity = mock(ComponentName.class);
+ when(taskInfo.topActivity.getPackageName()).thenReturn(packageName);
+ tasks.add(taskInfo);
+ when(mActivityTaskManager.getTasks(anyInt())).thenReturn(tasks);
+ }
+
private PromptInfo createTestPromptInfo() {
PromptInfo promptInfo = new PromptInfo();
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
index 358263df916b..92c8c9bb57ec 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@@ -118,7 +118,7 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
mIsStrongBiometric = isStrongBiometric;
mOperationId = operationId;
mRequireConfirmation = requireConfirmation;
- mActivityTaskManager = ActivityTaskManager.getInstance();
+ mActivityTaskManager = getActivityTaskManager();
mBiometricManager = context.getSystemService(BiometricManager.class);
mTaskStackListener = taskStackListener;
mLockoutTracker = lockoutTracker;
@@ -146,6 +146,10 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
return mStartTimeMs;
}
+ protected ActivityTaskManager getActivityTaskManager() {
+ return ActivityTaskManager.getInstance();
+ }
+
@Override
public void binderDied() {
final boolean clearListener = !isBiometricPrompt();
@@ -322,45 +326,50 @@ public abstract class AuthenticationClient<T> extends AcquisitionClient<T>
sendCancelOnly(listener);
}
});
- } else {
- // Allow system-defined limit of number of attempts before giving up
- final @LockoutTracker.LockoutMode int lockoutMode =
- handleFailedAttempt(getTargetUserId());
- if (lockoutMode != LockoutTracker.LOCKOUT_NONE) {
- markAlreadyDone();
- }
-
- final CoexCoordinator coordinator = CoexCoordinator.getInstance();
- coordinator.onAuthenticationRejected(SystemClock.uptimeMillis(), this, lockoutMode,
- new CoexCoordinator.Callback() {
- @Override
- public void sendAuthenticationResult(boolean addAuthTokenIfStrong) {
- if (listener != null) {
- try {
- listener.onAuthenticationFailed(getSensorId());
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to notify listener", e);
- }
- }
+ } else { // not authenticated
+ if (isBackgroundAuth) {
+ Slog.e(TAG, "cancelling due to background auth");
+ cancel();
+ } else {
+ // Allow system-defined limit of number of attempts before giving up
+ final @LockoutTracker.LockoutMode int lockoutMode =
+ handleFailedAttempt(getTargetUserId());
+ if (lockoutMode != LockoutTracker.LOCKOUT_NONE) {
+ markAlreadyDone();
}
- @Override
- public void sendHapticFeedback() {
- if (listener != null && mShouldVibrate) {
- vibrateError();
- }
- }
+ final CoexCoordinator coordinator = CoexCoordinator.getInstance();
+ coordinator.onAuthenticationRejected(SystemClock.uptimeMillis(), this, lockoutMode,
+ new CoexCoordinator.Callback() {
+ @Override
+ public void sendAuthenticationResult(boolean addAuthTokenIfStrong) {
+ if (listener != null) {
+ try {
+ listener.onAuthenticationFailed(getSensorId());
+ } catch (RemoteException e) {
+ Slog.e(TAG, "Unable to notify listener", e);
+ }
+ }
+ }
- @Override
- public void handleLifecycleAfterAuth() {
- AuthenticationClient.this.handleLifecycleAfterAuth(false /* authenticated */);
- }
+ @Override
+ public void sendHapticFeedback() {
+ if (listener != null && mShouldVibrate) {
+ vibrateError();
+ }
+ }
- @Override
- public void sendAuthenticationCanceled() {
- sendCancelOnly(listener);
- }
- });
+ @Override
+ public void handleLifecycleAfterAuth() {
+ AuthenticationClient.this.handleLifecycleAfterAuth(false /* authenticated */);
+ }
+
+ @Override
+ public void sendAuthenticationCanceled() {
+ sendCancelOnly(listener);
+ }
+ });
+ }
}
}
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
index b44f4dc68274..3a93d82a68ee 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintService.java
@@ -331,12 +331,12 @@ public class FingerprintService extends SystemService {
provider.second.getSensorProperties(sensorId);
if (!isKeyguard && !Utils.isSettings(getContext(), opPackageName)
&& sensorProps != null && sensorProps.isAnyUdfpsType()) {
- identity = Binder.clearCallingIdentity();
try {
return authenticateWithPrompt(operationId, sensorProps, userId, receiver,
- ignoreEnrollmentState);
- } finally {
- Binder.restoreCallingIdentity(identity);
+ opPackageName, ignoreEnrollmentState);
+ } catch (PackageManager.NameNotFoundException e) {
+ Slog.e(TAG, "Invalid package", e);
+ return -1;
}
}
return provider.second.scheduleAuthenticate(provider.first, token, operationId, userId,
@@ -349,12 +349,15 @@ public class FingerprintService extends SystemService {
@NonNull final FingerprintSensorPropertiesInternal props,
final int userId,
final IFingerprintServiceReceiver receiver,
- boolean ignoreEnrollmentState) {
+ final String opPackageName,
+ boolean ignoreEnrollmentState) throws PackageManager.NameNotFoundException {
final Context context = getUiContext();
+ final Context promptContext = context.createPackageContextAsUser(
+ opPackageName, 0 /* flags */, UserHandle.getUserHandleForUid(userId));
final Executor executor = context.getMainExecutor();
- final BiometricPrompt biometricPrompt = new BiometricPrompt.Builder(context)
+ final BiometricPrompt biometricPrompt = new BiometricPrompt.Builder(promptContext)
.setTitle(context.getString(R.string.biometric_dialog_default_title))
.setSubtitle(context.getString(R.string.fingerprint_dialog_default_subtitle))
.setNegativeButton(
@@ -368,8 +371,7 @@ public class FingerprintService extends SystemService {
Slog.e(TAG, "Remote exception in negative button onClick()", e);
}
})
- .setAllowedSensorIds(new ArrayList<>(
- Collections.singletonList(props.sensorId)))
+ .setIsForLegacyFingerprintManager(props.sensorId)
.setIgnoreEnrollmentState(ignoreEnrollmentState)
.build();
@@ -423,8 +425,8 @@ public class FingerprintService extends SystemService {
}
};
- return biometricPrompt.authenticateUserForOperation(
- new CancellationSignal(), executor, promptCallback, userId, operationId);
+ return biometricPrompt.authenticateForOperation(
+ new CancellationSignal(), executor, promptCallback, operationId);
}
@Override