(1/N) Biometric error dialog
Add an error dialog to help user recover from biometric error for identity check feature Flags: android.hardware.biometrics.flag.mandatory_biometrics Fixes: 358641110 Fixes: 358179610 Test: atest DevelopmentSettingsDashboardFragmentTest Change-Id: I6099bc57672b945fa4fa4de98be35bd097403b22
This commit is contained in:
54
res/layout/biometric_lockout_error_dialog.xml
Normal file
54
res/layout/biometric_lockout_error_dialog.xml
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
~ Copyright (C) 2024 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.
|
||||||
|
-->
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:paddingLeft="24dp"
|
||||||
|
android:paddingRight="24dp">
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:src="@drawable/ic_settings_safety_center"
|
||||||
|
android:paddingTop="24dp"/>
|
||||||
|
<TextView
|
||||||
|
android:id="@id/title"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_horizontal"
|
||||||
|
android:textColor="?android:attr/textColorPrimary"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceLarge"
|
||||||
|
android:paddingTop="16dp"/>
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/description_1"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
android:paddingTop="16dp"
|
||||||
|
android:lineSpacingMultiplier="1.2"/>
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/description_2"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
|
android:textColor="?android:attr/textColorSecondary"
|
||||||
|
android:lineSpacingMultiplier="1.2"
|
||||||
|
android:paddingTop="16dp"/>
|
||||||
|
</LinearLayout>
|
@@ -938,6 +938,28 @@
|
|||||||
<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-->
|
<!-- Description for mandatory biometrics prompt-->
|
||||||
<string name="mandatory_biometrics_prompt_description">Identity Check is on and requires a biometric</string>
|
<string name="mandatory_biometrics_prompt_description">Identity Check is on and requires a biometric</string>
|
||||||
|
<!-- Text for link to identity check settings [CHAR LIMIT=100] -->
|
||||||
|
<string name="go_to_settings">Go to Settings</string>
|
||||||
|
<!-- Dialog title when identity check auth is requested but biometrics is in lockout state [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="identity_check_lockout_error_title">Identity Check is on and can’t verify it’s you</string>
|
||||||
|
<!-- Dialog title when identity check auth is requested but biometric hardware has an error. [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="identity_check_lockout_error_description_1">Biometrics failed too many times. Lock and unlock your device to retry.</string>
|
||||||
|
<!-- Dialog message when identity check auth is requested but biometrics is in lockout state. "Go to Settings" launches theft protection settings, in case user wishes to disable the feature. [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="identity_check_lockout_error_description_2">You can manage Identity Check in theft protection settings. Go to Settings</string>
|
||||||
|
<!-- Dialog title when identity check auth is requested but biometric hardware has an error. [CHAR LIMIT=100] -->
|
||||||
|
<string name="identity_check_general_error_title">Biometric required to continue</string>
|
||||||
|
<!-- Dialog message when identity check auth is requested but biometric hardware has an error. [CHAR LIMIT=NONE] -->
|
||||||
|
<string name="identity_check_general_error_description_1">Identity Check is on and requires a biometric, but your face or fingerprint sensor is unavailable\n<ul><li>Check that your camera is on and try again</li>\n<li>You can turn off Identity Check using your Google Account</li></ul></string>
|
||||||
|
<!-- Biometric error dialog button text for user to dismiss the dialog. [CHAR LIMIT=20] -->
|
||||||
|
<string name="identity_check_biometric_error_cancel">Cancel</string>
|
||||||
|
<!-- Biometric error dialog button text for user to acknowledge the message. [CHAR LIMIT=20] -->
|
||||||
|
<string name="identity_check_biometric_error_ok">OK</string>
|
||||||
|
<!-- Biometric error dialog button text to launch identity check settings. [CHAR LIMIT=80] -->
|
||||||
|
<string name="go_to_identity_check">Go to identity check</string>
|
||||||
|
<!-- Biometric error dialog button text to lock screen and recover biometric lockout state. [CHAR LIMIT=60] -->
|
||||||
|
<string name="identity_check_lockout_error_lock_screen">Lock screen</string>
|
||||||
|
<!-- Action for opening identity check settings page [CHAR LIMIT=NONE] [DO NOT TRANSLATE] -->
|
||||||
|
<string name="identity_check_settings_action"></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>
|
||||||
|
209
src/com/android/settings/development/BiometricErrorDialog.java
Normal file
209
src/com/android/settings/development/BiometricErrorDialog.java
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2024 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 com.android.settings.development;
|
||||||
|
|
||||||
|
import android.annotation.NonNull;
|
||||||
|
import android.annotation.Nullable;
|
||||||
|
import android.app.AlertDialog;
|
||||||
|
import android.app.Dialog;
|
||||||
|
import android.app.admin.DevicePolicyManager;
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.content.IntentFilter;
|
||||||
|
import android.content.pm.ResolveInfo;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.provider.Settings;
|
||||||
|
import android.text.SpannableString;
|
||||||
|
import android.text.Spanned;
|
||||||
|
import android.text.TextPaint;
|
||||||
|
import android.text.method.LinkMovementMethod;
|
||||||
|
import android.text.style.ClickableSpan;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import androidx.fragment.app.FragmentActivity;
|
||||||
|
|
||||||
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.Utils;
|
||||||
|
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
|
||||||
|
|
||||||
|
/** Initializes and shows biometric error dialogs related to identity check. */
|
||||||
|
public class BiometricErrorDialog extends InstrumentedDialogFragment {
|
||||||
|
private static final String TAG = "BiometricErrorDialog";
|
||||||
|
|
||||||
|
private static final String KEY_ERROR_CODE = "key_error_code";
|
||||||
|
private String mActionIdentityCheckSettings = Settings.ACTION_SETTINGS;
|
||||||
|
@Nullable private BroadcastReceiver mBroadcastReceiver;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
@Override
|
||||||
|
public Dialog onCreateDialog(
|
||||||
|
@Nullable Bundle savedInstanceState) {
|
||||||
|
final AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(getActivity());
|
||||||
|
final LayoutInflater inflater = getActivity().getLayoutInflater();
|
||||||
|
final boolean isLockoutError = getArguments().getString(KEY_ERROR_CODE).equals(
|
||||||
|
Utils.BiometricStatus.LOCKOUT.name());
|
||||||
|
final View customView = inflater.inflate(R.layout.biometric_lockout_error_dialog,
|
||||||
|
null);
|
||||||
|
final String identityCheckSettingsAction = getActivity().getString(
|
||||||
|
R.string.identity_check_settings_action);
|
||||||
|
mActionIdentityCheckSettings = identityCheckSettingsAction.isEmpty()
|
||||||
|
? mActionIdentityCheckSettings : identityCheckSettingsAction;
|
||||||
|
Log.d(TAG, mActionIdentityCheckSettings);
|
||||||
|
setTitle(customView, isLockoutError);
|
||||||
|
setBody(customView, isLockoutError);
|
||||||
|
alertDialogBuilder.setView(customView);
|
||||||
|
setPositiveButton(alertDialogBuilder, isLockoutError);
|
||||||
|
setNegativeButton(alertDialogBuilder, isLockoutError);
|
||||||
|
|
||||||
|
if (isLockoutError) {
|
||||||
|
mBroadcastReceiver = new BroadcastReceiver() {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
|
||||||
|
dismiss();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
getContext().registerReceiver(mBroadcastReceiver,
|
||||||
|
new IntentFilter(Intent.ACTION_SCREEN_OFF));
|
||||||
|
}
|
||||||
|
|
||||||
|
return alertDialogBuilder.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void dismiss() {
|
||||||
|
super.dismiss();
|
||||||
|
if (mBroadcastReceiver != null) {
|
||||||
|
getContext().unregisterReceiver(mBroadcastReceiver);
|
||||||
|
mBroadcastReceiver = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows an error dialog to prompt the user to resolve biometric errors for identity check.
|
||||||
|
* @param fragmentActivity calling activity
|
||||||
|
* @param errorCode refers to the biometric error
|
||||||
|
*/
|
||||||
|
public static BiometricErrorDialog showBiometricErrorDialog(FragmentActivity fragmentActivity,
|
||||||
|
Utils.BiometricStatus errorCode) {
|
||||||
|
final BiometricErrorDialog biometricErrorDialog = new BiometricErrorDialog();
|
||||||
|
final Bundle args = new Bundle();
|
||||||
|
args.putCharSequence(KEY_ERROR_CODE, errorCode.name());
|
||||||
|
biometricErrorDialog.setArguments(args);
|
||||||
|
biometricErrorDialog.show(fragmentActivity.getSupportFragmentManager(),
|
||||||
|
BiometricErrorDialog.class.getName());
|
||||||
|
return biometricErrorDialog;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setTitle(View view, boolean lockout) {
|
||||||
|
final TextView titleTextView = view.findViewById(R.id.title);
|
||||||
|
if (lockout) {
|
||||||
|
titleTextView.setText(R.string.identity_check_lockout_error_title);
|
||||||
|
} else {
|
||||||
|
titleTextView.setText(R.string.identity_check_general_error_title);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setBody(View view, boolean lockout) {
|
||||||
|
final TextView textView1 = view.findViewById(R.id.description_1);
|
||||||
|
final TextView textView2 = view.findViewById(R.id.description_2);
|
||||||
|
|
||||||
|
if (lockout) {
|
||||||
|
textView1.setText(R.string.identity_check_lockout_error_description_1);
|
||||||
|
textView2.setText(getClickableDescriptionForLockoutError());
|
||||||
|
textView2.setMovementMethod(LinkMovementMethod.getInstance());
|
||||||
|
} else {
|
||||||
|
textView1.setText(R.string.identity_check_general_error_description_1);
|
||||||
|
textView2.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private SpannableString getClickableDescriptionForLockoutError() {
|
||||||
|
final String description = getResources().getString(
|
||||||
|
R.string.identity_check_lockout_error_description_2);
|
||||||
|
final SpannableString spannableString = new SpannableString(description);
|
||||||
|
final ClickableSpan clickableSpan = new ClickableSpan() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View textView) {
|
||||||
|
dismiss();
|
||||||
|
final Intent autoLockSettingsIntent = new Intent(mActionIdentityCheckSettings);
|
||||||
|
final ResolveInfo autoLockSettingsInfo = getActivity().getPackageManager()
|
||||||
|
.resolveActivity(autoLockSettingsIntent, 0 /* flags */);
|
||||||
|
if (autoLockSettingsInfo != null) {
|
||||||
|
startActivity(autoLockSettingsIntent);
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Auto lock settings intent could not be resolved.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public void updateDrawState(TextPaint ds) {
|
||||||
|
super.updateDrawState(ds);
|
||||||
|
ds.setUnderlineText(true);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
final String goToSettings = getActivity().getString(R.string.go_to_settings);
|
||||||
|
spannableString.setSpan(clickableSpan, description.indexOf(goToSettings),
|
||||||
|
description.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
|
||||||
|
|
||||||
|
return spannableString;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setPositiveButton(AlertDialog.Builder alertDialogBuilder, boolean lockout) {
|
||||||
|
if (lockout) {
|
||||||
|
DevicePolicyManager devicePolicyManager = (DevicePolicyManager)
|
||||||
|
getContext().getSystemService(Context.DEVICE_POLICY_SERVICE);
|
||||||
|
alertDialogBuilder.setPositiveButton(R.string.identity_check_lockout_error_lock_screen,
|
||||||
|
(dialog, which) -> {
|
||||||
|
dialog.dismiss();
|
||||||
|
devicePolicyManager.lockNow();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
alertDialogBuilder.setPositiveButton(R.string.identity_check_biometric_error_ok,
|
||||||
|
(dialog, which) -> dialog.dismiss());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setNegativeButton(AlertDialog.Builder alertDialogBuilder, boolean lockout) {
|
||||||
|
if (lockout) {
|
||||||
|
alertDialogBuilder.setNegativeButton(R.string.identity_check_biometric_error_cancel,
|
||||||
|
(dialog, which) -> dialog.dismiss());
|
||||||
|
} else {
|
||||||
|
alertDialogBuilder.setNegativeButton(R.string.go_to_identity_check,
|
||||||
|
(dialog, which) -> {
|
||||||
|
final Intent autoLockSettingsIntent = new Intent(
|
||||||
|
mActionIdentityCheckSettings);
|
||||||
|
final ResolveInfo autoLockSettingsInfo = getActivity().getPackageManager()
|
||||||
|
.resolveActivity(autoLockSettingsIntent, 0 /* flags */);
|
||||||
|
if (autoLockSettingsInfo != null) {
|
||||||
|
startActivity(autoLockSettingsIntent);
|
||||||
|
} else {
|
||||||
|
Log.e(TAG, "Identity check settings intent could not be resolved.");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getMetricsCategory() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
@@ -76,6 +76,7 @@ import com.android.settings.development.graphicsdriver.GraphicsDriverEnableAngle
|
|||||||
import com.android.settings.development.qstile.DevelopmentTiles;
|
import com.android.settings.development.qstile.DevelopmentTiles;
|
||||||
import com.android.settings.development.storage.SharedDataPreferenceController;
|
import com.android.settings.development.storage.SharedDataPreferenceController;
|
||||||
import com.android.settings.overlay.FeatureFactory;
|
import com.android.settings.overlay.FeatureFactory;
|
||||||
|
import com.android.settings.password.ConfirmDeviceCredentialActivity;
|
||||||
import com.android.settings.search.BaseSearchIndexProvider;
|
import com.android.settings.search.BaseSearchIndexProvider;
|
||||||
import com.android.settings.search.actionbar.SearchMenuController;
|
import com.android.settings.search.actionbar.SearchMenuController;
|
||||||
import com.android.settings.widget.SettingsMainSwitchBar;
|
import com.android.settings.widget.SettingsMainSwitchBar;
|
||||||
@@ -377,6 +378,8 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
|
|||||||
userId, false /* hideBackground */);
|
userId, false /* hideBackground */);
|
||||||
} else if (biometricAuthStatus != Utils.BiometricStatus.NOT_ACTIVE) {
|
} else if (biometricAuthStatus != Utils.BiometricStatus.NOT_ACTIVE) {
|
||||||
mSwitchBar.setChecked(false);
|
mSwitchBar.setChecked(false);
|
||||||
|
BiometricErrorDialog.showBiometricErrorDialog(
|
||||||
|
getActivity(), biometricAuthStatus);
|
||||||
} else {
|
} else {
|
||||||
//Reset biometrics once enable dialog is shown
|
//Reset biometrics once enable dialog is shown
|
||||||
mIsBiometricsAuthenticated = false;
|
mIsBiometricsAuthenticated = false;
|
||||||
@@ -559,6 +562,10 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
|
|||||||
if (resultCode == RESULT_OK) {
|
if (resultCode == RESULT_OK) {
|
||||||
mIsBiometricsAuthenticated = true;
|
mIsBiometricsAuthenticated = true;
|
||||||
mSwitchBar.setChecked(true);
|
mSwitchBar.setChecked(true);
|
||||||
|
} else if (resultCode
|
||||||
|
== ConfirmDeviceCredentialActivity.BIOMETRIC_LOCKOUT_ERROR_RESULT) {
|
||||||
|
BiometricErrorDialog.showBiometricErrorDialog(getActivity(),
|
||||||
|
Utils.BiometricStatus.LOCKOUT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (AbstractPreferenceController controller : mPreferenceControllers) {
|
for (AbstractPreferenceController controller : mPreferenceControllers) {
|
||||||
|
@@ -43,6 +43,7 @@ import android.hardware.biometrics.BiometricConstants;
|
|||||||
import android.hardware.biometrics.BiometricManager;
|
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.Flags;
|
||||||
import android.hardware.biometrics.PromptInfo;
|
import android.hardware.biometrics.PromptInfo;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
@@ -82,6 +83,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
|
|||||||
"biometric_prompt_negative_button_text";
|
"biometric_prompt_negative_button_text";
|
||||||
public static final String BIOMETRIC_PROMPT_HIDE_BACKGROUND =
|
public static final String BIOMETRIC_PROMPT_HIDE_BACKGROUND =
|
||||||
"biometric_prompt_hide_background";
|
"biometric_prompt_hide_background";
|
||||||
|
public static final int BIOMETRIC_LOCKOUT_ERROR_RESULT = 100;
|
||||||
|
|
||||||
public static class InternalActivity extends ConfirmDeviceCredentialActivity {
|
public static class InternalActivity extends ConfirmDeviceCredentialActivity {
|
||||||
}
|
}
|
||||||
@@ -129,6 +131,10 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
|
|||||||
showConfirmCredentials();
|
showConfirmCredentials();
|
||||||
} else {
|
} else {
|
||||||
Log.i(TAG, "Finishing, device credential not requested");
|
Log.i(TAG, "Finishing, device credential not requested");
|
||||||
|
if (Flags.mandatoryBiometrics()
|
||||||
|
&& errorCode == BiometricPrompt.BIOMETRIC_ERROR_LOCKOUT_PERMANENT) {
|
||||||
|
setResult(BIOMETRIC_LOCKOUT_ERROR_RESULT);
|
||||||
|
}
|
||||||
finish();
|
finish();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -41,6 +41,8 @@ import androidx.fragment.app.FragmentActivity;
|
|||||||
|
|
||||||
import com.android.internal.logging.nano.MetricsProto;
|
import com.android.internal.logging.nano.MetricsProto;
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
|
import com.android.settings.Utils;
|
||||||
|
import com.android.settings.password.ConfirmDeviceCredentialActivity;
|
||||||
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
|
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
|
||||||
import com.android.settings.testutils.shadow.ShadowUserManager;
|
import com.android.settings.testutils.shadow.ShadowUserManager;
|
||||||
import com.android.settings.widget.SettingsMainSwitchBar;
|
import com.android.settings.widget.SettingsMainSwitchBar;
|
||||||
@@ -233,6 +235,21 @@ public class DevelopmentSettingsDashboardFragmentTest {
|
|||||||
assertThat(ShadowEnableDevelopmentSettingWarningDialog.mShown).isTrue();
|
assertThat(ShadowEnableDevelopmentSettingWarningDialog.mShown).isTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Config(shadows = ShadowBiometricErrorDialog.class)
|
||||||
|
@EnableFlags(Flags.FLAG_MANDATORY_BIOMETRICS)
|
||||||
|
public void onActivityResult_requestBiometricPrompt_showErrorDialog() {
|
||||||
|
when(mDashboard.getContext()).thenReturn(mContext);
|
||||||
|
|
||||||
|
Settings.Global.putInt(mContext.getContentResolver(),
|
||||||
|
Settings.Global.DEVELOPMENT_SETTINGS_ENABLED, 0);
|
||||||
|
mDashboard.onActivityResult(DevelopmentSettingsDashboardFragment.REQUEST_BIOMETRIC_PROMPT,
|
||||||
|
ConfirmDeviceCredentialActivity.BIOMETRIC_LOCKOUT_ERROR_RESULT, null);
|
||||||
|
|
||||||
|
assertThat(mSwitchBar.isChecked()).isFalse();
|
||||||
|
assertThat(ShadowBiometricErrorDialog.sShown).isTrue();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore
|
@Ignore
|
||||||
@Config(shadows = ShadowEnableDevelopmentSettingWarningDialog.class)
|
@Config(shadows = ShadowEnableDevelopmentSettingWarningDialog.class)
|
||||||
@@ -362,6 +379,16 @@ public class DevelopmentSettingsDashboardFragmentTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Implements(BiometricErrorDialog.class)
|
||||||
|
public static class ShadowBiometricErrorDialog {
|
||||||
|
static boolean sShown;
|
||||||
|
@Implementation
|
||||||
|
public static void showBiometricErrorDialog(FragmentActivity fragmentActivity,
|
||||||
|
Utils.BiometricStatus errorCode) {
|
||||||
|
sShown = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Implements(DisableDevSettingsDialogFragment.class)
|
@Implements(DisableDevSettingsDialogFragment.class)
|
||||||
public static class ShadowDisableDevSettingsDialogFragment {
|
public static class ShadowDisableDevSettingsDialogFragment {
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user