Snap for 12458821 from 3ef49b9d5f to 25Q1-release

Change-Id: I64b2986afe6e51870cd023d566dbf8e3e3a104b6
This commit is contained in:
Android Build Coastguard Worker
2024-10-05 01:23:23 +00:00
26 changed files with 456 additions and 883 deletions

View File

@@ -0,0 +1,9 @@
package: "com.android.settings.flags"
container: "system"
flag {
name: "catalyst_display_settings_screen"
namespace: "android_settings"
description: "Flag for Display"
bug: "323791114"
}

View File

@@ -0,0 +1,56 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright (C) 2024 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="412dp"
android:height="300dp"
android:viewportWidth="412"
android:viewportHeight="300">
<group>
<clip-path
android:pathData="M0,0h412v300h-412z"/>
<path
android:pathData="M383.9,300H28.1C12.6,300 0,287.4 0,271.9V28.1C0,12.6 12.6,0 28.1,0H383.9C399.4,0 412,12.6 412,28.1V271.9C412,287.4 399.4,300 383.9,300Z"
android:fillColor="#000000"/>
<path
android:pathData="M132.8,179.6H79.2V188.1H132.8V179.6Z"
android:fillColor="#669DF6"/>
<path
android:pathData="M172.9,179.6H142.5V188.1H172.9V179.6Z"
android:fillColor="#669DF6"/>
<path
android:pathData="M158.4,195.5H79.2V204H158.4V195.5Z"
android:fillColor="#669DF6"/>
<path
android:pathData="M202.2,195.5H168.1V204H202.2V195.5Z"
android:fillColor="#669DF6"/>
<path
android:pathData="M246,195.5H211.9V204H246V195.5Z"
android:fillColor="#669DF6"/>
<path
android:pathData="M255.8,179.6H182.7V188.1H255.8V179.6Z"
android:fillColor="#669DF6"/>
<path
android:pathData="M292.3,179.6H265.5V188.1H292.3V179.6Z"
android:fillColor="#669DF6"/>
<path
android:pathData="M328.9,179.6H302.1V188.1H328.9V179.6Z"
android:fillColor="#669DF6"/>
<path
android:pathData="M142.7,67.9H131.2C129.6,67.9 128.3,69.2 128.3,70.8H67.8C59.9,70.8 53.4,77.3 53.4,85.2V217.6C53.4,225.5 59.9,232 67.8,232H344.2C352.1,232 358.6,225.5 358.6,217.6V85.2C358.6,77.3 352.1,70.8 344.2,70.8H203.1C203.1,69.2 201.8,67.9 200.2,67.9H171.4C169.8,67.9 168.5,69.2 168.5,70.8H145.5C145.5,69.2 144.3,67.9 142.7,67.9ZM344.2,73.7C350.6,73.7 355.7,78.9 355.7,85.2V217.6C355.7,223.9 350.5,229.1 344.2,229.1H67.8C61.4,229.1 56.3,223.9 56.3,217.6V85.2C56.3,78.9 61.5,73.7 67.8,73.7H344.2Z"
android:fillColor="#80868B"/>
</group>
</vector>

View File

