Make fields of ShadowFingerprintManager static for context level instance
1.Converted instances fields to static fields to ensure proper state management.
2.add tests for the same in ShadowFingerprintManagerTest.
3.add tests for FingerprintManager instance behaviour across application and activity contexts in ContextTest
4.Applied google java format
5. Added permissions in AndroidManifest.xml
diff --git a/integration_tests/ctesque/src/androidTest/java/android/app/ContextTest.java b/integration_tests/ctesque/src/androidTest/java/android/app/ContextTest.java
index 323ebc8..17cbd44 100644
--- a/integration_tests/ctesque/src/androidTest/java/android/app/ContextTest.java
+++ b/integration_tests/ctesque/src/androidTest/java/android/app/ContextTest.java
@@ -11,6 +11,7 @@
import android.content.ClipboardManager;
import android.content.ComponentName;
import android.content.Context;
+import android.hardware.fingerprint.FingerprintManager;
import android.media.AudioManager;
import android.os.BatteryManager;
import android.view.autofill.AutofillManager;
@@ -30,6 +31,7 @@
GrantPermissionRule.grant(
Manifest.permission.MODIFY_AUDIO_SETTINGS,
Manifest.permission.GET_ACCOUNTS,
+ Manifest.permission.USE_BIOMETRIC,
Manifest.permission.INTERNET,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE);
@@ -464,4 +466,67 @@
});
}
}
+
+ @Test
+ public void fingerprintManager_applicationInstance_isNotSameAsActivityInstance() {
+ FingerprintManager applicationFingerprintManager =
+ (FingerprintManager)
+ ApplicationProvider.getApplicationContext()
+ .getSystemService(Context.FINGERPRINT_SERVICE);
+ try (ActivityScenario<TestActivity> scenario = ActivityScenario.launch(TestActivity.class)) {
+ scenario.onActivity(
+ activity -> {
+ FingerprintManager activityFingerprintManager =
+ (FingerprintManager) activity.getSystemService(Context.FINGERPRINT_SERVICE);
+ assertThat(applicationFingerprintManager)
+ .isNotSameInstanceAs(activityFingerprintManager);
+ });
+ }
+ }
+
+ @Test
+ public void fingerprintManager_activityInstance_isSameAsActivityInstance() {
+ try (ActivityScenario<TestActivity> scenario = ActivityScenario.launch(TestActivity.class)) {
+ scenario.onActivity(
+ activity -> {
+ FingerprintManager activityFingerprintManager =
+ (FingerprintManager) activity.getSystemService(Context.FINGERPRINT_SERVICE);
+ FingerprintManager anotherActivityFingerprintManager =
+ (FingerprintManager) activity.getSystemService(Context.FINGERPRINT_SERVICE);
+ assertThat(anotherActivityFingerprintManager)
+ .isSameInstanceAs(activityFingerprintManager);
+ });
+ }
+ }
+
+ @Test
+ public void fingerprintManager_instance_hasConsistentFingerprintState() {
+ FingerprintManager applicationFingerprintManager =
+ (FingerprintManager)
+ ApplicationProvider.getApplicationContext()
+ .getSystemService(Context.FINGERPRINT_SERVICE);
+
+ try (ActivityScenario<TestActivity> scenario = ActivityScenario.launch(TestActivity.class)) {
+ scenario.onActivity(
+ activity -> {
+ FingerprintManager activityFingerprintManager =
+ (FingerprintManager) activity.getSystemService(Context.FINGERPRINT_SERVICE);
+
+ boolean isApplicationFingerprintAvailable =
+ applicationFingerprintManager.isHardwareDetected();
+ boolean isActivityFingerprintAvailable =
+ activityFingerprintManager.isHardwareDetected();
+
+ assertThat(isActivityFingerprintAvailable).isEqualTo(isApplicationFingerprintAvailable);
+
+ boolean hasApplicationEnrolledFingerprints =
+ applicationFingerprintManager.hasEnrolledFingerprints();
+ boolean hasActivityEnrolledFingerprints =
+ activityFingerprintManager.hasEnrolledFingerprints();
+
+ assertThat(hasActivityEnrolledFingerprints)
+ .isEqualTo(hasApplicationEnrolledFingerprints);
+ });
+ }
+ }
}
diff --git a/integration_tests/ctesque/src/main/AndroidManifest.xml b/integration_tests/ctesque/src/main/AndroidManifest.xml
index 8eb4e40..9efa934 100644
--- a/integration_tests/ctesque/src/main/AndroidManifest.xml
+++ b/integration_tests/ctesque/src/main/AndroidManifest.xml
@@ -8,5 +8,6 @@
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+ <uses-permission android:name="android.permission.USE_BIOMETRIC" />
<application />
</manifest>
diff --git a/robolectric/src/test/java/org/robolectric/shadows/ShadowFingerprintManagerTest.java b/robolectric/src/test/java/org/robolectric/shadows/ShadowFingerprintManagerTest.java
index 76b080b..5ade8f3 100644
--- a/robolectric/src/test/java/org/robolectric/shadows/ShadowFingerprintManagerTest.java
+++ b/robolectric/src/test/java/org/robolectric/shadows/ShadowFingerprintManagerTest.java
@@ -6,6 +6,7 @@
import static org.mockito.Mockito.verify;
import static org.robolectric.Shadows.shadowOf;
+import android.app.Activity;
import android.content.Context;
import android.hardware.fingerprint.FingerprintManager;
import android.hardware.fingerprint.FingerprintManager.AuthenticationCallback;
@@ -19,7 +20,9 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
+import org.robolectric.Robolectric;
import org.robolectric.annotation.Config;
+import org.robolectric.shadows.testing.TestActivity;
@RunWith(AndroidJUnit4.class)
@Config(minSdk = M)
@@ -120,4 +123,39 @@
public void getSensorPropertiesInternal_notNull() {
assertThat(manager.getSensorPropertiesInternal()).isNotNull();
}
+
+ @Test
+ public void fingerprintManager_activityContextEnabled_differentInstancesHaveConsistentState() {
+ String originalProperty = System.getProperty("robolectric.createActivityContexts", "");
+ System.setProperty("robolectric.createActivityContexts", "true");
+
+ Activity activity = null;
+ try {
+ FingerprintManager applicationFingerprintManager =
+ (FingerprintManager)
+ ApplicationProvider.getApplicationContext()
+ .getSystemService(Context.FINGERPRINT_SERVICE);
+
+ activity = Robolectric.setupActivity(TestActivity.class);
+ FingerprintManager activityFingerprintManager =
+ (FingerprintManager) activity.getSystemService(Context.FINGERPRINT_SERVICE);
+
+ boolean isApplicationFingerprintAvailable =
+ applicationFingerprintManager.isHardwareDetected();
+ boolean isActivityFingerprintAvailable = activityFingerprintManager.isHardwareDetected();
+ assertThat(isActivityFingerprintAvailable).isEqualTo(isApplicationFingerprintAvailable);
+
+ boolean hasApplicationEnrolledFingerprints =
+ applicationFingerprintManager.hasEnrolledFingerprints();
+ boolean hasActivityEnrolledFingerprints =
+ activityFingerprintManager.hasEnrolledFingerprints();
+ assertThat(hasActivityEnrolledFingerprints).isEqualTo(hasApplicationEnrolledFingerprints);
+
+ } finally {
+ if (activity != null) {
+ activity.finish();
+ }
+ System.setProperty("robolectric.createActivityContexts", originalProperty);
+ }
+ }
}
diff --git a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowFingerprintManager.java b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowFingerprintManager.java
index 9bd665c..88f00f0 100644
--- a/shadows/framework/src/main/java/org/robolectric/shadows/ShadowFingerprintManager.java
+++ b/shadows/framework/src/main/java/org/robolectric/shadows/ShadowFingerprintManager.java
@@ -24,6 +24,7 @@
import org.robolectric.annotation.HiddenApi;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
+import org.robolectric.annotation.Resetter;
import org.robolectric.util.ReflectionHelpers;
import org.robolectric.util.ReflectionHelpers.ClassParameter;
@@ -34,10 +35,18 @@
private static final String TAG = "ShadowFingerprintManager";
- private boolean isHardwareDetected;
- protected CryptoObject pendingCryptoObject;
- private AuthenticationCallback pendingCallback;
- private List<Fingerprint> fingerprints = Collections.emptyList();
+ private static boolean isHardwareDetected;
+ protected static CryptoObject pendingCryptoObject;
+ private static AuthenticationCallback pendingCallback;
+ private static List<Fingerprint> fingerprints = Collections.emptyList();
+
+ @Resetter
+ public static void reset() {
+ isHardwareDetected = false;
+ pendingCryptoObject = null;
+ pendingCallback = null;
+ fingerprints = Collections.emptyList();
+ }
/**
* Simulates a successful fingerprint authentication. An authentication request must have been