Snap for 12385180 from aa7114cf3e to 24Q4-release
Change-Id: I3b00cbccde707c1d5538b737899d1e75a45dda9e
This commit is contained in:
@@ -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",
|
||||
}
|
||||
}
|
||||
|
||||
9
aconfig/catalyst/about_phone.aconfig
Normal file
9
aconfig/catalyst/about_phone.aconfig
Normal file
@@ -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"
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -6973,4 +6973,103 @@
|
||||
column="5"/>
|
||||
</issue>
|
||||
|
||||
</issues>
|
||||
<issue
|
||||
id="HardCodedColor"
|
||||
severity="Error"
|
||||
message="Avoid using hardcoded color"
|
||||
category="Correctness"
|
||||
priority="4"
|
||||
summary="Using hardcoded color"
|
||||
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
|
||||
errorLine1=" android:color="@color/accessibility_feature_background"/>"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/drawable/ic_pointer_and_touchpad.xml"
|
||||
line="22"
|
||||
column="13"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="HardCodedColor"
|
||||
severity="Error"
|
||||
message="Avoid using hardcoded color"
|
||||
category="Correctness"
|
||||
priority="4"
|
||||
summary="Using hardcoded color"
|
||||
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
|
||||
errorLine1=" <color name="pointer_fill_outline_color">#FFFFFF</color>"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values-night/colors.xml"
|
||||
line="81"
|
||||
column="5"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="HardCodedColor"
|
||||
severity="Error"
|
||||
message="Avoid using hardcoded color"
|
||||
category="Correctness"
|
||||
priority="4"
|
||||
summary="Using hardcoded color"
|
||||
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
|
||||
errorLine1=" <color name="pointer_fill_outline_color">#000000</color>"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
<location
|
||||
file="res/values/colors.xml"
|
||||
line="223"
|
||||
column="5"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="HardCodedColor"
|
||||
severity="Error"
|
||||
message="Avoid using hardcoded color"
|
||||
category="Correctness"
|
||||
priority="4"
|
||||
summary="Using hardcoded color"
|
||||
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
|
||||
errorLine1=" android:color="@color/pointer_fill_outline_color" />"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
|
||||
<location
|
||||
file="res/drawable/pointer_icon_fill_color_foreground.xml"
|
||||
line="25"
|
||||
column="25"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="HardCodedColor"
|
||||
severity="Error"
|
||||
message="Avoid using hardcoded color"
|
||||
category="Correctness"
|
||||
priority="4"
|
||||
summary="Using hardcoded color"
|
||||
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
|
||||
errorLine1=" android:color="@color/pointer_fill_outline_color" />"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
|
||||
<location
|
||||
file="res/drawable/pointer_icon_fill_color_foreground.xml"
|
||||
line="47"
|
||||
column="25"/>
|
||||
</issue>
|
||||
|
||||
<issue
|
||||
id="HardCodedColor"
|
||||
severity="Error"
|
||||
message="Avoid using hardcoded color"
|
||||
category="Correctness"
|
||||
priority="4"
|
||||
summary="Using hardcoded color"
|
||||
explanation="Hardcoded color values are bad because theme changes cannot be uniformly applied.Instead use the theme specific colors such as `?android:attr/textColorPrimary` in attributes.
This ensures that a theme change from a light to a dark theme can be uniformlyapplied across the app."
|
||||
errorLine1=" android:color="@color/pointer_fill_outline_color" />"
|
||||
errorLine2=" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~">
|
||||
|
||||
<location
|
||||
file="res/drawable/pointer_icon_fill_color_foreground.xml"
|
||||
line="64"
|
||||
column="25"/>
|
||||
</issue>
|
||||
|
||||
</issues>
|
||||
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>
|
||||
@@ -73,18 +73,17 @@
|
||||
android:orientation="vertical"
|
||||
app:layout_constraintGuide_percent="0.5" />
|
||||
|
||||
<!-- End time title (non-clickable preference), left-aligned to edge of time display -->
|
||||
<!-- End time title (non-clickable preference), right-aligned -->
|
||||
<TextView
|
||||
android:id="@+id/end_time_label"
|
||||
android:clickable="false"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintStart_toStartOf="@+id/end_time"
|
||||
app:layout_constraintStart_toEndOf="@+id/guideline"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintHorizontal_bias="0"
|
||||
app:layout_constraintHorizontal_bias="1"
|
||||
android:textAppearance="@*android:style/TextAppearance.DeviceDefault.Medium"
|
||||
android:text="@string/zen_mode_end_time"
|
||||
android:importantForAccessibility="no" />
|
||||
|
||||
@@ -938,6 +938,30 @@
|
||||
<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">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 message when identity check auth is requested but biometrics is in lockout state. [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 and there is a two factor authentication. [CHAR LIMIT=NONE] -->
|
||||
<string name="identity_check_lockout_error_two_factor_auth_description_1">Biometrics failed too many times. Try again.</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 />
|
||||
<!-- Title shown for menu item that launches watch unlock settings. [CHAR LIMIT=40] -->
|
||||
<string name ="security_settings_remoteauth_preference_title">Remote Authenticator Unlock</string>
|
||||
@@ -1739,10 +1763,13 @@
|
||||
<string name="lockpassword_password_recently_used">Device admin doesn\'t allow using a recent
|
||||
password</string>
|
||||
|
||||
<!-- [CHAR_LIMIT=NONE] Error shown when the user tries to set an ascending or descending sequence of digits -->
|
||||
<!-- [CHAR_LIMIT=NONE] Error shown when the user tries to set an ascending or descending sequence of digits as PIN -->
|
||||
<string name="lockpassword_pin_no_sequential_digits">Ascending, descending, or repeated sequence
|
||||
of digits isn\'t allowed</string>
|
||||
|
||||
<!-- Error shown when the user tries to set an ascending or descending sequence of alphanumeric characters in the password [CHAR_LIMIT=NONE] -->
|
||||
<string name="lockpassword_password_no_sequential_characters">Ascending, descending, or repeated sequence of characters isn\'t allowed</string>
|
||||
|
||||
<!-- Label for Confirm button when entering PIN / password the second time. [CHAR LIMIT=30] -->
|
||||
<string name="lockpassword_confirm_label">Confirm</string>
|
||||
|
||||
@@ -12102,7 +12129,7 @@
|
||||
<!-- Summary for _satellite_setting_preference_layout. [CHAR LIMIT=NONE]-->
|
||||
<string name="satellite_setting_enabled_summary">Send and receive text messages by satellite. Included with your account.</string>
|
||||
<!-- Summary for _satellite_setting_preference_layout. [CHAR LIMIT=NONE]-->
|
||||
<string name="satellite_setting_disabled_summary">Send and receive text messages by satellite. Non included with your account.</string>
|
||||
<string name="satellite_setting_disabled_summary">Send and receive text messages by satellite. Not included with your account.</string>
|
||||
<!-- Search keywords for "_satellite_setting_preference_layout" [CHAR_LIMIT=NONE] -->
|
||||
<string name="keywords_satellite_setting">Satellite messaging</string>
|
||||
<!-- Category name "About satellite messaging" [CHAR_LIMIT=NONE] -->
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* <p>
|
||||
* 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<String> 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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
32
src/com/android/settings/sound/AudioSwitchUtils.kt
Normal file
32
src/com/android/settings/sound/AudioSwitchUtils.kt
Normal file
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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<IdentityCheckBiometricErrorDialog> 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<IdentityCheckBiometricErrorDialog> 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));
|
||||
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user