diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 2c62ebd684c..177e750c892 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -132,6 +132,7 @@
+
diff --git a/res/values/config.xml b/res/values/config.xml
index c9cc4556861..c20f08035c2 100644
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -848,4 +848,7 @@
false
+
+
+ false
diff --git a/res/values/strings.xml b/res/values/strings.xml
index ddf69813aa1..c5a938e6f18 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -924,6 +924,10 @@
Require eyes to be open
To unlock the phone, your eyes must be open
+
+
+
+
Always require confirmation
@@ -5722,6 +5726,8 @@
Edit accessibility shortcuts
Choose your shortcut for %1$s
+
+ To use this, turn on the %1$s shortcut on an accessibility feature\'s page
Continue
diff --git a/res/xml/accessibility_shortcuts_settings.xml b/res/xml/accessibility_shortcuts_settings.xml
index c8070564eb4..18ec9e927ba 100644
--- a/res/xml/accessibility_shortcuts_settings.xml
+++ b/res/xml/accessibility_shortcuts_settings.xml
@@ -19,7 +19,8 @@
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="accessibility_shortcuts_settings"
android:persistent="false"
- android:title="@string/accessibility_shortcuts_settings_title">
+ android:title="@string/accessibility_shortcuts_settings_title"
+ settings:searchable="false">
+ settings:controller="com.android.settings.accessibility.HardwareShortcutFromLockscreenPreferenceController"/>
diff --git a/src/com/android/settings/accessibility/AccessibilityButtonFragment.java b/src/com/android/settings/accessibility/AccessibilityButtonFragment.java
index 60e4bb28fea..116554d735a 100644
--- a/src/com/android/settings/accessibility/AccessibilityButtonFragment.java
+++ b/src/com/android/settings/accessibility/AccessibilityButtonFragment.java
@@ -16,9 +16,14 @@
package com.android.settings.accessibility;
-import android.app.settings.SettingsEnums;
-import android.os.Bundle;
+import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE;
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.os.Bundle;
+import android.provider.Settings;
+
+import com.android.internal.accessibility.util.ShortcutUtils;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
@@ -61,5 +66,13 @@ public class AccessibilityButtonFragment extends DashboardFragment {
}
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
- new BaseSearchIndexProvider(R.xml.accessibility_button_settings);
+ new BaseSearchIndexProvider(R.xml.accessibility_button_settings) {
+ @Override
+ protected boolean isPageSearchEnabled(Context context) {
+ // Page should be unsearchable if there are no active button targets
+ String targets = Settings.Secure.getStringForUser(context.getContentResolver(),
+ ShortcutUtils.convertToKey(SOFTWARE), context.getUserId());
+ return targets != null && !targets.isEmpty();
+ }
+ };
}
diff --git a/src/com/android/settings/accessibility/AccessibilityButtonPreferenceController.java b/src/com/android/settings/accessibility/AccessibilityButtonPreferenceController.java
index 68a765c9230..d9ee3cd31f7 100644
--- a/src/com/android/settings/accessibility/AccessibilityButtonPreferenceController.java
+++ b/src/com/android/settings/accessibility/AccessibilityButtonPreferenceController.java
@@ -16,9 +16,13 @@
package com.android.settings.accessibility;
+import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE;
+
import android.content.Context;
import android.content.res.Resources;
+import android.view.accessibility.AccessibilityManager;
+import androidx.annotation.NonNull;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
@@ -32,14 +36,39 @@ import java.util.List;
* Preference controller for accessibility button preference.
*/
public class AccessibilityButtonPreferenceController extends BasePreferenceController {
-
public AccessibilityButtonPreferenceController(Context context, String key) {
super(context, key);
}
@Override
public int getAvailabilityStatus() {
- return AVAILABLE;
+ if (!com.android.settings.accessibility.Flags.fixA11ySettingsSearch()) {
+ return AVAILABLE;
+ } else {
+ if (mContext.getSystemService(AccessibilityManager.class)
+ .getAccessibilityShortcutTargets(SOFTWARE).isEmpty()) {
+ return DISABLED_DEPENDENT_SETTING;
+ } else {
+ return AVAILABLE;
+ }
+ }
+ }
+
+ @Override
+ public void updateState(@NonNull Preference preference) {
+ super.updateState(preference);
+ refreshSummary(preference);
+ }
+
+ @Override
+ public @NonNull CharSequence getSummary() {
+ if (getAvailabilityStatus() == AVAILABLE) {
+ return "";
+ } else {
+ return mContext.getString(
+ R.string.accessibility_shortcut_unassigned_setting_unavailable_summary,
+ AccessibilityUtil.getShortcutSummaryList(mContext, SOFTWARE));
+ }
}
@Override
@@ -47,7 +76,6 @@ public class AccessibilityButtonPreferenceController extends BasePreferenceContr
super.displayPreference(screen);
final Preference preference = screen.findPreference(getPreferenceKey());
preference.setTitle(getPreferenceTitleResource());
-
}
@Override
diff --git a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceController.java b/src/com/android/settings/accessibility/HardwareShortcutFromLockscreenPreferenceController.java
similarity index 58%
rename from src/com/android/settings/accessibility/AccessibilityShortcutPreferenceController.java
rename to src/com/android/settings/accessibility/HardwareShortcutFromLockscreenPreferenceController.java
index d204bb761db..a6d5b7bc7fe 100644
--- a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceController.java
+++ b/src/com/android/settings/accessibility/HardwareShortcutFromLockscreenPreferenceController.java
@@ -15,6 +15,7 @@
*/
package com.android.settings.accessibility;
+import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.HARDWARE;
import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
@@ -22,16 +23,21 @@ import android.content.ContentResolver;
import android.content.Context;
import android.os.UserHandle;
import android.provider.Settings;
+import android.view.accessibility.AccessibilityManager;
+
+import androidx.annotation.NonNull;
+import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
/**
- * Settings page for accessibility shortcut
+ * Setting to allow the hardware shortcut to turn on from the lock screen
*/
-public class AccessibilityShortcutPreferenceController extends TogglePreferenceController {
-
- public AccessibilityShortcutPreferenceController(Context context, String preferenceKey) {
+public class HardwareShortcutFromLockscreenPreferenceController
+ extends TogglePreferenceController {
+ public HardwareShortcutFromLockscreenPreferenceController(
+ Context context, String preferenceKey) {
super(context, preferenceKey);
}
@@ -56,7 +62,33 @@ public class AccessibilityShortcutPreferenceController extends TogglePreferenceC
@Override
public int getAvailabilityStatus() {
- return AVAILABLE;
+ if (!com.android.settings.accessibility.Flags.fixA11ySettingsSearch()) {
+ return AVAILABLE;
+ } else {
+ if (mContext.getSystemService(AccessibilityManager.class)
+ .getAccessibilityShortcutTargets(HARDWARE).isEmpty()) {
+ return DISABLED_DEPENDENT_SETTING;
+ } else {
+ return AVAILABLE;
+ }
+ }
+ }
+
+ @Override
+ public void updateState(@NonNull Preference preference) {
+ super.updateState(preference);
+ refreshSummary(preference);
+ }
+
+ @Override
+ public @NonNull CharSequence getSummary() {
+ if (getAvailabilityStatus() == AVAILABLE) {
+ return mContext.getString(R.string.accessibility_shortcut_description);
+ } else {
+ return mContext.getString(
+ R.string.accessibility_shortcut_unassigned_setting_unavailable_summary,
+ AccessibilityUtil.getShortcutSummaryList(mContext, HARDWARE));
+ }
}
@Override
diff --git a/src/com/android/settings/biometrics/face/FaceAttentionController.java b/src/com/android/settings/biometrics/face/FaceAttentionController.java
new file mode 100644
index 00000000000..f035dfd0719
--- /dev/null
+++ b/src/com/android/settings/biometrics/face/FaceAttentionController.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2025 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.face;
+
+import static android.hardware.biometrics.BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION;
+
+import android.content.Context;
+import android.hardware.face.FaceManager;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.settings.Utils;
+
+public class FaceAttentionController {
+
+ @Nullable private byte[] mToken;
+ private FaceManager mFaceManager;
+
+ public interface OnSetAttentionListener {
+ /**
+ * Calls when setting attention is completed from FaceManager.
+ */
+ void onSetAttentionCompleted(boolean success);
+ }
+
+ public interface OnGetAttentionListener {
+ /**
+ * Calls when getting attention is completed from FaceManager.
+ */
+ void onGetAttentionCompleted(boolean success, boolean enabled);
+ }
+
+ @Nullable private OnSetAttentionListener mSetListener;
+ @Nullable private OnGetAttentionListener mGetListener;
+
+ private final FaceManager.SetFeatureCallback mSetFeatureCallback =
+ new FaceManager.SetFeatureCallback() {
+ @Override
+ public void onCompleted(boolean success, int feature) {
+ if (feature == FEATURE_REQUIRE_ATTENTION) {
+ if (mSetListener != null) {
+ mSetListener.onSetAttentionCompleted(success);
+ }
+ }
+ }
+ };
+
+ private final FaceManager.GetFeatureCallback mGetFeatureCallback =
+ new FaceManager.GetFeatureCallback() {
+ @Override
+ public void onCompleted(
+ boolean success, @NonNull int[] features, @NonNull boolean[] featureState) {
+ boolean requireAttentionEnabled = false;
+ for (int i = 0; i < features.length; i++) {
+ if (features[i] == FEATURE_REQUIRE_ATTENTION) {
+ requireAttentionEnabled = featureState[i];
+ }
+ }
+ if (mGetListener != null) {
+ mGetListener.onGetAttentionCompleted(success, requireAttentionEnabled);
+ }
+ }
+ };
+
+ public FaceAttentionController(@NonNull Context context) {
+ mFaceManager = Utils.getFaceManagerOrNull(context);
+ }
+
+ /**
+ * Set the challenge token
+ */
+ public void setToken(@Nullable byte[] token) {
+ mToken = token;
+ }
+
+ /**
+ * Get the gaze status
+ */
+ public void getAttentionStatus(int userId,
+ @Nullable OnGetAttentionListener listener) {
+ mGetListener = listener;
+ mFaceManager.getFeature(userId, FEATURE_REQUIRE_ATTENTION, mGetFeatureCallback);
+ }
+
+ /**
+ * Set the gaze status
+ */
+ public void setAttentionStatus(
+ int userId, boolean enabled, @Nullable OnSetAttentionListener listener) {
+ mSetListener = listener;
+ mFaceManager.setFeature(userId, FEATURE_REQUIRE_ATTENTION, enabled, mToken,
+ mSetFeatureCallback);
+ }
+}
diff --git a/src/com/android/settings/biometrics/face/FaceEnrollEducation.java b/src/com/android/settings/biometrics/face/FaceEnrollEducation.java
index 6862bc921d7..7b0b8ef0f56 100644
--- a/src/com/android/settings/biometrics/face/FaceEnrollEducation.java
+++ b/src/com/android/settings/biometrics/face/FaceEnrollEducation.java
@@ -69,6 +69,7 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
private View mIllustrationAccessibility;
private Intent mResultIntent;
private boolean mAccessibilityEnabled;
+ protected Intent mExtraInfoIntent;
private final CompoundButton.OnCheckedChangeListener mSwitchDiversityListener =
new CompoundButton.OnCheckedChangeListener() {
@@ -171,12 +172,7 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
mFooterBarMixin.setPrimaryButton(footerButton);
final Button accessibilityButton = findViewById(R.id.accessibility_button);
- accessibilityButton.setOnClickListener(view -> {
- mSwitchDiversity.setChecked(true);
- accessibilityButton.setVisibility(View.GONE);
- mSwitchDiversity.setVisibility(View.VISIBLE);
- mSwitchDiversity.addOnLayoutChangeListener(mSwitchDiversityOnLayoutChangeListener);
- });
+ accessibilityButton.setOnClickListener(this::onAccessibilityButtonClicked);
mSwitchDiversity = findViewById(R.id.toggle_diversity);
mSwitchDiversity.setListener(mSwitchDiversityListener);
@@ -263,6 +259,9 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
if (mResultIntent != null) {
intent.putExtras(mResultIntent);
}
+ if (mExtraInfoIntent != null) {
+ intent.putExtras(mExtraInfoIntent);
+ }
intent.putExtra(EXTRA_KEY_REQUIRE_DIVERSITY, !mSwitchDiversity.isChecked());
intent.putExtra(BiometricUtils.EXTRA_ENROLL_REASON,
@@ -282,6 +281,13 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
}
+ protected void onAccessibilityButtonClicked(View view) {
+ mSwitchDiversity.setChecked(true);
+ view.setVisibility(View.GONE);
+ mSwitchDiversity.setVisibility(View.VISIBLE);
+ mSwitchDiversity.addOnLayoutChangeListener(mSwitchDiversityOnLayoutChangeListener);
+ }
+
protected void onSkipButtonClick(View view) {
if (!BiometricUtils.tryStartingNextBiometricEnroll(this, ENROLL_NEXT_BIOMETRIC_REQUEST,
"edu_skip")) {
diff --git a/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java b/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java
index 71c46787261..c7e2141c53a 100644
--- a/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java
+++ b/src/com/android/settings/biometrics/face/FaceSettingsAttentionPreferenceController.java
@@ -16,12 +16,8 @@
package com.android.settings.biometrics.face;
-import static android.hardware.biometrics.BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION;
-
import android.content.Context;
import android.hardware.face.FaceManager;
-import android.hardware.face.FaceManager.GetFeatureCallback;
-import android.hardware.face.FaceManager.SetFeatureCallback;
import android.provider.Settings;
import androidx.annotation.Nullable;
@@ -31,6 +27,7 @@ import androidx.preference.TwoStatePreference;
import com.android.settings.R;
import com.android.settings.Utils;
+import com.android.settings.flags.Flags;
/**
* Preference controller that manages the ability to use face authentication with/without
@@ -40,14 +37,13 @@ public class FaceSettingsAttentionPreferenceController extends FaceSettingsPrefe
public static final String KEY = "security_settings_face_require_attention";
- private byte[] mToken;
- private FaceManager mFaceManager;
private TwoStatePreference mPreference;
+ private boolean mGazeEnabled;
- private final SetFeatureCallback mSetFeatureCallback = new SetFeatureCallback() {
- @Override
- public void onCompleted(boolean success, int feature) {
- if (feature == FEATURE_REQUIRE_ATTENTION) {
+ private FaceAttentionController mFaceAttentionController;
+
+ private final FaceAttentionController.OnSetAttentionListener mSetAttentionListener =
+ (success) -> {
mPreference.setEnabled(true);
if (!success) {
mPreference.setChecked(!mPreference.isChecked());
@@ -56,31 +52,23 @@ public class FaceSettingsAttentionPreferenceController extends FaceSettingsPrefe
Settings.Secure.FACE_UNLOCK_ATTENTION_REQUIRED,
mPreference.isChecked() ? 1 : 0, getUserId());
}
- }
- }
- };
+ };
- private final GetFeatureCallback mGetFeatureCallback = new GetFeatureCallback() {
- @Override
- public void onCompleted(boolean success, int[] features, boolean[] featureState) {
- boolean requireAttentionEnabled = false;
- for (int i = 0; i < features.length; i++) {
- if (features[i] == FEATURE_REQUIRE_ATTENTION) {
- requireAttentionEnabled = featureState[i];
+ private final FaceAttentionController.OnGetAttentionListener mOnGetAttentionListener =
+ (success, requireAttentionEnabled) -> {
+ mPreference.setChecked(requireAttentionEnabled);
+ if (getRestrictingAdmin() != null) {
+ mPreference.setEnabled(false);
+ } else {
+ mPreference.setEnabled(success);
}
- }
- mPreference.setChecked(requireAttentionEnabled);
- if (getRestrictingAdmin() != null) {
- mPreference.setEnabled(false);
- } else {
- mPreference.setEnabled(success);
- }
- }
- };
+ };
public FaceSettingsAttentionPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
- mFaceManager = Utils.getFaceManagerOrNull(context);
+ mFaceAttentionController = new FaceAttentionController(context);
+ mGazeEnabled = context.getResources().getBoolean(R.bool.config_gazeEnabled)
+ && Flags.biometricsOnboardingEducation();
}
public FaceSettingsAttentionPreferenceController(Context context) {
@@ -88,7 +76,9 @@ public class FaceSettingsAttentionPreferenceController extends FaceSettingsPrefe
}
public void setToken(byte[] token) {
- mToken = token;
+ if (mFaceAttentionController != null) {
+ mFaceAttentionController.setToken(token);
+ }
}
/**
@@ -109,6 +99,11 @@ public class FaceSettingsAttentionPreferenceController extends FaceSettingsPrefe
if (Utils.isPrivateProfile(getUserId(), mContext)) {
preference.setSummary(mContext.getString(
R.string.private_space_face_settings_require_attention_details));
+ } else if (mGazeEnabled) {
+ preference.setTitle(mContext.getString(
+ R.string.security_settings_face_settings_gaze));
+ preference.setSummary(mContext.getString(
+ R.string.security_settings_face_settings_gaze_details));
}
}
@@ -119,8 +114,7 @@ public class FaceSettingsAttentionPreferenceController extends FaceSettingsPrefe
}
// Set to disabled until we know the true value.
mPreference.setEnabled(false);
- mFaceManager.getFeature(getUserId(), FEATURE_REQUIRE_ATTENTION,
- mGetFeatureCallback);
+ mFaceAttentionController.getAttentionStatus(getUserId(), mOnGetAttentionListener);
// Ideally returns a cached value.
return true;
@@ -131,9 +125,7 @@ public class FaceSettingsAttentionPreferenceController extends FaceSettingsPrefe
// Optimistically update state and set to disabled until we know it succeeded.
mPreference.setEnabled(false);
mPreference.setChecked(isChecked);
-
- mFaceManager.setFeature(getUserId(), FEATURE_REQUIRE_ATTENTION,
- isChecked, mToken, mSetFeatureCallback);
+ mFaceAttentionController.setAttentionStatus(getUserId(), isChecked, mSetAttentionListener);
return true;
}
diff --git a/src/com/android/settings/development/DesktopModePreferenceController.java b/src/com/android/settings/development/DesktopModePreferenceController.java
index 8012d31b9f6..4c6da1ee1cd 100644
--- a/src/com/android/settings/development/DesktopModePreferenceController.java
+++ b/src/com/android/settings/development/DesktopModePreferenceController.java
@@ -89,7 +89,7 @@ public class DesktopModePreferenceController extends DeveloperOptionsPreferenceC
final boolean shouldDevOptionBeEnabled = switch (toggleOverride) {
case OVERRIDE_OFF -> false;
case OVERRIDE_ON -> true;
- case OVERRIDE_UNSET -> DesktopModeStatus.shouldDevOptionBeEnabledByDefault();
+ case OVERRIDE_UNSET -> DesktopModeStatus.shouldDevOptionBeEnabledByDefault(mContext);
};
((TwoStatePreference) mPreference).setChecked(shouldDevOptionBeEnabled);
}
diff --git a/src/com/android/settings/network/CellularSecurityPreferenceController.java b/src/com/android/settings/network/CellularSecurityPreferenceController.java
index a184553c0f3..087cfaf840a 100644
--- a/src/com/android/settings/network/CellularSecurityPreferenceController.java
+++ b/src/com/android/settings/network/CellularSecurityPreferenceController.java
@@ -23,6 +23,7 @@ import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.safetycenter.SafetyCenterManager;
+import android.safetycenter.SafetySourceData;
import android.telephony.SubscriptionInfo;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
@@ -48,6 +49,7 @@ import java.util.List;
public class CellularSecurityPreferenceController extends BasePreferenceController {
private static final String LOG_TAG = "CellularSecurityPreferenceController";
+ private static final String SAFETY_SOURCE_ID = "AndroidCellularNetworkSecurity";
private @Nullable TelephonyManager mTelephonyManager;
@@ -72,7 +74,6 @@ public class CellularSecurityPreferenceController extends BasePreferenceControll
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
|| !Flags.enableIdentifierDisclosureTransparencyUnsolEvents()
|| !Flags.enableModemCipherTransparencyUnsolEvents()
- || !Flags.enableIdentifierDisclosureTransparency()
|| !Flags.enableModemCipherTransparency()) {
return UNSUPPORTED_ON_DEVICE;
}
@@ -134,13 +135,30 @@ public class CellularSecurityPreferenceController extends BasePreferenceControll
if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
return super.handlePreferenceTreeClick(preference);
}
- boolean isSafetyCenterSupported = isSafetyCenterSupported();
- if (isSafetyCenterSupported && areNotificationsEnabled()) {
+ if (!isSafetyCenterSupported()) {
+ // Realistically, it's unlikely to end up in handlePreferenceTreeClick with SafetyCenter
+ // being not supported on the device.
+ return false;
+ }
+ // Need to check that both Safety Center is available on device, and also that the HALs are
+ // enabled before showing the Safety Center UI. Otherwise, we need to take them to the page
+ // where the HALs can be enabled.
+ SafetyCenterManager safetyCenterManager = mContext.getSystemService(
+ SafetyCenterManager.class);
+ SafetySourceData data = null;
+ if (safetyCenterManager.isSafetyCenterEnabled()) {
+ data = safetyCenterManager.getSafetySourceData(SAFETY_SOURCE_ID);
+ }
+ // Can only redirect to SafetyCenter if it has received data via the SafetySource, as
+ // SafetyCenter doesn't support redirecting to a specific page associated with a source
+ // if it hasn't received data from that source. See b/373942609 for details.
+ if (data != null && areNotificationsEnabled()) {
Intent safetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER);
safetyCenterIntent.putExtra(SafetyCenterManager.EXTRA_SAFETY_SOURCES_GROUP_ID,
"AndroidCellularNetworkSecuritySources");
mContext.startActivity(safetyCenterIntent);
} else {
+ Log.v(LOG_TAG, "Hardware APIs not enabled, or data source is null.");
final Bundle bundle = new Bundle();
bundle.putString(CellularSecuritySettingsFragment.KEY_CELLULAR_SECURITY_PREFERENCE, "");
diff --git a/src/com/android/settings/network/telephony/CellularSecurityNotificationsDividerController.java b/src/com/android/settings/network/telephony/CellularSecurityNotificationsDividerController.java
index 131882704f5..51d91a48a89 100644
--- a/src/com/android/settings/network/telephony/CellularSecurityNotificationsDividerController.java
+++ b/src/com/android/settings/network/telephony/CellularSecurityNotificationsDividerController.java
@@ -62,7 +62,6 @@ public class CellularSecurityNotificationsDividerController extends
public int getAvailabilityStatus() {
if (!Flags.enableIdentifierDisclosureTransparencyUnsolEvents()
|| !Flags.enableModemCipherTransparencyUnsolEvents()
- || !Flags.enableIdentifierDisclosureTransparency()
|| !Flags.enableModemCipherTransparency()) {
return UNSUPPORTED_ON_DEVICE;
}
diff --git a/src/com/android/settings/network/telephony/CellularSecurityNotificationsPreferenceController.java b/src/com/android/settings/network/telephony/CellularSecurityNotificationsPreferenceController.java
index 4e2d285b8d5..17aca091b73 100644
--- a/src/com/android/settings/network/telephony/CellularSecurityNotificationsPreferenceController.java
+++ b/src/com/android/settings/network/telephony/CellularSecurityNotificationsPreferenceController.java
@@ -180,7 +180,6 @@ public class CellularSecurityNotificationsPreferenceController extends
private boolean areFlagsEnabled() {
if (!Flags.enableIdentifierDisclosureTransparencyUnsolEvents()
|| !Flags.enableModemCipherTransparencyUnsolEvents()
- || !Flags.enableIdentifierDisclosureTransparency()
|| !Flags.enableModemCipherTransparency()) {
return false;
}
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonFragmentTest.java
index 94312a60eee..386463a5666 100644
--- a/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonFragmentTest.java
@@ -19,6 +19,8 @@ package com.android.settings.accessibility;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
+import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
@@ -39,6 +41,7 @@ import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
+import com.android.internal.accessibility.util.ShortcutUtils;
import com.android.settings.R;
import com.android.settings.testutils.XmlTestUtils;
import com.android.settings.testutils.shadow.ShadowFragment;
@@ -132,6 +135,7 @@ public class AccessibilityButtonFragmentTest {
}
@Test
+ @DisableFlags(com.android.settings.accessibility.Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
public void getNonIndexableKeys_existInXmlLayout() {
final List niks = AccessibilityButtonFragment.SEARCH_INDEX_DATA_PROVIDER
.getNonIndexableKeys(mContext);
@@ -139,7 +143,38 @@ public class AccessibilityButtonFragmentTest {
XmlTestUtils.getKeysFromPreferenceXml(mContext,
R.xml.accessibility_button_settings);
- assertThat(keys).containsAtLeastElementsIn(niks);
+ assertThat(keys).isNotNull();
+ assertThat(niks).containsAtLeastElementsIn(keys);
+ }
+
+ @Test
+ @EnableFlags(com.android.settings.accessibility.Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
+ public void getNonIndexableKeys_noTargets_doesNotExistInXmlLayout() {
+ Settings.Secure.putStringForUser(mContext.getContentResolver(),
+ ShortcutUtils.convertToKey(SOFTWARE), "", mContext.getUserId());
+ final List niks = AccessibilityButtonFragment.SEARCH_INDEX_DATA_PROVIDER
+ .getNonIndexableKeys(mContext);
+ final List keys =
+ XmlTestUtils.getKeysFromPreferenceXml(mContext,
+ R.xml.accessibility_button_settings);
+
+ assertThat(keys).isNotNull();
+ assertThat(niks).containsAtLeastElementsIn(keys);
+ }
+
+ @Test
+ @EnableFlags(com.android.settings.accessibility.Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
+ public void getNonIndexableKeys_hasTargets_expectedKeys() {
+ Settings.Secure.putStringForUser(mContext.getContentResolver(),
+ ShortcutUtils.convertToKey(SOFTWARE), "Foo", mContext.getUserId());
+ final List niks = AccessibilityButtonFragment.SEARCH_INDEX_DATA_PROVIDER
+ .getNonIndexableKeys(mContext);
+
+ // Some keys should show up anyway, as they're flagged as unsearchable in the xml.
+ assertThat(niks).containsAtLeast(
+ "accessibility_button_preview",
+ "accessibility_button_footer",
+ "accessibility_button_or_gesture");
}
private static class TestAccessibilityButtonFragment extends AccessibilityButtonFragment {
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonPreferenceControllerTest.java
index 85aa77c1ab8..e5169cd0082 100644
--- a/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityButtonPreferenceControllerTest.java
@@ -20,6 +20,10 @@ import static android.provider.Settings.Secure.NAVIGATION_MODE;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_2BUTTON;
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
+import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE;
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
@@ -31,12 +35,15 @@ import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Flags;
import android.provider.Settings;
+import android.view.accessibility.AccessibilityManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
+import com.android.settings.testutils.shadow.SettingsShadowResources;
+import com.android.settings.testutils.shadow.ShadowAccessibilityManager;
import com.android.settingslib.search.SearchIndexableRaw;
import org.junit.Before;
@@ -48,11 +55,17 @@ import org.mockito.Spy;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
import java.util.ArrayList;
import java.util.List;
/** Tests for {@link AccessibilityButtonPreferenceController}. */
+@Config(shadows = {
+ SettingsShadowResources.class,
+ com.android.settings.testutils.shadow.ShadowAccessibilityManager.class
+})
@RunWith(RobolectricTestRunner.class)
public class AccessibilityButtonPreferenceControllerTest {
@@ -68,9 +81,12 @@ public class AccessibilityButtonPreferenceControllerTest {
private PreferenceScreen mScreen;
private Preference mPreference;
private AccessibilityButtonPreferenceController mController;
+ private ShadowAccessibilityManager mShadowAccessibilityManager;
@Before
public void setUp() {
+ mShadowAccessibilityManager = Shadow.extract(
+ mContext.getSystemService(AccessibilityManager.class));
mController = new AccessibilityButtonPreferenceController(mContext, "test_key");
mPreference = new Preference(mContext);
mPreference.setKey("test_key");
@@ -163,4 +179,20 @@ public class AccessibilityButtonPreferenceControllerTest {
assertThat(raw.screenTitle).isEqualTo(
mResources.getString(R.string.accessibility_shortcuts_settings_title));
}
+
+ @Test
+ @EnableFlags(com.android.settings.accessibility.Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
+ public void getAvailabilityStatus_settingEmpty_disabled() {
+ mShadowAccessibilityManager.setAccessibilityShortcutTargets(SOFTWARE, List.of());
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING);
+ }
+
+ @Test
+ @EnableFlags(com.android.settings.accessibility.Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
+ public void getAvailabilityStatus_settingNotEmpty_available() {
+ mShadowAccessibilityManager.setAccessibilityShortcutTargets(SOFTWARE, List.of("Foo"));
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+ }
}
diff --git a/tests/unit/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/accessibility/HardwareShortcutFromLockscreenPreferenceControllerTest.java
similarity index 56%
rename from tests/unit/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceControllerTest.java
rename to tests/robotests/src/com/android/settings/accessibility/HardwareShortcutFromLockscreenPreferenceControllerTest.java
index 7d903ee01a4..30541a6a2b6 100644
--- a/tests/unit/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/HardwareShortcutFromLockscreenPreferenceControllerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2020 The Android Open Source Project
+ * 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.
@@ -16,36 +16,57 @@
package com.android.settings.accessibility;
+import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.HARDWARE;
import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
-
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING;
import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.os.UserHandle;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
+import android.view.accessibility.AccessibilityManager;
import androidx.preference.SwitchPreference;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.testutils.shadow.SettingsShadowResources;
+import com.android.settings.testutils.shadow.ShadowAccessibilityManager;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
-@RunWith(AndroidJUnit4.class)
-public class AccessibilityShortcutPreferenceControllerTest {
+import java.util.List;
- private Context mContext;
+@Config(shadows = {
+ SettingsShadowResources.class,
+ com.android.settings.testutils.shadow.ShadowAccessibilityManager.class
+})
+@RunWith(RobolectricTestRunner.class)
+public class HardwareShortcutFromLockscreenPreferenceControllerTest {
+ @Rule
+ public SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
+ private Context mContext = ApplicationProvider.getApplicationContext();
private SwitchPreference mPreference;
- private AccessibilityShortcutPreferenceController mController;
+ private HardwareShortcutFromLockscreenPreferenceController mController;
+ private ShadowAccessibilityManager mShadowAccessibilityManager;
@Before
public void setUp() {
- mContext = ApplicationProvider.getApplicationContext();
+ mShadowAccessibilityManager = Shadow.extract(
+ mContext.getSystemService(AccessibilityManager.class));
mPreference = new SwitchPreference(mContext);
- mController = new AccessibilityShortcutPreferenceController(mContext,
+ mController = new HardwareShortcutFromLockscreenPreferenceController(mContext,
"accessibility_shortcut_preference");
}
@@ -89,4 +110,20 @@ public class AccessibilityShortcutPreferenceControllerTest {
Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN, ON,
UserHandle.USER_CURRENT)).isEqualTo(OFF);
}
+
+ @Test
+ @EnableFlags(Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
+ public void getAvailabilityStatus_settingEmpty_disabled() {
+ mShadowAccessibilityManager.setAccessibilityShortcutTargets(HARDWARE, List.of());
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING);
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
+ public void getAvailabilityStatus_settingNotEmpty_available() {
+ mShadowAccessibilityManager.setAccessibilityShortcutTargets(HARDWARE, List.of("Foo"));
+
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/display/ColorContrastFragmentTest.java b/tests/robotests/src/com/android/settings/display/ColorContrastFragmentTest.java
index 47a7363b531..1e6827ba9f3 100644
--- a/tests/robotests/src/com/android/settings/display/ColorContrastFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/display/ColorContrastFragmentTest.java
@@ -28,7 +28,6 @@ import android.content.Context;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
-import com.android.settings.accessibility.ShortcutsSettingsFragment;
import com.android.settings.testutils.XmlTestUtils;
import org.junit.Before;
@@ -79,7 +78,7 @@ public class ColorContrastFragmentTest {
@Test
public void getNonIndexableKeys_existInXmlLayout() {
final List niks =
- ShortcutsSettingsFragment.SEARCH_INDEX_DATA_PROVIDER
+ ColorContrastFragment.SEARCH_INDEX_DATA_PROVIDER
.getNonIndexableKeys(mContext);
final List keys =
XmlTestUtils.getKeysFromPreferenceXml(mContext,
diff --git a/tests/unit/src/com/android/settings/network/CellularSecurityPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/CellularSecurityPreferenceControllerTest.java
index 7f05913cd82..03f6bcdb238 100644
--- a/tests/unit/src/com/android/settings/network/CellularSecurityPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/CellularSecurityPreferenceControllerTest.java
@@ -26,7 +26,6 @@ import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -50,7 +49,6 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
@@ -148,36 +146,17 @@ public final class CellularSecurityPreferenceControllerTest {
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
}
- @Test
- public void handlePreferenceTreeClick_safetyCenterSupported_shouldRedirectToSafetyCenter() {
- final ArgumentCaptor intentCaptor = ArgumentCaptor.forClass(Intent.class);
-
- doReturn(true).when(mTelephonyManager).isNullCipherNotificationsEnabled();
- doReturn(true).when(mTelephonyManager)
- .isCellularIdentifierDisclosureNotificationsEnabled();
- doReturn(true).when(mTelephonyManager).isNullCipherAndIntegrityPreferenceEnabled();
- boolean prefHandled = mController.handlePreferenceTreeClick(mPreference);
-
- assertThat(prefHandled).isTrue();
- verify(mContext).startActivity(intentCaptor.capture());
- assertThat(intentCaptor.getValue().getAction()).isEqualTo(Intent.ACTION_SAFETY_CENTER);
- }
-
private void enableFlags(boolean enabled) {
if (enabled) {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS);
mSetFlagsRule.enableFlags(
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS);
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY);
- mSetFlagsRule.enableFlags(
- Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY);
} else {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS);
mSetFlagsRule.disableFlags(
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS);
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY);
- mSetFlagsRule.disableFlags(
- Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY);
}
}
}
diff --git a/tests/unit/src/com/android/settings/network/telephony/CellularSecurityNotificationsDividerControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/CellularSecurityNotificationsDividerControllerTest.java
index 4e2351f1c7d..998f82ef9eb 100644
--- a/tests/unit/src/com/android/settings/network/telephony/CellularSecurityNotificationsDividerControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/telephony/CellularSecurityNotificationsDividerControllerTest.java
@@ -129,15 +129,11 @@ public class CellularSecurityNotificationsDividerControllerTest {
mSetFlagsRule.enableFlags(
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS);
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY);
- mSetFlagsRule.enableFlags(
- Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY);
} else {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS);
mSetFlagsRule.disableFlags(
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS);
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY);
- mSetFlagsRule.disableFlags(
- Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY);
}
}
}
diff --git a/tests/unit/src/com/android/settings/network/telephony/CellularSecurityNotificationsPreferenceControllerTest.java b/tests/unit/src/com/android/settings/network/telephony/CellularSecurityNotificationsPreferenceControllerTest.java
index 8a72bd5fae3..c520918c665 100644
--- a/tests/unit/src/com/android/settings/network/telephony/CellularSecurityNotificationsPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/network/telephony/CellularSecurityNotificationsPreferenceControllerTest.java
@@ -233,15 +233,11 @@ public class CellularSecurityNotificationsPreferenceControllerTest {
mSetFlagsRule.enableFlags(
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS);
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY);
- mSetFlagsRule.enableFlags(
- Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY);
} else {
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS);
mSetFlagsRule.disableFlags(
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS);
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY);
- mSetFlagsRule.disableFlags(
- Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY);
}
}
}