fix fingerprint enrollment on Google devices with side FP scanner

This commit is contained in:
Dmitry Muhomor
2024-07-08 10:21:18 +03:00
committed by Joey
parent ef2ee257a9
commit 58b0657a69
4 changed files with 133 additions and 0 deletions

View File

@@ -55,6 +55,7 @@ android_library {
srcs: [
"src/**/*.java",
"src/**/*.kt",
"src/**/*.aidl",
"Evolver/src/**/*.java",
"Evolver/src/**/*.kt",
],

View File

@@ -1647,4 +1647,6 @@
<!-- Packages that will not show Display over other apps permission -->
<string-array name="display_over_apps_permission_change_exempt">
</string-array>
<string-array name="fingerprint_acquired_vendor" />
</resources>

View File

@@ -25,21 +25,34 @@ import static com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrol
import android.animation.Animator;
import android.animation.ObjectAnimator;
import android.app.AlertDialog;
import android.content.Context;
import android.content.res.Configuration;
import android.hardware.biometrics.BiometricFingerprintConstants;
import android.hardware.fingerprint.FingerprintManager;
import android.os.Build;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.util.Log;
import android.view.View;
import android.view.animation.AccelerateInterpolator;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.util.Preconditions;
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling;
import com.google.hardware.biometrics.sidefps.IFingerprintExt;
import java.util.function.Function;
import java.util.function.Supplier;
public class SfpsEnrollmentFeatureImpl implements SfpsEnrollmentFeature {
static final String TAG = SfpsEnrollmentFeatureImpl.class.getSimpleName();
@VisibleForTesting
public static final int HELP_ANIMATOR_DURATION = 550;
@@ -89,8 +102,31 @@ public class SfpsEnrollmentFeatureImpl implements SfpsEnrollmentFeature {
};
}
private final boolean isGoogleDevice = "google".equals(Build.BRAND);
private float[] mEnrollStageThresholds;
@Override
public float getEnrollStageThreshold(@NonNull Context context, int index) {
if (isGoogleDevice) {
Log.d(TAG, "getEnrollStageThreshold " + index);
if (mEnrollStageThresholds == null) {
// TODO: extract these values automatically from SettingsGoogle resource:
// com.google.android.settings.R.array.config_sfps_enroll_stage_thresholds
mEnrollStageThresholds = new float[] {
0f, 0.04f, 0.48f, 0.52f
};
}
// this logic was copied from FingerprintManager.getEnrollStageThreshold()
if (index < 0 || index > mEnrollStageThresholds.length) {
Log.w(TAG, "Unsupported enroll stage index: " + index);
return index < 0 ? 0f : 1f;
}
return index == mEnrollStageThresholds.length ? 1f : mEnrollStageThresholds[index];
}
if (mFingerprintManager == null) {
mFingerprintManager = context.getSystemService(FingerprintManager.class);
}
@@ -113,4 +149,93 @@ public class SfpsEnrollmentFeatureImpl implements SfpsEnrollmentFeature {
public boolean shouldAdjustHeaderText(@NonNull Configuration conf, boolean isFolded) {
return conf.orientation == Configuration.ORIENTATION_LANDSCAPE;
}
@Override
public void handleOnEnrollmentHelp(int helpMsgId, CharSequence helpString, Supplier<FingerprintEnrollEnrolling> enrollingSupplier) {
if (isGoogleDevice) {
Log.d(TAG, "handleOnEnrollmentHelp, helpMsgId: " + helpMsgId + ", helpString: " + helpString, new Throwable());
if (helpMsgId == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR_BASE ||
helpMsgId == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_IMMOBILE) {
Context ctx = enrollingSupplier.get();
Log.d(TAG, "getVendorString: " + getVendorString(ctx, 0));
if (getGoogleFingerprintExt() == null) {
return;
}
if (mHelpDialog != null) {
mHelpDialog.dismiss();
mHelpDialog = null;
}
var d = new AlertDialog.Builder(ctx);
d.setMessage(getVendorString(ctx, VENDOR_STRING_FINGERPRINT_ACQUIRED_IMMOBILE));
d.setPositiveButton(android.R.string.ok, (dialog, which) -> {
resumeEnroll();
});
mHelpDialog = d.show();
}
}
}
private AlertDialog mHelpDialog;
@Override
public CharSequence getFeaturedVendorString(Context context, int id, CharSequence msg) {
if (!isGoogleDevice) {
return msg;
}
Log.d(TAG, "getFeaturedVendorString, id: " + id + ", msg: " + msg, new Throwable());
if (id == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_VENDOR_BASE ||
id == BiometricFingerprintConstants.FINGERPRINT_ACQUIRED_IMMOBILE) {
return getVendorString(context, VENDOR_STRING_FINGERPRINT_ACQUIRED_IMMOBILE);
}
return msg;
}
private static final int VENDOR_STRING_FINGERPRINT_ACQUIRED_IMMOBILE = 0;
private static String getVendorString(Context ctx, int index) {
String[] strings = ctx.getResources().getStringArray(R.array.fingerprint_acquired_vendor);
Preconditions.checkArgumentInRange(index, 0, strings.length - 1, "vendor string index");
return strings[index];
}
@Nullable
private static IFingerprintExt getGoogleFingerprintExt() {
String fpServiceName = android.hardware.biometrics.fingerprint.IFingerprint.class.getName() + "/default";
IBinder fpService = ServiceManager.getService(fpServiceName);
if (fpService == null) {
throw new IllegalStateException(fpServiceName + " is null");
}
IBinder fpServiceExt;
try {
fpServiceExt = fpService.getExtension();
} catch (RemoteException e) {
throw new IllegalStateException(e);
}
if (fpServiceExt == null) {
Log.e(TAG, "no IFingerprintExt");
return null;
}
return IFingerprintExt.Stub.asInterface(fpServiceExt);
}
private static void resumeEnroll() {
IFingerprintExt fpExt = getGoogleFingerprintExt();
if (fpExt == null) {
return;
}
try {
fpExt.resumeEnroll();
} catch (RemoteException e) {
Log.e(TAG, "", e);
}
}
}

View File

@@ -0,0 +1,5 @@
package com.google.hardware.biometrics.sidefps;
interface IFingerprintExt {
void resumeEnroll() = 1;
}