Snap for 12985272 from 574ba31dd3 to 25Q2-release
Change-Id: Ica67b141b05b2ca06c736022ff72d8c0690cda8b
This commit is contained in:
@@ -132,6 +132,7 @@
|
|||||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||||
<uses-permission android:name="android.permission.READ_APP_SPECIFIC_LOCALES" />
|
<uses-permission android:name="android.permission.READ_APP_SPECIFIC_LOCALES" />
|
||||||
<uses-permission android:name="android.permission.QUERY_ADMIN_POLICY" />
|
<uses-permission android:name="android.permission.QUERY_ADMIN_POLICY" />
|
||||||
|
<uses-permission android:name="android.permission.MANAGE_SAFETY_CENTER" />
|
||||||
<uses-permission android:name="android.permission.READ_SAFETY_CENTER_STATUS" />
|
<uses-permission android:name="android.permission.READ_SAFETY_CENTER_STATUS" />
|
||||||
<uses-permission android:name="android.permission.SEND_SAFETY_CENTER_UPDATE" />
|
<uses-permission android:name="android.permission.SEND_SAFETY_CENTER_UPDATE" />
|
||||||
<uses-permission android:name="android.permission.START_VIEW_APP_FEATURES" />
|
<uses-permission android:name="android.permission.START_VIEW_APP_FEATURES" />
|
||||||
|
|||||||
@@ -848,4 +848,7 @@
|
|||||||
|
|
||||||
<!-- Disable the Testing Setting Menu for user builds, i.e only display the menu on userdebug/eng builds -->
|
<!-- Disable the Testing Setting Menu for user builds, i.e only display the menu on userdebug/eng builds -->
|
||||||
<bool name="config_hide_testing_settings_menu_for_user_builds">false</bool>
|
<bool name="config_hide_testing_settings_menu_for_user_builds">false</bool>
|
||||||
|
|
||||||
|
<!-- Whether the Gaze is enabled -->
|
||||||
|
<bool name="config_gazeEnabled">false</bool>
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
@@ -924,6 +924,10 @@
|
|||||||
<string name="security_settings_face_settings_require_attention">Require eyes to be open</string>
|
<string name="security_settings_face_settings_require_attention">Require eyes to be open</string>
|
||||||
<!-- Text shown on the details of a toggle which disables/enables face unlock, depending if the user's eyes are open. [CHAR LIMIT=70] -->
|
<!-- Text shown on the details of a toggle which disables/enables face unlock, depending if the user's eyes are open. [CHAR LIMIT=70] -->
|
||||||
<string name="security_settings_face_settings_require_attention_details">To unlock the phone, your eyes must be open</string>
|
<string name="security_settings_face_settings_require_attention_details">To unlock the phone, your eyes must be open</string>
|
||||||
|
<!-- Text shown on a toggle which disables/enables face unlock, depending if the gaze supported. [CHAR LIMIT=30] -->
|
||||||
|
<string name="security_settings_face_settings_gaze"></string>
|
||||||
|
<!-- Text shown on the details of a toggle which disables/enables face unlock, depending if the gaze supported. [CHAR LIMIT=70] -->
|
||||||
|
<string name="security_settings_face_settings_gaze_details"></string>
|
||||||
<!-- When authenticating in apps, always require confirmation (e.g. confirm button) after a face is authenticated. [CHAR LIMIT=50] -->
|
<!-- When authenticating in apps, always require confirmation (e.g. confirm button) after a face is authenticated. [CHAR LIMIT=50] -->
|
||||||
<string name="security_settings_face_settings_require_confirmation">Always require confirmation</string>
|
<string name="security_settings_face_settings_require_confirmation">Always require confirmation</string>
|
||||||
<!-- When authenticating in apps, always require confirmation (e.g. confirm button) after a face is authenticated. [CHAR LIMIT=70] -->
|
<!-- When authenticating in apps, always require confirmation (e.g. confirm button) after a face is authenticated. [CHAR LIMIT=70] -->
|
||||||
@@ -5722,6 +5726,8 @@
|
|||||||
<string name="accessibility_shortcut_edit_screen_title">Edit accessibility shortcuts</string>
|
<string name="accessibility_shortcut_edit_screen_title">Edit accessibility shortcuts</string>
|
||||||
<!-- Prompt for editing the shortcuts of multiple accessibility features. [CHAR LIMIT=NONE] -->
|
<!-- Prompt for editing the shortcuts of multiple accessibility features. [CHAR LIMIT=NONE] -->
|
||||||
<string name="accessibility_shortcut_edit_screen_prompt">Choose your shortcut for %1$s</string>
|
<string name="accessibility_shortcut_edit_screen_prompt">Choose your shortcut for %1$s</string>
|
||||||
|
<!-- Summary to display when a shortcut setting is disabled, due to the shortcut being unassigned -->
|
||||||
|
<string name="accessibility_shortcut_unassigned_setting_unavailable_summary">To use this, turn on the %1$s shortcut on an accessibility feature\'s page</string>
|
||||||
|
|
||||||
<!-- Button text for the accessibility dialog continue to the next screen for hearing aid. [CHAR LIMIT=32] -->
|
<!-- Button text for the accessibility dialog continue to the next screen for hearing aid. [CHAR LIMIT=32] -->
|
||||||
<string name="accessibility_hearingaid_instruction_continue_button">Continue</string>
|
<string name="accessibility_hearingaid_instruction_continue_button">Continue</string>
|
||||||
|
|||||||
@@ -19,7 +19,8 @@
|
|||||||
xmlns:settings="http://schemas.android.com/apk/res-auto"
|
xmlns:settings="http://schemas.android.com/apk/res-auto"
|
||||||
android:key="accessibility_shortcuts_settings"
|
android:key="accessibility_shortcuts_settings"
|
||||||
android:persistent="false"
|
android:persistent="false"
|
||||||
android:title="@string/accessibility_shortcuts_settings_title">
|
android:title="@string/accessibility_shortcuts_settings_title"
|
||||||
|
settings:searchable="false">
|
||||||
|
|
||||||
<Preference
|
<Preference
|
||||||
android:fragment="com.android.settings.accessibility.AccessibilityButtonFragment"
|
android:fragment="com.android.settings.accessibility.AccessibilityButtonFragment"
|
||||||
@@ -33,5 +34,5 @@
|
|||||||
android:persistent="false"
|
android:persistent="false"
|
||||||
android:title="@string/accessibility_shortcut_service_on_lock_screen_title"
|
android:title="@string/accessibility_shortcut_service_on_lock_screen_title"
|
||||||
android:summary="@string/accessibility_shortcut_description"
|
android:summary="@string/accessibility_shortcut_description"
|
||||||
settings:controller="com.android.settings.accessibility.AccessibilityShortcutPreferenceController"/>
|
settings:controller="com.android.settings.accessibility.HardwareShortcutFromLockscreenPreferenceController"/>
|
||||||
</PreferenceScreen>
|
</PreferenceScreen>
|
||||||
|
|||||||
@@ -16,9 +16,14 @@
|
|||||||
|
|
||||||
package com.android.settings.accessibility;
|
package com.android.settings.accessibility;
|
||||||
|
|
||||||
import android.app.settings.SettingsEnums;
|
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE;
|
||||||
import android.os.Bundle;
|
|
||||||
|
|
||||||
|
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.R;
|
||||||
import com.android.settings.dashboard.DashboardFragment;
|
import com.android.settings.dashboard.DashboardFragment;
|
||||||
import com.android.settings.search.BaseSearchIndexProvider;
|
import com.android.settings.search.BaseSearchIndexProvider;
|
||||||
@@ -61,5 +66,13 @@ public class AccessibilityButtonFragment extends DashboardFragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
|
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();
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,9 +16,13 @@
|
|||||||
|
|
||||||
package com.android.settings.accessibility;
|
package com.android.settings.accessibility;
|
||||||
|
|
||||||
|
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
|
import android.view.accessibility.AccessibilityManager;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
import androidx.preference.PreferenceScreen;
|
import androidx.preference.PreferenceScreen;
|
||||||
|
|
||||||
@@ -32,14 +36,39 @@ import java.util.List;
|
|||||||
* Preference controller for accessibility button preference.
|
* Preference controller for accessibility button preference.
|
||||||
*/
|
*/
|
||||||
public class AccessibilityButtonPreferenceController extends BasePreferenceController {
|
public class AccessibilityButtonPreferenceController extends BasePreferenceController {
|
||||||
|
|
||||||
public AccessibilityButtonPreferenceController(Context context, String key) {
|
public AccessibilityButtonPreferenceController(Context context, String key) {
|
||||||
super(context, key);
|
super(context, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getAvailabilityStatus() {
|
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
|
@Override
|
||||||
@@ -47,7 +76,6 @@ public class AccessibilityButtonPreferenceController extends BasePreferenceContr
|
|||||||
super.displayPreference(screen);
|
super.displayPreference(screen);
|
||||||
final Preference preference = screen.findPreference(getPreferenceKey());
|
final Preference preference = screen.findPreference(getPreferenceKey());
|
||||||
preference.setTitle(getPreferenceTitleResource());
|
preference.setTitle(getPreferenceTitleResource());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
package com.android.settings.accessibility;
|
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.OFF;
|
||||||
import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
|
import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
|
||||||
|
|
||||||
@@ -22,16 +23,21 @@ import android.content.ContentResolver;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
import android.provider.Settings;
|
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.R;
|
||||||
import com.android.settings.core.TogglePreferenceController;
|
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 class HardwareShortcutFromLockscreenPreferenceController
|
||||||
|
extends TogglePreferenceController {
|
||||||
public AccessibilityShortcutPreferenceController(Context context, String preferenceKey) {
|
public HardwareShortcutFromLockscreenPreferenceController(
|
||||||
|
Context context, String preferenceKey) {
|
||||||
super(context, preferenceKey);
|
super(context, preferenceKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +62,33 @@ public class AccessibilityShortcutPreferenceController extends TogglePreferenceC
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int getAvailabilityStatus() {
|
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
|
@Override
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -69,6 +69,7 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
|
|||||||
private View mIllustrationAccessibility;
|
private View mIllustrationAccessibility;
|
||||||
private Intent mResultIntent;
|
private Intent mResultIntent;
|
||||||
private boolean mAccessibilityEnabled;
|
private boolean mAccessibilityEnabled;
|
||||||
|
protected Intent mExtraInfoIntent;
|
||||||
|
|
||||||
private final CompoundButton.OnCheckedChangeListener mSwitchDiversityListener =
|
private final CompoundButton.OnCheckedChangeListener mSwitchDiversityListener =
|
||||||
new CompoundButton.OnCheckedChangeListener() {
|
new CompoundButton.OnCheckedChangeListener() {
|
||||||
@@ -171,12 +172,7 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
|
|||||||
mFooterBarMixin.setPrimaryButton(footerButton);
|
mFooterBarMixin.setPrimaryButton(footerButton);
|
||||||
|
|
||||||
final Button accessibilityButton = findViewById(R.id.accessibility_button);
|
final Button accessibilityButton = findViewById(R.id.accessibility_button);
|
||||||
accessibilityButton.setOnClickListener(view -> {
|
accessibilityButton.setOnClickListener(this::onAccessibilityButtonClicked);
|
||||||
mSwitchDiversity.setChecked(true);
|
|
||||||
accessibilityButton.setVisibility(View.GONE);
|
|
||||||
mSwitchDiversity.setVisibility(View.VISIBLE);
|
|
||||||
mSwitchDiversity.addOnLayoutChangeListener(mSwitchDiversityOnLayoutChangeListener);
|
|
||||||
});
|
|
||||||
|
|
||||||
mSwitchDiversity = findViewById(R.id.toggle_diversity);
|
mSwitchDiversity = findViewById(R.id.toggle_diversity);
|
||||||
mSwitchDiversity.setListener(mSwitchDiversityListener);
|
mSwitchDiversity.setListener(mSwitchDiversityListener);
|
||||||
@@ -263,6 +259,9 @@ public class FaceEnrollEducation extends BiometricEnrollBase {
|
|||||||
if (mResultIntent != null) {
|
if (mResultIntent != null) {
|
||||||
intent.putExtras(mResultIntent);
|
intent.putExtras(mResultIntent);
|
||||||
}
|
}
|
||||||
|
if (mExtraInfoIntent != null) {
|
||||||
|
intent.putExtras(mExtraInfoIntent);
|
||||||
|
}
|
||||||
|
|
||||||
intent.putExtra(EXTRA_KEY_REQUIRE_DIVERSITY, !mSwitchDiversity.isChecked());
|
intent.putExtra(EXTRA_KEY_REQUIRE_DIVERSITY, !mSwitchDiversity.isChecked());
|
||||||
intent.putExtra(BiometricUtils.EXTRA_ENROLL_REASON,
|
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) {
|
protected void onSkipButtonClick(View view) {
|
||||||
if (!BiometricUtils.tryStartingNextBiometricEnroll(this, ENROLL_NEXT_BIOMETRIC_REQUEST,
|
if (!BiometricUtils.tryStartingNextBiometricEnroll(this, ENROLL_NEXT_BIOMETRIC_REQUEST,
|
||||||
"edu_skip")) {
|
"edu_skip")) {
|
||||||
|
|||||||
@@ -16,12 +16,8 @@
|
|||||||
|
|
||||||
package com.android.settings.biometrics.face;
|
package com.android.settings.biometrics.face;
|
||||||
|
|
||||||
import static android.hardware.biometrics.BiometricFaceConstants.FEATURE_REQUIRE_ATTENTION;
|
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.hardware.face.FaceManager;
|
import android.hardware.face.FaceManager;
|
||||||
import android.hardware.face.FaceManager.GetFeatureCallback;
|
|
||||||
import android.hardware.face.FaceManager.SetFeatureCallback;
|
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
@@ -31,6 +27,7 @@ import androidx.preference.TwoStatePreference;
|
|||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.Utils;
|
import com.android.settings.Utils;
|
||||||
|
import com.android.settings.flags.Flags;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preference controller that manages the ability to use face authentication with/without
|
* 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";
|
public static final String KEY = "security_settings_face_require_attention";
|
||||||
|
|
||||||
private byte[] mToken;
|
|
||||||
private FaceManager mFaceManager;
|
|
||||||
private TwoStatePreference mPreference;
|
private TwoStatePreference mPreference;
|
||||||
|
private boolean mGazeEnabled;
|
||||||
|
|
||||||
private final SetFeatureCallback mSetFeatureCallback = new SetFeatureCallback() {
|
private FaceAttentionController mFaceAttentionController;
|
||||||
@Override
|
|
||||||
public void onCompleted(boolean success, int feature) {
|
private final FaceAttentionController.OnSetAttentionListener mSetAttentionListener =
|
||||||
if (feature == FEATURE_REQUIRE_ATTENTION) {
|
(success) -> {
|
||||||
mPreference.setEnabled(true);
|
mPreference.setEnabled(true);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
mPreference.setChecked(!mPreference.isChecked());
|
mPreference.setChecked(!mPreference.isChecked());
|
||||||
@@ -56,31 +52,23 @@ public class FaceSettingsAttentionPreferenceController extends FaceSettingsPrefe
|
|||||||
Settings.Secure.FACE_UNLOCK_ATTENTION_REQUIRED,
|
Settings.Secure.FACE_UNLOCK_ATTENTION_REQUIRED,
|
||||||
mPreference.isChecked() ? 1 : 0, getUserId());
|
mPreference.isChecked() ? 1 : 0, getUserId());
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private final GetFeatureCallback mGetFeatureCallback = new GetFeatureCallback() {
|
private final FaceAttentionController.OnGetAttentionListener mOnGetAttentionListener =
|
||||||
@Override
|
(success, requireAttentionEnabled) -> {
|
||||||
public void onCompleted(boolean success, int[] features, boolean[] featureState) {
|
mPreference.setChecked(requireAttentionEnabled);
|
||||||
boolean requireAttentionEnabled = false;
|
if (getRestrictingAdmin() != null) {
|
||||||
for (int i = 0; i < features.length; i++) {
|
mPreference.setEnabled(false);
|
||||||
if (features[i] == FEATURE_REQUIRE_ATTENTION) {
|
} else {
|
||||||
requireAttentionEnabled = featureState[i];
|
mPreference.setEnabled(success);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
mPreference.setChecked(requireAttentionEnabled);
|
|
||||||
if (getRestrictingAdmin() != null) {
|
|
||||||
mPreference.setEnabled(false);
|
|
||||||
} else {
|
|
||||||
mPreference.setEnabled(success);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
public FaceSettingsAttentionPreferenceController(Context context, String preferenceKey) {
|
public FaceSettingsAttentionPreferenceController(Context context, String preferenceKey) {
|
||||||
super(context, 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) {
|
public FaceSettingsAttentionPreferenceController(Context context) {
|
||||||
@@ -88,7 +76,9 @@ public class FaceSettingsAttentionPreferenceController extends FaceSettingsPrefe
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setToken(byte[] token) {
|
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)) {
|
if (Utils.isPrivateProfile(getUserId(), mContext)) {
|
||||||
preference.setSummary(mContext.getString(
|
preference.setSummary(mContext.getString(
|
||||||
R.string.private_space_face_settings_require_attention_details));
|
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.
|
// Set to disabled until we know the true value.
|
||||||
mPreference.setEnabled(false);
|
mPreference.setEnabled(false);
|
||||||
mFaceManager.getFeature(getUserId(), FEATURE_REQUIRE_ATTENTION,
|
mFaceAttentionController.getAttentionStatus(getUserId(), mOnGetAttentionListener);
|
||||||
mGetFeatureCallback);
|
|
||||||
|
|
||||||
// Ideally returns a cached value.
|
// Ideally returns a cached value.
|
||||||
return true;
|
return true;
|
||||||
@@ -131,9 +125,7 @@ public class FaceSettingsAttentionPreferenceController extends FaceSettingsPrefe
|
|||||||
// Optimistically update state and set to disabled until we know it succeeded.
|
// Optimistically update state and set to disabled until we know it succeeded.
|
||||||
mPreference.setEnabled(false);
|
mPreference.setEnabled(false);
|
||||||
mPreference.setChecked(isChecked);
|
mPreference.setChecked(isChecked);
|
||||||
|
mFaceAttentionController.setAttentionStatus(getUserId(), isChecked, mSetAttentionListener);
|
||||||
mFaceManager.setFeature(getUserId(), FEATURE_REQUIRE_ATTENTION,
|
|
||||||
isChecked, mToken, mSetFeatureCallback);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ public class DesktopModePreferenceController extends DeveloperOptionsPreferenceC
|
|||||||
final boolean shouldDevOptionBeEnabled = switch (toggleOverride) {
|
final boolean shouldDevOptionBeEnabled = switch (toggleOverride) {
|
||||||
case OVERRIDE_OFF -> false;
|
case OVERRIDE_OFF -> false;
|
||||||
case OVERRIDE_ON -> true;
|
case OVERRIDE_ON -> true;
|
||||||
case OVERRIDE_UNSET -> DesktopModeStatus.shouldDevOptionBeEnabledByDefault();
|
case OVERRIDE_UNSET -> DesktopModeStatus.shouldDevOptionBeEnabledByDefault(mContext);
|
||||||
};
|
};
|
||||||
((TwoStatePreference) mPreference).setChecked(shouldDevOptionBeEnabled);
|
((TwoStatePreference) mPreference).setChecked(shouldDevOptionBeEnabled);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ import android.content.pm.PackageManager;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.safetycenter.SafetyCenterManager;
|
import android.safetycenter.SafetyCenterManager;
|
||||||
|
import android.safetycenter.SafetySourceData;
|
||||||
import android.telephony.SubscriptionInfo;
|
import android.telephony.SubscriptionInfo;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
@@ -48,6 +49,7 @@ import java.util.List;
|
|||||||
public class CellularSecurityPreferenceController extends BasePreferenceController {
|
public class CellularSecurityPreferenceController extends BasePreferenceController {
|
||||||
|
|
||||||
private static final String LOG_TAG = "CellularSecurityPreferenceController";
|
private static final String LOG_TAG = "CellularSecurityPreferenceController";
|
||||||
|
private static final String SAFETY_SOURCE_ID = "AndroidCellularNetworkSecurity";
|
||||||
|
|
||||||
private @Nullable TelephonyManager mTelephonyManager;
|
private @Nullable TelephonyManager mTelephonyManager;
|
||||||
|
|
||||||
@@ -72,7 +74,6 @@ public class CellularSecurityPreferenceController extends BasePreferenceControll
|
|||||||
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
|
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY)
|
||||||
|| !Flags.enableIdentifierDisclosureTransparencyUnsolEvents()
|
|| !Flags.enableIdentifierDisclosureTransparencyUnsolEvents()
|
||||||
|| !Flags.enableModemCipherTransparencyUnsolEvents()
|
|| !Flags.enableModemCipherTransparencyUnsolEvents()
|
||||||
|| !Flags.enableIdentifierDisclosureTransparency()
|
|
||||||
|| !Flags.enableModemCipherTransparency()) {
|
|| !Flags.enableModemCipherTransparency()) {
|
||||||
return UNSUPPORTED_ON_DEVICE;
|
return UNSUPPORTED_ON_DEVICE;
|
||||||
}
|
}
|
||||||
@@ -134,13 +135,30 @@ public class CellularSecurityPreferenceController extends BasePreferenceControll
|
|||||||
if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
|
if (!TextUtils.equals(preference.getKey(), getPreferenceKey())) {
|
||||||
return super.handlePreferenceTreeClick(preference);
|
return super.handlePreferenceTreeClick(preference);
|
||||||
}
|
}
|
||||||
boolean isSafetyCenterSupported = isSafetyCenterSupported();
|
if (!isSafetyCenterSupported()) {
|
||||||
if (isSafetyCenterSupported && areNotificationsEnabled()) {
|
// 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);
|
Intent safetyCenterIntent = new Intent(Intent.ACTION_SAFETY_CENTER);
|
||||||
safetyCenterIntent.putExtra(SafetyCenterManager.EXTRA_SAFETY_SOURCES_GROUP_ID,
|
safetyCenterIntent.putExtra(SafetyCenterManager.EXTRA_SAFETY_SOURCES_GROUP_ID,
|
||||||
"AndroidCellularNetworkSecuritySources");
|
"AndroidCellularNetworkSecuritySources");
|
||||||
mContext.startActivity(safetyCenterIntent);
|
mContext.startActivity(safetyCenterIntent);
|
||||||
} else {
|
} else {
|
||||||
|
Log.v(LOG_TAG, "Hardware APIs not enabled, or data source is null.");
|
||||||
final Bundle bundle = new Bundle();
|
final Bundle bundle = new Bundle();
|
||||||
bundle.putString(CellularSecuritySettingsFragment.KEY_CELLULAR_SECURITY_PREFERENCE, "");
|
bundle.putString(CellularSecuritySettingsFragment.KEY_CELLULAR_SECURITY_PREFERENCE, "");
|
||||||
|
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ public class CellularSecurityNotificationsDividerController extends
|
|||||||
public int getAvailabilityStatus() {
|
public int getAvailabilityStatus() {
|
||||||
if (!Flags.enableIdentifierDisclosureTransparencyUnsolEvents()
|
if (!Flags.enableIdentifierDisclosureTransparencyUnsolEvents()
|
||||||
|| !Flags.enableModemCipherTransparencyUnsolEvents()
|
|| !Flags.enableModemCipherTransparencyUnsolEvents()
|
||||||
|| !Flags.enableIdentifierDisclosureTransparency()
|
|
||||||
|| !Flags.enableModemCipherTransparency()) {
|
|| !Flags.enableModemCipherTransparency()) {
|
||||||
return UNSUPPORTED_ON_DEVICE;
|
return UNSUPPORTED_ON_DEVICE;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -180,7 +180,6 @@ public class CellularSecurityNotificationsPreferenceController extends
|
|||||||
private boolean areFlagsEnabled() {
|
private boolean areFlagsEnabled() {
|
||||||
if (!Flags.enableIdentifierDisclosureTransparencyUnsolEvents()
|
if (!Flags.enableIdentifierDisclosureTransparencyUnsolEvents()
|
||||||
|| !Flags.enableModemCipherTransparencyUnsolEvents()
|
|| !Flags.enableModemCipherTransparencyUnsolEvents()
|
||||||
|| !Flags.enableIdentifierDisclosureTransparency()
|
|
||||||
|| !Flags.enableModemCipherTransparency()) {
|
|| !Flags.enableModemCipherTransparency()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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_2BUTTON;
|
||||||
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
|
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 com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
@@ -39,6 +41,7 @@ import androidx.preference.PreferenceManager;
|
|||||||
import androidx.preference.PreferenceScreen;
|
import androidx.preference.PreferenceScreen;
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
|
import com.android.internal.accessibility.util.ShortcutUtils;
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.testutils.XmlTestUtils;
|
import com.android.settings.testutils.XmlTestUtils;
|
||||||
import com.android.settings.testutils.shadow.ShadowFragment;
|
import com.android.settings.testutils.shadow.ShadowFragment;
|
||||||
@@ -132,6 +135,7 @@ public class AccessibilityButtonFragmentTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@DisableFlags(com.android.settings.accessibility.Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
|
||||||
public void getNonIndexableKeys_existInXmlLayout() {
|
public void getNonIndexableKeys_existInXmlLayout() {
|
||||||
final List<String> niks = AccessibilityButtonFragment.SEARCH_INDEX_DATA_PROVIDER
|
final List<String> niks = AccessibilityButtonFragment.SEARCH_INDEX_DATA_PROVIDER
|
||||||
.getNonIndexableKeys(mContext);
|
.getNonIndexableKeys(mContext);
|
||||||
@@ -139,7 +143,38 @@ public class AccessibilityButtonFragmentTest {
|
|||||||
XmlTestUtils.getKeysFromPreferenceXml(mContext,
|
XmlTestUtils.getKeysFromPreferenceXml(mContext,
|
||||||
R.xml.accessibility_button_settings);
|
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<String> niks = AccessibilityButtonFragment.SEARCH_INDEX_DATA_PROVIDER
|
||||||
|
.getNonIndexableKeys(mContext);
|
||||||
|
final List<String> 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<String> 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 {
|
private static class TestAccessibilityButtonFragment extends AccessibilityButtonFragment {
|
||||||
|
|||||||
@@ -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_2BUTTON;
|
||||||
import static android.view.WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL;
|
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 com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import static org.mockito.Mockito.when;
|
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.platform.test.flag.junit.SetFlagsRule;
|
||||||
import android.provider.Flags;
|
import android.provider.Flags;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
import android.view.accessibility.AccessibilityManager;
|
||||||
|
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
import androidx.preference.PreferenceScreen;
|
import androidx.preference.PreferenceScreen;
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
import com.android.settings.R;
|
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 com.android.settingslib.search.SearchIndexableRaw;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -48,11 +55,17 @@ import org.mockito.Spy;
|
|||||||
import org.mockito.junit.MockitoJUnit;
|
import org.mockito.junit.MockitoJUnit;
|
||||||
import org.mockito.junit.MockitoRule;
|
import org.mockito.junit.MockitoRule;
|
||||||
import org.robolectric.RobolectricTestRunner;
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
import org.robolectric.shadow.api.Shadow;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/** Tests for {@link AccessibilityButtonPreferenceController}. */
|
/** Tests for {@link AccessibilityButtonPreferenceController}. */
|
||||||
|
@Config(shadows = {
|
||||||
|
SettingsShadowResources.class,
|
||||||
|
com.android.settings.testutils.shadow.ShadowAccessibilityManager.class
|
||||||
|
})
|
||||||
@RunWith(RobolectricTestRunner.class)
|
@RunWith(RobolectricTestRunner.class)
|
||||||
public class AccessibilityButtonPreferenceControllerTest {
|
public class AccessibilityButtonPreferenceControllerTest {
|
||||||
|
|
||||||
@@ -68,9 +81,12 @@ public class AccessibilityButtonPreferenceControllerTest {
|
|||||||
private PreferenceScreen mScreen;
|
private PreferenceScreen mScreen;
|
||||||
private Preference mPreference;
|
private Preference mPreference;
|
||||||
private AccessibilityButtonPreferenceController mController;
|
private AccessibilityButtonPreferenceController mController;
|
||||||
|
private ShadowAccessibilityManager mShadowAccessibilityManager;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
|
mShadowAccessibilityManager = Shadow.extract(
|
||||||
|
mContext.getSystemService(AccessibilityManager.class));
|
||||||
mController = new AccessibilityButtonPreferenceController(mContext, "test_key");
|
mController = new AccessibilityButtonPreferenceController(mContext, "test_key");
|
||||||
mPreference = new Preference(mContext);
|
mPreference = new Preference(mContext);
|
||||||
mPreference.setKey("test_key");
|
mPreference.setKey("test_key");
|
||||||
@@ -163,4 +179,20 @@ public class AccessibilityButtonPreferenceControllerTest {
|
|||||||
assertThat(raw.screenTitle).isEqualTo(
|
assertThat(raw.screenTitle).isEqualTo(
|
||||||
mResources.getString(R.string.accessibility_shortcuts_settings_title));
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -16,36 +16,57 @@
|
|||||||
|
|
||||||
package com.android.settings.accessibility;
|
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.OFF;
|
||||||
import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
|
import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
|
||||||
|
import static com.android.settings.core.BasePreferenceController.AVAILABLE;
|
||||||
import androidx.test.core.app.ApplicationProvider;
|
import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING;
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.os.UserHandle;
|
import android.os.UserHandle;
|
||||||
|
import android.platform.test.annotations.EnableFlags;
|
||||||
|
import android.platform.test.flag.junit.SetFlagsRule;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
import android.view.accessibility.AccessibilityManager;
|
||||||
|
|
||||||
import androidx.preference.SwitchPreference;
|
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.Before;
|
||||||
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
import org.robolectric.RobolectricTestRunner;
|
||||||
|
import org.robolectric.annotation.Config;
|
||||||
|
import org.robolectric.shadow.api.Shadow;
|
||||||
|
|
||||||
@RunWith(AndroidJUnit4.class)
|
import java.util.List;
|
||||||
public class AccessibilityShortcutPreferenceControllerTest {
|
|
||||||
|
|
||||||
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 SwitchPreference mPreference;
|
||||||
private AccessibilityShortcutPreferenceController mController;
|
private HardwareShortcutFromLockscreenPreferenceController mController;
|
||||||
|
private ShadowAccessibilityManager mShadowAccessibilityManager;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
mContext = ApplicationProvider.getApplicationContext();
|
mShadowAccessibilityManager = Shadow.extract(
|
||||||
|
mContext.getSystemService(AccessibilityManager.class));
|
||||||
mPreference = new SwitchPreference(mContext);
|
mPreference = new SwitchPreference(mContext);
|
||||||
mController = new AccessibilityShortcutPreferenceController(mContext,
|
mController = new HardwareShortcutFromLockscreenPreferenceController(mContext,
|
||||||
"accessibility_shortcut_preference");
|
"accessibility_shortcut_preference");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,4 +110,20 @@ public class AccessibilityShortcutPreferenceControllerTest {
|
|||||||
Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN, ON,
|
Settings.Secure.ACCESSIBILITY_SHORTCUT_ON_LOCK_SCREEN, ON,
|
||||||
UserHandle.USER_CURRENT)).isEqualTo(OFF);
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -28,7 +28,6 @@ import android.content.Context;
|
|||||||
import androidx.test.core.app.ApplicationProvider;
|
import androidx.test.core.app.ApplicationProvider;
|
||||||
|
|
||||||
import com.android.settings.R;
|
import com.android.settings.R;
|
||||||
import com.android.settings.accessibility.ShortcutsSettingsFragment;
|
|
||||||
import com.android.settings.testutils.XmlTestUtils;
|
import com.android.settings.testutils.XmlTestUtils;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
@@ -79,7 +78,7 @@ public class ColorContrastFragmentTest {
|
|||||||
@Test
|
@Test
|
||||||
public void getNonIndexableKeys_existInXmlLayout() {
|
public void getNonIndexableKeys_existInXmlLayout() {
|
||||||
final List<String> niks =
|
final List<String> niks =
|
||||||
ShortcutsSettingsFragment.SEARCH_INDEX_DATA_PROVIDER
|
ColorContrastFragment.SEARCH_INDEX_DATA_PROVIDER
|
||||||
.getNonIndexableKeys(mContext);
|
.getNonIndexableKeys(mContext);
|
||||||
final List<String> keys =
|
final List<String> keys =
|
||||||
XmlTestUtils.getKeysFromPreferenceXml(mContext,
|
XmlTestUtils.getKeysFromPreferenceXml(mContext,
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import static org.mockito.Mockito.doNothing;
|
|||||||
import static org.mockito.Mockito.doReturn;
|
import static org.mockito.Mockito.doReturn;
|
||||||
import static org.mockito.Mockito.doThrow;
|
import static org.mockito.Mockito.doThrow;
|
||||||
import static org.mockito.Mockito.spy;
|
import static org.mockito.Mockito.spy;
|
||||||
import static org.mockito.Mockito.verify;
|
|
||||||
import static org.mockito.Mockito.when;
|
import static org.mockito.Mockito.when;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
@@ -50,7 +49,6 @@ import org.junit.Before;
|
|||||||
import org.junit.Rule;
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.mockito.ArgumentCaptor;
|
|
||||||
import org.mockito.Mock;
|
import org.mockito.Mock;
|
||||||
import org.mockito.MockitoAnnotations;
|
import org.mockito.MockitoAnnotations;
|
||||||
|
|
||||||
@@ -148,36 +146,17 @@ public final class CellularSecurityPreferenceControllerTest {
|
|||||||
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
|
assertThat(mController.getAvailabilityStatus()).isEqualTo(UNSUPPORTED_ON_DEVICE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void handlePreferenceTreeClick_safetyCenterSupported_shouldRedirectToSafetyCenter() {
|
|
||||||
final ArgumentCaptor<Intent> 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) {
|
private void enableFlags(boolean enabled) {
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS);
|
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS);
|
||||||
mSetFlagsRule.enableFlags(
|
mSetFlagsRule.enableFlags(
|
||||||
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS);
|
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS);
|
||||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY);
|
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY);
|
||||||
mSetFlagsRule.enableFlags(
|
|
||||||
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY);
|
|
||||||
} else {
|
} else {
|
||||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS);
|
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS);
|
||||||
mSetFlagsRule.disableFlags(
|
mSetFlagsRule.disableFlags(
|
||||||
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS);
|
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS);
|
||||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY);
|
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY);
|
||||||
mSetFlagsRule.disableFlags(
|
|
||||||
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -129,15 +129,11 @@ public class CellularSecurityNotificationsDividerControllerTest {
|
|||||||
mSetFlagsRule.enableFlags(
|
mSetFlagsRule.enableFlags(
|
||||||
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS);
|
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS);
|
||||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY);
|
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY);
|
||||||
mSetFlagsRule.enableFlags(
|
|
||||||
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY);
|
|
||||||
} else {
|
} else {
|
||||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS);
|
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS);
|
||||||
mSetFlagsRule.disableFlags(
|
mSetFlagsRule.disableFlags(
|
||||||
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS);
|
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS);
|
||||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY);
|
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY);
|
||||||
mSetFlagsRule.disableFlags(
|
|
||||||
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -233,15 +233,11 @@ public class CellularSecurityNotificationsPreferenceControllerTest {
|
|||||||
mSetFlagsRule.enableFlags(
|
mSetFlagsRule.enableFlags(
|
||||||
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS);
|
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS);
|
||||||
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY);
|
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY);
|
||||||
mSetFlagsRule.enableFlags(
|
|
||||||
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY);
|
|
||||||
} else {
|
} else {
|
||||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS);
|
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY_UNSOL_EVENTS);
|
||||||
mSetFlagsRule.disableFlags(
|
mSetFlagsRule.disableFlags(
|
||||||
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS);
|
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY_UNSOL_EVENTS);
|
||||||
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY);
|
mSetFlagsRule.disableFlags(Flags.FLAG_ENABLE_MODEM_CIPHER_TRANSPARENCY);
|
||||||
mSetFlagsRule.disableFlags(
|
|
||||||
Flags.FLAG_ENABLE_IDENTIFIER_DISCLOSURE_TRANSPARENCY);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user