summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/hardware/biometrics/BiometricPrompt.java24
-rw-r--r--core/tests/coretests/src/android/hardware/biometrics/BiometricPromptTest.java102
-rw-r--r--core/tests/coretests/src/android/hardware/biometrics/OWNERS1
3 files changed, 122 insertions, 5 deletions
diff --git a/core/java/android/hardware/biometrics/BiometricPrompt.java b/core/java/android/hardware/biometrics/BiometricPrompt.java
index fa678fc5ee1a..2e40f6096ccb 100644
--- a/core/java/android/hardware/biometrics/BiometricPrompt.java
+++ b/core/java/android/hardware/biometrics/BiometricPrompt.java
@@ -142,6 +142,7 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
private PromptInfo mPromptInfo;
private ButtonInfo mNegativeButtonInfo;
private Context mContext;
+ private IAuthService mService;
/**
* Creates a builder for a {@link BiometricPrompt} dialog.
@@ -212,6 +213,18 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
}
/**
+ * @param service
+ * @return This builder.
+ * @hide
+ */
+ @RequiresPermission(TEST_BIOMETRIC)
+ @NonNull
+ public Builder setService(@NonNull IAuthService service) {
+ mService = service;
+ return this;
+ }
+
+ /**
* Sets an optional title, subtitle, and/or description that will override other text when
* the user is authenticating with PIN/pattern/password. Currently for internal use only.
* @return This builder.
@@ -472,7 +485,9 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
throw new IllegalArgumentException("Can't have both negative button behavior"
+ " and device credential enabled");
}
- return new BiometricPrompt(mContext, mPromptInfo, mNegativeButtonInfo);
+ mService = (mService == null) ? IAuthService.Stub.asInterface(
+ ServiceManager.getService(Context.AUTH_SERVICE)) : mService;
+ return new BiometricPrompt(mContext, mPromptInfo, mNegativeButtonInfo, mService);
}
}
@@ -521,7 +536,6 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
public void onAuthenticationFailed() {
mExecutor.execute(() -> {
mAuthenticationCallback.onAuthenticationFailed();
- mIsPromptShowing = false;
});
}
@@ -604,12 +618,12 @@ public class BiometricPrompt implements BiometricAuthenticator, BiometricConstan
private boolean mIsPromptShowing;
- private BiometricPrompt(Context context, PromptInfo promptInfo, ButtonInfo negativeButtonInfo) {
+ private BiometricPrompt(Context context, PromptInfo promptInfo, ButtonInfo negativeButtonInfo,
+ IAuthService service) {
mContext = context;
mPromptInfo = promptInfo;
mNegativeButtonInfo = negativeButtonInfo;
- mService = IAuthService.Stub.asInterface(
- ServiceManager.getService(Context.AUTH_SERVICE));
+ mService = service;
mIsPromptShowing = false;
}
diff --git a/core/tests/coretests/src/android/hardware/biometrics/BiometricPromptTest.java b/core/tests/coretests/src/android/hardware/biometrics/BiometricPromptTest.java
new file mode 100644
index 000000000000..66f3bca72aeb
--- /dev/null
+++ b/core/tests/coretests/src/android/hardware/biometrics/BiometricPromptTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.hardware.biometrics;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyLong;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.CancellationSignal;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.os.test.TestLooper;
+import android.platform.test.annotations.Presubmit;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.mockito.junit.MockitoRule;
+
+import java.util.concurrent.Executor;
+
+
+@Presubmit
+@RunWith(MockitoJUnitRunner.class)
+public class BiometricPromptTest {
+ @Rule
+ public final MockitoRule mockito = MockitoJUnit.rule();
+
+ @Mock
+ private Context mContext;
+ @Mock
+ private IAuthService mService;
+ private BiometricPrompt mBiometricPrompt;
+
+ private CancellationSignal mCancellationSignal;
+
+ private final TestLooper mLooper = new TestLooper();
+ private final Handler mHandler = new Handler(mLooper.getLooper());
+ private final Executor mExecutor = mHandler::post;
+
+ @Before
+ public void setUp() throws RemoteException {
+ mBiometricPrompt = new BiometricPrompt.Builder(mContext)
+ .setUseDefaultSubtitle()
+ .setUseDefaultTitle()
+ .setAllowedAuthenticators(BiometricManager.Authenticators.BIOMETRIC_STRONG
+ | BiometricManager.Authenticators.DEVICE_CREDENTIAL)
+ .setService(mService)
+ .build();
+
+ mCancellationSignal = new CancellationSignal();
+ when(mService.authenticate(any(), anyLong(), anyInt(), any(), anyString(), any()))
+ .thenReturn(0L);
+ when(mContext.getPackageName()).thenReturn("BiometricPromptTest");
+ }
+
+ @Test
+ public void testCancellationAfterAuthenticationFailed() throws RemoteException {
+ ArgumentCaptor<IBiometricServiceReceiver> biometricServiceReceiverCaptor =
+ ArgumentCaptor.forClass(IBiometricServiceReceiver.class);
+ BiometricPrompt.AuthenticationCallback callback =
+ new BiometricPrompt.AuthenticationCallback() {
+ @Override
+ public void onAuthenticationError(int errorCode, CharSequence errString) {
+ super.onAuthenticationError(errorCode, errString);
+ }};
+ mBiometricPrompt.authenticate(mCancellationSignal, mExecutor, callback);
+ mLooper.dispatchAll();
+
+ verify(mService).authenticate(any(), anyLong(), anyInt(),
+ biometricServiceReceiverCaptor.capture(), anyString(), any());
+
+ biometricServiceReceiverCaptor.getValue().onAuthenticationFailed();
+ mLooper.dispatchAll();
+ mCancellationSignal.cancel();
+
+ verify(mService).cancelAuthentication(any(), anyString(), anyLong());
+ }
+}
diff --git a/core/tests/coretests/src/android/hardware/biometrics/OWNERS b/core/tests/coretests/src/android/hardware/biometrics/OWNERS
new file mode 100644
index 000000000000..6a2192a2c7fb
--- /dev/null
+++ b/core/tests/coretests/src/android/hardware/biometrics/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/biometrics/OWNERS