@@ -15,23 +15,37 @@
limitations under the License.
-->
<!-- Theme.AppCompat.DayNight is in the parent View so that it's merged with the Theme.Settings
theme below. An AppCompat descendant (which Theme.Settings isn't) is necessary to inflate
TextInputLayout. -->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/Theme.AppCompat.DayNight"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:paddingBottom="8dp">
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
<EditText
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/edit_input_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@android:id/edit"
android:minHeight="48dp"
android:maxLines="1"
android:inputType="text|textCapSentences"
android:imeOptions="actionDone"
android:selectAllOnFocus="true"
android:hint="@string/zen_mode_edit_name_hint" />
android:theme="@style/Theme.Settings"
style="?attr/textInputFilledStyle"
app:endIconMode="clear_text"
app:errorEnabled="true"
android:hint="@string/zen_mode_edit_name_hint">
</LinearLayout>
<com.google.android.material.textfield.TextInputEditText
android:id="@android:id/edit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:maxLines="1"
android:inputType="text|textCapSentences"
android:imeOptions="actionDone"
android:selectAllOnFocus="true" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>

View File

@@ -1446,6 +1446,12 @@
<string name="private_space_category_lock">Lock</string>
<!-- The title of the category for settings related to hiding the private space [CHAR LIMIT=20] -->
<string name="private_space_category_hide">Hide</string>
<!-- Header on pattern confirm screen inside private space settings when separate lock set for private space [CHAR LIMIT=50] -->
<string name="private_space_confirm_your_pattern_header">Confirm your private space pattern</string>
<!-- Header on PIN confirm screen inside private space settings when separate lock set for private space [CHAR LIMIT=50] -->
<string name="private_space_confirm_your_pin_header">Re-enter your private space PIN</string>
<!-- Header on password confirm screen inside private space when separate lock set for private space[CHAR LIMIT=50] -->
<string name="private_space_confirm_your_password_header">Re-enter your private space password</string>
<!-- Text shown when "Add fingerprint" button is disabled -->
<string name="fingerprint_add_max">You can add up to <xliff:g id="count" example="5">%d</xliff:g> fingerprints</string>
@@ -9585,6 +9591,9 @@
<!-- Modes: Hint for the EditText for editing a mode's name [CHAR LIMIT=30] -->
<string name="zen_mode_edit_name_hint">Mode name</string>
<!-- Modes: Error message when editing a mode's name and the name is empty [CHAR LIMIT=40] -->
<string name="zen_mode_edit_name_empty_error">Mode name cannot be empty</string>
<!-- Modes: Text shown above the list of icons in the mode editor. [CHAR LIMIT=40] -->
<string name="zen_mode_edit_choose_icon_title">Choose an icon</string>

View File

@@ -73,6 +73,9 @@
<item name="notification_importance_button_background_color_selected">?androidprv:attr/materialColorSecondaryContainer</item>
<item name="notification_importance_button_border_color_selected">?androidprv:attr/materialColorOnSecondaryContainer</item>
<item name="notification_importance_button_foreground_color_selected">?androidprv:attr/materialColorOnSecondaryContainer</item>
<!-- For AppCompat widgets, e.g. TextInputLayout -->
<item name="colorAccent">?android:attr/colorAccent</item>
</style>
<!-- Variant of the settings theme with no action bar. -->

View File

@@ -120,37 +120,14 @@
settings:controller="com.android.settings.inputmethod.PointerTouchpadPreferenceController"
settings:searchable="true"/>
</PreferenceCategory>
<PreferenceCategory
android:key="physical_keyboard_options_category"
android:persistent="false"
android:title="@string/keyboard_category_title">
<SwitchPreferenceCompat
<Preference
android:icon="@drawable/ic_sticky_keys"
android:key="toggle_keyboard_sticky_keys"
android:key="physical_keyboard_a11y"
android:title="@string/keyboard_a11y_settings"
android:summary="@string/keyboard_a11y_settings_summary"
android:persistent="false"
android:summary="@string/sticky_keys_summary"
android:title="@string/sticky_keys"
settings:controller="com.android.settings.accessibility.KeyboardStickyKeyPreferenceController"
settings:searchable="true" />
<SwitchPreferenceCompat
android:icon="@drawable/ic_bounce_keys"
android:key="toggle_keyboard_bounce_keys"
android:persistent="false"
android:title="@string/bounce_keys"
settings:controller="com.android.settings.accessibility.KeyboardBounceKeyPreferenceController"
settings:searchable="true" />
<SwitchPreferenceCompat
android:icon="@drawable/ic_slow_keys"
android:key="toggle_keyboard_slow_keys"
android:persistent="false"
android:title="@string/slow_keys"
settings:controller="com.android.settings.accessibility.KeyboardSlowKeyPreferenceController"
settings:searchable="true" />
android:fragment="com.android.settings.inputmethod.PhysicalKeyboardA11yFragment"
settings:controller="com.android.settings.inputmethod.PhysicalKeyboardA11yPreferenceController" />
</PreferenceCategory>
<PreferenceCategory

View File

@@ -1505,17 +1505,18 @@ public final class Utils extends com.android.settingslib.Utils {
* @return biometric status when mandatory biometrics authentication is requested
*/
public static BiometricStatus requestBiometricAuthenticationForMandatoryBiometrics(
@NonNull Context context,
boolean biometricsAuthenticationRequested, int userId) {
@NonNull Context context, boolean biometricsAuthenticationRequested, int userId) {
final BiometricManager biometricManager = context.getSystemService(BiometricManager.class);
if (biometricManager == null) {
Log.e(TAG, "Biometric Manager is null.");
return BiometricStatus.NOT_ACTIVE;
}
final int status = biometricManager.canAuthenticate(userId,
BiometricManager.Authenticators.MANDATORY_BIOMETRICS);
if (android.hardware.biometrics.Flags.mandatoryBiometrics()
&& !biometricsAuthenticationRequested) {
final UserManager userManager = context.getSystemService(
UserManager.class);
final int status = biometricManager.canAuthenticate(getEffectiveUserId(
userManager, userId), BiometricManager.Authenticators.MANDATORY_BIOMETRICS);
switch(status) {
case BiometricManager.BIOMETRIC_SUCCESS:
return BiometricStatus.OK;
@@ -1544,8 +1545,10 @@ public final class Utils extends com.android.settingslib.Utils {
*/
public static void launchBiometricPromptForMandatoryBiometrics(@NonNull Fragment fragment,
int requestCode, int userId, boolean hideBackground) {
final UserManager userManager = (UserManager) fragment.getContext().getSystemService(
UserManager.class);
fragment.startActivityForResult(getIntentForBiometricAuthentication(fragment.getResources(),
userId, hideBackground), requestCode);
getEffectiveUserId(userManager, userId), hideBackground), requestCode);
}
/**
@@ -1561,21 +1564,32 @@ public final class Utils extends com.android.settingslib.Utils {
*/
public static void launchBiometricPromptForMandatoryBiometrics(@NonNull Activity activity,
int requestCode, int userId, boolean hideBackground) {
final UserManager userManager = activity.getSystemService(UserManager.class);
activity.startActivityForResult(getIntentForBiometricAuthentication(
activity.getResources(), userId, hideBackground), requestCode);
activity.getResources(), getEffectiveUserId(userManager, userId),
hideBackground), requestCode);
}
private static Intent getIntentForBiometricAuthentication(Resources resources, int userId,
boolean hideBackground) {
private static int getEffectiveUserId(UserManager userManager, int userId) {
if (userManager != null) {
return userManager.getCredentialOwnerProfile(userId);
}
return userId;
}
private static Intent getIntentForBiometricAuthentication(Resources resources,
int effectiveUserId, boolean hideBackground) {
final Intent intent = new Intent();
intent.putExtra(BIOMETRIC_PROMPT_AUTHENTICATORS,
BiometricManager.Authenticators.MANDATORY_BIOMETRICS);
if (android.hardware.biometrics.Flags.mandatoryBiometrics()) {
intent.putExtra(BIOMETRIC_PROMPT_AUTHENTICATORS,
BiometricManager.Authenticators.MANDATORY_BIOMETRICS);
}
intent.putExtra(BIOMETRIC_PROMPT_NEGATIVE_BUTTON_TEXT,
resources.getString(R.string.cancel));
intent.putExtra(KeyguardManager.EXTRA_DESCRIPTION,
resources.getString(R.string.mandatory_biometrics_prompt_description));
intent.putExtra(ChooseLockSettingsHelper.EXTRA_KEY_ALLOW_ANY_USER, true);
intent.putExtra(EXTRA_USER_ID, userId);
intent.putExtra(EXTRA_USER_ID, effectiveUserId);
intent.putExtra(BIOMETRIC_PROMPT_HIDE_BACKGROUND, hideBackground);
intent.setClassName(SETTINGS_PACKAGE_NAME,
ConfirmDeviceCredentialActivity.InternalActivity.class.getName());

View File

@@ -30,7 +30,6 @@ import android.os.UserHandle;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.view.InputDevice;
import android.view.accessibility.AccessibilityManager;
import androidx.annotation.NonNull;
@@ -45,7 +44,6 @@ import com.android.settings.R;
import com.android.settings.accessibility.AccessibilityUtil.AccessibilityServiceFragmentType;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.development.Enable16kUtils;
import com.android.settings.inputmethod.PhysicalKeyboardFragment;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.RestrictedPreference;
@@ -73,14 +71,12 @@ public class AccessibilitySettings extends DashboardFragment implements
private static final String CATEGORY_DISPLAY = "display_category";
@VisibleForTesting
static final String CATEGORY_DOWNLOADED_SERVICES = "user_installed_services_category";
private static final String CATEGORY_KEYBOARD_OPTIONS = "physical_keyboard_options_category";
@VisibleForTesting
static final String CATEGORY_INTERACTION_CONTROL = "interaction_control_category";
private static final String[] CATEGORIES = new String[]{
CATEGORY_SCREEN_READER, CATEGORY_CAPTIONS, CATEGORY_AUDIO, CATEGORY_DISPLAY,
CATEGORY_SPEECH, CATEGORY_INTERACTION_CONTROL,
CATEGORY_KEYBOARD_OPTIONS, CATEGORY_DOWNLOADED_SERVICES
CATEGORY_SPEECH, CATEGORY_INTERACTION_CONTROL, CATEGORY_DOWNLOADED_SERVICES
};
// Extras passed to sub-fragments.
@@ -275,7 +271,7 @@ public class AccessibilitySettings extends DashboardFragment implements
* @return The service summary
*/
public static CharSequence getServiceSummary(Context context, AccessibilityServiceInfo info,
boolean serviceEnabled) {
boolean serviceEnabled) {
if (serviceEnabled && info.crashed) {
return context.getText(R.string.accessibility_summary_state_stopped);
}
@@ -461,7 +457,6 @@ public class AccessibilitySettings extends DashboardFragment implements
// Hide category if it is empty.
updatePreferenceCategoryVisibility(CATEGORY_SCREEN_READER);
updatePreferenceCategoryVisibility(CATEGORY_SPEECH);
updatePreferenceCategoryVisibility(CATEGORY_KEYBOARD_OPTIONS);
}
/**
@@ -556,9 +551,7 @@ public class AccessibilitySettings extends DashboardFragment implements
/**
* Updates preferences related to system configurations.
*/
protected void updateSystemPreferences() {
updateKeyboardPreferencesVisibility();
}
protected void updateSystemPreferences() {}
private void updatePreferencesState() {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
@@ -567,53 +560,6 @@ public class AccessibilitySettings extends DashboardFragment implements
findPreference(controller.getPreferenceKey())));
}
private void updateKeyboardPreferencesVisibility() {
if (!mCategoryToPrefCategoryMap.containsKey(CATEGORY_KEYBOARD_OPTIONS)) {
return;
}
boolean isVisible = isAnyHardKeyboardsExist()
&& isAnyKeyboardPreferenceAvailable();
mCategoryToPrefCategoryMap.get(CATEGORY_KEYBOARD_OPTIONS).setVisible(
isVisible);
if (isVisible) {
//set summary here.
findPreference(KeyboardBounceKeyPreferenceController.PREF_KEY).setSummary(
getContext().getString(R.string.bounce_keys_summary,
PhysicalKeyboardFragment.BOUNCE_KEYS_THRESHOLD));
findPreference(KeyboardSlowKeyPreferenceController.PREF_KEY).setSummary(
getContext().getString(R.string.slow_keys_summary,
PhysicalKeyboardFragment.SLOW_KEYS_THRESHOLD));
}
}
static boolean isAnyHardKeyboardsExist() {
for (int deviceId : InputDevice.getDeviceIds()) {
final InputDevice device = InputDevice.getDevice(deviceId);
if (device != null && !device.isVirtual() && device.isFullKeyboard()) {
return true;
}
}
return false;
}
private boolean isAnyKeyboardPreferenceAvailable() {
for (List<AbstractPreferenceController> controllerList : getPreferenceControllers()) {
for (AbstractPreferenceController controller : controllerList) {
if (controller.getPreferenceKey().equals(
KeyboardBounceKeyPreferenceController.PREF_KEY)
|| controller.getPreferenceKey().equals(
KeyboardSlowKeyPreferenceController.PREF_KEY)
|| controller.getPreferenceKey().equals(
KeyboardStickyKeyPreferenceController.PREF_KEY)) {
if (controller.isAvailable()) {
return true;
}
}
}
}
return false;
}
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
new BaseSearchIndexProvider(R.xml.accessibility_settings) {
@Override
@@ -671,10 +617,12 @@ public class AccessibilitySettings extends DashboardFragment implements
};
@Override
public void onInputDeviceAdded(int deviceId) {}
public void onInputDeviceAdded(int deviceId) {
}
@Override
public void onInputDeviceRemoved(int deviceId) {}
public void onInputDeviceRemoved(int deviceId) {
}
@Override
public void onInputDeviceChanged(int deviceId) {

View File

@@ -1,79 +0,0 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.accessibility;
import android.content.Context;
import android.hardware.input.InputSettings;
import android.util.Log;
import androidx.annotation.NonNull;
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
import com.android.settings.inputmethod.PhysicalKeyboardFragment;
import java.util.List;
/**
* A toggle preference controller for keyboard bounce key.
*/
public class KeyboardBounceKeyPreferenceController extends TogglePreferenceController {
private static final String TAG = "BounceKeyPrefController";
static final String PREF_KEY = "toggle_keyboard_bounce_keys";
public KeyboardBounceKeyPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
}
@Override
public int getAvailabilityStatus() {
return InputSettings.isAccessibilityBounceKeysFeatureEnabled()
? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
@Override
public boolean isChecked() {
return InputSettings.isAccessibilityBounceKeysEnabled(mContext);
}
@Override
public boolean setChecked(boolean isChecked) {
InputSettings.setAccessibilityBounceKeysThreshold(mContext,
isChecked ? PhysicalKeyboardFragment.BOUNCE_KEYS_THRESHOLD
: 0);
return true;
}
@Override
public int getSliceHighlightMenuRes() {
return R.string.menu_key_accessibility;
}
@Override
public void updateNonIndexableKeys(@NonNull List<String> keys) {
super.updateNonIndexableKeys(keys);
if (Flags.fixA11ySettingsSearch() && !AccessibilitySettings.isAnyHardKeyboardsExist()) {
if (keys.contains(getPreferenceKey())) {
Log.w(TAG, "Skipping updateNonIndexableKeys, key already in list.");
return;
}
keys.add(getPreferenceKey());
}
}
}

View File

@@ -1,80 +0,0 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.accessibility;
import android.content.Context;
import android.hardware.input.InputSettings;
import android.util.Log;
import androidx.annotation.NonNull;
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
import com.android.settings.inputmethod.PhysicalKeyboardFragment;
import java.util.List;
/**
* A toggle preference controller for keyboard slow key.
*/
public class KeyboardSlowKeyPreferenceController extends TogglePreferenceController {
private static final String TAG = "SlowKeyPrefController";
static final String PREF_KEY = "toggle_keyboard_slow_keys";
public KeyboardSlowKeyPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
}
@Override
public int getAvailabilityStatus() {
return InputSettings.isAccessibilitySlowKeysFeatureFlagEnabled()
? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
@Override
public boolean isChecked() {
return InputSettings.isAccessibilitySlowKeysEnabled(mContext);
}
@Override
public boolean setChecked(boolean isChecked) {
InputSettings.setAccessibilitySlowKeysThreshold(mContext,
isChecked ? PhysicalKeyboardFragment.SLOW_KEYS_THRESHOLD
: 0);
return true;
}
@Override
public int getSliceHighlightMenuRes() {
return R.string.menu_key_accessibility;
}
@Override
public void updateNonIndexableKeys(@NonNull List<String> keys) {
super.updateNonIndexableKeys(keys);
if (Flags.fixA11ySettingsSearch() && !AccessibilitySettings.isAnyHardKeyboardsExist()) {
if (keys.contains(getPreferenceKey())) {
Log.w(TAG, "Skipping updateNonIndexableKeys, key already in list.");
return;
}
keys.add(getPreferenceKey());
}
}
}

View File

@@ -1,76 +0,0 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.accessibility;
import android.content.Context;
import android.hardware.input.InputSettings;
import android.util.Log;
import androidx.annotation.NonNull;
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
import java.util.List;
/**
* A toggle preference controller for keyboard sticky key.
*/
public class KeyboardStickyKeyPreferenceController extends TogglePreferenceController {
private static final String TAG = "StickyKeyPrefController";
static final String PREF_KEY = "toggle_keyboard_sticky_keys";
public KeyboardStickyKeyPreferenceController(Context context, String preferenceKey) {
super(context, preferenceKey);
}
@Override
public int getAvailabilityStatus() {
return InputSettings.isAccessibilityStickyKeysFeatureEnabled()
? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
@Override
public boolean isChecked() {
return InputSettings.isAccessibilityStickyKeysEnabled(mContext);
}
@Override
public boolean setChecked(boolean isChecked) {
InputSettings.setAccessibilityStickyKeysEnabled(mContext, isChecked);
return true;
}
@Override
public int getSliceHighlightMenuRes() {
return R.string.menu_key_accessibility;
}
@Override
public void updateNonIndexableKeys(@NonNull List<String> keys) {
super.updateNonIndexableKeys(keys);
if (Flags.fixA11ySettingsSearch() && !AccessibilitySettings.isAnyHardKeyboardsExist()) {
if (keys.contains(getPreferenceKey())) {
Log.w(TAG, "Skipping updateNonIndexableKeys, key already in list.");
return;
}
keys.add(getPreferenceKey());
}
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.inputmethod;
import static com.android.settings.keyboard.Flags.keyboardAndTouchpadA11yNewPageEnabled;
import android.content.Context;
import android.view.InputDevice;
import com.android.settings.core.BasePreferenceController;
/** Controller that shows and updates the Physical Keyboard a11y preference. */
public class PhysicalKeyboardA11yPreferenceController extends BasePreferenceController {
public PhysicalKeyboardA11yPreferenceController(Context context,
String preferenceKey) {
super(context, preferenceKey);
}
@Override
public int getAvailabilityStatus() {
return keyboardAndTouchpadA11yNewPageEnabled()
&& isAnyHardKeyboardsExist() ? AVAILABLE : CONDITIONALLY_UNAVAILABLE;
}
private static boolean isAnyHardKeyboardsExist() {
for (int deviceId : InputDevice.getDeviceIds()) {
final InputDevice device = InputDevice.getDevice(deviceId);
if (device != null && !device.isVirtual() && device.isFullKeyboard()) {
return true;
}
}
return false;
}
}

View File

@@ -195,19 +195,19 @@ public class SatelliteSetting extends RestrictedDashboardFragment {
final String[] link = new String[1];
link[0] = readSatelliteMoreInfoString(mSubId);
footerPreference.setLearnMoreAction(view -> {
if (!link[0].isEmpty()) {
Intent helpIntent = HelpUtils.getHelpIntent(mActivity, link[0],
this.getClass().getName());
if (helpIntent != null) {
mActivity.startActivityForResult(helpIntent, /*requestCode=*/ 0);
if (link[0] != null && !link[0].isEmpty()) {
footerPreference.setLearnMoreAction(view -> {
if (!link[0].isEmpty()) {
Intent helpIntent = HelpUtils.getHelpIntent(mActivity, link[0],
this.getClass().getName());
if (helpIntent != null) {
mActivity.startActivityForResult(helpIntent, /*requestCode=*/ 0);
}
}
}
});
footerPreference.setLearnMoreText(
getResources().getString(R.string.more_about_satellite_messaging));
// TODO : b/320467418 add rounded rectangle border line to footer preference.
});
footerPreference.setLearnMoreText(
getResources().getString(R.string.more_about_satellite_messaging));
}
}
}

View File

@@ -44,12 +44,12 @@ constructor(
context: Context,
key: String,
private val callStateRepository: CallStateRepository = CallStateRepository(context),
private val videoCallingRepository: VideoCallingRepository = VideoCallingRepository(context),
) : TogglePreferenceController(context, key), On4gLteUpdateListener {
private var subId = SubscriptionManager.INVALID_SUBSCRIPTION_ID
private var preference: TwoStatePreference? = null
private var callingPreferenceCategoryController: CallingPreferenceCategoryController? = null
private val repository = VideoCallingRepository(context)
private var videoCallEditable = false
private var isInCall = false
@@ -71,14 +71,18 @@ constructor(
override fun displayPreference(screen: PreferenceScreen) {
super.displayPreference(screen)
preference = screen.findPreference(preferenceKey)
Log.d(TAG, "init ui")
preference?.isVisible = false
callingPreferenceCategoryController?.updateChildVisible(preferenceKey, false)
}
override fun onViewCreated(viewLifecycleOwner: LifecycleOwner) {
repository.isVideoCallReadyFlow(subId).collectLatestWithLifecycle(viewLifecycleOwner) {
isReady ->
preference?.isVisible = isReady
callingPreferenceCategoryController?.updateChildVisible(preferenceKey, isReady)
}
videoCallingRepository.isVideoCallReadyFlow(subId)
.collectLatestWithLifecycle(viewLifecycleOwner) { isReady ->
Log.d(TAG, "isVideoCallReadyFlow: update visible")
preference?.isVisible = isReady
callingPreferenceCategoryController?.updateChildVisible(preferenceKey, isReady)
}
callStateRepository.callStateFlow(subId).collectLatestWithLifecycle(viewLifecycleOwner) {
callState ->
isInCall = callState != TelephonyManager.CALL_STATE_IDLE
@@ -129,10 +133,10 @@ constructor(
class VideoCallingSearchItem(private val context: Context) :
MobileNetworkSettingsSearchItem {
private val repository = VideoCallingRepository(context)
private val videoCallingRepository = VideoCallingRepository(context)
private fun isAvailable(subId: Int): Boolean = runBlocking {
repository.isVideoCallReadyFlow(subId).first()
videoCallingRepository.isVideoCallReadyFlow(subId).first()
}
override fun getSearchResult(subId: Int): MobileNetworkSettingsSearchResult? {

View File

@@ -30,13 +30,15 @@ import android.app.admin.DevicePolicyManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageItemInfo;
import android.content.pm.PackageManager;
import android.content.pm.ServiceInfo;
import android.content.pm.ResolveInfo;
import android.os.Bundle;
import android.os.UserHandle;
import android.os.UserManager;
import android.service.notification.NotificationListenerService;
import android.text.TextUtils;
import android.util.Slog;
import android.view.WindowManager;
@@ -49,6 +51,8 @@ import com.android.internal.app.AlertActivity;
import com.android.internal.app.AlertController;
import com.android.settings.R;
import java.util.List;
/** @hide */
public class NotificationAccessConfirmationActivity extends Activity
implements DialogInterface {
@@ -113,6 +117,31 @@ public class NotificationAccessConfirmationActivity extends Activity
return;
}
// Check NLS service info.
String requiredPermission = Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE;
Intent NLSIntent = new Intent(NotificationListenerService.SERVICE_INTERFACE);
List<ResolveInfo> matchedServiceList = getPackageManager().queryIntentServicesAsUser(
NLSIntent, /* flags */ 0, mUserId);
boolean hasNLSIntentFilter = false;
for (ResolveInfo service : matchedServiceList) {
if (service.serviceInfo.packageName.equals(mComponentName.getPackageName())) {
if (!requiredPermission.equals(service.serviceInfo.permission)) {
Slog.e(LOG_TAG, "Service " + mComponentName + " lacks permission "
+ requiredPermission);
finish();
return;
}
hasNLSIntentFilter = true;
break;
}
}
if (!hasNLSIntentFilter) {
Slog.e(LOG_TAG, "Service " + mComponentName + " lacks an intent-filter action "
+ "for android.service.notification.NotificationListenerService.");
finish();
return;
}
AlertController.AlertParams p = new AlertController.AlertParams(this);
p.mTitle = getString(
R.string.notification_listener_security_warning_title,
@@ -147,19 +176,6 @@ public class NotificationAccessConfirmationActivity extends Activity
}
private void onAllow() {
String requiredPermission = Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE;
try {
ServiceInfo serviceInfo = getPackageManager().getServiceInfo(mComponentName, 0);
if (!requiredPermission.equals(serviceInfo.permission)) {
Slog.e(LOG_TAG,
"Service " + mComponentName + " lacks permission " + requiredPermission);
return;
}
} catch (PackageManager.NameNotFoundException e) {
Slog.e(LOG_TAG, "Failed to get service info for " + mComponentName, e);
return;
}
mNm.setNotificationListenerAccessGranted(mComponentName, true);
finish();
@@ -170,12 +186,6 @@ public class NotificationAccessConfirmationActivity extends Activity
return AlertActivity.dispatchPopulateAccessibilityEvent(this, event);
}
@Override
public void onBackPressed() {
// Suppress finishing the activity on back button press,
// consistently with the permission dialog behavior
}
@Override
public void cancel() {
finish();

View File

@@ -17,9 +17,11 @@
package com.android.settings.notification.modes;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import android.content.Context;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.widget.EditText;
@@ -28,14 +30,18 @@ import androidx.annotation.Nullable;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.widget.LayoutPreference;
import com.google.android.material.textfield.TextInputLayout;
import java.util.function.Consumer;
class ZenModeEditNamePreferenceController extends AbstractZenModePreferenceController {
private final Consumer<String> mModeNameSetter;
@Nullable private TextInputLayout mInputLayout;
@Nullable private EditText mEditText;
private boolean mIsSettingText;
@@ -50,7 +56,8 @@ class ZenModeEditNamePreferenceController extends AbstractZenModePreferenceContr
super.displayPreference(screen);
if (mEditText == null) {
LayoutPreference pref = checkNotNull(screen.findPreference(getPreferenceKey()));
mEditText = pref.findViewById(android.R.id.edit);
mInputLayout = checkNotNull(pref.findViewById(R.id.edit_input_layout));
mEditText = checkNotNull(pref.findViewById(android.R.id.edit));
mEditText.addTextChangedListener(new TextWatcher() {
@Override
@@ -61,9 +68,11 @@ class ZenModeEditNamePreferenceController extends AbstractZenModePreferenceContr
@Override
public void afterTextChanged(Editable s) {
if (!mIsSettingText) {
mModeNameSetter.accept(s.toString());
if (mIsSettingText) {
return;
}
mModeNameSetter.accept(s.toString());
updateErrorState(s.toString());
}
});
}
@@ -79,9 +88,20 @@ class ZenModeEditNamePreferenceController extends AbstractZenModePreferenceContr
if (!modeName.equals(currentText)) {
mEditText.setText(modeName);
}
updateErrorState(modeName);
} finally {
mIsSettingText = false;
}
}
}
private void updateErrorState(String currentName) {
checkState(mInputLayout != null);
if (TextUtils.isEmpty(currentName)) {
mInputLayout.setError(
mContext.getString(R.string.zen_mode_edit_name_empty_error));
} else {
mInputLayout.setError(null);
}
}
}

View File

@@ -39,6 +39,7 @@ import android.os.CountDownTimer;
import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.text.Editable;
import android.text.InputType;
@@ -65,6 +66,7 @@ import com.android.internal.widget.LockscreenCredential;
import com.android.internal.widget.TextViewInputDisabler;
import com.android.settings.R;
import com.android.settings.SetupRedactionInterstitial;
import com.android.settings.Utils;
import com.android.settingslib.animation.AppearAnimationUtils;
import com.android.settingslib.animation.DisappearAnimationUtils;
@@ -290,6 +292,14 @@ public class ConfirmLockPassword extends ConfirmDeviceCredentialBaseActivity {
CONFIRM_WORK_PROFILE_PIN_HEADER,
() -> getString(R.string.lockpassword_confirm_your_work_pin_header));
}
if (android.multiuser.Flags.showCustomUnlockTitleInsidePrivateProfile()
&& Utils.isPrivateProfile(mEffectiveUserId, getActivity())
&& !UserManager.get(getActivity())
.isQuietModeEnabled(UserHandle.of(mEffectiveUserId))) {
return mIsAlpha ? getString(R.string.private_space_confirm_your_password_header)
: getString(R.string.private_space_confirm_your_pin_header);
}
return mIsAlpha ? getString(R.string.lockpassword_confirm_your_password_header)
: getString(R.string.lockpassword_confirm_your_pin_header);
}

View File

@@ -34,6 +34,7 @@ import android.os.AsyncTask;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManager;
import android.text.TextUtils;
import android.util.Log;
@@ -55,6 +56,7 @@ import com.android.internal.widget.LockPatternView.Cell;
import com.android.internal.widget.LockscreenCredential;
import com.android.settings.R;
import com.android.settings.SetupRedactionInterstitial;
import com.android.settings.Utils;
import com.android.settingslib.animation.AppearAnimationCreator;
import com.android.settingslib.animation.AppearAnimationUtils;
import com.android.settingslib.animation.DisappearAnimationUtils;
@@ -422,6 +424,12 @@ public class ConfirmLockPattern extends ConfirmDeviceCredentialBaseActivity {
CONFIRM_WORK_PROFILE_PATTERN_HEADER,
() -> getString(R.string.lockpassword_confirm_your_work_pattern_header));
}
if (android.multiuser.Flags.showCustomUnlockTitleInsidePrivateProfile()
&& Utils.isPrivateProfile(mEffectiveUserId, getActivity())
&& !UserManager.get(getActivity())
.isQuietModeEnabled(UserHandle.of(mEffectiveUserId))) {
return getString(R.string.private_space_confirm_your_pattern_header);
}
return getString(R.string.lockpassword_confirm_your_pattern_header);
}

View File

@@ -564,6 +564,8 @@ public class UtilsTest {
@Test
@EnableFlags(Flags.FLAG_MANDATORY_BIOMETRICS)
public void testRequestBiometricAuthentication_biometricManagerReturnsSuccessForDifferentUser_shouldReturnError() {
when(mContext.getSystemService(UserManager.class)).thenReturn(mMockUserManager);
when(mMockUserManager.getCredentialOwnerProfile(USER_ID)).thenReturn(USER_ID);
when(mBiometricManager.canAuthenticate(anyInt(),
eq(BiometricManager.Authenticators.MANDATORY_BIOMETRICS)))
.thenReturn(BiometricManager.BIOMETRIC_ERROR_HW_UNAVAILABLE);
@@ -579,6 +581,8 @@ public class UtilsTest {
@EnableFlags(Flags.FLAG_MANDATORY_BIOMETRICS)
public void testLaunchBiometricPrompt_checkIntentValues() {
when(mFragment.getContext()).thenReturn(mContext);
when(mContext.getSystemService(UserManager.class)).thenReturn(mMockUserManager);
when(mMockUserManager.getCredentialOwnerProfile(USER_ID)).thenReturn(USER_ID);
final int requestCode = 1;
final ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);

View File

@@ -1,163 +0,0 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.accessibility;
import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.core.BasePreferenceController;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import java.util.ArrayList;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class KeyboardBounceKeyPreferenceControllerTest {
private static final String KEY_ACCESSIBILITY_BOUNCE_KEYS =
Settings.Secure.ACCESSIBILITY_BOUNCE_KEYS;
private static final int UNKNOWN = -1;
@Rule
public final SetFlagsRule mSetFlagRule = new SetFlagsRule();
private final Context mContext = ApplicationProvider.getApplicationContext();
private final SwitchPreference mSwitchPreference = spy(new SwitchPreference(mContext));
private final KeyboardBounceKeyPreferenceController mController =
new KeyboardBounceKeyPreferenceController(mContext,
KeyboardBounceKeyPreferenceController.PREF_KEY);
@Before
public void setUp() {
final PreferenceManager preferenceManager = new PreferenceManager(mContext);
final PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
mSwitchPreference.setKey(KeyboardBounceKeyPreferenceController.PREF_KEY);
screen.addPreference(mSwitchPreference);
mController.displayPreference(screen);
}
@Test
public void getAvailabilityStatus_byDefault_shouldReturnAvailable() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.AVAILABLE);
}
@Test
public void isChecked_disableBounceKey_onResumeShouldReturnFalse() {
Settings.Secure.putInt(mContext.getContentResolver(), KEY_ACCESSIBILITY_BOUNCE_KEYS, OFF);
mController.updateState(mSwitchPreference);
assertThat(mController.isChecked()).isFalse();
assertThat(mSwitchPreference.isChecked()).isFalse();
}
@Test
public void isChecked_enableBounceKey_onResumeShouldReturnTrue() {
Settings.Secure.putInt(mContext.getContentResolver(), KEY_ACCESSIBILITY_BOUNCE_KEYS, ON);
mController.updateState(mSwitchPreference);
assertThat(mController.isChecked()).isTrue();
assertThat(mSwitchPreference.isChecked()).isTrue();
}
@Test
public void performClick_enableBounceKey_shouldReturnTrue() {
Settings.Secure.putInt(mContext.getContentResolver(), KEY_ACCESSIBILITY_BOUNCE_KEYS, OFF);
mController.updateState(mSwitchPreference);
mSwitchPreference.performClick();
verify(mSwitchPreference).setChecked(true);
assertThat(mController.isChecked()).isTrue();
assertThat(mSwitchPreference.isChecked()).isTrue();
}
@Test
public void performClick_disableBounceKey_shouldReturnFalse() {
Settings.Secure.putInt(mContext.getContentResolver(), KEY_ACCESSIBILITY_BOUNCE_KEYS, ON);
mController.updateState(mSwitchPreference);
mSwitchPreference.performClick();
verify(mSwitchPreference).setChecked(false);
assertThat(mController.isChecked()).isFalse();
assertThat(mSwitchPreference.isChecked()).isFalse();
}
@Test
public void setChecked_setFalse_shouldDisableBounceKey() {
mController.setChecked(false);
assertThat(Settings.Secure.getInt(
mContext.getContentResolver(), KEY_ACCESSIBILITY_BOUNCE_KEYS, UNKNOWN)).isEqualTo(
OFF);
}
@Test
public void setChecked_setTrue_shouldEnableBounceKey() {
mController.setChecked(true);
assertThat(Settings.Secure.getInt(
mContext.getContentResolver(), KEY_ACCESSIBILITY_BOUNCE_KEYS,
UNKNOWN)).isNotEqualTo(OFF);
}
@Test
@EnableFlags(Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
public void updateNonIndexableKeys_physicalKeyboardExists_returnEmptyList() {
Assume.assumeTrue(AccessibilitySettings.isAnyHardKeyboardsExist());
List<String> nonIndexableKeys = new ArrayList<>();
mController.updateNonIndexableKeys(nonIndexableKeys);
assertThat(nonIndexableKeys).isEmpty();
}
@Test
@EnableFlags(Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
public void updateNonIndexableKeys_noPhysicalKeyboard_returnPreKey() {
Assume.assumeFalse(AccessibilitySettings.isAnyHardKeyboardsExist());
List<String> nonIndexableKeys = new ArrayList<>();
mController.updateNonIndexableKeys(nonIndexableKeys);
assertThat(nonIndexableKeys).contains(mController.getPreferenceKey());
}
}

View File

@@ -1,163 +0,0 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.accessibility;
import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.core.BasePreferenceController;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import java.util.ArrayList;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class KeyboardSlowKeyPreferenceControllerTest {
private static final String KEY_ACCESSIBILITY_SLOW_KEYS =
Settings.Secure.ACCESSIBILITY_SLOW_KEYS;
private static final int UNKNOWN = -1;
@Rule
public final SetFlagsRule mSetFlagRule = new SetFlagsRule();
private final Context mContext = ApplicationProvider.getApplicationContext();
private final SwitchPreference mSwitchPreference = spy(new SwitchPreference(mContext));
private final KeyboardSlowKeyPreferenceController mController =
new KeyboardSlowKeyPreferenceController(mContext,
KeyboardSlowKeyPreferenceController.PREF_KEY);
@Before
public void setUp() {
final PreferenceManager preferenceManager = new PreferenceManager(mContext);
final PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
mSwitchPreference.setKey(KeyboardSlowKeyPreferenceController.PREF_KEY);
screen.addPreference(mSwitchPreference);
mController.displayPreference(screen);
}
@Test
public void getAvailabilityStatus_byDefault_shouldReturnAvailable() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.AVAILABLE);
}
@Test
public void isChecked_disableSlowKey_onResumeShouldReturnFalse() {
Settings.Secure.putInt(mContext.getContentResolver(), KEY_ACCESSIBILITY_SLOW_KEYS, OFF);
mController.updateState(mSwitchPreference);
assertThat(mController.isChecked()).isFalse();
assertThat(mSwitchPreference.isChecked()).isFalse();
}
@Test
public void isChecked_enableSlowKey_onResumeShouldReturnTrue() {
Settings.Secure.putInt(mContext.getContentResolver(), KEY_ACCESSIBILITY_SLOW_KEYS, ON);
mController.updateState(mSwitchPreference);
assertThat(mController.isChecked()).isTrue();
assertThat(mSwitchPreference.isChecked()).isTrue();
}
@Test
public void performClick_enableSlowKey_shouldReturnTrue() {
Settings.Secure.putInt(mContext.getContentResolver(), KEY_ACCESSIBILITY_SLOW_KEYS, OFF);
mController.updateState(mSwitchPreference);
mSwitchPreference.performClick();
verify(mSwitchPreference).setChecked(true);
assertThat(mController.isChecked()).isTrue();
assertThat(mSwitchPreference.isChecked()).isTrue();
}
@Test
public void performClick_disableSlowKey_shouldReturnFalse() {
Settings.Secure.putInt(mContext.getContentResolver(), KEY_ACCESSIBILITY_SLOW_KEYS, ON);
mController.updateState(mSwitchPreference);
mSwitchPreference.performClick();
verify(mSwitchPreference).setChecked(false);
assertThat(mController.isChecked()).isFalse();
assertThat(mSwitchPreference.isChecked()).isFalse();
}
@Test
public void setChecked_setFalse_shouldDisableSlowKey() {
mController.setChecked(false);
assertThat(Settings.Secure.getInt(
mContext.getContentResolver(), KEY_ACCESSIBILITY_SLOW_KEYS, UNKNOWN)).isEqualTo(
OFF);
}
@Test
public void setChecked_setTrue_shouldEnableSlowKey() {
mController.setChecked(true);
assertThat(Settings.Secure.getInt(
mContext.getContentResolver(), KEY_ACCESSIBILITY_SLOW_KEYS, UNKNOWN)).isNotEqualTo(
OFF);
}
@Test
@EnableFlags(Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
public void updateNonIndexableKeys_physicalKeyboardExists_returnEmptyList() {
Assume.assumeTrue(AccessibilitySettings.isAnyHardKeyboardsExist());
List<String> nonIndexableKeys = new ArrayList<>();
mController.updateNonIndexableKeys(nonIndexableKeys);
assertThat(nonIndexableKeys).isEmpty();
}
@Test
@EnableFlags(Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
public void updateNonIndexableKeys_noPhysicalKeyboard_returnPreKey() {
Assume.assumeFalse(AccessibilitySettings.isAnyHardKeyboardsExist());
List<String> nonIndexableKeys = new ArrayList<>();
mController.updateNonIndexableKeys(nonIndexableKeys);
assertThat(nonIndexableKeys).contains(mController.getPreferenceKey());
}
}

View File

@@ -1,161 +0,0 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.accessibility;
import static com.android.settings.accessibility.AccessibilityUtil.State.OFF;
import static com.android.settings.accessibility.AccessibilityUtil.State.ON;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.content.Context;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.preference.SwitchPreference;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.core.BasePreferenceController;
import org.junit.Assume;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
import java.util.ArrayList;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
public class KeyboardStickyKeyPreferenceControllerTest {
private static final String KEY_ACCESSIBILITY_STICKY_KEYS =
Settings.Secure.ACCESSIBILITY_STICKY_KEYS;
private static final int UNKNOWN = -1;
@Rule
public final SetFlagsRule mSetFlagRule = new SetFlagsRule();
private final Context mContext = ApplicationProvider.getApplicationContext();
private final SwitchPreference mSwitchPreference = spy(new SwitchPreference(mContext));
private final KeyboardStickyKeyPreferenceController mController =
new KeyboardStickyKeyPreferenceController(mContext,
KeyboardStickyKeyPreferenceController.PREF_KEY);
@Before
public void setUp() {
final PreferenceManager preferenceManager = new PreferenceManager(mContext);
final PreferenceScreen screen = preferenceManager.createPreferenceScreen(mContext);
mSwitchPreference.setKey(KeyboardStickyKeyPreferenceController.PREF_KEY);
screen.addPreference(mSwitchPreference);
mController.displayPreference(screen);
}
@Test
public void getAvailabilityStatus_byDefault_shouldReturnAvailable() {
assertThat(mController.getAvailabilityStatus()).isEqualTo(
BasePreferenceController.AVAILABLE);
}
@Test
public void isChecked_disableStickyKey_onResumeShouldReturnFalse() {
Settings.Secure.putInt(mContext.getContentResolver(), KEY_ACCESSIBILITY_STICKY_KEYS, OFF);
mController.updateState(mSwitchPreference);
assertThat(mController.isChecked()).isFalse();
assertThat(mSwitchPreference.isChecked()).isFalse();
}
@Test
public void isChecked_enableStickyKey_onResumeShouldReturnTrue() {
Settings.Secure.putInt(mContext.getContentResolver(), KEY_ACCESSIBILITY_STICKY_KEYS, ON);
mController.updateState(mSwitchPreference);
assertThat(mController.isChecked()).isTrue();
assertThat(mSwitchPreference.isChecked()).isTrue();
}
@Test
public void performClick_enableStickyKey_shouldReturnTrue() {
Settings.Secure.putInt(mContext.getContentResolver(), KEY_ACCESSIBILITY_STICKY_KEYS, OFF);
mController.updateState(mSwitchPreference);
mSwitchPreference.performClick();
verify(mSwitchPreference).setChecked(true);
assertThat(mController.isChecked()).isTrue();
assertThat(mSwitchPreference.isChecked()).isTrue();
}
@Test
public void performClick_disableStickyKey_shouldReturnFalse() {
Settings.Secure.putInt(mContext.getContentResolver(), KEY_ACCESSIBILITY_STICKY_KEYS, ON);
mController.updateState(mSwitchPreference);
mSwitchPreference.performClick();
verify(mSwitchPreference).setChecked(false);
assertThat(mController.isChecked()).isFalse();
assertThat(mSwitchPreference.isChecked()).isFalse();
}
@Test
public void setChecked_setFalse_shouldDisableStickyKey() {
mController.setChecked(false);
assertThat(Settings.Secure.getInt(
mContext.getContentResolver(), KEY_ACCESSIBILITY_STICKY_KEYS, UNKNOWN)).isEqualTo(OFF);
}
@Test
public void setChecked_setTrue_shouldEnableStickyKey() {
mController.setChecked(true);
assertThat(Settings.Secure.getInt(
mContext.getContentResolver(), KEY_ACCESSIBILITY_STICKY_KEYS, UNKNOWN)).isEqualTo(ON);
}
@Test
@EnableFlags(Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
public void updateNonIndexableKeys_physicalKeyboardExists_returnEmptyList() {
Assume.assumeTrue(AccessibilitySettings.isAnyHardKeyboardsExist());
List<String> nonIndexableKeys = new ArrayList<>();
mController.updateNonIndexableKeys(nonIndexableKeys);
assertThat(nonIndexableKeys).isEmpty();
}
@Test
@EnableFlags(Flags.FLAG_FIX_A11Y_SETTINGS_SEARCH)
public void updateNonIndexableKeys_noPhysicalKeyboard_returnPreKey() {
Assume.assumeFalse(AccessibilitySettings.isAnyHardKeyboardsExist());
List<String> nonIndexableKeys = new ArrayList<>();
mController.updateNonIndexableKeys(nonIndexableKeys);
assertThat(nonIndexableKeys).contains(mController.getPreferenceKey());
}
}

View File

@@ -0,0 +1,98 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.inputmethod;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.view.InputDevice;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.keyboard.Flags;
import com.android.settings.testutils.shadow.ShadowInputDevice;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnit;
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
/** Tests for {@link PhysicalKeyboardA11yPreferenceController} */
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {
com.android.settings.testutils.shadow.ShadowInputDevice.class,
})
public class PhysicalKeyboardA11yPreferenceControllerTest {
@Rule
public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
@Rule
public MockitoRule rule = MockitoJUnit.rule();
private static final String PREFERENCE_KEY = "physical_keyboard_a11y";
private Context mContext;
private PhysicalKeyboardA11yPreferenceController mController;
@Mock
InputDevice mInputDevice;
@Before
public void setUp() {
mContext = ApplicationProvider.getApplicationContext();
mController = new PhysicalKeyboardA11yPreferenceController(mContext, PREFERENCE_KEY);
}
@Test
@EnableFlags(Flags.FLAG_KEYBOARD_AND_TOUCHPAD_A11Y_NEW_PAGE_ENABLED)
public void getAvailabilityStatus_expected() {
int deviceId = 1;
ShadowInputDevice.sDeviceIds = new int[]{deviceId};
when(mInputDevice.isVirtual()).thenReturn(false);
when(mInputDevice.isFullKeyboard()).thenReturn(true);
ShadowInputDevice.addDevice(deviceId, mInputDevice);
assertThat(InputDevice.getDeviceIds()).isNotEmpty();
assertThat(mController.getAvailabilityStatus())
.isEqualTo(BasePreferenceController.AVAILABLE);
}
@Test
@EnableFlags(Flags.FLAG_KEYBOARD_AND_TOUCHPAD_A11Y_NEW_PAGE_ENABLED)
public void getAvailabilityStatus_deviceIsNotAsExpected_unavailable() {
int deviceId = 1;
ShadowInputDevice.sDeviceIds = new int[]{deviceId};
when(mInputDevice.isVirtual()).thenReturn(true);
when(mInputDevice.isFullKeyboard()).thenReturn(false);
ShadowInputDevice.addDevice(deviceId, mInputDevice);
assertThat(InputDevice.getDeviceIds()).isNotEmpty();
assertThat(mController.getAvailabilityStatus())
.isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE);
}
}

View File

@@ -31,8 +31,6 @@ import android.widget.TextView;
import androidx.annotation.Nullable;
import com.android.settings.R;
import com.google.common.base.Strings;
import org.junit.Test;
@@ -45,15 +43,14 @@ import org.robolectric.RuntimeEnvironment;
public class NotificationAccessConfirmationActivityTest {
@Test
public void start_showsDialog() {
public void start_withMissingIntentFilter_finishes() {
ComponentName cn = new ComponentName("com.example", "com.example.SomeService");
installPackage(cn.getPackageName(), "X");
NotificationAccessConfirmationActivity activity = startActivityWithIntent(cn);
assertThat(activity.isFinishing()).isFalse();
assertThat(getDialogText(activity)).isEqualTo(
activity.getString(R.string.notification_listener_security_warning_summary, "X"));
assertThat(getDialogText(activity)).isNull();
assertThat(activity.isFinishing()).isTrue();
}
@Test

View File

@@ -35,6 +35,8 @@ import com.android.settingslib.notification.modes.TestModeBuilder;
import com.android.settingslib.notification.modes.ZenMode;
import com.android.settingslib.widget.LayoutPreference;
import com.google.android.material.textfield.TextInputLayout;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -55,6 +57,7 @@ public class ZenModeEditNamePreferenceControllerTest {
private ZenModeEditNamePreferenceController mController;
private LayoutPreference mPreference;
private TextInputLayout mTextInputLayout;
private EditText mEditText;
@Mock private Consumer<String> mNameSetter;
@@ -64,12 +67,15 @@ public class ZenModeEditNamePreferenceControllerTest {
Context context = RuntimeEnvironment.application;
PreferenceManager preferenceManager = new PreferenceManager(context);
// Inflation is a test in itself, because it will crash if the Theme isn't set correctly.
PreferenceScreen preferenceScreen = preferenceManager.inflateFromResource(context,
R.xml.modes_edit_name_icon, null);
mPreference = preferenceScreen.findPreference("name");
mController = new ZenModeEditNamePreferenceController(context, "name", mNameSetter);
mController.displayPreference(preferenceScreen);
mTextInputLayout = mPreference.findViewById(R.id.edit_input_layout);
mEditText = mPreference.findViewById(android.R.id.edit);
assertThat(mEditText).isNotNull();
}
@@ -88,11 +94,24 @@ public class ZenModeEditNamePreferenceControllerTest {
public void onEditText_callsNameSetter() {
ZenMode mode = new TestModeBuilder().setName("A fancy name").build();
mController.updateState(mPreference, mode);
EditText editText = mPreference.findViewById(android.R.id.edit);
editText.setText("An even fancier name");
mEditText.setText("An even fancier name");
verify(mNameSetter).accept("An even fancier name");
verifyNoMoreInteractions(mNameSetter);
}
@Test
public void onEditText_emptyText_showsError() {
ZenMode mode = new TestModeBuilder().setName("Default name").build();
mController.updateState(mPreference, mode);
mEditText.setText("");
assertThat(mTextInputLayout.getError()).isNotNull();
mEditText.setText("this is fine");
assertThat(mTextInputLayout.getError()).isNull();
}
}

View File

@@ -47,6 +47,8 @@ class VideoCallingPreferenceControllerTest {
private val context: Context = ApplicationProvider.getApplicationContext()
private val mockCallStateRepository = mock<CallStateRepository> {}
private val mockVideoCallingRepository = mock<VideoCallingRepository> {}
private var controller =
spy(
@@ -54,6 +56,7 @@ class VideoCallingPreferenceControllerTest {
context = context,
key = TEST_KEY,
callStateRepository = mockCallStateRepository,
videoCallingRepository = mockVideoCallingRepository
)
) {
on { queryImsState(SUB_ID) } doReturn mockVtQueryImsState
@@ -70,6 +73,42 @@ class VideoCallingPreferenceControllerTest {
controller.displayPreference(preferenceScreen)
}
@Test
fun displayPreference_uiInitState_isHidden() {
assertThat(preference.isVisible).isFalse()
}
@Test
fun onViewCreated_videoCallIsNotReady_isHidden() = runBlocking {
mockVideoCallingRepository.stub {
on { isVideoCallReadyFlow(SUB_ID) } doReturn flowOf(false)
}
mockCallStateRepository.stub {
on { callStateFlow(SUB_ID) } doReturn flowOf(TelephonyManager.CALL_STATE_IDLE)
}
controller.onViewCreated(TestLifecycleOwner())
delay(100)
assertThat(preference.isVisible).isFalse()
}
@Test
fun onViewCreated_videoCallIsNotReady_isShown() = runBlocking {
mockVideoCallingRepository.stub {
on { isVideoCallReadyFlow(SUB_ID) } doReturn flowOf(true)
}
mockCallStateRepository.stub {
on { callStateFlow(SUB_ID) } doReturn flowOf(TelephonyManager.CALL_STATE_IDLE)
}
controller.onViewCreated(TestLifecycleOwner())
delay(100)
assertThat(preference.isVisible).isTrue()
}
@Test
fun updateState_4gLteOff_disabledAndUnchecked() {
mockQueryVoLteState.stub { on { isEnabledByUser } doReturn false }
@@ -82,6 +121,9 @@ class VideoCallingPreferenceControllerTest {
@Test
fun updateState_4gLteOnWithoutCall_enabledAndChecked() = runBlocking {
mockVideoCallingRepository.stub {
on { isVideoCallReadyFlow(SUB_ID) } doReturn flowOf(true)
}
mockVtQueryImsState.stub {
on { isEnabledByUser } doReturn true
on { isAllowUserControl } doReturn true
@@ -101,6 +143,9 @@ class VideoCallingPreferenceControllerTest {
@Test
fun updateState_4gLteOnWithCall_disabledAndChecked() = runBlocking {
mockVideoCallingRepository.stub {
on { isVideoCallReadyFlow(SUB_ID) } doReturn flowOf(true)
}
mockVtQueryImsState.stub {
on { isEnabledByUser } doReturn true
on { isAllowUserControl } doReturn true