diff options
author | Joe Bolinger <jbolinger@google.com> | 2022-03-18 23:56:35 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-05-16 21:11:25 +0000 |
commit | 8a5bbe3094120c9fec151cf952b51a205a8dbed9 (patch) | |
tree | 9f64893f06f7b3d6ec03aa406afbc1e6cacee320 | |
parent | 187187a31441e44c29d13c1a04c932abc420b709 (diff) | |
download | base-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
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 |