Fix biometric lint issues and update lint-baseline
Test: Biometric integration test app on API 23, 27-30
Test: ./gradlew biometric:biometric:test
Test: ./gradlew biometric:biometric:connectedAndroidTest
Test: ./gradlew biometric:integration-tests:testapp:connectedAndroidTest
Change-Id: Icc2f9b0c4358d2c207f0992258d8217800160c36
diff --git a/biometric/biometric/lint-baseline.xml b/biometric/biometric/lint-baseline.xml
index 3b429d7..8f1aa4b 100644
--- a/biometric/biometric/lint-baseline.xml
+++ b/biometric/biometric/lint-baseline.xml
@@ -1,99 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
-<issues format="5" by="lint 4.2.0-alpha15" client="gradle" variant="debug" version="4.2.0-alpha15">
-
- <issue
- id="ObsoleteLintCustomCheck"
- message="Lint found an issue registry (`androidx.fragment.lint.FragmentIssueRegistry`) which is older than the current API level; these checks may not work correctly.

Recompile the checks against the latest version. Custom check API version is 6 (3.6), current lint API level is 8 (4.1)">
- <location
- file="../../../../../../home/jeffrygaston/.gradle/caches/transforms-2/files-2.1/e3e8070ff55bdd44622c92131fecd482/fragment-1.2.5/jars/lint.jar"/>
- </issue>
-
- <issue
- id="UnusedAttribute"
- message="Attribute `accessibilityLiveRegion` is only used in API level 19 and higher (current min is 14)"
- errorLine1=" android:accessibilityLiveRegion="polite""
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="src/main/res/layout/fingerprint_dialog_layout.xml"
- line="69"
- column="13"/>
- </issue>
-
- <issue
- id="BanUncheckedReflection"
- message="Calling Method.invoke without an SDK check"
- errorLine1=" canAuthenticateWithCrypto.invoke(mBiometricManager, crypto);"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="src/main/java/androidx/biometric/BiometricManager.java"
- line="426"
- column="29"/>
- </issue>
-
- <issue
- id="UnsafeNewApiCall"
- message="This call is to a method from API 28, the call containing class null is not annotated with @RequiresApi(x) where x is at least 28. Either annotate the containing class with at least @RequiresApi(28) or move the call to a static method in a wrapper class annotated with at least @RequiresApi(28)."
- errorLine1=" ? CryptoObjectUtils.unwrapFromBiometricPrompt(result.getCryptoObject())"
- errorLine2=" ~~~~~~~~~~~~~~~">
- <location
- file="src/main/java/androidx/biometric/AuthenticationCallbackProvider.java"
- line="229"
- column="82"/>
- </issue>
-
- <issue
- id="VectorRaster"
- message="This attribute is not supported in images generated from this vector icon for API < 24; check generated icon to make sure it looks acceptable"
- errorLine1=" android:trimPathEnd="1" android:trimPathOffset="0""
- errorLine2=" ~~~~~~~~~~~~~~~~~~~">
- <location
- file="src/main/res/drawable-v23/fingerprint_dialog_error.xml"
- line="26"
- column="19"/>
- </issue>
-
- <issue
- id="VectorRaster"
- message="This attribute is not supported in images generated from this vector icon for API < 24; check generated icon to make sure it looks acceptable"
- errorLine1=" android:trimPathEnd="1" android:trimPathOffset="0""
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="src/main/res/drawable-v23/fingerprint_dialog_error.xml"
- line="26"
- column="43"/>
- </issue>
-
- <issue
- id="VectorRaster"
- message="This attribute is not supported in images generated from this vector icon for API < 24; check generated icon to make sure it looks acceptable"
- errorLine1=" android:trimPathStart="0"/>"
- errorLine2=" ~~~~~~~~~~~~~~~~~~~~~">
- <location
- file="src/main/res/drawable-v23/fingerprint_dialog_error.xml"
- line="27"
- column="19"/>
- </issue>
-
- <issue
- id="TrulyRandom"
- message="Potentially insecure random numbers on Android 4.3 and older. Read https://android-developers.blogspot.com/2013/08/some-securerandom-thoughts.html for more info."
- errorLine1=" KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, KEYSTORE_INSTANCE);"
- errorLine2=" ~~~~~~~~~~~">
- <location
- file="src/main/java/androidx/biometric/CryptoObjectUtils.java"
- line="253"
- column="34"/>
- </issue>
-
- <issue
- id="ContentDescription"
- message="Missing `contentDescription` attribute on image"
- errorLine1=" <ImageView"
- errorLine2=" ~~~~~~~~~">
- <location
- file="src/main/res/layout/fingerprint_dialog_layout.xml"
- line="51"
- column="10"/>
- </issue>
+<issues format="5" by="lint 4.2.0-beta02" client="gradle" variant="debug" version="4.2.0-beta02">
</issues>
diff --git a/biometric/biometric/src/main/java/androidx/biometric/AuthenticationCallbackProvider.java b/biometric/biometric/src/main/java/androidx/biometric/AuthenticationCallbackProvider.java
index db6e9f0..973c722 100644
--- a/biometric/biometric/src/main/java/androidx/biometric/AuthenticationCallbackProvider.java
+++ b/biometric/biometric/src/main/java/androidx/biometric/AuthenticationCallbackProvider.java
@@ -226,7 +226,7 @@
android.hardware.biometrics.BiometricPrompt.AuthenticationResult result) {
final BiometricPrompt.CryptoObject crypto = result != null
- ? CryptoObjectUtils.unwrapFromBiometricPrompt(result.getCryptoObject())
+ ? CryptoObjectUtils.unwrapFromBiometricPrompt(getCryptoObject(result))
: null;
@BiometricPrompt.AuthenticationResultType final int authenticationType;
@@ -252,5 +252,20 @@
}
};
}
+
+ /**
+ * Gets the crypto object from the given framework authentication result.
+ *
+ * @param result An instance of
+ * {@link android.hardware.biometrics.BiometricPrompt.AuthenticationResult}.
+ * @return The value returned by calling {@link
+ * android.hardware.biometrics.BiometricPrompt.AuthenticationResult#getCryptoObject()} for
+ * the given result object.
+ */
+ @Nullable
+ static android.hardware.biometrics.BiometricPrompt.CryptoObject getCryptoObject(
+ @NonNull android.hardware.biometrics.BiometricPrompt.AuthenticationResult result) {
+ return result.getCryptoObject();
+ }
}
}
diff --git a/biometric/biometric/src/main/java/androidx/biometric/BiometricFragment.java b/biometric/biometric/src/main/java/androidx/biometric/BiometricFragment.java
index 3b28c82..3121f90 100644
--- a/biometric/biometric/src/main/java/androidx/biometric/BiometricFragment.java
+++ b/biometric/biometric/src/main/java/androidx/biometric/BiometricFragment.java
@@ -440,6 +440,11 @@
return;
}
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
+ Log.e(TAG, "Unable to show fingerprint dialog on API <19.");
+ return;
+ }
+
if (isAdded()) {
mViewModel.setFingerprintDialogDismissedInstantly(true);
if (!DeviceUtils.shouldHideFingerprintDialog(context, Build.MODEL)) {
diff --git a/biometric/biometric/src/main/java/androidx/biometric/BiometricManager.java b/biometric/biometric/src/main/java/androidx/biometric/BiometricManager.java
index 2334cd6..ae96709 100644
--- a/biometric/biometric/src/main/java/androidx/biometric/BiometricManager.java
+++ b/biometric/biometric/src/main/java/androidx/biometric/BiometricManager.java
@@ -423,7 +423,9 @@
if (crypto != null) {
try {
final Object result =
- canAuthenticateWithCrypto.invoke(mBiometricManager, crypto);
+ Build.VERSION.SDK_INT == Build.VERSION_CODES.Q
+ ? canAuthenticateWithCrypto.invoke(mBiometricManager, crypto)
+ : null;
if (result instanceof Integer) {
return (int) result;
}
diff --git a/biometric/biometric/src/main/java/androidx/biometric/BiometricViewModel.java b/biometric/biometric/src/main/java/androidx/biometric/BiometricViewModel.java
index 12ecf70..47efe15 100644
--- a/biometric/biometric/src/main/java/androidx/biometric/BiometricViewModel.java
+++ b/biometric/biometric/src/main/java/androidx/biometric/BiometricViewModel.java
@@ -154,7 +154,7 @@
/**
* Reference to latest {@link androidx.fragment.app.FragmentActivity} hosting BiometricPrompt
*/
- @NonNull private WeakReference<FragmentActivity> mClientActivity;
+ @Nullable private WeakReference<FragmentActivity> mClientActivity;
/**
* Info about the appearance and behavior of the prompt provided by the client application.
@@ -299,7 +299,7 @@
*/
@Nullable
public FragmentActivity getClientActivity() {
- return mClientActivity.get();
+ return mClientActivity != null ? mClientActivity.get() : null;
}
/**
diff --git a/biometric/biometric/src/main/java/androidx/biometric/CryptoObjectUtils.java b/biometric/biometric/src/main/java/androidx/biometric/CryptoObjectUtils.java
index 051a392b..436d6a3 100644
--- a/biometric/biometric/src/main/java/androidx/biometric/CryptoObjectUtils.java
+++ b/biometric/biometric/src/main/java/androidx/biometric/CryptoObjectUtils.java
@@ -16,6 +16,7 @@
package androidx.biometric;
+import android.annotation.SuppressLint;
import android.os.Build;
import android.security.keystore.KeyGenParameterSpec;
import android.security.keystore.KeyProperties;
@@ -235,6 +236,7 @@
*
* @return An internal-only instance of {@link androidx.biometric.BiometricPrompt.CryptoObject}.
*/
+ @SuppressLint("TrulyRandom")
@RequiresApi(Build.VERSION_CODES.M)
@Nullable
static BiometricPrompt.CryptoObject createFakeCryptoObject() {
diff --git a/biometric/biometric/src/main/java/androidx/biometric/FingerprintDialogFragment.java b/biometric/biometric/src/main/java/androidx/biometric/FingerprintDialogFragment.java
index 13da791..13ae176 100644
--- a/biometric/biometric/src/main/java/androidx/biometric/FingerprintDialogFragment.java
+++ b/biometric/biometric/src/main/java/androidx/biometric/FingerprintDialogFragment.java
@@ -142,11 +142,15 @@
@Nullable
TextView mHelpMessageView;
+ // Prevent direct instantiation.
+ private FingerprintDialogFragment() {}
+
/**
* Creates a new instance of {@link FingerprintDialogFragment}.
*
* @return A {@link FingerprintDialogFragment}.
*/
+ @RequiresApi(Build.VERSION_CODES.KITKAT)
@NonNull
static FingerprintDialogFragment newInstance() {
return new FingerprintDialogFragment();
diff --git a/biometric/biometric/src/main/res/drawable-v23/fingerprint_dialog_error.xml b/biometric/biometric/src/main/res/drawable-v23/fingerprint_dialog_error.xml
index 5faccf8..568431be 100644
--- a/biometric/biometric/src/main/res/drawable-v23/fingerprint_dialog_error.xml
+++ b/biometric/biometric/src/main/res/drawable-v23/fingerprint_dialog_error.xml
@@ -15,8 +15,9 @@
~ limitations under the License.
-->
-<vector xmlns:android="http://schemas.android.com/apk/res/android" android:width="24dp"
- android:height="24dp" android:viewportHeight="24" android:viewportWidth="24">
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools" android:width="24dp" android:height="24dp"
+ android:viewportHeight="24" android:viewportWidth="24">
<group android:name="_R_G">
<group android:name="_R_G_L_1_G" android:rotation="10" android:translateX="12"
android:translateY="12">
@@ -24,7 +25,7 @@
android:strokeAlpha="1" android:strokeColor="#ff5722"
android:strokeLineCap="round" android:strokeLineJoin="round" android:strokeWidth="2"
android:trimPathEnd="1" android:trimPathOffset="0"
- android:trimPathStart="0"/>
+ android:trimPathStart="0" tools:ignore="VectorRaster" />
</group>
<group android:name="_R_G_L_0_G" android:translateX="12" android:translateY="12">
<group android:name="_R_G_L_0_G_D_0_P_0_G_0_T_0" android:pivotY="-0.012"
@@ -41,4 +42,5 @@
</group>
</group>
</group>
+
</vector>
\ No newline at end of file
diff --git a/biometric/biometric/src/main/res/layout/fingerprint_dialog_layout.xml b/biometric/biometric/src/main/res/layout-v19/fingerprint_dialog_layout.xml
similarity index 85%
rename from biometric/biometric/src/main/res/layout/fingerprint_dialog_layout.xml
rename to biometric/biometric/src/main/res/layout-v19/fingerprint_dialog_layout.xml
index 8b3fa21..b79910a 100644
--- a/biometric/biometric/src/main/res/layout/fingerprint_dialog_layout.xml
+++ b/biometric/biometric/src/main/res/layout-v19/fingerprint_dialog_layout.xml
@@ -15,14 +15,16 @@
~ limitations under the License.
-->
-<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical">
+<ScrollView
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical">
- <LinearLayout android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:orientation="vertical">
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
<TextView
android:id="@+id/fingerprint_subtitle"
@@ -54,6 +56,7 @@
android:layout_height="@dimen/fingerprint_icon_size"
android:layout_gravity="center_horizontal"
android:layout_marginTop="32dp"
+ android:contentDescription="@string/fingerprint_dialog_icon_description"
android:scaleType="fitXY" />
<TextView
diff --git a/biometric/biometric/src/main/res/values/strings.xml b/biometric/biometric/src/main/res/values/strings.xml
index a5bff76..605afc7 100644
--- a/biometric/biometric/src/main/res/values/strings.xml
+++ b/biometric/biometric/src/main/res/values/strings.xml
@@ -45,4 +45,7 @@
<!-- Error message for when the app requests PIN, pattern, or password authentication on a
device without Keyguard. Generally not shown to the user. [CHAR LIMIT=NONE] -->
<string name="generic_error_no_keyguard">This device does not support PIN, pattern, or password.</string>
+ <!-- Content description for the icon shown on the fingerprint dialog during authentication.
+ This is not shown but may be read aloud to the user for accessibility. [CHAR LIMIT=NONE] -->
+ <string name="fingerprint_dialog_icon_description">Fingerprint icon</string>
</resources>