diff --git a/aconfig/Android.bp b/aconfig/Android.bp
index c1afd6a2476..8be93f04c56 100644
--- a/aconfig/Android.bp
+++ b/aconfig/Android.bp
@@ -9,6 +9,7 @@ aconfig_declarations {
container: "system",
srcs: [
"*.aconfig",
+ "catalyst/*.aconfig",
],
}
@@ -77,4 +78,4 @@ aconfig_declarations {
java_aconfig_library {
name: "keyboard_flags_lib",
aconfig_declarations: "keyboard_flags",
-}
\ No newline at end of file
+}
diff --git a/aconfig/catalyst/about_phone.aconfig b/aconfig/catalyst/about_phone.aconfig
new file mode 100644
index 00000000000..086304193c2
--- /dev/null
+++ b/aconfig/catalyst/about_phone.aconfig
@@ -0,0 +1,9 @@
+package: "com.android.settings.flags"
+container: "system"
+
+flag {
+ name: "catalyst_legal_information"
+ namespace: "android_settings"
+ description: "Flag for Legal information"
+ bug: "323791114"
+}
diff --git a/aconfig/settings_flag_declarations.aconfig b/aconfig/settings_flag_declarations.aconfig
index b8cb4d9bcdf..a9c7bd59f23 100644
--- a/aconfig/settings_flag_declarations.aconfig
+++ b/aconfig/settings_flag_declarations.aconfig
@@ -50,16 +50,16 @@ flag {
bug: "351884562"
}
-flag {
- name: "catalyst_legal_information"
- namespace: "android_settings"
- description: "This flag controls the About phone > Legal information page migration"
- bug: "323791114"
-}
-
flag {
name: "updated_suggestion_card_aosp"
namespace: "android_settings"
description: "Use updated suggestion card(s) in AOSP Settings"
bug: "323258154"
}
+
+flag {
+ name: "catalyst"
+ namespace: "android_settings"
+ description: "Flag for all screens"
+ bug: "323791114"
+}
diff --git a/color-check-baseline.xml b/color-check-baseline.xml
index 4c47607fe16..75d4aba8304 100644
--- a/color-check-baseline.xml
+++ b/color-check-baseline.xml
@@ -6973,4 +6973,103 @@
column="5"/>
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/biometric_lockout_error_dialog.xml b/res/layout/biometric_lockout_error_dialog.xml
new file mode 100644
index 00000000000..8d4275b6aaa
--- /dev/null
+++ b/res/layout/biometric_lockout_error_dialog.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/modes_set_schedule_layout.xml b/res/layout/modes_set_schedule_layout.xml
index d53e2e42a91..e90dc7c5420 100644
--- a/res/layout/modes_set_schedule_layout.xml
+++ b/res/layout/modes_set_schedule_layout.xml
@@ -73,18 +73,17 @@
android:orientation="vertical"
app:layout_constraintGuide_percent="0.5" />
-
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f05fdd12b67..cd847f7400e 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -938,6 +938,30 @@
Face, fingerprints, and %s added
Identity Check is on and requires a biometric
+
+ Go to Settings
+
+ Identity Check is on and can’t verify it’s you
+
+ Biometrics failed too many times. Lock and unlock your device to retry.
+
+ Biometrics failed too many times. Try again.
+
+ You can manage Identity Check in theft protection settings. Go to Settings
+
+ Biometric required to continue
+
+ Identity Check is on and requires a biometric, but your face or fingerprint sensor is unavailable\n- Check that your camera is on and try again
\n- You can turn off Identity Check using your Google Account
+
+ Cancel
+
+ OK
+
+ Go to identity check
+
+ Lock screen
+
+
Remote Authenticator Unlock
@@ -1739,10 +1763,13 @@
Device admin doesn\'t allow using a recent
password
-
+
Ascending, descending, or repeated sequence
of digits isn\'t allowed
+
+ Ascending, descending, or repeated sequence of characters isn\'t allowed
+
Confirm
@@ -12102,7 +12129,7 @@
Send and receive text messages by satellite. Included with your account.
- Send and receive text messages by satellite. Non included with your account.
+ Send and receive text messages by satellite. Not included with your account.
Satellite messaging
diff --git a/src/com/android/settings/MainClear.java b/src/com/android/settings/MainClear.java
index 711d7943ffa..1800a38fd5b 100644
--- a/src/com/android/settings/MainClear.java
+++ b/src/com/android/settings/MainClear.java
@@ -65,11 +65,13 @@ import android.widget.TextView;
import androidx.annotation.VisibleForTesting;
+import com.android.settings.biometrics.IdentityCheckBiometricErrorDialog;
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
import com.android.settings.flags.Flags;
import com.android.settings.network.SubscriptionUtil;
import com.android.settings.password.ChooseLockSettingsHelper;
+import com.android.settings.password.ConfirmDeviceCredentialActivity;
import com.android.settings.password.ConfirmLockPattern;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
@@ -178,6 +180,12 @@ public class MainClear extends InstrumentedFragment implements OnGlobalLayoutLis
if (resultCode != Activity.RESULT_OK) {
establishInitialState();
+ if (requestCode == BIOMETRICS_REQUEST) {
+ if (resultCode == ConfirmDeviceCredentialActivity.BIOMETRIC_LOCKOUT_ERROR_RESULT) {
+ IdentityCheckBiometricErrorDialog.showBiometricErrorDialog(getActivity(),
+ Utils.BiometricStatus.LOCKOUT, true /* twoFactorAuthentication */);
+ }
+ }
return;
}
@@ -192,6 +200,8 @@ public class MainClear extends InstrumentedFragment implements OnGlobalLayoutLis
userId, false /* hideBackground */);
return;
} else if (biometricAuthStatus != Utils.BiometricStatus.NOT_ACTIVE) {
+ IdentityCheckBiometricErrorDialog.showBiometricErrorDialog(getActivity(),
+ biometricAuthStatus, true /* twoFactorAuthentication */);
return;
}
}
diff --git a/src/com/android/settings/ResetNetwork.java b/src/com/android/settings/ResetNetwork.java
index ad9f35e889b..f86e29f14d1 100644
--- a/src/com/android/settings/ResetNetwork.java
+++ b/src/com/android/settings/ResetNetwork.java
@@ -18,8 +18,11 @@ package com.android.settings;
import android.app.Activity;
import android.app.settings.SettingsEnums;
+import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.content.res.Resources;
import android.os.Bundle;
import android.provider.Settings;
@@ -66,7 +69,7 @@ import java.util.Optional;
* prompt, followed by a keyguard pattern trace if the user has defined one, followed by a final
* strongly-worded "THIS WILL RESET EVERYTHING" prompt. If at any time the phone is allowed to go
* to sleep, is locked, et cetera, then the confirmation sequence is abandoned.
- *
+ *
* This is the initial screen.
*/
public class ResetNetwork extends InstrumentedFragment {
@@ -81,8 +84,20 @@ public class ResetNetwork extends InstrumentedFragment {
private View mContentView;
private Spinner mSubscriptionSpinner;
private Button mInitiateButton;
- @VisibleForTesting View mEsimContainer;
- @VisibleForTesting CheckBox mEsimCheckbox;
+ @VisibleForTesting
+ View mEsimContainer;
+ @VisibleForTesting
+ CheckBox mEsimCheckbox;
+
+ private BroadcastReceiver mDefaultSubChangeReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ if (intent.getAction() != SubscriptionManager.ACTION_DEFAULT_SUBSCRIPTION_CHANGED) {
+ return;
+ }
+ establishInitialState(getActiveSubscriptionInfoList());
+ }
+ };
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
@@ -97,6 +112,7 @@ public class ResetNetwork extends InstrumentedFragment {
/**
* Keyguard validation is run using the standard {@link ConfirmLockPattern}
* component as a subactivity
+ *
* @param request the request code to be returned once confirmation finishes
* @return true if confirmation launched
*/
@@ -139,7 +155,7 @@ public class ResetNetwork extends InstrumentedFragment {
SubscriptionInfo subscription = mSubscriptions.get(selectedIndex);
int subId = subscription.getSubscriptionId();
request.setResetTelephonyAndNetworkPolicyManager(subId)
- .setResetApn(subId);
+ .setResetApn(subId);
if (Flags.resetMobileNetworkSettings()) {
request.setResetImsSubId(subId);
}
@@ -215,7 +231,6 @@ public class ResetNetwork extends InstrumentedFragment {
}
int selectedIndex = 0;
- int size = mSubscriptions.size();
List subscriptionNames = new ArrayList<>();
for (SubscriptionInfo record : mSubscriptions) {
if (record.getSubscriptionId() == defaultSubscription) {
@@ -281,6 +296,8 @@ public class ResetNetwork extends InstrumentedFragment {
@Override
public void onResume() {
super.onResume();
+ getContext().registerReceiver(mDefaultSubChangeReceiver,
+ new IntentFilter(SubscriptionManager.ACTION_DEFAULT_SUBSCRIPTION_CHANGED));
if (mContentView == null) {
return;
@@ -297,6 +314,12 @@ public class ResetNetwork extends InstrumentedFragment {
establishInitialState(updatedSubscriptions);
}
+ @Override
+ public void onPause() {
+ super.onPause();
+ getContext().unregisterReceiver(mDefaultSubChangeReceiver);
+ }
+
private boolean showEuiccSettings(Context context) {
if (!SubscriptionUtil.isSimHardwareVisible(context)) {
return false;
diff --git a/src/com/android/settings/SettingsApplication.java b/src/com/android/settings/SettingsApplication.java
index 7e008e43667..b1177dd2d87 100644
--- a/src/com/android/settings/SettingsApplication.java
+++ b/src/com/android/settings/SettingsApplication.java
@@ -16,8 +16,6 @@
package com.android.settings;
-import static com.android.settingslib.flags.Flags.settingsCatalyst;
-
import android.app.Application;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -73,7 +71,7 @@ public class SettingsApplication extends Application {
public void onCreate() {
super.onCreate();
- if (settingsCatalyst()) {
+ if (Flags.catalyst()) {
PreferenceScreenRegistry.INSTANCE.setPreferenceScreensSupplier(
this::getPreferenceScreens);
}
diff --git a/src/com/android/settings/Utils.java b/src/com/android/settings/Utils.java
index 62a4ce36753..57a5380e87d 100644
--- a/src/com/android/settings/Utils.java
+++ b/src/com/android/settings/Utils.java
@@ -1522,6 +1522,7 @@ public final class Utils extends com.android.settingslib.Utils {
case BiometricManager.BIOMETRIC_ERROR_LOCKOUT:
return BiometricStatus.LOCKOUT;
case BiometricManager.BIOMETRIC_ERROR_MANDATORY_NOT_ACTIVE:
+ case BiometricManager.BIOMETRIC_ERROR_NOT_ENABLED_FOR_APPS:
return BiometricStatus.NOT_ACTIVE;
default:
return BiometricStatus.ERROR;
diff --git a/src/com/android/settings/biometrics/BiometricEnrollActivity.java b/src/com/android/settings/biometrics/BiometricEnrollActivity.java
index dbbe30beaa5..ec215670d0a 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollActivity.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollActivity.java
@@ -58,6 +58,7 @@ import com.android.settings.overlay.FeatureFactory;
import com.android.settings.password.ChooseLockGeneric;
import com.android.settings.password.ChooseLockPattern;
import com.android.settings.password.ChooseLockSettingsHelper;
+import com.android.settings.password.ConfirmDeviceCredentialActivity;
import com.google.android.setupcompat.util.WizardManagerHelper;
import com.google.android.setupdesign.transition.TransitionHelper;
@@ -452,7 +453,9 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
Utils.launchBiometricPromptForMandatoryBiometrics(this,
BIOMETRIC_AUTH_REQUEST, mUserId, true /* hideBackground */);
} else if (biometricStatus != Utils.BiometricStatus.NOT_ACTIVE) {
- finish();
+ IdentityCheckBiometricErrorDialog
+ .showBiometricErrorDialogAndFinishActivityOnDismiss(this,
+ biometricStatus);
}
}
} else {
@@ -486,7 +489,11 @@ public class BiometricEnrollActivity extends InstrumentedActivity {
}
break;
case BIOMETRIC_AUTH_REQUEST:
- if (resultCode != RESULT_OK) {
+ if (resultCode == ConfirmDeviceCredentialActivity.BIOMETRIC_LOCKOUT_ERROR_RESULT) {
+ IdentityCheckBiometricErrorDialog
+ .showBiometricErrorDialogAndFinishActivityOnDismiss(this,
+ Utils.BiometricStatus.LOCKOUT);
+ } else if (resultCode != RESULT_OK) {
finish();
}
default:
diff --git a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
index 6f9b94a7fba..1f7b3e512b2 100644
--- a/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
+++ b/src/com/android/settings/biometrics/BiometricEnrollIntroduction.java
@@ -39,6 +39,7 @@ import com.android.settings.SetupWizardUtils;
import com.android.settings.Utils;
import com.android.settings.password.ChooseLockGeneric;
import com.android.settings.password.ChooseLockSettingsHelper;
+import com.android.settings.password.ConfirmDeviceCredentialActivity;
import com.android.settings.password.SetupSkipDialog;
import com.google.android.setupcompat.template.FooterBarMixin;
@@ -425,7 +426,9 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
Utils.launchBiometricPromptForMandatoryBiometrics(this,
BIOMETRIC_AUTH_REQUEST, mUserId, true /* hideBackground */);
} else if (biometricStatus != Utils.BiometricStatus.NOT_ACTIVE) {
- finish();
+ IdentityCheckBiometricErrorDialog
+ .showBiometricErrorDialogAndFinishActivityOnDismiss(this,
+ biometricStatus);
}
} else {
setResult(resultCode, data);
@@ -457,7 +460,13 @@ public abstract class BiometricEnrollIntroduction extends BiometricEnrollBase
}
} else if (requestCode == BIOMETRIC_AUTH_REQUEST) {
if (resultCode != RESULT_OK) {
- finish();
+ if (resultCode == ConfirmDeviceCredentialActivity.BIOMETRIC_LOCKOUT_ERROR_RESULT) {
+ IdentityCheckBiometricErrorDialog
+ .showBiometricErrorDialogAndFinishActivityOnDismiss(this,
+ Utils.BiometricStatus.LOCKOUT);
+ } else {
+ finish();
+ }
}
}
super.onActivityResult(requestCode, resultCode, data);
diff --git a/src/com/android/settings/biometrics/IdentityCheckBiometricErrorDialog.java b/src/com/android/settings/biometrics/IdentityCheckBiometricErrorDialog.java
new file mode 100644
index 00000000000..a4b10fc2e72
--- /dev/null
+++ b/src/com/android/settings/biometrics/IdentityCheckBiometricErrorDialog.java
@@ -0,0 +1,254 @@
+/*
+ * 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.biometrics;
+
+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 IdentityCheckBiometricErrorDialog extends InstrumentedDialogFragment {
+ private static final String TAG = "BiometricErrorDialog";
+
+ private static final String KEY_ERROR_CODE = "key_error_code";
+ private static final String KEY_TWO_FACTOR_AUTHENTICATION = "key_two_factor_authentication";
+ private static final String KEY_FINISH_ACTIVITY = "key_finish_activity";
+
+ private String mActionIdentityCheckSettings = Settings.ACTION_SETTINGS;
+ @Nullable private BroadcastReceiver mBroadcastReceiver;
+ private boolean mShouldFinishActivity = false;
+
+ @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 boolean twoFactorAuthentication = getArguments().getBoolean(
+ KEY_TWO_FACTOR_AUTHENTICATION);
+ final String identityCheckSettingsAction = getActivity().getString(
+ R.string.identity_check_settings_action);
+ mActionIdentityCheckSettings = identityCheckSettingsAction.isEmpty()
+ ? mActionIdentityCheckSettings : identityCheckSettingsAction;
+ mShouldFinishActivity = getArguments().getBoolean(
+ KEY_FINISH_ACTIVITY);
+
+ setTitle(customView, isLockoutError);
+ setBody(customView, isLockoutError, twoFactorAuthentication);
+ alertDialogBuilder.setView(customView);
+ setPositiveButton(alertDialogBuilder, isLockoutError, twoFactorAuthentication);
+ if (!isLockoutError || !twoFactorAuthentication) {
+ 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 onDestroyView() {
+ super.onDestroyView();
+ if (mBroadcastReceiver != null) {
+ getContext().unregisterReceiver(mBroadcastReceiver);
+ mBroadcastReceiver = null;
+ }
+ if (mShouldFinishActivity && getActivity() != null) {
+ getActivity().finish();
+ }
+ }
+
+ /**
+ * 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
+ * @param twoFactorAuthentication if the surface requests LSKF before identity check auth
+ */
+ public static void showBiometricErrorDialog(FragmentActivity fragmentActivity,
+ Utils.BiometricStatus errorCode, boolean twoFactorAuthentication) {
+ showBiometricErrorDialog(fragmentActivity, errorCode, twoFactorAuthentication,
+ false /* finishActivityOnDismiss */);
+ }
+
+ /**
+ * Shows an error dialog to prompt the user to resolve biometric errors for identity check.
+ * Finishes the activity once the dialog is dismissed.
+ * @param fragmentActivity calling activity
+ * @param errorCode refers to the biometric error
+ */
+ public static void showBiometricErrorDialogAndFinishActivityOnDismiss(
+ FragmentActivity fragmentActivity, Utils.BiometricStatus errorCode) {
+ showBiometricErrorDialog(fragmentActivity, errorCode, true /* twoFactorAuthentication */,
+ true /* finishActivityOnDismiss */);
+ }
+
+ private static void showBiometricErrorDialog(FragmentActivity fragmentActivity,
+ Utils.BiometricStatus errorCode, boolean twoFactorAuthentication,
+ boolean finishActivityOnDismiss) {
+ final IdentityCheckBiometricErrorDialog identityCheckBiometricErrorDialog =
+ new IdentityCheckBiometricErrorDialog();
+ final Bundle args = new Bundle();
+ args.putCharSequence(KEY_ERROR_CODE, errorCode.name());
+ args.putBoolean(KEY_TWO_FACTOR_AUTHENTICATION, twoFactorAuthentication);
+ args.putBoolean(KEY_FINISH_ACTIVITY, finishActivityOnDismiss);
+ identityCheckBiometricErrorDialog.setArguments(args);
+ identityCheckBiometricErrorDialog.show(fragmentActivity.getSupportFragmentManager(),
+ IdentityCheckBiometricErrorDialog.class.getName());
+ }
+ 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, boolean twoFactorAuthentication) {
+ final TextView textView1 = view.findViewById(R.id.description_1);
+ final TextView textView2 = view.findViewById(R.id.description_2);
+
+ if (lockout) {
+ if (twoFactorAuthentication) {
+ textView1.setText(
+ R.string.identity_check_lockout_error_two_factor_auth_description_1);
+ } else {
+ 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,
+ boolean twoFactorAuthentication) {
+ if (lockout) {
+ if (twoFactorAuthentication) {
+ alertDialogBuilder.setPositiveButton((R.string.okay),
+ (dialog, which) -> dialog.dismiss());
+ } else {
+ 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;
+ }
+}
diff --git a/src/com/android/settings/biometrics/combination/BiometricsSettingsBase.java b/src/com/android/settings/biometrics/combination/BiometricsSettingsBase.java
index 43b5da28044..1d8b7a10a3c 100644
--- a/src/com/android/settings/biometrics/combination/BiometricsSettingsBase.java
+++ b/src/com/android/settings/biometrics/combination/BiometricsSettingsBase.java
@@ -46,10 +46,12 @@ import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollBase;
import com.android.settings.biometrics.BiometricStatusPreferenceController;
import com.android.settings.biometrics.BiometricUtils;
+import com.android.settings.biometrics.IdentityCheckBiometricErrorDialog;
import com.android.settings.core.SettingsBaseActivity;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.password.ChooseLockGeneric;
import com.android.settings.password.ChooseLockSettingsHelper;
+import com.android.settings.password.ConfirmDeviceCredentialActivity;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.transition.SettingsTransitionHelper;
@@ -323,7 +325,9 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
BIOMETRIC_AUTH_REQUEST,
mUserId, true /* hideBackground */);
} else if (biometricAuthStatus != Utils.BiometricStatus.NOT_ACTIVE) {
- finish();
+ IdentityCheckBiometricErrorDialog
+ .showBiometricErrorDialogAndFinishActivityOnDismiss(getActivity(),
+ biometricAuthStatus);
return;
}
} else {
@@ -339,7 +343,13 @@ public abstract class BiometricsSettingsBase extends DashboardFragment {
} else if (requestCode == BIOMETRIC_AUTH_REQUEST) {
mBiometricsAuthenticationRequested = false;
if (resultCode != RESULT_OK) {
- finish();
+ if (resultCode == ConfirmDeviceCredentialActivity.BIOMETRIC_LOCKOUT_ERROR_RESULT) {
+ IdentityCheckBiometricErrorDialog
+ .showBiometricErrorDialogAndFinishActivityOnDismiss(getActivity(),
+ Utils.BiometricStatus.LOCKOUT);
+ } else {
+ finish();
+ }
}
}
}
diff --git a/src/com/android/settings/biometrics/face/FaceSettings.java b/src/com/android/settings/biometrics/face/FaceSettings.java
index d42b570b30d..5a3949b8923 100644
--- a/src/com/android/settings/biometrics/face/FaceSettings.java
+++ b/src/com/android/settings/biometrics/face/FaceSettings.java
@@ -45,9 +45,11 @@ import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollBase;
import com.android.settings.biometrics.BiometricUtils;
+import com.android.settings.biometrics.IdentityCheckBiometricErrorDialog;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.password.ChooseLockSettingsHelper;
+import com.android.settings.password.ConfirmDeviceCredentialActivity;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -325,7 +327,9 @@ public class FaceSettings extends DashboardFragment {
BIOMETRIC_AUTH_REQUEST,
mUserId, true /* hideBackground */);
} else if (biometricAuthStatus != Utils.BiometricStatus.NOT_ACTIVE) {
- finish();
+ IdentityCheckBiometricErrorDialog
+ .showBiometricErrorDialogAndFinishActivityOnDismiss(getActivity(),
+ biometricAuthStatus);
}
}
} else if (requestCode == ENROLL_REQUEST) {
@@ -336,7 +340,13 @@ public class FaceSettings extends DashboardFragment {
} else if (requestCode == BIOMETRIC_AUTH_REQUEST) {
mBiometricsAuthenticationRequested = false;
if (resultCode != RESULT_OK) {
- finish();
+ if (resultCode == ConfirmDeviceCredentialActivity.BIOMETRIC_LOCKOUT_ERROR_RESULT) {
+ IdentityCheckBiometricErrorDialog
+ .showBiometricErrorDialogAndFinishActivityOnDismiss(getActivity(),
+ Utils.BiometricStatus.LOCKOUT);
+ } else {
+ finish();
+ }
}
}
}
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
index 20d453f2ea8..adb6700de9b 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
@@ -71,12 +71,14 @@ import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollBase;
import com.android.settings.biometrics.BiometricUtils;
import com.android.settings.biometrics.GatekeeperPasswordProvider;
+import com.android.settings.biometrics.IdentityCheckBiometricErrorDialog;
import com.android.settings.core.SettingsBaseActivity;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.password.ChooseLockGeneric;
import com.android.settings.password.ChooseLockSettingsHelper;
+import com.android.settings.password.ConfirmDeviceCredentialActivity;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.HelpUtils;
import com.android.settingslib.RestrictedLockUtils;
@@ -1010,7 +1012,10 @@ public class FingerprintSettings extends SubSettings {
BIOMETRIC_AUTH_REQUEST,
mUserId, true /* hideBackground */);
} else if (biometricAuthStatus != Utils.BiometricStatus.NOT_ACTIVE) {
- finish();
+ IdentityCheckBiometricErrorDialog
+ .showBiometricErrorDialogAndFinishActivityOnDismiss(
+ getActivity(),
+ biometricAuthStatus);
}
} else {
Log.d(TAG, "Data null or GK PW missing");
@@ -1065,7 +1070,13 @@ public class FingerprintSettings extends SubSettings {
} else if (requestCode == BIOMETRIC_AUTH_REQUEST) {
mBiometricsAuthenticationRequested = false;
if (resultCode != RESULT_OK) {
- finish();
+ if (resultCode == ConfirmDeviceCredentialActivity.BIOMETRIC_LOCKOUT_ERROR_RESULT) {
+ IdentityCheckBiometricErrorDialog
+ .showBiometricErrorDialogAndFinishActivityOnDismiss(getActivity(),
+ Utils.BiometricStatus.LOCKOUT);
+ } else {
+ finish();
+ }
}
}
}
diff --git a/src/com/android/settings/dashboard/DashboardFragment.java b/src/com/android/settings/dashboard/DashboardFragment.java
index 220856ae664..6333f22b95b 100644
--- a/src/com/android/settings/dashboard/DashboardFragment.java
+++ b/src/com/android/settings/dashboard/DashboardFragment.java
@@ -15,8 +15,6 @@
*/
package com.android.settings.dashboard;
-import static com.android.settingslib.flags.Flags.settingsCatalyst;
-
import android.app.Activity;
import android.app.settings.SettingsEnums;
import android.content.ContentResolver;
@@ -390,7 +388,7 @@ public abstract class DashboardFragment extends SettingsPreferenceFragment
/** Returns if catalyst is enabled on current screen. */
protected final boolean isCatalystEnabled() {
- if (!settingsCatalyst()) {
+ if (!Flags.catalyst()) {
return false;
}
Context context = getContext();
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index 5933015017b..09b7503397e 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -57,6 +57,7 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
+import com.android.settings.biometrics.IdentityCheckBiometricErrorDialog;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.dashboard.RestrictedDashboardFragment;
import com.android.settings.development.autofill.AutofillCategoryController;
@@ -76,6 +77,7 @@ import com.android.settings.development.graphicsdriver.GraphicsDriverEnableAngle
import com.android.settings.development.qstile.DevelopmentTiles;
import com.android.settings.development.storage.SharedDataPreferenceController;
import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.password.ConfirmDeviceCredentialActivity;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.actionbar.SearchMenuController;
import com.android.settings.widget.SettingsMainSwitchBar;
@@ -377,6 +379,8 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
userId, false /* hideBackground */);
} else if (biometricAuthStatus != Utils.BiometricStatus.NOT_ACTIVE) {
mSwitchBar.setChecked(false);
+ IdentityCheckBiometricErrorDialog.showBiometricErrorDialog(getActivity(),
+ biometricAuthStatus, false /* twoFactorAuthentication */);
} else {
//Reset biometrics once enable dialog is shown
mIsBiometricsAuthenticated = false;
@@ -559,6 +563,10 @@ public class DevelopmentSettingsDashboardFragment extends RestrictedDashboardFra
if (resultCode == RESULT_OK) {
mIsBiometricsAuthenticated = true;
mSwitchBar.setChecked(true);
+ } else if (resultCode
+ == ConfirmDeviceCredentialActivity.BIOMETRIC_LOCKOUT_ERROR_RESULT) {
+ IdentityCheckBiometricErrorDialog.showBiometricErrorDialog(getActivity(),
+ Utils.BiometricStatus.LOCKOUT, false /* twoFactorAuthentication */);
}
}
for (AbstractPreferenceController controller : mPreferenceControllers) {
diff --git a/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java b/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java
index a9f94b49b45..e8a4e8d2923 100644
--- a/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java
@@ -36,10 +36,12 @@ import androidx.preference.Preference;
import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.settings.R;
import com.android.settings.Utils;
+import com.android.settings.biometrics.IdentityCheckBiometricErrorDialog;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.password.ChooseLockSettingsHelper;
+import com.android.settings.password.ConfirmDeviceCredentialActivity;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
@@ -235,10 +237,18 @@ public class BuildNumberPreferenceController extends BasePreferenceController im
userId, false /* hideBackground */);
} else if (biometricAuthStatus == Utils.BiometricStatus.NOT_ACTIVE) {
enableDevelopmentSettings();
+ } else {
+ IdentityCheckBiometricErrorDialog.showBiometricErrorDialog(mFragment.getActivity(),
+ biometricAuthStatus, true /* twoFactorAuthentication */);
+ }
+ } else if (requestCode == REQUEST_IDENTITY_CHECK_FOR_DEV_PREF) {
+ if (resultCode == Activity.RESULT_OK) {
+ enableDevelopmentSettings();
+ } else if (resultCode
+ == ConfirmDeviceCredentialActivity.BIOMETRIC_LOCKOUT_ERROR_RESULT) {
+ IdentityCheckBiometricErrorDialog.showBiometricErrorDialog(mFragment.getActivity(),
+ Utils.BiometricStatus.LOCKOUT, true /* twoFactorAuthentication */);
}
- } else if (requestCode == REQUEST_IDENTITY_CHECK_FOR_DEV_PREF
- && resultCode == Activity.RESULT_OK) {
- enableDevelopmentSettings();
}
mProcessingLastDevHit = false;
return true;
diff --git a/src/com/android/settings/password/ChooseLockGeneric.java b/src/com/android/settings/password/ChooseLockGeneric.java
index 09091102f24..ef6a9ad7559 100644
--- a/src/com/android/settings/password/ChooseLockGeneric.java
+++ b/src/com/android/settings/password/ChooseLockGeneric.java
@@ -84,6 +84,7 @@ import com.android.settings.Utils;
import com.android.settings.biometrics.BiometricEnrollActivity;
import com.android.settings.biometrics.BiometricEnrollBase;
import com.android.settings.biometrics.BiometricUtils;
+import com.android.settings.biometrics.IdentityCheckBiometricErrorDialog;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.safetycenter.LockScreenSafetySource;
@@ -500,11 +501,18 @@ public class ChooseLockGeneric extends SettingsActivity {
BIOMETRIC_AUTH_REQUEST,
mUserId, true /* hideBackground */);
} else if (biometricAuthStatus != Utils.BiometricStatus.NOT_ACTIVE) {
- finish();
+ IdentityCheckBiometricErrorDialog
+ .showBiometricErrorDialogAndFinishActivityOnDismiss(getActivity(),
+ biometricAuthStatus);
}
} else if (requestCode == BIOMETRIC_AUTH_REQUEST) {
if (resultCode == Activity.RESULT_OK) {
mBiometricsAuthSuccessful = true;
+ } else if (resultCode
+ == ConfirmDeviceCredentialActivity.BIOMETRIC_LOCKOUT_ERROR_RESULT) {
+ IdentityCheckBiometricErrorDialog
+ .showBiometricErrorDialogAndFinishActivityOnDismiss(getActivity(),
+ Utils.BiometricStatus.LOCKOUT);
} else {
finish();
}
diff --git a/src/com/android/settings/password/ChooseLockPassword.java b/src/com/android/settings/password/ChooseLockPassword.java
index bcf17954c57..aba9eddce21 100644
--- a/src/com/android/settings/password/ChooseLockPassword.java
+++ b/src/com/android/settings/password/ChooseLockPassword.java
@@ -927,7 +927,9 @@ public class ChooseLockPassword extends SettingsActivity {
: R.string.lockpassword_pin_too_long));
break;
case CONTAINS_SEQUENCE:
- messages.add(getString(R.string.lockpassword_pin_no_sequential_digits));
+ messages.add(getString(mIsAlphaMode
+ ? R.string.lockpassword_password_no_sequential_characters
+ : R.string.lockpassword_pin_no_sequential_digits));
break;
case RECENTLY_USED:
DevicePolicyManager devicePolicyManager =
diff --git a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
index e987ebea1cb..d656934a26b 100644
--- a/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
+++ b/src/com/android/settings/password/ConfirmDeviceCredentialActivity.java
@@ -43,6 +43,7 @@ import android.hardware.biometrics.BiometricConstants;
import android.hardware.biometrics.BiometricManager;
import android.hardware.biometrics.BiometricPrompt;
import android.hardware.biometrics.BiometricPrompt.AuthenticationCallback;
+import android.hardware.biometrics.Flags;
import android.hardware.biometrics.PromptInfo;
import android.os.Bundle;
import android.os.Handler;
@@ -82,6 +83,7 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
"biometric_prompt_negative_button_text";
public static final String BIOMETRIC_PROMPT_HIDE_BACKGROUND =
"biometric_prompt_hide_background";
+ public static final int BIOMETRIC_LOCKOUT_ERROR_RESULT = 100;
public static class InternalActivity extends ConfirmDeviceCredentialActivity {
}
@@ -129,6 +131,10 @@ public class ConfirmDeviceCredentialActivity extends FragmentActivity {
showConfirmCredentials();
} else {
Log.i(TAG, "Finishing, device credential not requested");
+ if (Flags.mandatoryBiometrics()
+ && errorCode == BiometricPrompt.BIOMETRIC_ERROR_LOCKOUT_PERMANENT) {
+ setResult(BIOMETRIC_LOCKOUT_ERROR_RESULT);
+ }
finish();
}
}
diff --git a/src/com/android/settings/sound/AudioSwitchPreferenceController.java b/src/com/android/settings/sound/AudioSwitchPreferenceController.java
index 5938362a14e..e9787a704bc 100644
--- a/src/com/android/settings/sound/AudioSwitchPreferenceController.java
+++ b/src/com/android/settings/sound/AudioSwitchPreferenceController.java
@@ -45,6 +45,7 @@ import androidx.preference.PreferenceScreen;
import com.android.settings.bluetooth.Utils;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.FeatureFlags;
+import com.android.settings.sounde.AudioSwitchUtils;
import com.android.settingslib.bluetooth.A2dpProfile;
import com.android.settingslib.bluetooth.BluetoothCallback;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
@@ -68,7 +69,8 @@ import java.util.concurrent.FutureTask;
* updating the current status of switcher entry. Subclasses must overwrite
*/
public abstract class AudioSwitchPreferenceController extends BasePreferenceController
- implements BluetoothCallback, LifecycleObserver, OnStart, OnStop {
+ implements BluetoothCallback, LifecycleObserver, OnStart, OnStop,
+ LocalBluetoothProfileManager.ServiceListener {
private static final String TAG = "AudioSwitchPrefCtrl";
@@ -149,6 +151,11 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont
return;
}
mLocalBluetoothManager.setForegroundActivity(mContext);
+ if (!AudioSwitchUtils.isLeAudioProfileReady(mProfileManager)) {
+ if (mProfileManager != null) {
+ mProfileManager.addServiceListener(this);
+ }
+ }
register();
}
@@ -159,6 +166,9 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont
return;
}
mLocalBluetoothManager.setForegroundActivity(null);
+ if (mProfileManager != null) {
+ mProfileManager.removeServiceListener(this);
+ }
unregister();
}
@@ -193,6 +203,20 @@ public abstract class AudioSwitchPreferenceController extends BasePreferenceCont
updateState(mPreference);
}
+ @Override
+ public void onServiceConnected() {
+ Log.d(TAG, "onServiceConnected");
+ if (AudioSwitchUtils.isLeAudioProfileReady(mProfileManager)) {
+ updateState(mPreference);
+ }
+ }
+
+ @Override
+ public void onServiceDisconnected() {
+ Log.d(TAG, "onServiceDisconnected()");
+ // Do nothing.
+ }
+
public void setCallback(AudioSwitchCallback callback) {
mAudioSwitchPreferenceCallback = callback;
}
diff --git a/src/com/android/settings/sound/AudioSwitchUtils.kt b/src/com/android/settings/sound/AudioSwitchUtils.kt
new file mode 100644
index 00000000000..de36bb14d31
--- /dev/null
+++ b/src/com/android/settings/sound/AudioSwitchUtils.kt
@@ -0,0 +1,32 @@
+/*
+ * 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.sounde
+
+import com.android.settingslib.bluetooth.LocalBluetoothProfileManager
+
+/**
+ * Utilities class for audio switcher controllers
+ */
+class AudioSwitchUtils {
+ companion object {
+
+ /** Check if LE Audio profile is ready. */
+ @JvmStatic
+ fun isLeAudioProfileReady(profileManager: LocalBluetoothProfileManager?): Boolean =
+ profileManager?.getLeAudioProfile()?.isProfileReady() ?: false
+ }
+}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/MainClearTest.java b/tests/robotests/src/com/android/settings/MainClearTest.java
index b705ae14cac..0f823d6ab33 100644
--- a/tests/robotests/src/com/android/settings/MainClearTest.java
+++ b/tests/robotests/src/com/android/settings/MainClearTest.java
@@ -55,7 +55,11 @@ import android.widget.LinearLayout;
import android.widget.ScrollView;
import androidx.fragment.app.FragmentActivity;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
+import com.android.settings.biometrics.IdentityCheckBiometricErrorDialog;
+import com.android.settings.password.ConfirmDeviceCredentialActivity;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settings.testutils.shadow.ShadowUtils;
import com.android.settingslib.development.DevelopmentSettingsEnabler;
@@ -114,6 +118,10 @@ public class MainClearTest {
@Mock
private Intent mMockIntent;
+ @Mock
+ private FragmentManager mMockFragmentManager;
+ @Mock
+ private FragmentTransaction mMockFragmentTransaction;
private MainClear mMainClear;
private ShadowActivity mShadowActivity;
@@ -391,6 +399,9 @@ public class MainClearTest {
@Test
@EnableFlags(Flags.FLAG_MANDATORY_BIOMETRICS)
public void testOnActivityResultInternal_keyguardRequestNotTriggeringBiometricPrompt_lockoutError() {
+ final ArgumentCaptor argumentCaptor =
+ ArgumentCaptor.forClass(IdentityCheckBiometricErrorDialog.class);
+
when(mContext.getResources()).thenReturn(mResources);
when(mMockActivity.getSystemService(BiometricManager.class)).thenReturn(mBiometricManager);
when(mResources.getString(anyInt())).thenReturn(TEST_ACCOUNT_NAME);
@@ -400,12 +411,17 @@ public class MainClearTest {
doReturn(true).when(mMainClear).isValidRequestCode(eq(MainClear.KEYGUARD_REQUEST));
doNothing().when(mMainClear).startActivityForResult(any(), anyInt());
doReturn(mMockActivity).when(mMainClear).getActivity();
+ doReturn(mMockFragmentManager).when(mMockActivity).getSupportFragmentManager();
+ doReturn(mMockFragmentTransaction).when(mMockFragmentManager).beginTransaction();
doReturn(mContext).when(mMainClear).getContext();
mMainClear
.onActivityResultInternal(MainClear.KEYGUARD_REQUEST, Activity.RESULT_OK, null);
verify(mMainClear).isValidRequestCode(eq(MainClear.KEYGUARD_REQUEST));
+ verify(mMainClear.getActivity().getSupportFragmentManager().beginTransaction()).add(
+ argumentCaptor.capture(), any());
+ assertThat(argumentCaptor.getValue()).isInstanceOf(IdentityCheckBiometricErrorDialog.class);
verify(mMainClear, never()).startActivityForResult(any(), eq(MainClear.BIOMETRICS_REQUEST));
verify(mMainClear, never()).establishInitialState();
verify(mMainClear, never()).getAccountConfirmationIntent();
@@ -427,6 +443,29 @@ public class MainClearTest {
verify(mMainClear).showFinalConfirmation();
}
+ @Test
+ public void testOnActivityResultInternal_biometricRequestTriggeringBiometricErrorDialog() {
+ final ArgumentCaptor argumentCaptor =
+ ArgumentCaptor.forClass(IdentityCheckBiometricErrorDialog.class);
+
+ doReturn(true).when(mMainClear).isValidRequestCode(
+ eq(MainClear.BIOMETRICS_REQUEST));
+ doNothing().when(mMainClear).establishInitialState();
+ doReturn(mMockActivity).when(mMainClear).getActivity();
+ doReturn(mMockFragmentManager).when(mMockActivity).getSupportFragmentManager();
+ doReturn(mMockFragmentTransaction).when(mMockFragmentManager).beginTransaction();
+ doReturn(mContext).when(mMainClear).getContext();
+
+ mMainClear
+ .onActivityResultInternal(MainClear.BIOMETRICS_REQUEST,
+ ConfirmDeviceCredentialActivity.BIOMETRIC_LOCKOUT_ERROR_RESULT, null);
+
+ verify(mMainClear).isValidRequestCode(eq(MainClear.BIOMETRICS_REQUEST));
+ verify(mMainClear.getActivity().getSupportFragmentManager().beginTransaction()).add(
+ argumentCaptor.capture(), any());
+ verify(mMainClear).establishInitialState();
+ }
+
@Test
public void testOnActivityResultInternal_biometricRequestTriggeringInitialState() {
doReturn(true).when(mMainClear).isValidRequestCode(eq(MainClear.BIOMETRICS_REQUEST));
diff --git a/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java
index 9f45edb4930..9b6896c38e8 100644
--- a/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/development/DevelopmentSettingsDashboardFragmentTest.java
@@ -41,6 +41,9 @@ import androidx.fragment.app.FragmentActivity;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
+import com.android.settings.Utils;
+import com.android.settings.biometrics.IdentityCheckBiometricErrorDialog;
+import com.android.settings.password.ConfirmDeviceCredentialActivity;
import com.android.settings.testutils.shadow.ShadowAlertDialogCompat;
import com.android.settings.testutils.shadow.ShadowUserManager;
import com.android.settings.widget.SettingsMainSwitchBar;
@@ -233,6 +236,22 @@ public class DevelopmentSettingsDashboardFragmentTest {
assertThat(ShadowEnableDevelopmentSettingWarningDialog.mShown).isTrue();
}
+ @Test
+ @Config(shadows = ShadowIdentityCheckBiometricErrorDialog.class)
+ @Ignore("b/354820314")
+ @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(ShadowIdentityCheckBiometricErrorDialog.sShown).isTrue();
+ }
+
@Test
@Ignore
@Config(shadows = ShadowEnableDevelopmentSettingWarningDialog.class)
@@ -362,6 +381,16 @@ public class DevelopmentSettingsDashboardFragmentTest {
}
}
+ @Implements(IdentityCheckBiometricErrorDialog.class)
+ public static class ShadowIdentityCheckBiometricErrorDialog {
+ static boolean sShown;
+ @Implementation
+ public static void showBiometricErrorDialog(FragmentActivity fragmentActivity,
+ Utils.BiometricStatus errorCode) {
+ sShown = true;
+ }
+ }
+
@Implements(DisableDevSettingsDialogFragment.class)
public static class ShadowDisableDevSettingsDialogFragment {
diff --git a/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java b/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java
index 1e81ec066d5..2559618d143 100644
--- a/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java
+++ b/tests/robotests/src/com/android/settings/password/ChooseLockPasswordTest.java
@@ -71,7 +71,6 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
-import org.robolectric.Shadows;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowDrawable;
@@ -314,7 +313,7 @@ public class ChooseLockPasswordTest {
/* minComplexity= */ PASSWORD_COMPLEXITY_NONE,
/* passwordType= */ PASSWORD_QUALITY_ALPHABETIC,
/* userEnteredPassword= */ LockscreenCredential.createPassword("12345678"),
- "Ascending, descending, or repeated sequence of digits isn't allowed");
+ "Ascending, descending, or repeated sequence of characters isn't allowed");
}
@Test
@@ -356,7 +355,7 @@ public class ChooseLockPasswordTest {
/* minComplexity= */ PASSWORD_COMPLEXITY_LOW,
/* passwordType= */ PASSWORD_QUALITY_ALPHABETIC,
/* userEnteredPassword= */ LockscreenCredential.createPassword("12345678"),
- "Ascending, descending, or repeated sequence of digits isn't allowed");
+ "Ascending, descending, or repeated sequence of characters isn't allowed");
}
@Test
diff --git a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingLabelSimTest.kt b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingLabelSimTest.kt
index 1910153fb89..60686c91539 100644
--- a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingLabelSimTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingLabelSimTest.kt
@@ -39,6 +39,7 @@ import com.android.settings.R
import com.android.settings.network.SimOnboardingService
import com.android.settingslib.spa.testutils.waitUntilExists
import org.junit.Assert.assertEquals
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -129,6 +130,7 @@ class SimOnboardingLabelSimTest {
}
@Test
+ @Ignore
fun simOnboardingLabelSimImpl_showItem_show3Items() {
preSetupContent()
diff --git a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingSelectSimTest.kt b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingSelectSimTest.kt
index 385bc420d60..4655a873b76 100644
--- a/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingSelectSimTest.kt
+++ b/tests/spa_unit/src/com/android/settings/spa/network/SimOnboardingSelectSimTest.kt
@@ -35,6 +35,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.settings.R
import com.android.settings.network.SimOnboardingService
import com.android.settingslib.spa.testutils.waitUntilExists
+import org.junit.Ignore
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
@@ -142,6 +143,7 @@ class SimOnboardingSelectSimTest {
}
@Test
+ @Ignore
fun simOnboardingSelectSimImpl_showItem_show3Items() {
mockSimOnboardingService.stub {
on { targetSubId }.doReturn(SUB_ID_1)
@@ -168,9 +170,6 @@ class SimOnboardingSelectSimTest {
SimOnboardingSelectSimImpl(nextAction, cancelAction, mockSimOnboardingService)
}
}
-// composeTestRule.setContent {
-// SimOnboardingSelectSimImpl(nextAction, cancelAction, mockSimOnboardingService)
-// }
composeTestRule.onNodeWithText(DISPLAY_NAME_1).assertIsDisplayed()
composeTestRule.waitUntilExists(hasText(NUMBER_1))
diff --git a/tests/unit/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java b/tests/unit/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
index 34878e1ef2c..7e942d9e94e 100644
--- a/tests/unit/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/deviceinfo/BuildNumberPreferenceControllerTest.java
@@ -246,26 +246,6 @@ public class BuildNumberPreferenceControllerTest {
eq(BuildNumberPreferenceController.REQUEST_IDENTITY_CHECK_FOR_DEV_PREF));
}
- @Test
- @UiThreadTest
- @RequiresFlagsEnabled(Flags.FLAG_MANDATORY_BIOMETRICS)
- public void onActivityResult_confirmPasswordRequestCompleted_lockoutError() {
- when(mUserManager.isAdminUser()).thenReturn(true);
- when(mBiometricManager.canAuthenticate(mContext.getUserId(),
- BiometricManager.Authenticators.MANDATORY_BIOMETRICS))
- .thenReturn(BiometricManager.BIOMETRIC_ERROR_LOCKOUT);
-
- final boolean activityResultHandled = mController.onActivityResult(
- BuildNumberPreferenceController.REQUEST_CONFIRM_PASSWORD_FOR_DEV_PREF,
- Activity.RESULT_OK,
- null);
-
- assertThat(activityResultHandled).isTrue();
- verify(mFragment, never()).startActivityForResult(any(),
- eq(BuildNumberPreferenceController.REQUEST_IDENTITY_CHECK_FOR_DEV_PREF));
- assertThat(DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)).isFalse();
- }
-
@Test
public void onActivityResult_confirmBiometricAuthentication_enableDevPref() {
when(mUserManager.isAdminUser()).thenReturn(true);