Loading core/java/android/hardware/biometrics/BiometricPrompt.java +29 −9 Original line number Diff line number Diff line Loading @@ -421,6 +421,18 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan return this; } /** * 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}. * Loading Loading @@ -883,28 +895,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"); Loading @@ -916,7 +936,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()); } /** Loading Loading @@ -1050,7 +1070,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); } Loading Loading @@ -1109,7 +1129,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) { Loading core/java/android/hardware/biometrics/ITestSessionCallback.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -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); } core/java/android/hardware/biometrics/PromptInfo.java +20 −2 Original line number Diff line number Diff line Loading @@ -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() { Loading @@ -68,6 +69,7 @@ public class PromptInfo implements Parcelable { mAllowedSensorIds = in.readArrayList(Integer.class.getClassLoader(), java.lang.Integer.class); mAllowBackgroundAuthentication = in.readBoolean(); mIgnoreEnrollmentState = in.readBoolean(); mIsForLegacyFingerprintManager = in.readBoolean(); } public static final Creator<PromptInfo> CREATOR = new Creator<PromptInfo>() { Loading Loading @@ -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; Loading Loading @@ -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) { Loading @@ -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() { Loading Loading @@ -272,4 +286,8 @@ public class PromptInfo implements Parcelable { public boolean isIgnoreEnrollmentState() { return mIgnoreEnrollmentState; } public boolean isForLegacyFingerprintManager() { return mIsForLegacyFingerprintManager; } } packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +7 −3 Original line number Diff line number Diff line Loading @@ -147,7 +147,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba final TaskStackListener mTaskStackListener = new TaskStackListener() { @Override public void onTaskStackChanged() { mHandler.post(AuthController.this::handleTaskStackChanged); mHandler.post(AuthController.this::cancelIfOwnerIsNotInForeground); } }; Loading Loading @@ -198,7 +198,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba } }; private void handleTaskStackChanged() { private void cancelIfOwnerIsNotInForeground() { mExecution.assertIsMainThread(); if (mCurrentDialog != null) { try { Loading @@ -210,7 +210,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba 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(); Loading Loading @@ -885,6 +885,10 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba mCurrentDialog = newDialog; mCurrentDialog.show(mWindowManager, savedState); mOrientationListener.enable(); if (!promptInfo.isAllowBackgroundAuthentication()) { mHandler.post(this::cancelIfOwnerIsNotInForeground); } } private void onDialogDismissed(@DismissedReason int reason) { Loading packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java +26 −6 Original line number Diff line number Diff line Loading @@ -598,16 +598,26 @@ public class AuthControllerTest extends SysuiTestCase { mAuthController.mLastBiometricPromptInfo.getAuthenticators()); } @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(); Loading Loading @@ -725,6 +735,16 @@ public class AuthControllerTest extends SysuiTestCase { BIOMETRIC_MULTI_SENSOR_FINGERPRINT_AND_FACE); } 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(); Loading Loading
core/java/android/hardware/biometrics/BiometricPrompt.java +29 −9 Original line number Diff line number Diff line Loading @@ -421,6 +421,18 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan return this; } /** * 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}. * Loading Loading @@ -883,28 +895,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"); Loading @@ -916,7 +936,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()); } /** Loading Loading @@ -1050,7 +1070,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); } Loading Loading @@ -1109,7 +1129,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) { Loading
core/java/android/hardware/biometrics/ITestSessionCallback.aidl +1 −1 Original line number Diff line number Diff line Loading @@ -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); }
core/java/android/hardware/biometrics/PromptInfo.java +20 −2 Original line number Diff line number Diff line Loading @@ -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() { Loading @@ -68,6 +69,7 @@ public class PromptInfo implements Parcelable { mAllowedSensorIds = in.readArrayList(Integer.class.getClassLoader(), java.lang.Integer.class); mAllowBackgroundAuthentication = in.readBoolean(); mIgnoreEnrollmentState = in.readBoolean(); mIsForLegacyFingerprintManager = in.readBoolean(); } public static final Creator<PromptInfo> CREATOR = new Creator<PromptInfo>() { Loading Loading @@ -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; Loading Loading @@ -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) { Loading @@ -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() { Loading Loading @@ -272,4 +286,8 @@ public class PromptInfo implements Parcelable { public boolean isIgnoreEnrollmentState() { return mIgnoreEnrollmentState; } public boolean isForLegacyFingerprintManager() { return mIsForLegacyFingerprintManager; } }
packages/SystemUI/src/com/android/systemui/biometrics/AuthController.java +7 −3 Original line number Diff line number Diff line Loading @@ -147,7 +147,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba final TaskStackListener mTaskStackListener = new TaskStackListener() { @Override public void onTaskStackChanged() { mHandler.post(AuthController.this::handleTaskStackChanged); mHandler.post(AuthController.this::cancelIfOwnerIsNotInForeground); } }; Loading Loading @@ -198,7 +198,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba } }; private void handleTaskStackChanged() { private void cancelIfOwnerIsNotInForeground() { mExecution.assertIsMainThread(); if (mCurrentDialog != null) { try { Loading @@ -210,7 +210,7 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba 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(); Loading Loading @@ -885,6 +885,10 @@ public class AuthController extends CoreStartable implements CommandQueue.Callba mCurrentDialog = newDialog; mCurrentDialog.show(mWindowManager, savedState); mOrientationListener.enable(); if (!promptInfo.isAllowBackgroundAuthentication()) { mHandler.post(this::cancelIfOwnerIsNotInForeground); } } private void onDialogDismissed(@DismissedReason int reason) { Loading
packages/SystemUI/tests/src/com/android/systemui/biometrics/AuthControllerTest.java +26 −6 Original line number Diff line number Diff line Loading @@ -598,16 +598,26 @@ public class AuthControllerTest extends SysuiTestCase { mAuthController.mLastBiometricPromptInfo.getAuthenticators()); } @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(); Loading Loading @@ -725,6 +735,16 @@ public class AuthControllerTest extends SysuiTestCase { BIOMETRIC_MULTI_SENSOR_FINGERPRINT_AND_FACE); } 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(); Loading