Merge "Add mandatory biometric prompt to platform surfaces (1/N)" into main
This commit is contained in:
committed by
Android (Google) Code Review
commit
62db4b3a4d
@@ -934,7 +934,8 @@
|
|||||||
<string name="security_settings_fingerprint_single_face_watch_preference_summary">Face, fingerprint, and <xliff:g id="watch" example="Dani's Watch">%s</xliff:g> added</string>
|
<string name="security_settings_fingerprint_single_face_watch_preference_summary">Face, fingerprint, and <xliff:g id="watch" example="Dani's Watch">%s</xliff:g> added</string>
|
||||||
<!-- Message showing that multiple fingerprints, face, and the current watch is set up. Shown for a menu item that launches fingerprint, face, and active unlock settings or enrollment. [CHAR LIMIT=80]-->
|
<!-- Message showing that multiple fingerprints, face, and the current watch is set up. Shown for a menu item that launches fingerprint, face, and active unlock settings or enrollment. [CHAR LIMIT=80]-->
|
||||||
<string name="security_settings_fingerprint_multiple_face_watch_preference_summary">Face, fingerprints, and <xliff:g id="watch" example="Dani's Watch">%s</xliff:g> added</string>
|
<string name="security_settings_fingerprint_multiple_face_watch_preference_summary">Face, fingerprints, and <xliff:g id="watch" example="Dani's Watch">%s</xliff:g> added</string>
|
||||||
|
<!-- Description for mandatory biometrics prompt-->
|
||||||
|
<string name="mandatory_biometrics_prompt_description">This is needed since Identity Check is on</string>
|
||||||
<!-- RemoteAuth unlock enrollment and settings --><skip />
|
<!-- RemoteAuth unlock enrollment and settings --><skip />
|
||||||
<!-- Title shown for menu item that launches watch unlock settings. [CHAR LIMIT=40] -->
|
<!-- Title shown for menu item that launches watch unlock settings. [CHAR LIMIT=40] -->
|
||||||
<string name ="security_settings_remoteauth_preference_title">Remote Authenticator Unlock</string>
|
<string name ="security_settings_remoteauth_preference_title">Remote Authenticator Unlock</string>
|
||||||
|
@@ -24,6 +24,9 @@ import static android.os.UserManager.USER_TYPE_PROFILE_PRIVATE;
|
|||||||
import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
|
import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
|
||||||
import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
|
import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
|
||||||
|
|
||||||
|
import static com.android.settings.password.ConfirmDeviceCredentialActivity.BIOMETRIC_PROMPT_AUTHENTICATORS;
|
||||||
|
import static com.android.settings.password.ConfirmDeviceCredentialActivity.BIOMETRIC_PROMPT_NEGATIVE_BUTTON_TEXT;
|
||||||
|
|
||||||
import android.app.ActionBar;
|
import android.app.ActionBar;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.ActivityManager;
|
import android.app.ActivityManager;
|
||||||
@@ -54,6 +57,7 @@ import android.graphics.drawable.AdaptiveIconDrawable;
|
|||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.graphics.drawable.VectorDrawable;
|
import android.graphics.drawable.VectorDrawable;
|
||||||
|
import android.hardware.biometrics.BiometricManager;
|
||||||
import android.hardware.biometrics.SensorProperties;
|
import android.hardware.biometrics.SensorProperties;
|
||||||
import android.hardware.face.Face;
|
import android.hardware.face.Face;
|
||||||
import android.hardware.face.FaceManager;
|
import android.hardware.face.FaceManager;
|
||||||
@@ -122,6 +126,7 @@ import com.android.settings.dashboard.profileselector.ProfileFragmentBridge;
|
|||||||
import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
|
import com.android.settings.dashboard.profileselector.ProfileSelectFragment;
|
||||||
import com.android.settings.dashboard.profileselector.ProfileSelectFragment.ProfileType;
|
import com.android.settings.dashboard.profileselector.ProfileSelectFragment.ProfileType;
|
||||||
import com.android.settings.password.ChooseLockSettingsHelper;
|
import com.android.settings.password.ChooseLockSettingsHelper;
|
||||||
|
import com.android.settings.password.ConfirmDeviceCredentialActivity;
|
||||||
import com.android.settingslib.widget.ActionBarShadowController;
|
import com.android.settingslib.widget.ActionBarShadowController;
|
||||||
import com.android.settingslib.widget.AdaptiveIcon;
|
import com.android.settingslib.widget.AdaptiveIcon;
|
||||||
|
|
||||||
@@ -1478,6 +1483,55 @@ public final class Utils extends com.android.settingslib.Utils {
|
|||||||
disableComponent(pm, new ComponentName(context, Settings.CreateShortcutActivity.class));
|
disableComponent(pm, new ComponentName(context, Settings.CreateShortcutActivity.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request biometric authentication if all requirements for mandatory biometrics is satisfied.
|
||||||
|
* @param context of the corresponding activity/fragment
|
||||||
|
* @param biometricsSuccessfullyAuthenticated if the user has already authenticated using
|
||||||
|
* biometrics
|
||||||
|
* @param biometricsAuthenticationRequested if the activity/fragment has already requested for
|
||||||
|
* biometric prompt
|
||||||
|
* @return true if all requirements for mandatory biometrics is satisfied
|
||||||
|
*/
|
||||||
|
public static boolean requestBiometricAuthenticationForMandatoryBiometrics(
|
||||||
|
@NonNull Context context,
|
||||||
|
boolean biometricsSuccessfullyAuthenticated,
|
||||||
|
boolean biometricsAuthenticationRequested) {
|
||||||
|
final BiometricManager biometricManager = context.getSystemService(BiometricManager.class);
|
||||||
|
if (biometricManager == null) {
|
||||||
|
Log.e(TAG, "Biometric Manager is null.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
final int status = biometricManager.canAuthenticate(
|
||||||
|
BiometricManager.Authenticators.MANDATORY_BIOMETRICS);
|
||||||
|
return android.hardware.biometrics.Flags.mandatoryBiometrics()
|
||||||
|
&& status == BiometricManager.BIOMETRIC_SUCCESS
|
||||||
|
&& !biometricsSuccessfullyAuthenticated
|
||||||
|
&& !biometricsAuthenticationRequested;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Launch biometric prompt for mandatory biometrics. Call
|
||||||
|
* {@link #requestBiometricAuthenticationForMandatoryBiometrics(Context, boolean, boolean)}
|
||||||
|
* to check if all requirements for mandatory biometrics is satisfied
|
||||||
|
* before launching biometric prompt.
|
||||||
|
*
|
||||||
|
* @param fragment corresponding fragment of the surface
|
||||||
|
* @param requestCode for starting the new activity
|
||||||
|
*/
|
||||||
|
public static void launchBiometricPromptForMandatoryBiometrics(@NonNull Fragment fragment,
|
||||||
|
int requestCode) {
|
||||||
|
final Intent intent = new Intent();
|
||||||
|
intent.putExtra(BIOMETRIC_PROMPT_AUTHENTICATORS,
|
||||||
|
BiometricManager.Authenticators.MANDATORY_BIOMETRICS);
|
||||||
|
intent.putExtra(BIOMETRIC_PROMPT_NEGATIVE_BUTTON_TEXT,
|
||||||
|
fragment.getString(R.string.cancel));
|
||||||
|
intent.putExtra(KeyguardManager.EXTRA_DESCRIPTION,
|
||||||
|
fragment.getString(R.string.mandatory_biometrics_prompt_description));
|
||||||
|
intent.setClassName(SETTINGS_PACKAGE_NAME,
|
||||||
|
ConfirmDeviceCredentialActivity.class.getName());
|
||||||
|
fragment.startActivityForResult(intent, requestCode);
|
||||||
|
}
|
||||||
|
|
||||||
private static void disableComponent(PackageManager pm, ComponentName componentName) {
|
private static void disableComponent(PackageManager pm, ComponentName componentName) {
|
||||||
pm.setComponentEnabledSetting(componentName,
|
pm.setComponentEnabledSetting(componentName,
|
||||||
PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
|
PackageManager.COMPONENT_ENABLED_STATE_DISABLED, PackageManager.DONT_KILL_APP);
|
||||||
|
@@ -68,6 +68,8 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity {
|
|||||||
public static final String EXTRA_FINISHED_ENROLL_FACE = "finished_enrolling_face";
|
public static final String EXTRA_FINISHED_ENROLL_FACE = "finished_enrolling_face";
|
||||||
public static final String EXTRA_FINISHED_ENROLL_FINGERPRINT = "finished_enrolling_fingerprint";
|
public static final String EXTRA_FINISHED_ENROLL_FINGERPRINT = "finished_enrolling_fingerprint";
|
||||||
public static final String EXTRA_LAUNCHED_POSTURE_GUIDANCE = "launched_posture_guidance";
|
public static final String EXTRA_LAUNCHED_POSTURE_GUIDANCE = "launched_posture_guidance";
|
||||||
|
public static final String EXTRA_BIOMETRICS_AUTHENTICATED_SUCCESSFULLY =
|
||||||
|
"biometrics_authenticated_successfully";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used by the choose fingerprint wizard to indicate the wizard is
|
* Used by the choose fingerprint wizard to indicate the wizard is
|
||||||
@@ -115,6 +117,7 @@ public abstract class BiometricEnrollBase extends InstrumentedActivity {
|
|||||||
public static final int LEARN_MORE_REQUEST = 3;
|
public static final int LEARN_MORE_REQUEST = 3;
|
||||||
public static final int CONFIRM_REQUEST = 4;
|
public static final int CONFIRM_REQUEST = 4;
|
||||||
public static final int ENROLL_REQUEST = 5;
|
public static final int ENROLL_REQUEST = 5;
|
||||||
|
public static final int BIOMETRIC_AUTH_REQUEST = 6;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Request code when starting another biometric enrollment from within a biometric flow. For
|
* Request code when starting another biometric enrollment from within a biometric flow. For
|
||||||
|
@@ -65,6 +65,7 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
|
|||||||
static final int CONFIRM_REQUEST = 2001;
|
static final int CONFIRM_REQUEST = 2001;
|
||||||
private static final int CHOOSE_LOCK_REQUEST = 2002;
|
private static final int CHOOSE_LOCK_REQUEST = 2002;
|
||||||
protected static final int ACTIVE_UNLOCK_REQUEST = 2003;
|
protected static final int ACTIVE_UNLOCK_REQUEST = 2003;
|
||||||
|
private static final int BIOMETRIC_AUTH_REQUEST = 2004;
|
||||||
|
|
||||||
private static final String SAVE_STATE_CONFIRM_CREDETIAL = "confirm_credential";
|
private static final String SAVE_STATE_CONFIRM_CREDETIAL = "confirm_credential";
|
||||||
private static final String DO_NOT_FINISH_ACTIVITY = "do_not_finish_activity";
|
private static final String DO_NOT_FINISH_ACTIVITY = "do_not_finish_activity";
|
||||||
@@ -72,10 +73,15 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
|
|||||||
static final String RETRY_PREFERENCE_KEY = "retry_preference_key";
|
static final String RETRY_PREFERENCE_KEY = "retry_preference_key";
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final String RETRY_PREFERENCE_BUNDLE = "retry_preference_bundle";
|
static final String RETRY_PREFERENCE_BUNDLE = "retry_preference_bundle";
|
||||||
|
private static final String BIOMETRICS_AUTH_REQUESTED = "biometrics_auth_requested";
|
||||||
|
private static final String BIOMETRICS_AUTHENTICATED_SUCCESSFULLY =
|
||||||
|
"biometrics_authenticated_successfully";
|
||||||
|
|
||||||
protected int mUserId;
|
protected int mUserId;
|
||||||
protected long mGkPwHandle;
|
protected long mGkPwHandle;
|
||||||
private boolean mConfirmCredential;
|
private boolean mConfirmCredential;
|
||||||
|
private boolean mBiometricsAuthenticationRequested;
|
||||||
|
private boolean mBiometricsSuccessfullyAuthenticated;
|
||||||
@Nullable private FaceManager mFaceManager;
|
@Nullable private FaceManager mFaceManager;
|
||||||
@Nullable private FingerprintManager mFingerprintManager;
|
@Nullable private FingerprintManager mFingerprintManager;
|
||||||
// Do not finish() if choosing/confirming credential, showing fp/face settings, or launching
|
// Do not finish() if choosing/confirming credential, showing fp/face settings, or launching
|
||||||
@@ -113,6 +119,9 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
|
|||||||
mGkPwHandle = BiometricUtils.getGatekeeperPasswordHandle(getIntent());
|
mGkPwHandle = BiometricUtils.getGatekeeperPasswordHandle(getIntent());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mBiometricsSuccessfullyAuthenticated = getIntent().getBooleanExtra(
|
||||||
|
BIOMETRICS_AUTHENTICATED_SUCCESSFULLY, false);
|
||||||
|
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
mConfirmCredential = savedInstanceState.getBoolean(SAVE_STATE_CONFIRM_CREDETIAL);
|
mConfirmCredential = savedInstanceState.getBoolean(SAVE_STATE_CONFIRM_CREDETIAL);
|
||||||
mDoNotFinishActivity = savedInstanceState.getBoolean(DO_NOT_FINISH_ACTIVITY);
|
mDoNotFinishActivity = savedInstanceState.getBoolean(DO_NOT_FINISH_ACTIVITY);
|
||||||
@@ -123,11 +132,20 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
|
|||||||
mGkPwHandle = savedInstanceState.getLong(
|
mGkPwHandle = savedInstanceState.getLong(
|
||||||
ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE);
|
ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE);
|
||||||
}
|
}
|
||||||
|
mBiometricsAuthenticationRequested = savedInstanceState.getBoolean(
|
||||||
|
BIOMETRICS_AUTH_REQUESTED);
|
||||||
|
mBiometricsSuccessfullyAuthenticated = savedInstanceState.getBoolean(
|
||||||
|
BIOMETRICS_AUTHENTICATED_SUCCESSFULLY);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mGkPwHandle == 0L && !mConfirmCredential) {
|
if (mGkPwHandle == 0L && !mConfirmCredential) {
|
||||||
mConfirmCredential = true;
|
mConfirmCredential = true;
|
||||||
launchChooseOrConfirmLock();
|
launchChooseOrConfirmLock();
|
||||||
|
} else if (Utils.requestBiometricAuthenticationForMandatoryBiometrics(
|
||||||
|
getActivity(), mBiometricsSuccessfullyAuthenticated,
|
||||||
|
mBiometricsAuthenticationRequested)) {
|
||||||
|
mBiometricsAuthenticationRequested = true;
|
||||||
|
Utils.launchBiometricPromptForMandatoryBiometrics(this, BIOMETRIC_AUTH_REQUEST);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateUnlockPhonePreferenceSummary();
|
updateUnlockPhonePreferenceSummary();
|
||||||
@@ -141,6 +159,12 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
|
|||||||
@Override
|
@Override
|
||||||
public void onResume() {
|
public void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
if (Utils.requestBiometricAuthenticationForMandatoryBiometrics(getActivity(),
|
||||||
|
mBiometricsSuccessfullyAuthenticated, mBiometricsAuthenticationRequested)
|
||||||
|
&& mGkPwHandle != 0L) {
|
||||||
|
mBiometricsAuthenticationRequested = true;
|
||||||
|
Utils.launchBiometricPromptForMandatoryBiometrics(this, BIOMETRIC_AUTH_REQUEST);
|
||||||
|
}
|
||||||
if (!mConfirmCredential) {
|
if (!mConfirmCredential) {
|
||||||
mDoNotFinishActivity = false;
|
mDoNotFinishActivity = false;
|
||||||
}
|
}
|
||||||
@@ -177,6 +201,9 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
|
|||||||
extras.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
|
extras.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
|
||||||
extras.putInt(BiometricEnrollBase.EXTRA_KEY_SENSOR_ID, sensorId);
|
extras.putInt(BiometricEnrollBase.EXTRA_KEY_SENSOR_ID, sensorId);
|
||||||
extras.putLong(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, challenge);
|
extras.putLong(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, challenge);
|
||||||
|
extras.putBoolean(
|
||||||
|
BiometricEnrollBase.EXTRA_BIOMETRICS_AUTHENTICATED_SUCCESSFULLY,
|
||||||
|
mBiometricsSuccessfullyAuthenticated);
|
||||||
onFaceOrFingerprintPreferenceTreeClick(preference);
|
onFaceOrFingerprintPreferenceTreeClick(preference);
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
if (retry) {
|
if (retry) {
|
||||||
@@ -206,6 +233,9 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
|
|||||||
final Bundle extras = preference.getExtras();
|
final Bundle extras = preference.getExtras();
|
||||||
extras.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
|
extras.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
|
||||||
extras.putLong(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, challenge);
|
extras.putLong(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, challenge);
|
||||||
|
extras.putBoolean(
|
||||||
|
BiometricEnrollBase.EXTRA_BIOMETRICS_AUTHENTICATED_SUCCESSFULLY,
|
||||||
|
mBiometricsSuccessfullyAuthenticated);
|
||||||
onFaceOrFingerprintPreferenceTreeClick(preference);
|
onFaceOrFingerprintPreferenceTreeClick(preference);
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
if (retry) {
|
if (retry) {
|
||||||
@@ -288,6 +318,10 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
|
|||||||
outState.putString(RETRY_PREFERENCE_KEY, mRetryPreferenceKey);
|
outState.putString(RETRY_PREFERENCE_KEY, mRetryPreferenceKey);
|
||||||
outState.putBundle(RETRY_PREFERENCE_BUNDLE, mRetryPreferenceExtra);
|
outState.putBundle(RETRY_PREFERENCE_BUNDLE, mRetryPreferenceExtra);
|
||||||
}
|
}
|
||||||
|
outState.putBoolean(BIOMETRICS_AUTH_REQUESTED,
|
||||||
|
mBiometricsAuthenticationRequested);
|
||||||
|
outState.putBoolean(BIOMETRICS_AUTHENTICATED_SUCCESSFULLY,
|
||||||
|
mBiometricsSuccessfullyAuthenticated);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -315,6 +349,13 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
|
|||||||
}
|
}
|
||||||
mRetryPreferenceKey = null;
|
mRetryPreferenceKey = null;
|
||||||
mRetryPreferenceExtra = null;
|
mRetryPreferenceExtra = null;
|
||||||
|
} else if (requestCode == BIOMETRIC_AUTH_REQUEST) {
|
||||||
|
mBiometricsAuthenticationRequested = false;
|
||||||
|
if (resultCode == RESULT_OK) {
|
||||||
|
mBiometricsSuccessfullyAuthenticated = true;
|
||||||
|
} else {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -20,8 +20,10 @@ import static android.app.Activity.RESULT_OK;
|
|||||||
import static android.app.admin.DevicePolicyResources.Strings.Settings.FACE_SETTINGS_FOR_WORK_TITLE;
|
import static android.app.admin.DevicePolicyResources.Strings.Settings.FACE_SETTINGS_FOR_WORK_TITLE;
|
||||||
|
|
||||||
import static com.android.settings.Utils.isPrivateProfile;
|
import static com.android.settings.Utils.isPrivateProfile;
|
||||||
|
import static com.android.settings.biometrics.BiometricEnrollBase.BIOMETRIC_AUTH_REQUEST;
|
||||||
import static com.android.settings.biometrics.BiometricEnrollBase.CONFIRM_REQUEST;
|
import static com.android.settings.biometrics.BiometricEnrollBase.CONFIRM_REQUEST;
|
||||||
import static com.android.settings.biometrics.BiometricEnrollBase.ENROLL_REQUEST;
|
import static com.android.settings.biometrics.BiometricEnrollBase.ENROLL_REQUEST;
|
||||||
|
import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_BIOMETRICS_AUTHENTICATED_SUCCESSFULLY;
|
||||||
import static com.android.settings.biometrics.BiometricEnrollBase.RESULT_FINISHED;
|
import static com.android.settings.biometrics.BiometricEnrollBase.RESULT_FINISHED;
|
||||||
import static com.android.settings.biometrics.BiometricEnrollBase.RESULT_TIMEOUT;
|
import static com.android.settings.biometrics.BiometricEnrollBase.RESULT_TIMEOUT;
|
||||||
|
|
||||||
@@ -66,6 +68,8 @@ public class FaceSettings extends DashboardFragment {
|
|||||||
private static final String TAG = "FaceSettings";
|
private static final String TAG = "FaceSettings";
|
||||||
private static final String KEY_TOKEN = "hw_auth_token";
|
private static final String KEY_TOKEN = "hw_auth_token";
|
||||||
private static final String KEY_RE_ENROLL_FACE = "re_enroll_face_unlock";
|
private static final String KEY_RE_ENROLL_FACE = "re_enroll_face_unlock";
|
||||||
|
private static final String KEY_BIOMETRICS_SUCCESSFULLY_AUTHENTICATED =
|
||||||
|
"biometrics_successfully_authenticated";
|
||||||
|
|
||||||
private static final String PREF_KEY_DELETE_FACE_DATA =
|
private static final String PREF_KEY_DELETE_FACE_DATA =
|
||||||
"security_settings_face_delete_faces_container";
|
"security_settings_face_delete_faces_container";
|
||||||
@@ -93,6 +97,8 @@ public class FaceSettings extends DashboardFragment {
|
|||||||
private FaceFeatureProvider mFaceFeatureProvider;
|
private FaceFeatureProvider mFaceFeatureProvider;
|
||||||
|
|
||||||
private boolean mConfirmingPassword;
|
private boolean mConfirmingPassword;
|
||||||
|
private boolean mBiometricsAuthenticationRequested;
|
||||||
|
private boolean mBiometricsSuccessfullyAuthenticated;
|
||||||
|
|
||||||
private final FaceSettingsRemoveButtonPreferenceController.Listener mRemovalListener = () -> {
|
private final FaceSettingsRemoveButtonPreferenceController.Listener mRemovalListener = () -> {
|
||||||
|
|
||||||
@@ -144,6 +150,8 @@ public class FaceSettings extends DashboardFragment {
|
|||||||
public void onSaveInstanceState(Bundle outState) {
|
public void onSaveInstanceState(Bundle outState) {
|
||||||
super.onSaveInstanceState(outState);
|
super.onSaveInstanceState(outState);
|
||||||
outState.putByteArray(KEY_TOKEN, mToken);
|
outState.putByteArray(KEY_TOKEN, mToken);
|
||||||
|
outState.putBoolean(KEY_BIOMETRICS_SUCCESSFULLY_AUTHENTICATED,
|
||||||
|
mBiometricsSuccessfullyAuthenticated);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -163,6 +171,8 @@ public class FaceSettings extends DashboardFragment {
|
|||||||
mToken = getIntent().getByteArrayExtra(KEY_TOKEN);
|
mToken = getIntent().getByteArrayExtra(KEY_TOKEN);
|
||||||
mSensorId = getIntent().getIntExtra(BiometricEnrollBase.EXTRA_KEY_SENSOR_ID, -1);
|
mSensorId = getIntent().getIntExtra(BiometricEnrollBase.EXTRA_KEY_SENSOR_ID, -1);
|
||||||
mChallenge = getIntent().getLongExtra(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, 0L);
|
mChallenge = getIntent().getLongExtra(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, 0L);
|
||||||
|
mBiometricsSuccessfullyAuthenticated = getIntent().getBooleanExtra(
|
||||||
|
EXTRA_BIOMETRICS_AUTHENTICATED_SUCCESSFULLY, false);
|
||||||
|
|
||||||
mUserId = getActivity().getIntent().getIntExtra(
|
mUserId = getActivity().getIntent().getIntExtra(
|
||||||
Intent.EXTRA_USER_ID, UserHandle.myUserId());
|
Intent.EXTRA_USER_ID, UserHandle.myUserId());
|
||||||
@@ -231,6 +241,8 @@ public class FaceSettings extends DashboardFragment {
|
|||||||
|
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
mToken = savedInstanceState.getByteArray(KEY_TOKEN);
|
mToken = savedInstanceState.getByteArray(KEY_TOKEN);
|
||||||
|
mBiometricsSuccessfullyAuthenticated = savedInstanceState.getBoolean(
|
||||||
|
KEY_BIOMETRICS_SUCCESSFULLY_AUTHENTICATED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,6 +288,10 @@ public class FaceSettings extends DashboardFragment {
|
|||||||
Log.e(TAG, "Password not set");
|
Log.e(TAG, "Password not set");
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
} else if (Utils.requestBiometricAuthenticationForMandatoryBiometrics(getActivity(),
|
||||||
|
mBiometricsSuccessfullyAuthenticated, mBiometricsAuthenticationRequested)) {
|
||||||
|
mBiometricsAuthenticationRequested = true;
|
||||||
|
Utils.launchBiometricPromptForMandatoryBiometrics(this, BIOMETRIC_AUTH_REQUEST);
|
||||||
} else {
|
} else {
|
||||||
mAttentionController.setToken(mToken);
|
mAttentionController.setToken(mToken);
|
||||||
mEnrollController.setToken(mToken);
|
mEnrollController.setToken(mToken);
|
||||||
@@ -318,6 +334,13 @@ public class FaceSettings extends DashboardFragment {
|
|||||||
setResult(resultCode, data);
|
setResult(resultCode, data);
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
|
} else if (requestCode == BIOMETRIC_AUTH_REQUEST) {
|
||||||
|
mBiometricsAuthenticationRequested = false;
|
||||||
|
if (resultCode == RESULT_OK) {
|
||||||
|
mBiometricsSuccessfullyAuthenticated = true;
|
||||||
|
} else {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -23,6 +23,7 @@ import static android.app.admin.DevicePolicyResources.UNDEFINED;
|
|||||||
|
|
||||||
import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME;
|
import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME;
|
||||||
import static com.android.settings.Utils.isPrivateProfile;
|
import static com.android.settings.Utils.isPrivateProfile;
|
||||||
|
import static com.android.settings.biometrics.BiometricEnrollBase.BIOMETRIC_AUTH_REQUEST;
|
||||||
import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_FROM_SETTINGS_SUMMARY;
|
import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_FROM_SETTINGS_SUMMARY;
|
||||||
import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_KEY_CHALLENGE;
|
import static com.android.settings.biometrics.BiometricEnrollBase.EXTRA_KEY_CHALLENGE;
|
||||||
|
|
||||||
@@ -218,6 +219,10 @@ public class FingerprintSettings extends SubSettings {
|
|||||||
"security_settings_fingerprint_unlock_category";
|
"security_settings_fingerprint_unlock_category";
|
||||||
private static final String KEY_FINGERPRINT_UNLOCK_FOOTER =
|
private static final String KEY_FINGERPRINT_UNLOCK_FOOTER =
|
||||||
"security_settings_fingerprint_footer";
|
"security_settings_fingerprint_footer";
|
||||||
|
private static final String KEY_BIOMETRICS_AUTHENTICATION_REQUESTED =
|
||||||
|
"biometrics_authentication_requested";
|
||||||
|
private static final String KEY_BIOMETRICS_SUCCESSFULLY_AUTHENTICATED =
|
||||||
|
"biometrics_successfully_authenticated";
|
||||||
|
|
||||||
private static final int MSG_REFRESH_FINGERPRINT_TEMPLATES = 1000;
|
private static final int MSG_REFRESH_FINGERPRINT_TEMPLATES = 1000;
|
||||||
private static final int MSG_FINGER_AUTH_SUCCESS = 1001;
|
private static final int MSG_FINGER_AUTH_SUCCESS = 1001;
|
||||||
@@ -251,6 +256,8 @@ public class FingerprintSettings extends SubSettings {
|
|||||||
private boolean mInFingerprintLockout;
|
private boolean mInFingerprintLockout;
|
||||||
private byte[] mToken;
|
private byte[] mToken;
|
||||||
private boolean mLaunchedConfirm;
|
private boolean mLaunchedConfirm;
|
||||||
|
private boolean mBiometricsAuthenticationRequested;
|
||||||
|
private boolean mBiometricsSuccessfullyAuthenticated;
|
||||||
private boolean mHasFirstEnrolled = true;
|
private boolean mHasFirstEnrolled = true;
|
||||||
private Drawable mHighlightDrawable;
|
private Drawable mHighlightDrawable;
|
||||||
private int mUserId;
|
private int mUserId;
|
||||||
@@ -423,6 +430,8 @@ public class FingerprintSettings extends SubSettings {
|
|||||||
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
|
ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN);
|
||||||
mChallenge = activity.getIntent()
|
mChallenge = activity.getIntent()
|
||||||
.getLongExtra(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, -1L);
|
.getLongExtra(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, -1L);
|
||||||
|
mBiometricsSuccessfullyAuthenticated = getIntent().getBooleanExtra(
|
||||||
|
BiometricEnrollBase.EXTRA_BIOMETRICS_AUTHENTICATED_SUCCESSFULLY, false);
|
||||||
|
|
||||||
mAuthenticateSidecar = (FingerprintAuthenticateSidecar)
|
mAuthenticateSidecar = (FingerprintAuthenticateSidecar)
|
||||||
getFragmentManager().findFragmentByTag(TAG_AUTHENTICATE_SIDECAR);
|
getFragmentManager().findFragmentByTag(TAG_AUTHENTICATE_SIDECAR);
|
||||||
@@ -464,6 +473,10 @@ public class FingerprintSettings extends SubSettings {
|
|||||||
mIsEnrolling = savedInstanceState.getBoolean(KEY_IS_ENROLLING, mIsEnrolling);
|
mIsEnrolling = savedInstanceState.getBoolean(KEY_IS_ENROLLING, mIsEnrolling);
|
||||||
mHasFirstEnrolled = savedInstanceState.getBoolean(KEY_HAS_FIRST_ENROLLED,
|
mHasFirstEnrolled = savedInstanceState.getBoolean(KEY_HAS_FIRST_ENROLLED,
|
||||||
mHasFirstEnrolled);
|
mHasFirstEnrolled);
|
||||||
|
mBiometricsSuccessfullyAuthenticated = savedInstanceState.getBoolean(
|
||||||
|
KEY_BIOMETRICS_SUCCESSFULLY_AUTHENTICATED);
|
||||||
|
mBiometricsAuthenticationRequested = savedInstanceState.getBoolean(
|
||||||
|
KEY_BIOMETRICS_AUTHENTICATION_REQUESTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
// (mLaunchedConfirm or mIsEnrolling) means that we are waiting an activity result.
|
// (mLaunchedConfirm or mIsEnrolling) means that we are waiting an activity result.
|
||||||
@@ -472,6 +485,10 @@ public class FingerprintSettings extends SubSettings {
|
|||||||
if (mToken == null) {
|
if (mToken == null) {
|
||||||
mLaunchedConfirm = true;
|
mLaunchedConfirm = true;
|
||||||
launchChooseOrConfirmLock();
|
launchChooseOrConfirmLock();
|
||||||
|
} else if (Utils.requestBiometricAuthenticationForMandatoryBiometrics(getActivity(),
|
||||||
|
mBiometricsSuccessfullyAuthenticated, mBiometricsAuthenticationRequested)) {
|
||||||
|
mBiometricsAuthenticationRequested = true;
|
||||||
|
Utils.launchBiometricPromptForMandatoryBiometrics(this, BIOMETRIC_AUTH_REQUEST);
|
||||||
} else if (!mHasFirstEnrolled) {
|
} else if (!mHasFirstEnrolled) {
|
||||||
mIsEnrolling = true;
|
mIsEnrolling = true;
|
||||||
addFirstFingerprint(null);
|
addFirstFingerprint(null);
|
||||||
@@ -751,6 +768,12 @@ public class FingerprintSettings extends SubSettings {
|
|||||||
|
|
||||||
mCalibrator = FeatureFactory.getFeatureFactory().getFingerprintFeatureProvider()
|
mCalibrator = FeatureFactory.getFeatureFactory().getFingerprintFeatureProvider()
|
||||||
.getUdfpsEnrollCalibrator(getActivity().getApplicationContext(), null, null);
|
.getUdfpsEnrollCalibrator(getActivity().getApplicationContext(), null, null);
|
||||||
|
|
||||||
|
if (Utils.requestBiometricAuthenticationForMandatoryBiometrics(getActivity(),
|
||||||
|
mBiometricsSuccessfullyAuthenticated, mBiometricsAuthenticationRequested)) {
|
||||||
|
mBiometricsAuthenticationRequested = true;
|
||||||
|
Utils.launchBiometricPromptForMandatoryBiometrics(this, BIOMETRIC_AUTH_REQUEST);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updatePreferences() {
|
private void updatePreferences() {
|
||||||
@@ -798,6 +821,10 @@ public class FingerprintSettings extends SubSettings {
|
|||||||
outState.putSerializable("mFingerprintsRenaming", mFingerprintsRenaming);
|
outState.putSerializable("mFingerprintsRenaming", mFingerprintsRenaming);
|
||||||
outState.putBoolean(KEY_IS_ENROLLING, mIsEnrolling);
|
outState.putBoolean(KEY_IS_ENROLLING, mIsEnrolling);
|
||||||
outState.putBoolean(KEY_HAS_FIRST_ENROLLED, mHasFirstEnrolled);
|
outState.putBoolean(KEY_HAS_FIRST_ENROLLED, mHasFirstEnrolled);
|
||||||
|
outState.putBoolean(KEY_BIOMETRICS_AUTHENTICATION_REQUESTED,
|
||||||
|
mBiometricsAuthenticationRequested);
|
||||||
|
outState.putBoolean(KEY_BIOMETRICS_SUCCESSFULLY_AUTHENTICATED,
|
||||||
|
mBiometricsSuccessfullyAuthenticated);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -1018,6 +1045,13 @@ public class FingerprintSettings extends SubSettings {
|
|||||||
mIsEnrolling = false;
|
mIsEnrolling = false;
|
||||||
mHasFirstEnrolled = true;
|
mHasFirstEnrolled = true;
|
||||||
updateAddPreference();
|
updateAddPreference();
|
||||||
|
} else if (requestCode == BIOMETRIC_AUTH_REQUEST) {
|
||||||
|
mBiometricsAuthenticationRequested = false;
|
||||||
|
if (resultCode == RESULT_OK) {
|
||||||
|
mBiometricsSuccessfullyAuthenticated = true;
|
||||||
|
} else {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -16,8 +16,11 @@
|
|||||||
|
|
||||||
package com.android.settings.password;
|
package com.android.settings.password;
|
||||||
|
|
||||||
|
import static android.hardware.biometrics.BiometricConstants.BIOMETRIC_ERROR_USER_CANCELED;
|
||||||
|
|
||||||
import android.app.settings.SettingsEnums;
|
import android.app.settings.SettingsEnums;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
|
import android.hardware.biometrics.BiometricManager;
|
||||||
import android.hardware.biometrics.BiometricPrompt;
|
import android.hardware.biometrics.BiometricPrompt;
|
||||||
import android.hardware.biometrics.BiometricPrompt.AuthenticationCallback;
|
import android.hardware.biometrics.BiometricPrompt.AuthenticationCallback;
|
||||||
import android.hardware.biometrics.BiometricPrompt.AuthenticationResult;
|
import android.hardware.biometrics.BiometricPrompt.AuthenticationResult;
|
||||||
@@ -137,7 +140,7 @@ public class BiometricFragment extends InstrumentedFragment {
|
|||||||
BiometricPrompt.Builder promptBuilder = new BiometricPrompt.Builder(getContext())
|
BiometricPrompt.Builder promptBuilder = new BiometricPrompt.Builder(getContext())
|
||||||
.setTitle(promptInfo.getTitle())
|
.setTitle(promptInfo.getTitle())
|
||||||
.setUseDefaultTitle() // use default title if title is null/empty
|
.setUseDefaultTitle() // use default title if title is null/empty
|
||||||
.setDeviceCredentialAllowed(true)
|
.setAllowedAuthenticators(promptInfo.getAuthenticators())
|
||||||
.setSubtitle(promptInfo.getSubtitle())
|
.setSubtitle(promptInfo.getSubtitle())
|
||||||
.setDescription(promptInfo.getDescription())
|
.setDescription(promptInfo.getDescription())
|
||||||
.setTextForDeviceCredential(
|
.setTextForDeviceCredential(
|
||||||
@@ -170,6 +173,15 @@ public class BiometricFragment extends InstrumentedFragment {
|
|||||||
if (promptInfo.isUseDefaultSubtitle()) {
|
if (promptInfo.isUseDefaultSubtitle()) {
|
||||||
promptBuilder.setUseDefaultSubtitle();
|
promptBuilder.setUseDefaultSubtitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((promptInfo.getAuthenticators()
|
||||||
|
& BiometricManager.Authenticators.DEVICE_CREDENTIAL) == 0) {
|
||||||
|
promptBuilder.setNegativeButton(promptInfo.getNegativeButtonText(),
|
||||||
|
getContext().getMainExecutor(),
|
||||||
|
(dialog, which) -> mAuthenticationCallback.onAuthenticationError(
|
||||||
|
BIOMETRIC_ERROR_USER_CANCELED,
|
||||||
|
null /* errString */));
|
||||||
|
}
|
||||||
mBiometricPrompt = promptBuilder.build();
|
mBiometricPrompt = promptBuilder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -160,11 +160,13 @@ public class ChooseLockGeneric extends SettingsActivity {
|
|||||||
static final int CHOOSE_LOCK_BEFORE_BIOMETRIC_REQUEST = 103;
|
static final int CHOOSE_LOCK_BEFORE_BIOMETRIC_REQUEST = 103;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static final int SKIP_FINGERPRINT_REQUEST = 104;
|
static final int SKIP_FINGERPRINT_REQUEST = 104;
|
||||||
|
private static final int BIOMETRIC_AUTH_REQUEST = 105;
|
||||||
|
|
||||||
private LockPatternUtils mLockPatternUtils;
|
private LockPatternUtils mLockPatternUtils;
|
||||||
private DevicePolicyManager mDpm;
|
private DevicePolicyManager mDpm;
|
||||||
private boolean mRequestGatekeeperPasswordHandle = false;
|
private boolean mRequestGatekeeperPasswordHandle = false;
|
||||||
private boolean mPasswordConfirmed = false;
|
private boolean mPasswordConfirmed = false;
|
||||||
|
private boolean mBiometricsAuthSuccessful = false;
|
||||||
private boolean mWaitingForConfirmation = false;
|
private boolean mWaitingForConfirmation = false;
|
||||||
private boolean mWaitingForActivityResult = false;
|
private boolean mWaitingForActivityResult = false;
|
||||||
private LockscreenCredential mUserPassword;
|
private LockscreenCredential mUserPassword;
|
||||||
@@ -488,6 +490,17 @@ public class ChooseLockGeneric extends SettingsActivity {
|
|||||||
? data.getParcelableExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD)
|
? data.getParcelableExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD)
|
||||||
: null;
|
: null;
|
||||||
updatePreferencesOrFinish(false /* isRecreatingActivity */);
|
updatePreferencesOrFinish(false /* isRecreatingActivity */);
|
||||||
|
if (Utils.requestBiometricAuthenticationForMandatoryBiometrics(getContext(),
|
||||||
|
mBiometricsAuthSuccessful, mWaitingForConfirmation)) {
|
||||||
|
mWaitingForConfirmation = true;
|
||||||
|
Utils.launchBiometricPromptForMandatoryBiometrics(this, BIOMETRIC_AUTH_REQUEST);
|
||||||
|
}
|
||||||
|
} else if (requestCode == BIOMETRIC_AUTH_REQUEST) {
|
||||||
|
if (resultCode == Activity.RESULT_OK) {
|
||||||
|
mBiometricsAuthSuccessful = true;
|
||||||
|
} else {
|
||||||
|
finish();
|
||||||
|
}
|
||||||
} else if (requestCode == CHOOSE_LOCK_REQUEST) {
|
} else if (requestCode == CHOOSE_LOCK_REQUEST) {
|
||||||
if (resultCode != RESULT_CANCELED) {
|
if (resultCode != RESULT_CANCELED) {
|
||||||
getActivity().setResult(resultCode, data);
|
getActivity().setResult(resultCode, data);
|
||||||
|
@@ -17,10 +17,10 @@
|
|||||||
|
|
||||||
package com.android.settings.password;
|
package com.android.settings.password;
|
||||||
|
|
||||||
|
import static android.Manifest.permission.SET_BIOMETRIC_DIALOG_ADVANCED;
|
||||||
import static android.app.admin.DevicePolicyResources.Strings.Settings.CONFIRM_WORK_PROFILE_PASSWORD_HEADER;
|
import static android.app.admin.DevicePolicyResources.Strings.Settings.CONFIRM_WORK_PROFILE_PASSWORD_HEADER;
|
||||||
import static android.app.admin.DevicePolicyResources.Strings.Settings.CONFIRM_WORK_PROFILE_PATTERN_HEADER;
|
import static android.app.admin.DevicePolicyResources.Strings.Settings.CONFIRM_WORK_PROFILE_PATTERN_HEADER;
|
||||||
import static android.app.admin.DevicePolicyResources.Strings.Settings.CONFIRM_WORK_PROFILE_PIN_HEADER;
|
import static android.app.admin.DevicePolicyResources.Strings.Settings.CONFIRM_WORK_PROFILE_PIN_HEADER;
|
||||||
import static android.Manifest.permission.SET_BIOMETRIC_DIALOG_ADVANCED;
|
|
||||||
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
|
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_STATUS_BARS;
|
||||||
|
|
||||||
import static com.android.systemui.biometrics.Utils.toBitmap;
|
import static com.android.systemui.biometrics.Utils.toBitmap;
|
||||||
@@ -40,6 +40,7 @@ import android.content.res.Configuration;
|
|||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.hardware.biometrics.BiometricConstants;
|
import android.hardware.biometrics.BiometricConstants;
|
||||||
|
import android.hardware.biometrics.BiometricManager;
|
||||||
import android.hardware.biometrics.BiometricPrompt;
|
import android.hardware.biometrics.BiometricPrompt;
|
||||||
import android.hardware.biometrics.BiometricPrompt.AuthenticationCallback;
|
import android.hardware.biometrics.BiometricPrompt.AuthenticationCallback;
|
||||||
import android.hardware.biometrics.PromptInfo;
|
import android.hardware.biometrics.PromptInfo;
|
||||||
@@ -76,6 +77,9 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
|
|||||||
/** Use this extra value to provide a custom logo description for the biometric prompt. **/
|
/** Use this extra value to provide a custom logo description for the biometric prompt. **/
|
||||||
public static final String CUSTOM_BIOMETRIC_PROMPT_LOGO_DESCRIPTION_KEY =
|
public static final String CUSTOM_BIOMETRIC_PROMPT_LOGO_DESCRIPTION_KEY =
|
||||||
"custom_logo_description";
|
"custom_logo_description";
|
||||||
|
public static final String BIOMETRIC_PROMPT_AUTHENTICATORS = "biometric_prompt_authenticators";
|
||||||
|
public static final String BIOMETRIC_PROMPT_NEGATIVE_BUTTON_TEXT =
|
||||||
|
"biometric_prompt_negative_button_text";
|
||||||
|
|
||||||
public static class InternalActivity extends ConfirmDeviceCredentialActivity {
|
public static class InternalActivity extends ConfirmDeviceCredentialActivity {
|
||||||
}
|
}
|
||||||
@@ -177,6 +181,11 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
|
|||||||
mDetails = intent.getCharSequenceExtra(KeyguardManager.EXTRA_DESCRIPTION);
|
mDetails = intent.getCharSequenceExtra(KeyguardManager.EXTRA_DESCRIPTION);
|
||||||
String alternateButton = intent.getStringExtra(
|
String alternateButton = intent.getStringExtra(
|
||||||
KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL);
|
KeyguardManager.EXTRA_ALTERNATE_BUTTON_LABEL);
|
||||||
|
final int authenticators = intent.getIntExtra(BIOMETRIC_PROMPT_AUTHENTICATORS,
|
||||||
|
BiometricManager.Authenticators.DEVICE_CREDENTIAL
|
||||||
|
| BiometricManager.Authenticators.BIOMETRIC_WEAK);
|
||||||
|
final String negativeButtonText = intent.getStringExtra(
|
||||||
|
BIOMETRIC_PROMPT_NEGATIVE_BUTTON_TEXT);
|
||||||
final boolean frp =
|
final boolean frp =
|
||||||
KeyguardManager.ACTION_CONFIRM_FRP_CREDENTIAL.equals(intent.getAction());
|
KeyguardManager.ACTION_CONFIRM_FRP_CREDENTIAL.equals(intent.getAction());
|
||||||
final boolean repairMode =
|
final boolean repairMode =
|
||||||
@@ -213,6 +222,8 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
|
|||||||
promptInfo.setTitle(mTitle);
|
promptInfo.setTitle(mTitle);
|
||||||
promptInfo.setDescription(mDetails);
|
promptInfo.setDescription(mDetails);
|
||||||
promptInfo.setDisallowBiometricsIfPolicyExists(mCheckDevicePolicyManager);
|
promptInfo.setDisallowBiometricsIfPolicyExists(mCheckDevicePolicyManager);
|
||||||
|
promptInfo.setAuthenticators(authenticators);
|
||||||
|
promptInfo.setNegativeButtonText(negativeButtonText);
|
||||||
|
|
||||||
if (android.multiuser.Flags.enablePrivateSpaceFeatures()
|
if (android.multiuser.Flags.enablePrivateSpaceFeatures()
|
||||||
&& android.multiuser.Flags.usePrivateSpaceIconInBiometricPrompt()
|
&& android.multiuser.Flags.usePrivateSpaceIconInBiometricPrompt()
|
||||||
|
@@ -20,6 +20,10 @@ import static android.hardware.biometrics.SensorProperties.STRENGTH_CONVENIENCE;
|
|||||||
import static android.hardware.biometrics.SensorProperties.STRENGTH_STRONG;
|
import static android.hardware.biometrics.SensorProperties.STRENGTH_STRONG;
|
||||||
import static android.hardware.biometrics.SensorProperties.STRENGTH_WEAK;
|
import static android.hardware.biometrics.SensorProperties.STRENGTH_WEAK;
|
||||||
|
|
||||||
|
import static com.android.settings.Utils.SETTINGS_PACKAGE_NAME;
|
||||||
|
import static com.android.settings.password.ConfirmDeviceCredentialActivity.BIOMETRIC_PROMPT_AUTHENTICATORS;
|
||||||
|
import static com.android.settings.password.ConfirmDeviceCredentialActivity.BIOMETRIC_PROMPT_NEGATIVE_BUTTON_TEXT;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import static org.junit.Assert.assertNull;
|
import static org.junit.Assert.assertNull;
|
||||||
@@ -35,10 +39,12 @@ import static org.mockito.Mockito.verify;
|
|||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.app.ActionBar;
|
import android.app.ActionBar;
|
||||||
|
import android.app.KeyguardManager;
|
||||||
import android.app.admin.DevicePolicyManager;
|
import android.app.admin.DevicePolicyManager;
|
||||||
import android.app.admin.DevicePolicyResourcesManager;
|
import android.app.admin.DevicePolicyResourcesManager;
|
||||||
import android.content.ComponentName;
|
import android.content.ComponentName;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.content.pm.ApplicationInfo;
|
import android.content.pm.ApplicationInfo;
|
||||||
import android.content.pm.PackageManager;
|
import android.content.pm.PackageManager;
|
||||||
import android.content.pm.UserInfo;
|
import android.content.pm.UserInfo;
|
||||||
@@ -47,6 +53,8 @@ import android.graphics.Color;
|
|||||||
import android.graphics.drawable.BitmapDrawable;
|
import android.graphics.drawable.BitmapDrawable;
|
||||||
import android.graphics.drawable.ColorDrawable;
|
import android.graphics.drawable.ColorDrawable;
|
||||||
import android.graphics.drawable.VectorDrawable;
|
import android.graphics.drawable.VectorDrawable;
|
||||||
|
import android.hardware.biometrics.BiometricManager;
|
||||||
|
import android.hardware.biometrics.Flags;
|
||||||
import android.hardware.face.FaceManager;
|
import android.hardware.face.FaceManager;
|
||||||
import android.hardware.face.FaceSensorProperties;
|
import android.hardware.face.FaceSensorProperties;
|
||||||
import android.hardware.face.FaceSensorPropertiesInternal;
|
import android.hardware.face.FaceSensorPropertiesInternal;
|
||||||
@@ -61,21 +69,28 @@ import android.os.UserManager;
|
|||||||
import android.os.storage.DiskInfo;
|
import android.os.storage.DiskInfo;
|
||||||
import android.os.storage.StorageManager;
|
import android.os.storage.StorageManager;
|
||||||
import android.os.storage.VolumeInfo;
|
import android.os.storage.VolumeInfo;
|
||||||
|
import android.platform.test.annotations.RequiresFlagsEnabled;
|
||||||
|
import android.platform.test.flag.junit.CheckFlagsRule;
|
||||||
|
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
|
||||||
import android.util.IconDrawableFactory;
|
import android.util.IconDrawableFactory;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.ScrollView;
|
import android.widget.ScrollView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.core.graphics.drawable.IconCompat;
|
import androidx.core.graphics.drawable.IconCompat;
|
||||||
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentActivity;
|
import androidx.fragment.app.FragmentActivity;
|
||||||
|
|
||||||
import com.android.internal.widget.LockPatternUtils;
|
import com.android.internal.widget.LockPatternUtils;
|
||||||
|
import com.android.settings.password.ConfirmDeviceCredentialActivity;
|
||||||
import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
|
import com.android.settings.testutils.shadow.ShadowLockPatternUtils;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.mockito.ArgumentCaptor;
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
import org.robolectric.Robolectric;
|
import org.robolectric.Robolectric;
|
||||||
@@ -92,6 +107,9 @@ import java.util.List;
|
|||||||
@Config(shadows = ShadowLockPatternUtils.class)
|
@Config(shadows = ShadowLockPatternUtils.class)
|
||||||
public class UtilsTest {
|
public class UtilsTest {
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
|
||||||
|
|
||||||
private static final String PACKAGE_NAME = "com.android.app";
|
private static final String PACKAGE_NAME = "com.android.app";
|
||||||
private static final int USER_ID = 1;
|
private static final int USER_ID = 1;
|
||||||
|
|
||||||
@@ -113,6 +131,11 @@ public class UtilsTest {
|
|||||||
private IconDrawableFactory mIconDrawableFactory;
|
private IconDrawableFactory mIconDrawableFactory;
|
||||||
@Mock
|
@Mock
|
||||||
private ApplicationInfo mApplicationInfo;
|
private ApplicationInfo mApplicationInfo;
|
||||||
|
@Mock
|
||||||
|
private BiometricManager mBiometricManager;
|
||||||
|
@Mock
|
||||||
|
private Fragment mFragment;
|
||||||
|
|
||||||
private Context mContext;
|
private Context mContext;
|
||||||
private UserManager mUserManager;
|
private UserManager mUserManager;
|
||||||
private static final int FLAG_SYSTEM = 0x00000000;
|
private static final int FLAG_SYSTEM = 0x00000000;
|
||||||
@@ -128,6 +151,7 @@ public class UtilsTest {
|
|||||||
when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
|
when(mContext.getSystemService(Context.CONNECTIVITY_SERVICE))
|
||||||
.thenReturn(connectivityManager);
|
.thenReturn(connectivityManager);
|
||||||
when(mContext.getPackageManager()).thenReturn(mPackageManager);
|
when(mContext.getPackageManager()).thenReturn(mPackageManager);
|
||||||
|
when(mContext.getSystemService(BiometricManager.class)).thenReturn(mBiometricManager);
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@After
|
||||||
@@ -503,6 +527,62 @@ public class UtilsTest {
|
|||||||
assertThat(Utils.isFaceNotConvenienceBiometric(mContext)).isFalse();
|
assertThat(Utils.isFaceNotConvenienceBiometric(mContext)).isFalse();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
|
||||||
|
public void testRequestBiometricAuthentication_biometricManagerNull_shouldReturnFalse() {
|
||||||
|
when(mContext.getSystemService(Context.BIOMETRIC_SERVICE)).thenReturn(null);
|
||||||
|
assertThat(Utils.requestBiometricAuthenticationForMandatoryBiometrics(mContext,
|
||||||
|
false /* biometricsSuccessfullyAuthenticated */,
|
||||||
|
false /* biometricsAuthenticationRequested */)).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
|
||||||
|
public void testRequestBiometricAuthentication_biometricManagerReturnsSuccess_shouldReturnTrue()
|
||||||
|
throws InterruptedException {
|
||||||
|
when(mBiometricManager.canAuthenticate(
|
||||||
|
BiometricManager.Authenticators.MANDATORY_BIOMETRICS))
|
||||||
|
.thenReturn(BiometricManager.BIOMETRIC_SUCCESS);
|
||||||
|
boolean requestBiometricAuthenticationForMandatoryBiometrics =
|
||||||
|
Utils.requestBiometricAuthenticationForMandatoryBiometrics(mContext,
|
||||||
|
true /* biometricsSuccessfullyAuthenticated */,
|
||||||
|
false /* biometricsAuthenticationRequested */);
|
||||||
|
assertThat(requestBiometricAuthenticationForMandatoryBiometrics).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
|
||||||
|
public void testRequestBiometricAuthentication_biometricManagerReturnsError_shouldReturnFalse() {
|
||||||
|
when(mBiometricManager.canAuthenticate(
|
||||||
|
BiometricManager.Authenticators.MANDATORY_BIOMETRICS))
|
||||||
|
.thenReturn(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE);
|
||||||
|
assertThat(Utils.requestBiometricAuthenticationForMandatoryBiometrics(mContext,
|
||||||
|
false /* biometricsSuccessfullyAuthenticated */,
|
||||||
|
false /* biometricsAuthenticationRequested */)).isFalse();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
|
||||||
|
public void testLaunchBiometricPrompt_checkIntentValues() {
|
||||||
|
when(mFragment.getContext()).thenReturn(mContext);
|
||||||
|
|
||||||
|
final int requestCode = 1;
|
||||||
|
final ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
|
||||||
|
Utils.launchBiometricPromptForMandatoryBiometrics(mFragment, requestCode);
|
||||||
|
|
||||||
|
verify(mFragment).startActivityForResult(intentArgumentCaptor.capture(), eq(requestCode));
|
||||||
|
|
||||||
|
final Intent intent = intentArgumentCaptor.getValue();
|
||||||
|
|
||||||
|
assertThat(intent.getExtra(BIOMETRIC_PROMPT_AUTHENTICATORS)).isEqualTo(
|
||||||
|
BiometricManager.Authenticators.MANDATORY_BIOMETRICS);
|
||||||
|
assertThat(intent.getExtra(BIOMETRIC_PROMPT_NEGATIVE_BUTTON_TEXT)).isNotNull();
|
||||||
|
assertThat(intent.getExtra(KeyguardManager.EXTRA_DESCRIPTION)).isNotNull();
|
||||||
|
assertThat(intent.getComponent().getPackageName()).isEqualTo(SETTINGS_PACKAGE_NAME);
|
||||||
|
assertThat(intent.getComponent().getClassName()).isEqualTo(
|
||||||
|
ConfirmDeviceCredentialActivity.class.getName());
|
||||||
|
}
|
||||||
|
|
||||||
private void setUpForConfirmCredentialString(boolean isEffectiveUserManagedProfile) {
|
private void setUpForConfirmCredentialString(boolean isEffectiveUserManagedProfile) {
|
||||||
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mMockUserManager);
|
when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mMockUserManager);
|
||||||
when(mMockUserManager.getCredentialOwnerProfile(USER_ID)).thenReturn(USER_ID);
|
when(mMockUserManager.getCredentialOwnerProfile(USER_ID)).thenReturn(USER_ID);
|
||||||
|
Reference in New Issue
Block a user