Snap for 13061484 from fdb47cee3b to 25Q2-release

Change-Id: Ie5fa996b7118f2010f1aa442b97a1dac1dbdd649
This commit is contained in:
Android Build Coastguard Worker
2025-02-13 16:37:06 -08:00
93 changed files with 1087 additions and 1527 deletions

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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.
-->
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
<corners android:radius="@dimen/settingslib_expressive_radius_medium" />
<stroke android:width="1dp" android:color="@color/settingslib_materialColorOutline" />
</shape>

View File

@@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ 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.
-->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="?android:attr/colorControlHighlight">
<item android:drawable="@drawable/expressive_battery_hints_chip_bg"/>
</ripple>

View File

@@ -1,21 +0,0 @@
<!--
Copyright (C) 2016 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="24dp"
android:height="24dp" android:viewportWidth="960" android:viewportHeight="960"
android:tint="?android:attr/colorControlNormal">
<path android:fillColor="@android:color/white"
android:pathData="M480,880Q397,880 324,848.5Q251,817 197,763Q143,709 111.5,636Q80,563 80,480Q80,397 111.5,324Q143,251 197,197Q251,143 324,111.5Q397,80 480,80Q563,80 636,111.5Q709,143 763,197Q817,251 848.5,324Q880,397 880,480Q880,563 848.5,636Q817,709 763,763Q709,817 636,848.5Q563,880 480,880ZM480,800Q614,800 707,707Q800,614 800,480Q800,473 799.5,465.5Q799,458 799,453Q794,482 772,501Q750,520 720,520L640,520Q607,520 583.5,496.5Q560,473 560,440L560,400L400,400L400,320Q400,287 423.5,263.5Q447,240 480,240L520,240L520,240Q520,217 532.5,199.5Q545,182 563,171Q543,166 522.5,163Q502,160 480,160Q346,160 253,253Q160,346 160,480Q160,480 160,480Q160,480 160,480L360,480Q426,480 473,527Q520,574 520,640L520,680L400,680L400,790Q420,795 439.5,797.5Q459,800 480,800Z"/>
</vector>

View File

@@ -0,0 +1,25 @@
<!--
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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="32dp"
android:height="32dp"
android:viewportWidth="960"
android:viewportHeight="960"
android:tint="?android:attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M480,880Q396.67,880 323.67,848.5Q250.67,817 196.5,762.83Q142.33,708.67 111.17,635.33Q80,562 80,478.67Q80,395 111.17,322.5Q142.33,250 196.5,195.83Q250.67,141.67 323.67,110.83Q396.67,80 480,80Q563.67,80 636.5,110.83Q709.33,141.67 763.5,195.83Q817.67,250 848.83,322.5Q880,395 880,478.67Q880,562 848.83,635.33Q817.67,708.67 763.5,762.83Q709.33,817 636.5,848.5Q563.67,880 480,880ZM480,814Q512,778 534,734Q556,690 570,632.67L390.67,632.67Q404,687.33 426,732.33Q448,777.33 480,814ZM388.67,800.67Q366,764.33 349.5,723.17Q333,682 322,632.67L182.67,632.67Q217.67,696.67 265.5,736Q313.33,775.33 388.67,800.67ZM572,800Q638.67,778.67 691.5,735.67Q744.33,692.67 777.33,632.67L638.67,632.67Q627,681.33 610.83,722.5Q594.67,763.67 572,800ZM158,566L309.33,566Q306.33,541.33 305.5,520.5Q304.67,499.67 304.67,478.67Q304.67,455 305.83,435.5Q307,416 310,393.33L158,393.33Q151.67,416 149.17,435.17Q146.67,454.33 146.67,478.67Q146.67,503 149.17,523.17Q151.67,543.33 158,566ZM377.33,566L583.33,566Q587,538.67 588.17,519.17Q589.33,499.67 589.33,478.67Q589.33,458.33 588.17,439.5Q587,420.67 583.33,393.33L377.33,393.33Q373.67,420.67 372.5,439.5Q371.33,458.33 371.33,478.67Q371.33,499.67 372.5,519.17Q373.67,538.67 377.33,566ZM650,566L802,566Q808.33,543.33 810.83,523.17Q813.33,503 813.33,478.67Q813.33,454.33 810.83,435.17Q808.33,416 802,393.33L650.67,393.33Q653.67,423.33 654.83,442.17Q656,461 656,478.67Q656,500.33 654.5,519.83Q653,539.33 650,566ZM638,326.67L777.33,326.67Q745.67,264 692.83,221Q640,178 571.33,159.33Q594,195 610.17,235.5Q626.33,276 638,326.67ZM390.67,326.67L570.67,326.67Q559.33,276.67 535.67,230.67Q512,184.67 480,147.33Q450,177.33 429,219.67Q408,262 390.67,326.67ZM182.67,326.67L322.67,326.67Q333,278 348.83,237.83Q364.67,197.67 388,160Q319.33,178.67 267.5,221Q215.67,263.33 182.67,326.67Z"/>
</vector>

View File

@@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?><!--
~ 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.
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:minHeight="?android:attr/listPreferredItemHeightSmall"
android:orientation="vertical">
<include layout="@layout/settingslib_expressive_preference"
android:id="@+id/preference_frame"/>
<LinearLayout
android:id="@+id/warning_chip_frame"
android:visibility="gone"
android:clickable="false"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/settingslib_expressive_space_small1"
android:layout_marginTop="-8dp">
<Space
android:id="@+id/warning_padding_placeholder"
android:layout_width="@dimen/settingslib_expressive_space_medium3"
android:layout_height="1px"
android:layout_marginEnd="@dimen/settingslib_expressive_space_extrasmall6"/>
<include layout="@layout/power_anomaly_hints"/>
</LinearLayout>
</LinearLayout>

View File

@@ -44,7 +44,8 @@
android:textAlignment="textStart"
android:text="@string/add_a_language"
style="@style/Base.Widget.AppCompat.Button.Borderless"
android:textAppearance="?android:attr/textAppearanceListItem"/>
android:textAppearance="?android:attr/textAppearanceListItem"
android:visibility="gone"/>
</LinearLayout>

View File

@@ -17,13 +17,12 @@
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:gravity="center_vertical|start"
android:padding="8dp"
android:background="@drawable/battery_hints_chip_bg_ripple">
android:id="@+id/warning_chip"
android:padding="8dp">
<ImageView
android:layout_width="16dp"

View File

@@ -1,49 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2023 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:orientation="vertical">
<TextView
android:id="@+id/time_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="20dp"
android:textAlignment="viewStart"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="?android:attr/textColorPrimary" />
<TextView
android:id="@+id/time_summary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginVertical="4dp"
android:textAlignment="viewStart"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="?android:attr/textColorSecondary" />
<include layout="@layout/power_anomaly_hints"
android:visibility="gone"
android:id="@+id/anomaly_hints"
android:paddingBottom="20dp"/>
</LinearLayout>

View File

@@ -66,6 +66,8 @@
android:layout_gravity="center_vertical"
android:paddingStart="0dp"
android:paddingEnd="12dp"
android:progressBackgroundTint="@color/settingslib_materialColorOutline"
android:progressTint="@color/settingslib_materialColorPrimaryFixed"
android:layout_width="match_parent"
android:layout_height="48dp"/>

View File

@@ -16,8 +16,10 @@
<ScrollView
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:layout_height="wrap_content"
android:theme="@style/Theme.AppCompat.DayNight">
<LinearLayout
android:layout_width="match_parent"
@@ -43,17 +45,24 @@
android:id="@+id/private_dns_mode_provider"
layout="@layout/preference_widget_dialog_radiobutton"/>
<EditText
android:id="@+id/private_dns_mode_provider_hostname"
android:hint="@string/private_dns_mode_provider_hostname_hint"
style="@android:style/Widget.CompoundButton.RadioButton"
android:imeOptions="actionDone"
android:inputType="textFilter|textUri|textMultiLine"
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/private_dns_mode_provider_hostname_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="3dp"
android:layout_marginEnd="8dp"
android:minHeight="@dimen/developer_option_dialog_min_height"/>
android:hint="@string/private_dns_title"
android:theme="@style/Theme.Settings"
app:endIconMode="clear_text"
app:errorEnabled="true">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/private_dns_mode_provider_hostname"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionDone"
android:inputType="textFilter|textUri|textMultiLine"
android:layout_marginStart="3dp"
android:layout_marginEnd="8dp"/>
</com.google.android.material.textfield.TextInputLayout>
</RadioGroup>
<include

View File

@@ -22,7 +22,7 @@
<include layout="@layout/preference_app"/>
<LinearLayout
android:id="@+id/warning_chip"
android:id="@+id/warning_chip_frame"
android:visibility="gone"
android:clickable="false"
android:layout_width="match_parent"
@@ -32,13 +32,12 @@
android:orientation="horizontal"
android:paddingStart="?android:attr/listPreferredItemPaddingStart"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd">
<Space
android:id="@+id/warning_padding_placeholder"
android:layout_width="@dimen/secondary_app_icon_size"
android:layout_height="wrap_content"
android:layout_height="1px"
android:layout_marginEnd="16dp"/>
<include layout="@layout/power_anomaly_hints" />
<include layout="@layout/power_anomaly_hints"/>
</LinearLayout>
</LinearLayout>

View File

@@ -555,4 +555,10 @@
<dimen name="display_block_padding">5dp</dimen>
<dimen name="display_block_highlight_width">2dp</dimen>
<dimen name="display_block_corner_radius">10dp</dimen>
<!-- Locale Picker -->
<dimen name="locale_picker_dialog_icon_padding">10dp</dimen>
<dimen name="locale_picker_dialog_title_padding">16dp</dimen>
<dimen name="locale_picker_dialog_message_padding_left_right">24dp</dimen>
<dimen name="locale_picker_dialog_message_padding_bottom">32dp</dimen>
</resources>

View File

@@ -305,8 +305,6 @@
<!-- Title for Bluetooth device group with media capability group [CHAR LIMIT=none]-->
<string name="connected_device_media_device_title">Media devices</string>
<!-- Title for temporary bond device group [CHAR LIMIT=none]-->
<string name="connected_device_temp_bond_device_title">Guest devices</string>
<!-- Title for Bluetooth device group with media capability group [CHAR LIMIT=none]-->
<string name="connected_device_call_device_title">Call devices</string>
<!-- Title for connected device group [CHAR LIMIT=none]-->
@@ -502,7 +500,7 @@
<!-- The text of the confirmation dialog showing the system locale will be changed. [CHAR LIMIT=NONE]-->
<string name="desc_notice_device_locale_settings_change">Your device settings and regional preferences will change.</string>
<!-- A dialog button for confirmmation of system locale change. [CHAR LIMIT=25]-->
<!-- A dialog button for confirmation of system locale change. [CHAR LIMIT=25]-->
<string name="button_label_confirmation_of_system_locale_change">Change</string>
<!-- Title for saying this selected locale is unavailable to use. [CHAR LIMIT=50]-->
@@ -530,10 +528,11 @@
<!-- Category for more language settings. [CHAR LIMIT=NONE]-->
<string name="more_language_settings_category">More language settings</string>
<!-- Title for asking to change system locale region or not. [CHAR LIMIT=50]-->
<string name="title_change_system_locale_region">Change region to %s ?</string>
<string name="title_change_system_locale_region">Change region to <xliff:g id="system_language_region" example="Canada">%1$s</xliff:g> ?</string>
<!-- Message for asking to change system locale region or not. [CHAR LIMIT=50]-->
<string name="body_change_system_locale_region">Your device will keep %s as a system language</string>
<string name="top_intro_numbering_system_title">The digits used will be dependent on the numbering system</string>
<string name="body_change_system_locale_region">Your device will keep <xliff:g id="system_language" example="English">%1$s</xliff:g> as a system language</string>
<!-- Description for the numbering system language. [CHAR LIMIT=NONE]-->
<string name="top_intro_numbering_system_title">Most apps will use your regional preferences</string>
<!-- Regional Preferences begin -->
<!-- The title of the menu entry of regional preferences. [CHAR LIMIT=50] -->
@@ -2937,6 +2936,12 @@
<string name="emergency_address_title">Emergency address</string>
<!-- Summary of Update Emergency Address preference, explaining usage of emergency address [CHAR LIMIT=NONE] -->
<string name="emergency_address_summary">Used as your location when you make an emergency call over Wi\u2011Fi</string>
<!-- Title of a preference for private DNS provider hostname [CHAR LIMIT=40] -->
<string name="private_dns_title">Hostname</string>
<!-- Message of private dns hostname that the field is required. [CHAR LIMIT=NONE] -->
<string name="private_dns_field_require">The field is required</string>
<!-- The error if the private dns hostname is not valid -->
<string name="private_dns_hostname_invalid">The hostname you typed isn\u2019t valid</string>
<!-- Message of private dns that provides a help link. [CHAR LIMIT=NONE] -->
<string name="private_dns_help_message"><annotation id="url">Learn more</annotation> about Private DNS features</string>
<!-- Message to display when private dns is on. [CHAR LIMIT=10] -->
@@ -13968,13 +13973,15 @@
<string name="audio_sharing_share_with_button_label">Share with <xliff:g example="My buds" id="device_name">%1$s</xliff:g></string>
<!-- Text for audio sharing close button [CHAR LIMIT=none]-->
<string name="audio_sharing_close_button_label">Close</string>
<!-- Content for audio sharing share dialog with no device, ask users to connect device [CHAR LIMIT=none]-->
<!-- Content for audio sharing share dialog with no second device, ask users to connect device [CHAR LIMIT=none]-->
<string name="audio_sharing_dialog_connect_device_content">Connect another pair of compatible headphones, or share your stream\'s name and password with the other person</string>
<!-- Content for audio sharing share dialog with no device, ask users to scan qr code [CHAR LIMIT=none]-->
<!-- Content for audio sharing share dialog with no second device, ask users to scan qr code [CHAR LIMIT=none]-->
<string name="audio_sharing_dialog_qr_code_content">Let others scan this code and listen to your audio\n\nStream name: <xliff:g example="Pixel 8" id="stream_name">%1$s</xliff:g>\nPassword: <xliff:g example="123456" id="password">%2$s</xliff:g></string>
<!-- Content for audio sharing share dialog with no device, ask users to pair new device [CHAR LIMIT=none]-->
<!-- Content for audio sharing share dialog with no second device and no password, ask users to scan qr code [CHAR LIMIT=none]-->
<string name="audio_sharing_dialog_qr_code_content_no_password">Let others scan this code and listen to your audio\n\nStream name: <xliff:g example="Pixel 8" id="stream_name">%1$s</xliff:g></string>
<!-- Content for audio sharing share dialog with no second device, ask users to pair new device [CHAR LIMIT=none]-->
<string name="audio_sharing_dialog_pair_new_device_content">or pair another set of compatible headphones</string>
<!-- Content for audio sharing share dialog with no device, ask users to pair device [CHAR LIMIT=none]-->
<!-- Content for audio sharing share dialog with no second device, ask users to pair device [CHAR LIMIT=none]-->
<string name="audio_sharing_dialog_pair_device_content">Pair another set of compatible headphones, or share your audio stream QR code with the other person</string>
<!-- Text for sharing audio sharing state [CHAR LIMIT=none]-->
<string name="audio_sharing_sharing_label">Sharing audio</string>

View File

@@ -26,17 +26,6 @@
settings:allowDividerBelow="true"
settings:controller="com.android.settings.slices.SlicePreferenceController" />
<PreferenceCategory
android:key="audio_sharing_device_list"
android:title="@string/audio_sharing_device_group_title"
settings:controller="com.android.settings.connecteddevice.audiosharing.AudioSharingDevicePreferenceController">
</PreferenceCategory>
<PreferenceCategory
android:key="temp_bond_device_list"
android:title="@string/connected_device_temp_bond_device_title"
settings:controller="com.android.settings.connecteddevice.audiosharing.TemporaryBondDeviceGroupController" />
<Preference
android:fragment="com.android.settings.connecteddevice.audiosharing.AudioSharingDashboardFragment"
android:icon="@drawable/ic_bt_le_audio_sharing"
@@ -45,6 +34,12 @@
settings:controller="com.android.settings.connecteddevice.audiosharing.AudioSharingPreferenceController"
settings:searchable="false" />
<PreferenceCategory
android:key="audio_sharing_device_list"
android:title="@string/audio_sharing_device_group_title"
settings:controller="com.android.settings.connecteddevice.audiosharing.AudioSharingDevicePreferenceController">
</PreferenceCategory>
<PreferenceCategory
android:key="available_device_list"
android:title="@string/connected_device_media_device_title"

View File

@@ -31,6 +31,13 @@
<com.android.settingslib.widget.LayoutPreference
android:key="languages_picker"
android:layout="@layout/locale_order_list" />
<Preference
android:key="add_a_language"
android:title="@string/add_a_language"
android:icon="@drawable/ic_add_24dp"
settings:isPreferenceVisible="false"
settings:fragment="com.android.settings.localepicker.SystemLocalePickerFragment"/>
</PreferenceCategory>
<PreferenceCategory

View File

@@ -22,7 +22,6 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
@@ -139,13 +138,8 @@ public class ApprovalPreferenceController extends BasePreferenceController {
public void disable(final ComponentName cn) {
logSpecialPermissionChange(true, cn.getPackageName());
mNm.setNotificationListenerAccessGranted(cn, false);
if (!mNm.isNotificationPolicyAccessGrantedForPackage(
cn.getPackageName())) {
if (android.app.Flags.modesApi()) {
mNm.removeAutomaticZenRules(cn.getPackageName(), /* fromUser= */ true);
} else {
mNm.removeAutomaticZenRules(cn.getPackageName());
}
if (!mNm.isNotificationPolicyAccessGrantedForPackage(cn.getPackageName())) {
mNm.removeAutomaticZenRules(cn.getPackageName(), /* fromUser= */ true);
}
}

View File

@@ -56,7 +56,7 @@ public class FriendlyWarningDialogFragment extends InstrumentedDialogFragment {
NotificationAccessDetails parent = (NotificationAccessDetails) getTargetFragment();
final String summary = getResources().getString(
Flags.modesApi() && Flags.modesUi()
Flags.modesUi()
? R.string.notification_listener_disable_modes_warning_summary
: R.string.notification_listener_disable_warning_summary,
label);

View File

@@ -98,7 +98,7 @@ public class ScaryWarningDialogFragment extends InstrumentedDialogFragment {
((TextView) content.findViewById(R.id.prompt)).setText(prompt);
((TextView) content.findViewById(R.id.settings_description)).setText(
Flags.modesApi() && Flags.modesUi()
Flags.modesUi()
? R.string.nls_feature_modes_settings_summary
: R.string.nls_feature_settings_summary);

View File

@@ -59,12 +59,12 @@ public class FriendlyWarningDialogFragment extends InstrumentedDialogFragment {
final String label = args.getString(KEY_LABEL);
final String title = getResources().getString(
Flags.modesApi() && Flags.modesUi()
Flags.modesUi()
? R.string.zen_modes_access_revoke_warning_dialog_title
: R.string.zen_access_revoke_warning_dialog_title,
label);
final String summary = getResources()
.getString(Flags.modesApi() && Flags.modesUi()
.getString(Flags.modesUi()
? R.string.zen_modes_access_revoke_warning_dialog_summary
: R.string.zen_access_revoke_warning_dialog_summary);

View File

@@ -57,12 +57,12 @@ public class ScaryWarningDialogFragment extends InstrumentedDialogFragment {
final String label = args.getString(KEY_LABEL);
final String title = getResources().getString(
Flags.modesApi() && Flags.modesUi()
Flags.modesUi()
? R.string.zen_modes_access_warning_dialog_title
: R.string.zen_access_warning_dialog_title,
label);
final String summary = getResources()
.getString(Flags.modesApi() && Flags.modesUi()
.getString(Flags.modesUi()
? R.string.zen_modes_access_warning_dialog_summary
: R.string.zen_access_warning_dialog_summary);

View File

@@ -56,7 +56,7 @@ public class ZenAccessController extends BasePreferenceController {
public void displayPreference(PreferenceScreen screen) {
Preference preference = screen.findPreference(getPreferenceKey());
if (preference != null) {
preference.setTitle(Flags.modesApi() && Flags.modesUi()
preference.setTitle(Flags.modesUi()
? R.string.manage_zen_modes_access_title
: R.string.manage_zen_access_title);
}
@@ -116,11 +116,7 @@ public class ZenAccessController extends BasePreferenceController {
public static void deleteRules(final Context context, final String pkg) {
final NotificationManager mgr = context.getSystemService(NotificationManager.class);
if (android.app.Flags.modesApi()) {
mgr.removeAutomaticZenRules(pkg, /* fromUser= */ true);
} else {
mgr.removeAutomaticZenRules(pkg);
}
mgr.removeAutomaticZenRules(pkg, /* fromUser= */ true);
}
@VisibleForTesting

View File

@@ -51,7 +51,7 @@ public class ZenAccessDetails extends AppInfoWithHeader implements
@Override
public void onResume() {
super.onResume();
requireActivity().setTitle(Flags.modesApi() && Flags.modesUi()
requireActivity().setTitle(Flags.modesUi()
? R.string.manage_zen_modes_access_title
: R.string.manage_zen_access_title);
}
@@ -89,7 +89,7 @@ public class ZenAccessDetails extends AppInfoWithHeader implements
preference.setSummary(getString(R.string.zen_access_disabled_package_warning));
return;
}
preference.setTitle(Flags.modesApi() && Flags.modesUi()
preference.setTitle(Flags.modesUi()
? R.string.zen_modes_access_detail_switch
: R.string.zen_access_detail_switch);
preference.setChecked(ZenAccessController.hasAccess(context, mPackageName));

View File

@@ -26,7 +26,6 @@ import com.android.settings.connecteddevice.DevicePreferenceCallback;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.flags.Flags;
import com.android.settingslib.utils.ThreadUtils;
/** Controller to maintain available media Bluetooth devices */
@@ -61,14 +60,6 @@ public class AvailableMediaBluetoothDeviceUpdater extends BluetoothDeviceUpdater
@Override
public boolean isFilterMatched(CachedBluetoothDevice cachedDevice) {
// If the device is temporary bond, it shouldn't be shown here.
if (Flags.enableTemporaryBondDevicesUi()
&& BluetoothUtils.isTemporaryBondDevice(cachedDevice.getDevice())) {
Log.d(TAG,
"isFilterMatched() Filter out temporary bond device " + cachedDevice.getName());
return false;
}
final int currentAudioProfile;
if (mAudioMode == AudioManager.MODE_RINGTONE

View File

@@ -57,14 +57,6 @@ public class ConnectedBluetoothDeviceUpdater extends BluetoothDeviceUpdater {
@Override
public boolean isFilterMatched(CachedBluetoothDevice cachedDevice) {
// If the device is temporary bond, it shouldn't be shown here.
if (Flags.enableTemporaryBondDevicesUi()
&& BluetoothUtils.isTemporaryBondDevice(cachedDevice.getDevice())) {
Log.d(TAG,
"isFilterMatched() Filter out temporary bond device " + cachedDevice.getName());
return false;
}
final int currentAudioProfile;
if (mAudioMode == AudioManager.MODE_RINGTONE

View File

@@ -27,7 +27,6 @@ import com.android.settings.R;
import com.android.settings.SettingsActivity;
import com.android.settings.Utils;
import com.android.settings.connecteddevice.audiosharing.AudioSharingDevicePreferenceController;
import com.android.settings.connecteddevice.audiosharing.TemporaryBondDeviceGroupController;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.overlay.SurveyFeatureProvider;
@@ -35,7 +34,6 @@ import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.slices.SlicePreferenceController;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.HearingAidStatsLogUtils;
import com.android.settingslib.flags.Flags;
import com.android.settingslib.search.SearchIndexable;
@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
@@ -84,9 +82,6 @@ public class ConnectedDeviceDashboardFragment extends DashboardFragment {
}
if (BluetoothUtils.isAudioSharingUIAvailable(context)) {
use(AudioSharingDevicePreferenceController.class).init(this);
if (Flags.enableTemporaryBondDevicesUi()) {
use(TemporaryBondDeviceGroupController.class).init(this);
}
}
use(AvailableMediaDeviceGroupController.class).init(this);
use(ConnectedDeviceGroupController.class).init(this);

View File

@@ -29,7 +29,6 @@ import com.android.settings.connecteddevice.DevicePreferenceCallback;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.flags.Flags;
import com.android.settingslib.utils.ThreadUtils;
public class AudioSharingBluetoothDeviceUpdater extends BluetoothDeviceUpdater
@@ -52,14 +51,6 @@ public class AudioSharingBluetoothDeviceUpdater extends BluetoothDeviceUpdater
@Override
public boolean isFilterMatched(CachedBluetoothDevice cachedDevice) {
// If the device is temporary bond, it shouldn't be shown here.
if (Flags.enableTemporaryBondDevicesUi()
&& BluetoothUtils.isTemporaryBondDevice(cachedDevice.getDevice())) {
Log.d(TAG,
"isFilterMatched() Filter out temporary bond device " + cachedDevice.getName());
return false;
}
boolean isFilterMatched = false;
if (isDeviceConnected(cachedDevice) && isDeviceInCachedDevicesList(cachedDevice)) {
// If device is LE audio device and has a broadcast source,

View File

@@ -67,7 +67,6 @@ import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
/** PreferenceController to control the dialog to choose the active device for calls and alarms */
public class AudioSharingCallAudioPreferenceController extends AudioSharingBasePreferenceController
@@ -404,21 +403,11 @@ public class AudioSharingCallAudioPreferenceController extends AudioSharingBaseP
private void updateDeviceItemsInSharingSession() {
mGroupedConnectedDevices = AudioSharingUtils.fetchConnectedDevicesByGroupId(mBtManager);
if (Flags.enableTemporaryBondDevicesUi()) {
mGroupedConnectedDevices =
mGroupedConnectedDevices.entrySet().stream()
.filter(entry -> !anyTemporaryBondDevice(entry.getValue()))
.collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
mDeviceItemsInSharingSession =
AudioSharingUtils.buildOrderedConnectedLeadAudioSharingDeviceItem(
mBtManager, mGroupedConnectedDevices, /* filterByInSharing= */ true);
}
private boolean anyTemporaryBondDevice(List<BluetoothDevice> connectedDevices) {
return connectedDevices.stream().anyMatch(BluetoothUtils::isTemporaryBondDevice);
}
@Nullable
private Pair<Integer, AudioSharingDeviceItem> getActiveItemWithIndex() {
List<AudioSharingDeviceItem> deviceItems = new ArrayList<>(mDeviceItemsInSharingSession);

View File

@@ -186,14 +186,17 @@ public class AudioSharingDialogFragment extends InstrumentedDialogFragment {
Drawable qrCodeDrawable = metadata == null ? null : getQrCodeDrawable(metadata,
getContext()).orElse(null);
if (qrCodeDrawable != null) {
String broadcastName =
metadata.getBroadcastName() == null ? "" : metadata.getBroadcastName();
boolean hasPassword = metadata.getBroadcastCode() != null
&& metadata.getBroadcastCode().length > 0;
String message = hasPassword ? getString(
R.string.audio_sharing_dialog_qr_code_content, broadcastName,
new String(metadata.getBroadcastCode(), StandardCharsets.UTF_8)) :
getString(R.string.audio_sharing_dialog_qr_code_content_no_password,
broadcastName);
builder.setCustomImage(qrCodeDrawable)
.setCustomMessage(
getString(
R.string.audio_sharing_dialog_qr_code_content,
metadata.getBroadcastName(),
new String(
metadata.getBroadcastCode(),
StandardCharsets.UTF_8)))
.setCustomMessage(message)
.setCustomMessage2(R.string.audio_sharing_dialog_pair_new_device_content)
.setCustomNegativeButton(R.string.audio_streams_dialog_close,
v -> onCancelClick());

View File

@@ -1,170 +0,0 @@
/*
* 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.connecteddevice.audiosharing;
import android.content.Context;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceScreen;
import com.android.settings.bluetooth.BluetoothDeviceUpdater;
import com.android.settings.bluetooth.Utils;
import com.android.settings.connecteddevice.DevicePreferenceCallback;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settingslib.bluetooth.BluetoothCallback;
import com.android.settingslib.bluetooth.BluetoothEventManager;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.flags.Flags;
import com.android.settingslib.utils.ThreadUtils;
/**
* Controller to maintain the {@link androidx.preference.PreferenceGroup} for all connected
* temporary bond devices. It uses {@link DevicePreferenceCallback} to add/remove
* {@link Preference}
*/
public class TemporaryBondDeviceGroupController extends BasePreferenceController implements
DefaultLifecycleObserver, DevicePreferenceCallback, BluetoothCallback {
private static final String TAG = "TemporaryBondDeviceGroupController";
private static final String KEY = "temp_bond_device_list";
@Nullable
private final BluetoothEventManager mEventManager;
@Nullable
private PreferenceGroup mPreferenceGroup;
@Nullable
private BluetoothDeviceUpdater mBluetoothDeviceUpdater;
public TemporaryBondDeviceGroupController(@NonNull Context context) {
super(context, KEY);
LocalBluetoothManager btManager = Utils.getLocalBtManager(mContext);
mEventManager = btManager == null ? null : btManager.getEventManager();
}
@Override
public void onStart(@NonNull LifecycleOwner owner) {
if (!isAvailable()) {
Log.d(TAG, "Skip onStart(), feature is not supported.");
return;
}
if (mEventManager == null) {
Log.d(TAG, "onStart() Bluetooth is not supported on this device");
return;
}
var unused = ThreadUtils.postOnBackgroundThread(() -> {
mEventManager.registerCallback(this);
if (mBluetoothDeviceUpdater != null) {
mBluetoothDeviceUpdater.registerCallback();
mBluetoothDeviceUpdater.refreshPreference();
}
});
}
@Override
public void onStop(@NonNull LifecycleOwner owner) {
var unused = ThreadUtils.postOnBackgroundThread(() -> {
if (mBluetoothDeviceUpdater != null) {
mBluetoothDeviceUpdater.unregisterCallback();
}
if (mEventManager != null) {
mEventManager.unregisterCallback(this);
return;
}
Log.d(TAG, "onStop() Bluetooth is not supported on this device");
});
}
@Override
public void displayPreference(@NonNull PreferenceScreen screen) {
super.displayPreference(screen);
mPreferenceGroup = screen.findPreference(KEY);
if (mPreferenceGroup != null) {
mPreferenceGroup.setVisible(false);
}
if (isAvailable() && mBluetoothDeviceUpdater != null) {
mBluetoothDeviceUpdater.setPrefContext(screen.getContext());
mBluetoothDeviceUpdater.forceUpdate();
}
}
@Override
public void onDeviceAdded(@NonNull Preference preference) {
if (mPreferenceGroup != null) {
mPreferenceGroup.addPreference(preference);
Log.d(TAG, "Temporary bond device added");
if (mPreferenceGroup.getPreferenceCount() == 1) {
mPreferenceGroup.setVisible(true);
}
}
}
@Override
public void onDeviceRemoved(@NonNull Preference preference) {
if (mPreferenceGroup != null) {
mPreferenceGroup.removePreference(preference);
Log.d(TAG, "Temporary bond device removed");
if (mPreferenceGroup.getPreferenceCount() == 0) {
mPreferenceGroup.setVisible(false);
}
}
}
@Override
public int getAvailabilityStatus() {
return (BluetoothUtils.isAudioSharingUIAvailable(mContext)
&& mBluetoothDeviceUpdater != null && Flags.enableTemporaryBondDevicesUi())
? AVAILABLE_UNSEARCHABLE
: UNSUPPORTED_ON_DEVICE;
}
@Override
public String getPreferenceKey() {
return KEY;
}
/**
* Initialize the controller.
*
* @param fragment The fragment to provide the context and metrics category for {@link
* TemporaryBondDeviceGroupUpdater} and provide the host for dialogs.
*/
public void init(@NonNull DashboardFragment fragment) {
mBluetoothDeviceUpdater = new TemporaryBondDeviceGroupUpdater(fragment.getContext(),
TemporaryBondDeviceGroupController.this,
fragment.getMetricsCategory());
}
@VisibleForTesting
void setBluetoothDeviceUpdater(@Nullable BluetoothDeviceUpdater bluetoothDeviceUpdater) {
mBluetoothDeviceUpdater = bluetoothDeviceUpdater;
}
@VisibleForTesting
void setPreferenceGroup(@Nullable PreferenceGroup preferenceGroup) {
mPreferenceGroup = preferenceGroup;
}
}

View File

@@ -1,74 +0,0 @@
/*
* 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.connecteddevice.audiosharing;
import android.content.Context;
import android.util.Log;
import androidx.annotation.NonNull;
import com.android.settings.bluetooth.BluetoothDeviceUpdater;
import com.android.settings.connecteddevice.DevicePreferenceCallback;
import com.android.settingslib.bluetooth.BluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.flags.Flags;
/** Maintain and update connected temporary bond bluetooth devices */
public class TemporaryBondDeviceGroupUpdater extends BluetoothDeviceUpdater {
private static final String TAG = "TemporaryBondDeviceGroupUpdater";
private static final String PREF_KEY_PREFIX = "temp_bond_bt_";
public TemporaryBondDeviceGroupUpdater(
@NonNull Context context,
@NonNull DevicePreferenceCallback devicePreferenceCallback,
int metricsCategory) {
super(context, devicePreferenceCallback, metricsCategory);
}
@Override
public boolean isFilterMatched(@NonNull CachedBluetoothDevice cachedDevice) {
// Only connected temporary bond device should be shown in this section when Audio
// sharing UI is available.
boolean isFilterMatched = Flags.enableTemporaryBondDevicesUi()
&& BluetoothUtils.isTemporaryBondDevice(cachedDevice.getDevice())
&& isDeviceConnected(cachedDevice) && isDeviceInCachedDevicesList(cachedDevice)
&& BluetoothUtils.isAudioSharingUIAvailable(mContext);
Log.d(
TAG,
"isFilterMatched() device : "
+ cachedDevice.getName()
+ ", isFilterMatched : "
+ isFilterMatched);
return isFilterMatched;
}
@Override
protected String getPreferenceKeyPrefix() {
return PREF_KEY_PREFIX;
}
@Override
protected String getLogTag() {
return TAG;
}
@Override
protected void update(CachedBluetoothDevice cachedBluetoothDevice) {
super.update(cachedBluetoothDevice);
Log.d(TAG, "Map : " + mPreferenceMap);
}
}

View File

@@ -59,6 +59,7 @@ import com.android.settingslib.widget.TwoTargetPreference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.function.Consumer;
/**
* The Settings screen for External Displays configuration and connection management.
@@ -85,8 +86,6 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
BUILTIN_DISPLAY_LIST(70, "builtin_display_list_preference",
R.string.builtin_display_settings_category),
DISPLAYS_LIST(80, "displays_list_preference", null),
// If shown, footer should appear below everything.
FOOTER(90, "footer_preference", null);
@@ -333,15 +332,6 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
return args != null ? args.getInt(DISPLAY_ID_ARG, INVALID_DISPLAY) : INVALID_DISPLAY;
}
@NonNull
private PreferenceCategory getDisplaysListPreference(@NonNull Context context) {
if (mDisplaysPreference == null) {
mDisplaysPreference = new PreferenceCategory(context);
PrefBasics.DISPLAYS_LIST.apply(mDisplaysPreference);
}
return mDisplaysPreference;
}
@NonNull
private PreferenceCategory getBuiltinDisplayListPreference(@NonNull Context context) {
if (mBuiltinDisplayPreference == null) {
@@ -455,6 +445,26 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
EXTERNAL_DISPLAY_NOT_FOUND_FOOTER_RESOURCE));
}
private static PreferenceCategory getCategoryForDisplay(@NonNull Display display,
@NonNull PrefRefresh screen, @NonNull Context context) {
// The rest of the settings are in a category with the display name as the title.
String categoryKey = "expanded_display_items_" + display.getDisplayId();
var category = (PreferenceCategory) screen.findUnusedPreference(categoryKey);
if (category != null) {
screen.addPreference(category);
} else {
category = new PreferenceCategory(context);
screen.addPreference(category);
category.setPersistent(false);
category.setKey(categoryKey);
category.setTitle(display.getName());
category.setOrder(PrefBasics.BUILTIN_DISPLAY_LIST.order + 1);
}
return category;
}
private void showDisplaySettings(@NonNull Display display, @NonNull PrefRefresh screen,
@NonNull Context context) {
final var isEnabled = mInjector != null && mInjector.isDisplayEnabled(display);
@@ -469,8 +479,18 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
if (!isTopologyPaneEnabled(mInjector)) {
screen.addPreference(updateIllustrationImage(context, displayRotation));
}
screen.addPreference(updateResolutionPreference(context, display));
screen.addPreference(updateRotationPreference(context, display, displayRotation));
Consumer<Preference> adder;
if (isTopologyPaneEnabled(mInjector)) {
adder = getCategoryForDisplay(display, screen, context)::addPreference;
// The category may have already been populated if it was retrieved from the PrefRefresh
// backup, but we still need to update resolution and rotation items.
} else {
adder = screen::addPreference;
}
adder.accept(updateResolutionPreference(context, display));
adder.accept(updateRotationPreference(context, display, displayRotation));
if (isResolutionSettingEnabled(mInjector)) {
// Do not show the footer about changing resolution affecting apps. This is not in the
// UX design for v2, and there is no good place to put it, since (a) if it is on the
@@ -483,12 +503,12 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
// TODO(b/352648432): probably remove footer once the pane and rest of v2 UI is in
// place.
if (!isTopologyPaneEnabled(mInjector)) {
screen.addPreference(updateFooterPreference(context,
adder.accept(updateFooterPreference(context,
EXTERNAL_DISPLAY_CHANGE_RESOLUTION_FOOTER_RESOURCE));
}
}
if (isDisplaySizeSettingEnabled(mInjector)) {
screen.addPreference(updateSizePreference(context));
adder.accept(updateSizePreference(context));
}
}
@@ -508,23 +528,28 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
private void showDisplaysList(@NonNull List<Display> displaysToShow,
@NonNull PrefRefresh screen, @NonNull Context context) {
maybeAddV2Components(context, screen);
var displayGroupPref = getDisplaysListPreference(context);
if (!displaysToShow.isEmpty()) {
screen.addPreference(displayGroupPref);
}
try (var groupCleanable = new PrefRefresh(displayGroupPref)) {
for (var display : displaysToShow) {
var pref = getDisplayPreference(context, display, groupCleanable);
pref.setSummary(display.getMode().getPhysicalWidth() + " x "
+ display.getMode().getPhysicalHeight());
}
int order = PrefBasics.BUILTIN_DISPLAY_LIST.order;
for (var display : displaysToShow) {
var pref = getDisplayPreference(context, display, screen, ++order);
pref.setSummary(display.getMode().getPhysicalWidth() + " x "
+ display.getMode().getPhysicalHeight());
}
}
@VisibleForTesting
static String displayListDisplayCategoryKey(int displayId) {
return "display_list_display_category_" + displayId;
}
@VisibleForTesting
static String resolutionRotationPreferenceKey(int displayId) {
return "display_id_" + displayId;
}
private Preference getDisplayPreference(@NonNull Context context,
@NonNull Display display, @NonNull PrefRefresh groupCleanable) {
var itemKey = "display_id_" + display.getDisplayId();
var categoryKey = itemKey + "_category";
@NonNull Display display, @NonNull PrefRefresh groupCleanable, int categoryOrder) {
var itemKey = resolutionRotationPreferenceKey(display.getDisplayId());
var categoryKey = displayListDisplayCategoryKey(display.getDisplayId());
var category = (PreferenceCategory) groupCleanable.findUnusedPreference(categoryKey);
if (category != null) {
@@ -534,6 +559,7 @@ public class ExternalDisplayPreferenceFragment extends SettingsPreferenceFragmen
category = new PreferenceCategory(context);
category.setPersistent(false);
category.setKey(categoryKey);
category.setOrder(categoryOrder);
// Must add the category to the hierarchy before adding its descendants. Otherwise
// the category will not have a preference manager, which causes an exception when a
// child is added to it.

View File

@@ -16,6 +16,7 @@
package com.android.settings.development;
import static com.android.settings.development.BluetoothA2dpHwOffloadPreferenceController.A2DP_OFFLOAD_SUPPORTED_PROPERTY;
import static com.android.settings.development.BluetoothA2dpHwOffloadPreferenceController.A2DP_OFFLOAD_DISABLED_PROPERTY;
import android.bluetooth.BluetoothAdapter;
@@ -105,13 +106,14 @@ public class BluetoothLeAudioHwOffloadPreferenceController
(mBluetoothAdapter.isLeAudioSupported() == BluetoothStatusCodes.FEATURE_SUPPORTED);
final boolean leAudioOffloadSupported =
SystemProperties.getBoolean(LE_AUDIO_OFFLOAD_SUPPORTED_PROPERTY, false);
final boolean a2dpOffloadDisabled =
SystemProperties.getBoolean(A2DP_OFFLOAD_DISABLED_PROPERTY, false);
if (leAudioEnabled && leAudioOffloadSupported && !a2dpOffloadDisabled) {
((TwoStatePreference) mPreference).setChecked(true);
SystemProperties.set(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, "true");
} else {
final boolean a2dpOffloadSupported =
SystemProperties.getBoolean(A2DP_OFFLOAD_SUPPORTED_PROPERTY, false);
if(!leAudioEnabled || !leAudioOffloadSupported || !a2dpOffloadSupported) {
mPreference.setEnabled(false);
} else {
((TwoStatePreference) mPreference).setChecked(false);
SystemProperties.set(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, "false");
}
}

View File

@@ -98,7 +98,7 @@ public class DesktopExperiencePreferenceController extends DeveloperOptionsPrefe
@Override
public CharSequence getSummary() {
if (DesktopModeStatus.isInternalDisplayEligibleToHostDesktops(mContext)
if (DesktopModeStatus.isDeviceEligibleForDesktopMode(mContext)
&& !DesktopModeFlags.ENABLE_DESKTOP_WINDOWING_MODE.isTrue()) {
return mContext.getString(
R.string.enable_desktop_experience_features_summary_with_desktop);

View File

@@ -17,6 +17,7 @@
package com.android.settings.deviceinfo;
import android.content.Context;
import android.os.UserManager;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
@@ -30,6 +31,7 @@ import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.network.SubscriptionUtil;
import com.android.settingslib.Utils;
import java.util.ArrayList;
import java.util.List;
@@ -51,8 +53,13 @@ public class PhoneNumberPreferenceController extends BasePreferenceController {
@Override
public int getAvailabilityStatus() {
return SubscriptionUtil.isSimHardwareVisible(mContext) ?
AVAILABLE : UNSUPPORTED_ON_DEVICE;
if (!SubscriptionUtil.isSimHardwareVisible(mContext) || Utils.isWifiOnly(mContext)) {
return UNSUPPORTED_ON_DEVICE;
}
if (!mContext.getSystemService(UserManager.class).isAdminUser()) {
return DISABLED_FOR_USER;
}
return AVAILABLE;
}
@Override

View File

@@ -93,10 +93,10 @@ public class PowerUsageTimeController extends BasePreferenceController {
|| (summaryTimeMs == 0 && !TextUtils.equals(anomalyHintKey, preference.getKey()))) {
return false;
}
preference.setTimeTitle(mContext.getString(titleResId));
preference.setTimeSummary(getPowerUsageTimeInfo(summaryTimeMs));
preference.setTitle(mContext.getString(titleResId));
preference.setSummary(getPowerUsageTimeInfo(summaryTimeMs));
if (TextUtils.equals(anomalyHintKey, preference.getKey())) {
preference.setAnomalyHint(anomalyHintText);
preference.setHint(anomalyHintText);
}
preference.setVisible(true);
return true;

View File

@@ -17,74 +17,17 @@
package com.android.settings.fuelgauge;
import android.content.Context;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
import com.android.settings.R;
import com.android.settingslib.widget.GroupSectionDividerMixin;
/** Custom preference for displaying the app power usage time. */
public class PowerUsageTimePreference extends Preference {
public class PowerUsageTimePreference extends WarningFramePreference implements
GroupSectionDividerMixin {
private static final String TAG = "PowerUsageTimePreference";
@VisibleForTesting CharSequence mTimeTitle;
@VisibleForTesting CharSequence mTimeSummary;
@VisibleForTesting CharSequence mAnomalyHintText;
public PowerUsageTimePreference(Context context, AttributeSet attrs) {
super(context, attrs);
setLayoutResource(R.layout.power_usage_time);
}
void setTimeTitle(CharSequence timeTitle) {
if (!TextUtils.equals(mTimeTitle, timeTitle)) {
mTimeTitle = timeTitle;
notifyChanged();
}
}
void setTimeSummary(CharSequence timeSummary) {
if (!TextUtils.equals(mTimeSummary, timeSummary)) {
mTimeSummary = timeSummary;
notifyChanged();
}
}
void setAnomalyHint(CharSequence anomalyHintText) {
if (!TextUtils.equals(mAnomalyHintText, anomalyHintText)) {
mAnomalyHintText = anomalyHintText;
notifyChanged();
}
}
private void showAnomalyHint(PreferenceViewHolder view) {
if (TextUtils.isEmpty(mAnomalyHintText)) {
return;
}
final View anomalyHintView = view.findViewById(R.id.anomaly_hints);
if (anomalyHintView == null) {
return;
}
final TextView warningInfo = anomalyHintView.findViewById(R.id.warning_info);
if (warningInfo == null) {
return;
}
warningInfo.setText(mAnomalyHintText);
anomalyHintView.setVisibility(View.VISIBLE);
}
@Override
public void onBindViewHolder(PreferenceViewHolder view) {
super.onBindViewHolder(view);
((TextView) view.findViewById(R.id.time_title)).setText(mTimeTitle);
((TextView) view.findViewById(R.id.time_summary)).setText(mTimeSummary);
showAnomalyHint(view);
setSelectable(false);
}
}

View File

@@ -0,0 +1,97 @@
/*
* 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.fuelgauge;
import android.annotation.Nullable;
import android.content.Context;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.View;
import android.widget.TextView;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
import com.android.settings.R;
import com.android.settingslib.Utils;
import com.android.settingslib.widget.SettingsThemeHelper;
/**
* Custom preference for displaying the {@link Preference} with an optional hint chip.
*/
public class WarningFramePreference extends Preference {
private final int mTitleColorNormal;
private final int mSummaryColorNormal;
private final int mWarningChipBackgroundResId;
private final boolean mIsExpressiveTheme;
@Nullable private CharSequence mHintText;
public WarningFramePreference(Context context, AttributeSet attrs) {
super(context, attrs);
mIsExpressiveTheme = SettingsThemeHelper.isExpressiveTheme(context);
int layoutResId =
mIsExpressiveTheme
? R.layout.expressive_warning_frame_preference
: R.layout.warning_frame_preference;
setLayoutResource(layoutResId);
mWarningChipBackgroundResId =
mIsExpressiveTheme
? R.drawable.expressive_battery_hints_chip_bg_ripple
: R.drawable.battery_hints_chip_bg_ripple;
mTitleColorNormal =
Utils.getColorAttrDefaultColor(context, android.R.attr.textColorPrimary);
mSummaryColorNormal =
Utils.getColorAttrDefaultColor(context, android.R.attr.textColorSecondary);
}
/** Sets the text of hint to show. */
public void setHint(@Nullable CharSequence hintText) {
if (!TextUtils.equals(mHintText, hintText)) {
mHintText = hintText;
notifyChanged();
}
}
@Override
public void onBindViewHolder(PreferenceViewHolder view) {
super.onBindViewHolder(view);
if (mIsExpressiveTheme) {
final View preferenceFrame = view.findViewById(R.id.preference_frame);
preferenceFrame.setBackground(null);
preferenceFrame.setPadding(0, 0, 0, 0);
}
final View warningChipFrame = view.findViewById(R.id.warning_chip_frame);
warningChipFrame
.findViewById(R.id.warning_padding_placeholder)
.setVisibility(getIcon() != null ? View.VISIBLE : View.GONE);
if (!TextUtils.isEmpty(mHintText)) {
((TextView) warningChipFrame.findViewById(R.id.warning_info)).setText(mHintText);
warningChipFrame.setVisibility(View.VISIBLE);
warningChipFrame
.findViewById(R.id.warning_chip)
.setBackgroundResource(mWarningChipBackgroundResId);
} else {
warningChipFrame.setVisibility(View.GONE);
}
((TextView) view.findViewById(android.R.id.title)).setTextColor(mTitleColorNormal);
((TextView) view.findViewById(android.R.id.summary)).setTextColor(mSummaryColorNormal);
}
}

View File

@@ -1,61 +0,0 @@
/*
* Copyright (C) 2023 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.fuelgauge.batteryusage;
import android.annotation.Nullable;
import android.content.Context;
import android.text.TextUtils;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import androidx.preference.PreferenceViewHolder;
import com.android.settings.R;
class AnomalyAppItemPreference extends PowerGaugePreference {
private static final String TAG = "AnomalyAppItemPreference";
private CharSequence mAnomalyHintText;
AnomalyAppItemPreference(Context context) {
super(context, /* attrs */ null);
setLayoutResource(R.layout.anomaly_app_item_preference);
}
void setAnomalyHint(@Nullable CharSequence anomalyHintText) {
if (!TextUtils.equals(mAnomalyHintText, anomalyHintText)) {
mAnomalyHintText = anomalyHintText;
notifyChanged();
}
}
@Override
public void onBindViewHolder(PreferenceViewHolder viewHolder) {
super.onBindViewHolder(viewHolder);
final LinearLayout warningChipView =
(LinearLayout) viewHolder.findViewById(R.id.warning_chip);
if (!TextUtils.isEmpty(mAnomalyHintText)) {
((TextView) warningChipView.findViewById(R.id.warning_info)).setText(mAnomalyHintText);
warningChipView.setVisibility(View.VISIBLE);
} else {
warningChipView.setVisibility(View.GONE);
}
}
}

View File

@@ -381,15 +381,15 @@ public class BatteryUsageBreakdownController extends BasePreferenceController
continue;
}
final String prefKey = entry.getKey();
AnomalyAppItemPreference preference = mRootPreferenceGroup.findPreference(prefKey);
PowerGaugePreference preference = mRootPreferenceGroup.findPreference(prefKey);
if (preference != null) {
isAdded = true;
} else {
preference = (AnomalyAppItemPreference) mPreferenceCache.get(prefKey);
preference = (PowerGaugePreference) mPreferenceCache.get(prefKey);
}
// Creates new instance if cached preference is not found.
if (preference == null) {
preference = new AnomalyAppItemPreference(mPrefContext);
preference = new PowerGaugePreference(mPrefContext);
preference.setKey(prefKey);
mPreferenceCache.put(prefKey, preference);
}
@@ -398,7 +398,7 @@ public class BatteryUsageBreakdownController extends BasePreferenceController
preference.setOrder(++preferenceOrder);
preference.setSingleLineTitle(true);
// Updates App item preference style
preference.setAnomalyHint(isAnomalyBatteryDiffEntry(entry) ? mAnomalyHintString : null);
preference.setHint(isAnomalyBatteryDiffEntry(entry) ? mAnomalyHintString : null);
// Sets the BatteryDiffEntry to preference for launching detailed page.
preference.setBatteryDiffEntry(entry);
preference.setSelectable(entry.validForRestriction());

View File

@@ -28,7 +28,7 @@ import androidx.preference.PreferenceViewHolder;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settingslib.widget.AppPreference;
import com.android.settings.fuelgauge.WarningFramePreference;
/**
* Custom preference for displaying battery usage info as a bar and an icon on the left for the
@@ -37,7 +37,7 @@ import com.android.settingslib.widget.AppPreference;
* <p>The battery usage info could be usage percentage or usage time. The preference won't show any
* icon if it is null.
*/
public class PowerGaugePreference extends AppPreference {
public class PowerGaugePreference extends WarningFramePreference {
// Please see go/battery-usage-app-list-alpha
private static final float SELECTABLE_ALPHA = 1f;
@@ -51,7 +51,6 @@ public class PowerGaugePreference extends AppPreference {
private CharSequence mContentDescription;
private CharSequence mProgress;
private CharSequence mProgressContentDescription;
private boolean mShowAnomalyIcon;
public PowerGaugePreference(
Context context, Drawable icon, CharSequence contentDescription, BatteryEntry info) {
@@ -79,7 +78,6 @@ public class PowerGaugePreference extends AppPreference {
setWidgetLayoutResource(R.layout.preference_widget_summary);
mInfo = info;
mContentDescription = contentDescription;
mShowAnomalyIcon = false;
mTitleColorNormal =
Utils.getColorAttrDefaultColor(context, android.R.attr.textColorPrimary);
}
@@ -108,17 +106,6 @@ public class PowerGaugePreference extends AppPreference {
return mProgress.toString();
}
/** Sets whether to show anomaly icon */
public void shouldShowAnomalyIcon(boolean showAnomalyIcon) {
mShowAnomalyIcon = showAnomalyIcon;
notifyChanged();
}
/** Gets whether to show anomaly icon */
public boolean showAnomalyIcon() {
return mShowAnomalyIcon;
}
public void setBatteryDiffEntry(BatteryDiffEntry entry) {
mBatteryDiffEntry = entry;
}
@@ -149,12 +136,6 @@ public class PowerGaugePreference extends AppPreference {
if (!TextUtils.isEmpty(mProgressContentDescription)) {
subtitle.setContentDescription(mProgressContentDescription);
}
if (mShowAnomalyIcon) {
subtitle.setCompoundDrawablesRelativeWithIntrinsicBounds(
R.drawable.ic_warning_24dp, 0, 0, 0);
} else {
subtitle.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, 0, 0);
}
if (mContentDescription != null) {
final TextView titleView = (TextView) view.findViewById(android.R.id.title);
titleView.setContentDescription(mContentDescription);

View File

@@ -16,7 +16,6 @@
package com.android.settings.homepage.contextualcards.conditional;
import android.app.Flags;
import android.app.NotificationManager;
import android.app.settings.SettingsEnums;
import android.content.BroadcastReceiver;
@@ -87,12 +86,8 @@ public class DndConditionCardController implements ConditionalCardController {
@Override
public void onActionClick() {
if (Flags.modesApi()) {
mNotificationManager.setZenMode(Settings.Global.ZEN_MODE_OFF, null, TAG,
/* fromUser= */ true);
} else {
mNotificationManager.setZenMode(Settings.Global.ZEN_MODE_OFF, null, TAG);
}
mNotificationManager.setZenMode(Settings.Global.ZEN_MODE_OFF, null, TAG,
/* fromUser= */ true);
}
@Override

View File

@@ -29,19 +29,20 @@ import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import android.window.OnBackInvokedCallback;
import android.window.OnBackInvokedDispatcher;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.appcompat.app.AlertDialog;
import com.android.internal.app.LocaleStore;
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import com.android.settingslib.utils.CustomDialogHelper;
/**
* Create a dialog for system locale events.
@@ -58,7 +59,6 @@ public class LocaleDialogFragment extends InstrumentedDialogFragment {
static final String ARG_SHOW_DIALOG = "arg_show_dialog";
private boolean mShouldKeepDialog;
private AlertDialog mAlertDialog;
private OnBackInvokedDispatcher mBackDispatcher;
private OnBackInvokedCallback mBackCallback = () -> {
@@ -106,45 +106,53 @@ public class LocaleDialogFragment extends InstrumentedDialogFragment {
LocaleListEditor parentFragment = (LocaleListEditor) getParentFragment();
LocaleDialogController controller = getLocaleDialogController(getContext(), this,
parentFragment);
LocaleDialogController.DialogContent dialogContent = controller.getDialogContent();
ViewGroup viewGroup = (ViewGroup) LayoutInflater.from(getContext()).inflate(
R.layout.locale_dialog, null);
setDialogTitle(viewGroup, dialogContent.mTitle);
setDialogMessage(viewGroup, dialogContent.mMessage);
AlertDialog.Builder builder = new AlertDialog.Builder(getContext())
.setView(viewGroup);
if (!dialogContent.mPositiveButton.isEmpty()) {
builder.setPositiveButton(dialogContent.mPositiveButton, controller);
}
if (!dialogContent.mNegativeButton.isEmpty()) {
builder.setNegativeButton(dialogContent.mNegativeButton, controller);
}
mAlertDialog = builder.create();
getOnBackInvokedDispatcher().registerOnBackInvokedCallback(PRIORITY_DEFAULT, mBackCallback);
mAlertDialog.setCanceledOnTouchOutside(false);
mAlertDialog.setOnDismissListener(dialogInterface -> {
mAlertDialog.getOnBackInvokedDispatcher().unregisterOnBackInvokedCallback(
mBackCallback);
Dialog dialog = createDialog(getContext(), controller);
dialog.setCanceledOnTouchOutside(false);
getOnBackInvokedDispatcher(dialog).registerOnBackInvokedCallback(PRIORITY_DEFAULT,
mBackCallback);
dialog.setOnDismissListener(dialogInterface -> {
getOnBackInvokedDispatcher(dialog).unregisterOnBackInvokedCallback(
mBackCallback);
});
return mAlertDialog;
return dialog;
}
private static void setDialogTitle(View root, String content) {
TextView titleView = root.findViewById(R.id.dialog_title);
if (titleView == null) {
return;
private Dialog createDialog(Context context, LocaleDialogController controller) {
CustomDialogHelper dialogHelper = new CustomDialogHelper(context);
LocaleDialogController.DialogContent dialogContent = controller.getDialogContent();
dialogHelper.setIcon(context.getDrawable(R.drawable.ic_settings_language_32dp))
.setTitle(dialogContent.mTitle)
.setMessage(dialogContent.mMessage)
.setIconPadding(0,
context.getResources().getDimensionPixelSize(
R.dimen.locale_picker_dialog_icon_padding),
0, 0)
.setTitlePadding(0,
context.getResources().getDimensionPixelSize(
R.dimen.locale_picker_dialog_title_padding),
0,
context.getResources().getDimensionPixelSize(
R.dimen.locale_picker_dialog_title_padding))
.setMessagePadding(context.getResources().getDimensionPixelSize(
R.dimen.locale_picker_dialog_message_padding_left_right), 0,
context.getResources().getDimensionPixelSize(
R.dimen.locale_picker_dialog_message_padding_left_right),
context.getResources().getDimensionPixelSize(
R.dimen.locale_picker_dialog_message_padding_bottom))
.setPositiveButton(dialogContent.mPositiveButton,
view -> {
controller.onClick(dialogHelper.getDialog(),
DialogInterface.BUTTON_POSITIVE);
dialogHelper.getDialog().dismiss();
});
if (dialogContent.mNegativeButton != 0) {
dialogHelper.setBackButton(dialogContent.mNegativeButton, view -> {
controller.onClick(dialogHelper.getDialog(), DialogInterface.BUTTON_NEGATIVE);
dialogHelper.getDialog().dismiss();
});
}
titleView.setText(content);
}
private static void setDialogMessage(View root, String content) {
TextView textView = root.findViewById(R.id.dialog_msg);
if (textView == null) {
return;
}
textView.setText(content);
return dialogHelper.getDialog();
}
@VisibleForTesting
@@ -158,11 +166,11 @@ public class LocaleDialogFragment extends InstrumentedDialogFragment {
}
@VisibleForTesting
public OnBackInvokedDispatcher getOnBackInvokedDispatcher() {
public @NonNull OnBackInvokedDispatcher getOnBackInvokedDispatcher(@NonNull Dialog dialog) {
if (mBackDispatcher != null) {
return mBackDispatcher;
} else {
return mAlertDialog.getOnBackInvokedDispatcher();
return dialog.getOnBackInvokedDispatcher();
}
}
@@ -223,15 +231,15 @@ public class LocaleDialogFragment extends InstrumentedDialogFragment {
R.string.title_change_system_locale), mLocaleInfo.getFullNameNative());
dialogContent.mMessage = mContext.getString(
R.string.desc_notice_device_locale_settings_change);
dialogContent.mPositiveButton = mContext.getString(
R.string.button_label_confirmation_of_system_locale_change);
dialogContent.mNegativeButton = mContext.getString(R.string.cancel);
dialogContent.mPositiveButton =
R.string.button_label_confirmation_of_system_locale_change;
dialogContent.mNegativeButton = R.string.cancel;
break;
case DIALOG_NOT_AVAILABLE_LOCALE:
dialogContent.mTitle = String.format(mContext.getString(
R.string.title_unavailable_locale), mLocaleInfo.getFullNameNative());
dialogContent.mMessage = mContext.getString(R.string.desc_unavailable_locale);
dialogContent.mPositiveButton = mContext.getString(R.string.okay);
dialogContent.mPositiveButton = R.string.okay;
break;
case DIALOG_ADD_SYSTEM_LOCALE:
dialogContent.mTitle = String.format(mContext.getString(
@@ -239,8 +247,8 @@ public class LocaleDialogFragment extends InstrumentedDialogFragment {
mLocaleInfo.getFullNameNative());
dialogContent.mMessage = mContext.getString(
R.string.desc_system_locale_addition);
dialogContent.mPositiveButton = mContext.getString(R.string.add);
dialogContent.mNegativeButton = mContext.getString(R.string.cancel);
dialogContent.mPositiveButton = R.string.add;
dialogContent.mNegativeButton = R.string.cancel;
break;
default:
break;
@@ -252,8 +260,8 @@ public class LocaleDialogFragment extends InstrumentedDialogFragment {
static class DialogContent {
String mTitle = "";
String mMessage = "";
String mPositiveButton = "";
String mNegativeButton = "";
int mPositiveButton = 0;
int mNegativeButton = 0;
}
}
}

View File

@@ -43,9 +43,10 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.FragmentManager;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
import androidx.recyclerview.widget.RecyclerView;
@@ -53,10 +54,12 @@ import com.android.internal.app.LocalePicker;
import com.android.internal.app.LocaleStore;
import com.android.settings.R;
import com.android.settings.RestrictedSettingsFragment;
import com.android.settings.flags.Flags;
import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.search.SearchIndexable;
import com.android.settingslib.search.SearchIndexableRaw;
import com.android.settingslib.utils.CustomDialogHelper;
import com.android.settingslib.utils.StringUtil;
import com.android.settingslib.widget.LayoutPreference;
@@ -69,6 +72,8 @@ import java.util.Locale;
*/
@SearchIndexable
public class LocaleListEditor extends RestrictedSettingsFragment implements View.OnTouchListener {
public static final int REQUEST_LOCALE_PICKER = 0;
protected static final String INTENT_LOCALE_KEY = "localeInfo";
protected static final String EXTRA_SYSTEM_LOCALE_DIALOG_TYPE = "system_locale_dialog_type";
protected static final String EXTRA_RESULT_LOCALE = "result_locale";
@@ -81,16 +86,16 @@ public class LocaleListEditor extends RestrictedSettingsFragment implements View
private static final String INDEX_KEY_ADD_LANGUAGE = "add_language";
private static final String KEY_LANGUAGES_PICKER = "languages_picker";
private static final String KEY_CATEGORY_TERMS_OF_ADDRESS = "key_category_terms_of_address";
private static final String KEY_ADD_A_LANGUAGE = "add_a_language";
private static final String TAG_DIALOG_CONFIRM_SYSTEM_DEFAULT = "dialog_confirm_system_default";
private static final String TAG_DIALOG_NOT_AVAILABLE = "dialog_not_available_locale";
private static final String TAG_DIALOG_ADD_SYSTEM_LOCALE = "dialog_add_system_locale";
private static final int MENU_ID_REMOVE = Menu.FIRST + 1;
private static final int REQUEST_LOCALE_PICKER = 0;
private LocaleDragAndDropAdapter mAdapter;
private Menu mMenu;
private View mAddLanguage;
private AlertDialog mSuggestionDialog = null;
private Preference mAddLanguagePreference;
private boolean mRemoveMode;
private boolean mShowingRemoveDialog;
private boolean mLocaleAdditionMode = false;
@@ -281,7 +286,11 @@ public class LocaleListEditor extends RestrictedSettingsFragment implements View
private void setRemoveMode(boolean mRemoveMode) {
this.mRemoveMode = mRemoveMode;
mAdapter.setRemoveMode(mRemoveMode);
mAddLanguage.setVisibility(mRemoveMode ? View.INVISIBLE : View.VISIBLE);
if (Flags.settingsExpressiveDesignEnabled()) {
mAddLanguagePreference.setVisible(!mRemoveMode);
} else {
mAddLanguage.setVisibility(mRemoveMode ? View.INVISIBLE : View.VISIBLE);
}
updateVisibilityOfRemoveMenu();
}
@@ -330,7 +339,6 @@ public class LocaleListEditor extends RestrictedSettingsFragment implements View
private void showDialogForAddedLocale() {
Log.d(TAG, "show confirmation dialog");
Intent intent = this.getIntent();
String dialogType = intent.getStringExtra(EXTRA_SYSTEM_LOCALE_DIALOG_TYPE);
String appLocaleTag = intent.getStringExtra(EXTRA_APP_LOCALE);
LocaleStore.LocaleInfo localeInfo = LocaleStore.getLocaleInfo(
@@ -344,17 +352,6 @@ public class LocaleListEditor extends RestrictedSettingsFragment implements View
localeDialogFragment.show(mFragmentManager, TAG_DIALOG_ADD_SYSTEM_LOCALE);
}
private void customizeLayout(AlertDialog.Builder dialogBuilder, String language) {
View dialogView = getLocaleDialogView();
dialogBuilder.setView(dialogView);
TextView title = dialogView.findViewById(R.id.dialog_title);
title.setText(
String.format(getContext().getResources().getString(
R.string.title_system_locale_addition), language));
TextView message = dialogView.findViewById(R.id.dialog_msg);
message.setText(R.string.desc_system_locale_addition);
}
protected View getLocaleDialogView() {
LayoutInflater inflater = this.getLayoutInflater();
return inflater.inflate(R.layout.locale_dialog, null);
@@ -374,25 +371,33 @@ public class LocaleListEditor extends RestrictedSettingsFragment implements View
return;
}
int messagePaddingLeftRight = getContext().getResources().getDimensionPixelSize(
R.dimen.locale_picker_dialog_message_padding_left_right);
int messagePaddingBottom = getContext().getResources().getDimensionPixelSize(
R.dimen.locale_picker_dialog_message_padding_bottom);
// All locales selected, warning dialog, can't remove them all
if (checkedCount == mAdapter.getItemCount()) {
mShowingRemoveDialog = true;
new AlertDialog.Builder(getActivity())
.setTitle(R.string.dlg_remove_locales_error_title)
.setMessage(R.string.dlg_remove_locales_error_message)
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
mShowingRemoveDialog = false;
}
})
.create()
.show();
CustomDialogHelper dialogHelper = createRegionDialog(getContext(),
getContext().getString(R.string.dlg_remove_locales_error_title));
dialogHelper.setMessage(R.string.dlg_remove_locales_error_message)
.setMessagePadding(messagePaddingLeftRight, 0, messagePaddingLeftRight,
messagePaddingBottom)
.setPositiveButton(android.R.string.ok,
view -> {
dialogHelper.getDialog().dismiss();
})
.setBackButton(R.string.cancel, view -> {
dialogHelper.getDialog().dismiss();
});
dialogHelper.getDialog().setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(@NonNull DialogInterface dialog) {
mShowingRemoveDialog = false;
}
});
dialogHelper.getDialog().show();
return;
}
@@ -400,54 +405,63 @@ public class LocaleListEditor extends RestrictedSettingsFragment implements View
R.string.dlg_remove_locales_title);
mShowingRemoveDialog = true;
final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
CustomDialogHelper dialogHelper = createRegionDialog(getContext(), title);
if (mAdapter.isFirstLocaleChecked()) {
builder.setMessage(R.string.dlg_remove_locales_message);
dialogHelper.setMessage(R.string.dlg_remove_locales_message)
.setMessagePadding(messagePaddingLeftRight, 0, messagePaddingLeftRight,
messagePaddingBottom);
}
builder.setTitle(title)
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
setRemoveMode(false);
}
})
.setPositiveButton(R.string.locale_remove_menu,
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// This is a sensitive area to change.
// removeChecked() triggers a system update and "kills" the frame.
// This means that saveState + restoreState are called before
// setRemoveMode is called.
// So we want that mRemoveMode and dialog status have the right
// values
// before that save.
// We can't just call setRemoveMode(false) before calling
// removeCheched
// because that unchecks all items and removeChecked would have
// nothing
// to remove.
mRemoveMode = false;
mShowingRemoveDialog = false;
LocaleStore.LocaleInfo firstLocale =
mAdapter.getFeedItemList().get(0);
mAdapter.removeChecked();
boolean isFirstRemoved =
firstLocale != mAdapter.getFeedItemList().get(0);
showConfirmDialog(isFirstRemoved, isFirstRemoved ? firstLocale
: mAdapter.getFeedItemList().get(0));
setRemoveMode(false);
}
dialogHelper.setPositiveButton(R.string.locale_remove_menu,
view -> {
// This is a sensitive area to change.
// removeChecked() triggers a system update and "kills" the frame.
// This means that saveState + restoreState are called before
// setRemoveMode is called.
// So we want that mRemoveMode and dialog status have the right
// values
// before that save.
// We can't just call setRemoveMode(false) before calling
// removeCheched
// because that unchecks all items and removeChecked would have
// nothing
// to remove.
mRemoveMode = false;
mShowingRemoveDialog = false;
LocaleStore.LocaleInfo firstLocale =
mAdapter.getFeedItemList().get(0);
mAdapter.removeChecked();
boolean isFirstRemoved =
firstLocale != mAdapter.getFeedItemList().get(0);
showConfirmDialog(isFirstRemoved, isFirstRemoved ? firstLocale
: mAdapter.getFeedItemList().get(0));
setRemoveMode(false);
dialogHelper.getDialog().dismiss();
})
.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
mShowingRemoveDialog = false;
}
})
.create()
.show();
.setBackButton(R.string.cancel, view -> {
setRemoveMode(false);
dialogHelper.getDialog().dismiss();
});
dialogHelper.getDialog().setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(@NonNull DialogInterface dialog) {
mShowingRemoveDialog = false;
}
});
dialogHelper.getDialog().show();
}
private CustomDialogHelper createRegionDialog(Context context, String title) {
CustomDialogHelper dialogHelper = new CustomDialogHelper(context);
dialogHelper.setIcon(context.getDrawable(R.drawable.ic_settings_language_32dp))
.setTitle(title)
.setIconPadding(0, context.getResources().getDimensionPixelSize(
R.dimen.locale_picker_dialog_icon_padding), 0, 0)
.setTitlePadding(0, context.getResources().getDimensionPixelSize(
R.dimen.locale_picker_dialog_title_padding), 0,
context.getResources().getDimensionPixelSize(
R.dimen.locale_picker_dialog_title_padding));
return dialogHelper;
}
@Override
@@ -483,20 +497,23 @@ public class LocaleListEditor extends RestrictedSettingsFragment implements View
list.setAdapter(mAdapter);
list.setOnTouchListener(this);
list.requestFocus();
if (Flags.settingsExpressiveDesignEnabled()) {
mAddLanguagePreference = getPreferenceScreen().findPreference(KEY_ADD_A_LANGUAGE);
} else {
mAddLanguage = layout.findViewById(R.id.add_language);
mAddLanguage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(@NonNull View v) {
FeatureFactory.getFeatureFactory().getMetricsFeatureProvider()
.logSettingsTileClick(INDEX_KEY_ADD_LANGUAGE, getMetricsCategory());
mAddLanguage = layout.findViewById(R.id.add_language);
mAddLanguage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
FeatureFactory.getFeatureFactory().getMetricsFeatureProvider()
.logSettingsTileClick(INDEX_KEY_ADD_LANGUAGE, getMetricsCategory());
final Intent intent = new Intent(getActivity(),
LocalePickerWithRegionActivity.class);
intent.putExtras(getActivity().getIntent().getExtras());
startActivityForResult(intent, REQUEST_LOCALE_PICKER);
}
});
final Intent intent = new Intent(getActivity(),
LocalePickerWithRegionActivity.class);
intent.putExtras(getActivity().getIntent().getExtras());
startActivityForResult(intent, REQUEST_LOCALE_PICKER);
}
});
}
}
@Override

View File

@@ -75,9 +75,6 @@ public abstract class LocalePickerBaseListPreferenceController extends
public LocalePickerBaseListPreferenceController(@NonNull Context context,
@NonNull String preferenceKey) {
super(context, preferenceKey);
mLocaleList = getLocaleCollectorController(context).getSupportedLocaleList(null,
false, false);
mLocaleOptions = new ArrayList<>(mLocaleList.size());
mPreferences = new ArrayMap<>();
mMetricsFeatureProvider = FeatureFactory.getFeatureFactory().getMetricsFeatureProvider();
}
@@ -246,7 +243,7 @@ public abstract class LocalePickerBaseListPreferenceController extends
private void setupLocaleList() {
mLocaleList = getLocaleCollectorController(mContext).getSupportedLocaleList(
mParentLocale, false, mIsCountryMode);
mLocaleOptions.clear();
mLocaleOptions = new ArrayList<>(mLocaleList.size());
}
private List<LocaleStore.LocaleInfo> getSortedLocaleList(
@@ -262,7 +259,9 @@ public abstract class LocalePickerBaseListPreferenceController extends
boolean shouldShowLocaleEditor = shouldShowLocaleEditor(localeInfo);
if (shouldShowLocaleEditor) {
List<LocaleStore.LocaleInfo> feedItemList = getUserLocaleList();
feedItemList.add(localeInfo);
for (LocaleStore.LocaleInfo locale : mLocaleList) {
feedItemList.add(locale);
}
LocaleList localeList = new LocaleList(feedItemList.stream()
.map(LocaleStore.LocaleInfo::getLocale)
.toArray(Locale[]::new));

View File

@@ -23,14 +23,12 @@ import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import android.app.settings.SettingsEnums;
import android.content.ActivityNotFoundException;
import android.content.ContentResolver;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.ConnectivitySettingsManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.text.Editable;
import android.text.TextWatcher;
import android.text.method.LinkMovementMethod;
@@ -55,6 +53,7 @@ import com.android.settingslib.HelpUtils;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtilsInternal;
import com.google.android.material.textfield.TextInputLayout;
import com.google.common.net.InternetDomainName;
import java.util.HashMap;
@@ -64,7 +63,7 @@ import java.util.Map;
* Dialog to set the Private DNS
*/
public class PrivateDnsModeDialogPreference extends CustomDialogPreferenceCompat implements
DialogInterface.OnClickListener, RadioGroup.OnCheckedChangeListener, TextWatcher {
RadioGroup.OnCheckedChangeListener, TextWatcher {
public static final String ANNOTATION_URL = "url";
@@ -80,16 +79,9 @@ public class PrivateDnsModeDialogPreference extends CustomDialogPreferenceCompat
}
@VisibleForTesting
static final String MODE_KEY = Settings.Global.PRIVATE_DNS_MODE;
TextInputLayout mHostnameLayout;
@VisibleForTesting
static final String HOSTNAME_KEY = Settings.Global.PRIVATE_DNS_SPECIFIER;
public static String getHostnameFromSettings(ContentResolver cr) {
return Settings.Global.getString(cr, HOSTNAME_KEY);
}
@VisibleForTesting
EditText mEditText;
EditText mHostnameText;
@VisibleForTesting
RadioGroup mRadioGroup;
@VisibleForTesting
@@ -136,22 +128,17 @@ public class PrivateDnsModeDialogPreference extends CustomDialogPreferenceCompat
// by the controller.
holder.itemView.setEnabled(true);
}
setSaveButtonListener();
}
@Override
protected void onBindDialogView(View view) {
final Context context = getContext();
final ContentResolver contentResolver = context.getContentResolver();
mMode = ConnectivitySettingsManager.getPrivateDnsMode(context);
mEditText = view.findViewById(R.id.private_dns_mode_provider_hostname);
mEditText.addTextChangedListener(this);
mEditText.setText(getHostnameFromSettings(contentResolver));
mRadioGroup = view.findViewById(R.id.private_dns_radio_group);
mRadioGroup.setOnCheckedChangeListener(this);
mRadioGroup.check(PRIVATE_DNS_MAP.getOrDefault(mMode, R.id.private_dns_mode_opportunistic));
mRadioGroup.setOnCheckedChangeListener(this);
// Initial radio button text
final RadioButton offRadioButton = view.findViewById(R.id.private_dns_mode_off);
@@ -163,6 +150,13 @@ public class PrivateDnsModeDialogPreference extends CustomDialogPreferenceCompat
final RadioButton providerRadioButton = view.findViewById(R.id.private_dns_mode_provider);
providerRadioButton.setText(com.android.settingslib.R.string.private_dns_mode_provider);
mHostnameLayout = view.findViewById(R.id.private_dns_mode_provider_hostname_layout);
mHostnameText = view.findViewById(R.id.private_dns_mode_provider_hostname);
if (mHostnameText != null) {
mHostnameText.setText(ConnectivitySettingsManager.getPrivateDnsHostname(context));
mHostnameText.addTextChangedListener(this);
}
final TextView helpTextView = view.findViewById(R.id.private_dns_help_info);
helpTextView.setMovementMethod(LinkMovementMethod.getInstance());
final Intent helpIntent = HelpUtils.getHelpIntent(context,
@@ -176,22 +170,8 @@ public class PrivateDnsModeDialogPreference extends CustomDialogPreferenceCompat
} else {
helpTextView.setText("");
}
}
@Override
public void onClick(DialogInterface dialog, int which) {
if (which == DialogInterface.BUTTON_POSITIVE) {
final Context context = getContext();
if (mMode == PRIVATE_DNS_MODE_PROVIDER_HOSTNAME) {
// Only clickable if hostname is valid, so we could save it safely
ConnectivitySettingsManager.setPrivateDnsHostname(context,
mEditText.getText().toString());
}
FeatureFactory.getFeatureFactory().getMetricsFeatureProvider().action(context,
SettingsEnums.ACTION_PRIVATE_DNS_MODE, mMode);
ConnectivitySettingsManager.setPrivateDnsMode(context, mMode);
}
updateDialogInfo();
}
@Override
@@ -241,24 +221,58 @@ public class PrivateDnsModeDialogPreference extends CustomDialogPreferenceCompat
return getEnforcedAdmin() != null;
}
private Button getSaveButton() {
final AlertDialog dialog = (AlertDialog) getDialog();
if (dialog == null) {
return null;
}
return dialog.getButton(DialogInterface.BUTTON_POSITIVE);
}
private void updateDialogInfo() {
final boolean modeProvider = PRIVATE_DNS_MODE_PROVIDER_HOSTNAME == mMode;
if (mEditText != null) {
mEditText.setEnabled(modeProvider);
}
final Button saveButton = getSaveButton();
if (saveButton != null) {
saveButton.setEnabled(modeProvider
? InternetDomainName.isValid(mEditText.getText().toString())
: true);
if (mHostnameLayout != null) {
mHostnameLayout.setEnabled(modeProvider);
mHostnameLayout.setErrorEnabled(false);
}
}
private void setSaveButtonListener() {
View.OnClickListener onClickListener = v -> doSaveButton();
DialogInterface.OnShowListener onShowListener = dialog -> {
if (dialog == null) {
Log.e(TAG, "The DialogInterface is null!");
return;
}
Button saveButton = ((AlertDialog) dialog).getButton(DialogInterface.BUTTON_POSITIVE);
if (saveButton == null) {
Log.e(TAG, "Can't get the save button!");
return;
}
saveButton.setOnClickListener(onClickListener);
};
setOnShowListener(onShowListener);
}
@VisibleForTesting
void doSaveButton() {
Context context = getContext();
if (mMode == PRIVATE_DNS_MODE_PROVIDER_HOSTNAME) {
if (mHostnameLayout == null || mHostnameText == null) {
Log.e(TAG, "Can't find hostname resources!");
return;
}
if (mHostnameText.getText().isEmpty()) {
mHostnameLayout.setError(context.getString(R.string.private_dns_field_require));
Log.w(TAG, "The hostname is empty!");
return;
}
if (!InternetDomainName.isValid(mHostnameText.getText().toString())) {
mHostnameLayout.setError(context.getString(R.string.private_dns_hostname_invalid));
Log.w(TAG, "The hostname is invalid!");
return;
}
ConnectivitySettingsManager.setPrivateDnsHostname(context,
mHostnameText.getText().toString());
}
ConnectivitySettingsManager.setPrivateDnsMode(context, mMode);
FeatureFactory.getFeatureFactory().getMetricsFeatureProvider()
.action(context, SettingsEnums.ACTION_PRIVATE_DNS_MODE, mMode);
getDialog().dismiss();
}
}

View File

@@ -135,7 +135,7 @@ public class PrivateDnsPreferenceController extends BasePreferenceController
com.android.settingslib.R.string.private_dns_mode_opportunistic);
case PRIVATE_DNS_MODE_PROVIDER_HOSTNAME:
return dnsesResolved
? PrivateDnsModeDialogPreference.getHostnameFromSettings(cr)
? ConnectivitySettingsManager.getPrivateDnsHostname(mContext)
: res.getString(
com.android.settingslib.R.string.private_dns_mode_provider_failure);
}

View File

@@ -107,8 +107,8 @@ public class Enhanced4gBasePreferenceController extends TelephonyTogglePreferenc
}
final PersistableBundle carrierConfig = getCarrierConfigForSubId(subId);
if ((carrierConfig == null)
|| carrierConfig.getBoolean(CarrierConfigManager.KEY_HIDE_ENHANCED_4G_LTE_BOOL)) {
if (!CarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfig) ||
carrierConfig.getBoolean(CarrierConfigManager.KEY_HIDE_ENHANCED_4G_LTE_BOOL)) {
return CONDITIONALLY_UNAVAILABLE;
}

View File

@@ -25,6 +25,8 @@ import com.android.settings.R
import com.android.settings.flags.Flags
import com.android.settings.network.SubscriptionUtil
import com.android.settingslib.spa.framework.util.collectLatestWithLifecycle
import com.android.settingslib.spaprivileged.framework.common.userManager
import com.android.settingslib.Utils
/** Preference controller for "Phone number" */
class MobileNetworkPhoneNumberPreferenceController
@@ -41,13 +43,14 @@ constructor(
mSubId = subId
}
override fun getAvailabilityStatus(subId: Int): Int =
when {
!Flags.isDualSimOnboardingEnabled() -> CONDITIONALLY_UNAVAILABLE
SubscriptionManager.isValidSubscriptionId(subId) &&
SubscriptionUtil.isSimHardwareVisible(mContext) -> AVAILABLE
else -> CONDITIONALLY_UNAVAILABLE
}
override fun getAvailabilityStatus(subId: Int): Int = when {
!Flags.isDualSimOnboardingEnabled()
|| !SubscriptionManager.isValidSubscriptionId(subId)
|| !SubscriptionUtil.isSimHardwareVisible(mContext)
|| Utils.isWifiOnly(mContext) -> CONDITIONALLY_UNAVAILABLE
!mContext.userManager.isAdminUser -> DISABLED_FOR_USER
else -> AVAILABLE
}
override fun displayPreference(screen: PreferenceScreen) {
super.displayPreference(screen)

View File

@@ -59,7 +59,7 @@ abstract class AbstractZenModeHeaderController extends AbstractZenModePreference
@Override
public boolean isAvailable() {
return Flags.modesApi() && Flags.modesUi();
return Flags.modesUi();
}
protected void setUpHeader(PreferenceScreen screen, int iconSizePx) {

View File

@@ -43,7 +43,7 @@ class ZenSettingsObserver extends ContentObserver {
}
void register() {
if (Flags.modesApi() && Flags.modesUi()) {
if (Flags.modesUi()) {
mContext.getContentResolver().registerContentObserver(ZEN_MODE_URI, false, this);
mContext.getContentResolver().registerContentObserver(ZEN_MODE_CONFIG_ETAG_URI, false,
this);
@@ -51,7 +51,7 @@ class ZenSettingsObserver extends ContentObserver {
}
void unregister() {
if (Flags.modesApi() && Flags.modesUi()) {
if (Flags.modesUi()) {
mContext.getContentResolver().unregisterContentObserver(this);
}
}

View File

@@ -167,7 +167,7 @@ abstract public class AbstractZenModeAutomaticRulePreferenceController extends
mMetricsFeatureProvider.action(mContext,
SettingsEnums.ACTION_ZEN_MODE_RULE_NAME_CHANGE_OK);
AutomaticZenRule rule;
if (Flags.modesApi() && Flags.modesUi()) {
if (Flags.modesUi()) {
rule = new AutomaticZenRule.Builder(ruleName, mRuleInfo.defaultConditionId)
.setType(mRuleInfo.type)
.setOwner(mRuleInfo.serviceComponent)

View File

@@ -76,7 +76,7 @@ public class ZenAccessSettings extends EmptyTextSettings implements
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
setEmptyText(Flags.modesApi() && Flags.modesUi()
setEmptyText(Flags.modesUi()
? R.string.zen_modes_access_empty_text
: R.string.zen_access_empty_text);
}
@@ -89,7 +89,7 @@ public class ZenAccessSettings extends EmptyTextSettings implements
@Override
public void onResume() {
super.onResume();
requireActivity().setTitle(Flags.modesApi() && Flags.modesUi()
requireActivity().setTitle(Flags.modesUi()
? R.string.manage_zen_modes_access_title
: R.string.manage_zen_access_title);
reloadList();
@@ -145,7 +145,7 @@ public class ZenAccessSettings extends EmptyTextSettings implements
pref.setOnPreferenceClickListener(preference -> {
AppInfoBase.startAppInfoFragment(
ZenAccessDetails.class /* fragment */,
getString(Flags.modesApi() && Flags.modesUi()
getString(Flags.modesUi()
? R.string.manage_zen_modes_access_title
: R.string.manage_zen_access_title),
pkg,

View File

@@ -95,32 +95,19 @@ public class ZenModeBackend {
}
protected boolean updateZenRule(String id, AutomaticZenRule rule) {
if (android.app.Flags.modesApi()) {
return mNotificationManager.updateAutomaticZenRule(id, rule, /* fromUser= */ true);
} else {
return NotificationManager.from(mContext).updateAutomaticZenRule(id, rule);
}
return mNotificationManager.updateAutomaticZenRule(id, rule, /* fromUser= */ true);
}
protected void setZenMode(int zenMode) {
if (android.app.Flags.modesApi()) {
mNotificationManager.setZenMode(zenMode, null, TAG, /* fromUser= */ true);
} else {
NotificationManager.from(mContext).setZenMode(zenMode, null, TAG);
}
mNotificationManager.setZenMode(zenMode, null, TAG, /* fromUser= */ true);
mZenMode = getZenMode();
}
protected void setZenModeForDuration(int minutes) {
Uri conditionId = ZenModeConfig.toTimeCondition(mContext, minutes,
ActivityManager.getCurrentUser(), true).id;
if (android.app.Flags.modesApi()) {
mNotificationManager.setZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
conditionId, TAG, /* fromUser= */ true);
} else {
mNotificationManager.setZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
conditionId, TAG);
}
mNotificationManager.setZenMode(Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS,
conditionId, TAG, /* fromUser= */ true);
mZenMode = getZenMode();
}
@@ -190,14 +177,9 @@ public class ZenModeBackend {
int priorityConversationSenders) {
mPolicy = new NotificationManager.Policy(priorityCategories, priorityCallSenders,
priorityMessageSenders, suppressedVisualEffects, priorityConversationSenders);
if (android.app.Flags.modesApi()) {
mNotificationManager.setNotificationPolicy(mPolicy, /* fromUser= */ true);
} else {
mNotificationManager.setNotificationPolicy(mPolicy);
}
mNotificationManager.setNotificationPolicy(mPolicy, /* fromUser= */ true);
}
private int getNewSuppressedEffects(boolean suppress, int effectType) {
int effects = mPolicy.suppressedVisualEffects;
@@ -373,11 +355,7 @@ public class ZenModeBackend {
}
public boolean removeZenRule(String ruleId) {
if (android.app.Flags.modesApi()) {
return mNotificationManager.removeAutomaticZenRule(ruleId, /* fromUser= */ true);
} else {
return NotificationManager.from(mContext).removeAutomaticZenRule(ruleId);
}
return mNotificationManager.removeAutomaticZenRule(ruleId, /* fromUser= */ true);
}
public NotificationManager.Policy getConsolidatedPolicy() {
@@ -386,11 +364,7 @@ public class ZenModeBackend {
protected String addZenRule(AutomaticZenRule rule) {
try {
if (android.app.Flags.modesApi()) {
return mNotificationManager.addAutomaticZenRule(rule, /* fromUser= */ true);
} else {
return NotificationManager.from(mContext).addAutomaticZenRule(rule);
}
return mNotificationManager.addAutomaticZenRule(rule, /* fromUser= */ true);
} catch (Exception e) {
return null;
}

View File

@@ -104,16 +104,11 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase {
Bundle bundle = new Bundle();
bundle.putString(ZenCustomRuleSettings.RULE_ID, mId);
// When modes_api flag is on, we skip the radio button screen distinguishing
// between "default" and "custom" and take users directly to the custom
// settings screen.
String destination = ZenCustomRuleSettings.class.getName();
int sourceMetricsCategory = 0;
if (Flags.modesApi()) {
// From ZenRuleCustomPolicyPreferenceController#launchCustomSettings
destination = ZenCustomRuleConfigSettings.class.getName();
sourceMetricsCategory = SettingsEnums.ZEN_CUSTOM_RULE_SOUND_SETTINGS;
}
// Skip the radio button screen distinguishing between "default" and
// "custom" and take users directly to the custom settings screen.
// From ZenRuleCustomPolicyPreferenceController#launchCustomSettings
String destination = ZenCustomRuleConfigSettings.class.getName();
int sourceMetricsCategory = SettingsEnums.ZEN_CUSTOM_RULE_SOUND_SETTINGS;
new SubSettingLauncher(mContext)
.setDestination(destination)
.setArguments(bundle)
@@ -165,7 +160,7 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase {
protected void updateScheduleRule(ZenModeConfig.ScheduleInfo schedule) {
mRule.setConditionId(ZenModeConfig.toScheduleConditionId(schedule));
if (Flags.modesApi() && Flags.modesUi()) {
if (Flags.modesUi()) {
mRule.setTriggerDescription(
SystemZenRules.getTriggerDescriptionForScheduleTime(mContext, schedule));
}
@@ -174,7 +169,7 @@ public abstract class ZenModeRuleSettingsBase extends ZenModeSettingsBase {
protected void updateEventRule(ZenModeConfig.EventInfo event) {
mRule.setConditionId(ZenModeConfig.toEventConditionId(event));
if (Flags.modesApi() && Flags.modesUi()) {
if (Flags.modesUi()) {
mRule.setTriggerDescription(
SystemZenRules.getTriggerDescriptionForScheduleEvent(mContext, event));
}

View File

@@ -19,7 +19,6 @@ package com.android.settings.notification.zen;
import static android.app.slice.Slice.EXTRA_TOGGLE_STATE;
import android.annotation.ColorInt;
import android.app.Flags;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.settings.SettingsEnums;
@@ -117,12 +116,8 @@ public class ZenModeSliceBuilder {
} else {
zenMode = Settings.Global.ZEN_MODE_OFF;
}
if (Flags.modesApi()) {
NotificationManager.from(context).setZenMode(zenMode, /* conditionId= */ null, TAG,
/* fromUser= */ true);
} else {
NotificationManager.from(context).setZenMode(zenMode, null /* conditionId */, TAG);
}
NotificationManager.from(context).setZenMode(zenMode, /* conditionId= */ null, TAG,
/* fromUser= */ true);
// Do not notifyChange on Uri. The service takes longer to update the current value than it
// does for the Slice to check the current value again. Let {@link SliceBroadcastRelay}
// handle it.

View File

@@ -19,19 +19,14 @@ package com.android.settings.notification.zen;
import android.app.AutomaticZenRule;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.text.TextUtils;
import android.view.View;
import androidx.fragment.app.Fragment;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceScreen;
import com.android.internal.logging.nano.MetricsProto;
import com.android.settings.R;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.core.SubSettingLauncher;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.widget.ActionButtonsPreference;
@@ -87,7 +82,6 @@ public class ZenRuleButtonsPreferenceController extends AbstractZenModePreferenc
mMetricsFeatureProvider.action(mContext,
SettingsEnums.ACTION_ZEN_MODE_RULE_NAME_CHANGE_OK);
mRule.setName(ruleName);
mRule.setModified(true);
mBackend.updateZenRule(mId, mRule);
}
});

View File

@@ -143,8 +143,7 @@ public class ZenRulePreference extends PrimarySwitchPreference {
private String computeRuleSummary(AutomaticZenRule rule) {
if (rule != null) {
if (Flags.modesApi() && Flags.modesUi()
&& !TextUtils.isEmpty(rule.getTriggerDescription())) {
if (Flags.modesUi() && !TextUtils.isEmpty(rule.getTriggerDescription())) {
return rule.getTriggerDescription();
}

View File

@@ -181,7 +181,7 @@ public class ZenRuleSelectionDialog extends InstrumentedDialogFragment {
rt.title = mContext.getString(R.string.zen_schedule_rule_type_name);
rt.packageName = ZenModeConfig.getEventConditionProvider().getPackageName();
rt.defaultConditionId = ZenModeConfig.toScheduleConditionId(schedule);
if (Flags.modesApi() && Flags.modesUi()) {
if (Flags.modesUi()) {
rt.type = AutomaticZenRule.TYPE_SCHEDULE_TIME;
rt.defaultTriggerDescription = SystemZenRules.getTriggerDescriptionForScheduleTime(
mContext, schedule);
@@ -201,7 +201,7 @@ public class ZenRuleSelectionDialog extends InstrumentedDialogFragment {
rt.title = mContext.getString(R.string.zen_event_rule_type_name);
rt.packageName = ZenModeConfig.getScheduleConditionProvider().getPackageName();
rt.defaultConditionId = ZenModeConfig.toEventConditionId(event);
if (Flags.modesApi() && Flags.modesUi()) {
if (Flags.modesUi()) {
rt.type = AutomaticZenRule.TYPE_SCHEDULE_CALENDAR;
rt.defaultTriggerDescription = SystemZenRules.getTriggerDescriptionForScheduleEvent(
mContext, event);

View File

@@ -560,6 +560,7 @@ public class ChooseLockPassword extends SettingsActivity {
setupPasswordRequirementsView(headerLayout);
mPasswordRestrictionView.setLayoutManager(new LinearLayoutManager(getActivity()));
mPasswordRestrictionView.setAccessibilityLiveRegion(ACCESSIBILITY_LIVE_REGION_POLITE);
mPasswordEntry = view.findViewById(R.id.password_entry);
mPasswordEntry.setOnEditorActionListener(this);
mPasswordEntry.addTextChangedListener(this);
@@ -770,7 +771,7 @@ public class ChooseLockPassword extends SettingsActivity {
// If the stage changed, announce the header for accessibility. This
// is a no-op when accessibility is disabled.
if (previousStage != stage) {
mLayout.announceForAccessibility(mLayout.getHeaderText());
getActivity().setTitle(mLayout.getHeaderText());
}
}

View File

@@ -20,9 +20,9 @@ import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.android.settings.R;
@@ -66,15 +66,20 @@ public class PasswordRequirementAdapter extends
return mRequirements[position].hashCode();
}
@Override
public void onViewAttachedToWindow(@NonNull PasswordRequirementViewHolder holder) {
holder.mDescriptionText.announceForAccessibility(holder.mDescriptionText.getText());
}
@Override
public void onBindViewHolder(PasswordRequirementViewHolder holder, int position) {
final int fontSize = mContext.getResources().getDimensionPixelSize(
R.dimen.password_requirement_font_size);
final String requirement = mRequirements[position];
holder.mDescriptionText.setAccessibilityDelegate(new View.AccessibilityDelegate() {
@Override
public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(host, info);
holder.mDescriptionText.setStateDescription(requirement);
}
});
holder.mDescriptionText.setText(mRequirements[position]);
if (mIsTooShortError) {
holder.mDescriptionText.setTextAppearance(R.style.ScreenLockPasswordHintTextFontStyle);

View File

@@ -32,7 +32,7 @@ public class ShortcutsUpdateReceiver extends BroadcastReceiver {
@Override
public void onReceive(@NonNull Context context, @NonNull Intent intent) {
if (!Flags.modesApi() || !Flags.modesUi()) {
if (!Flags.modesUi()) {
return;
}

View File

@@ -86,7 +86,7 @@ public class ShortcutsUpdater {
private static ComponentName maybeGetReplacingComponent(Context context, ComponentName cn) {
// ZenModeSettingsActivity is replaced by ModesSettingsActivity and will be deleted
// soon (so we shouldn't use ZenModeSettingsActivity.class).
if (Flags.modesApi() && Flags.modesUi()
if (Flags.modesUi()
&& cn.getClassName().endsWith("Settings$ZenModeSettingsActivity")) {
return new ComponentName(context, Settings.ModesSettingsActivity.class);
}

View File

@@ -33,7 +33,7 @@ public class TopLevelSoundPreferenceController extends BasePreferenceController
@Override
public void updateState(Preference preference) {
super.updateState(preference);
preference.setSummary(Flags.modesApi() && Flags.modesUi()
preference.setSummary(Flags.modesUi()
? R.string.sound_dashboard_summary
: R.string.sound_dashboard_summary_with_dnd);
}

View File

@@ -68,9 +68,6 @@ public class ConnectedBluetoothDeviceUpdaterTest {
private static final String MAC_ADDRESS = "04:52:C7:0B:D8:3C";
private static final String TEST_EXCLUSIVE_MANAGER = "com.test.manager";
private static final String TEMP_BOND_METADATA =
"<TEMP_BOND_TYPE>le_audio_sharing</TEMP_BOND_TYPE>";
private static final int METADATA_FAST_PAIR_CUSTOMIZED_FIELDS = 25;
@Rule
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
@@ -408,22 +405,6 @@ public class ConnectedBluetoothDeviceUpdaterTest {
verify(mBluetoothDeviceUpdater, never()).addPreference(mCachedBluetoothDevice);
}
@Test
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI)
public void update_temporaryBondDevice_removePreference() {
setUpDeviceUpdaterWithAudioMode(AudioManager.MODE_NORMAL);
when(mBluetoothDeviceUpdater
.isDeviceConnected(any(CachedBluetoothDevice.class))).thenReturn(true);
when(mCachedBluetoothDevice.isConnectedHfpDevice()).thenReturn(true);
when(mBluetoothDevice.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
.thenReturn(TEMP_BOND_METADATA.getBytes());
mBluetoothDeviceUpdater.update(mCachedBluetoothDevice);
verify(mBluetoothDeviceUpdater).removePreference(mCachedBluetoothDevice);
verify(mBluetoothDeviceUpdater, never()).addPreference(mCachedBluetoothDevice);
}
private void setUpDeviceUpdaterWithAudioMode(int audioMode) {
mAudioManager.setMode(audioMode);
mBluetoothDeviceUpdater = spy(new ConnectedBluetoothDeviceUpdater(mContext,

View File

@@ -75,7 +75,6 @@ public class ConnectedDeviceDashboardFragmentTest {
private static final String KEY_AUDIO_SHARING_SETTINGS =
"connected_device_audio_sharing_settings";
private static final String KEY_ADD_BT_DEVICES = "add_bt_devices";
private static final String KEY_TEMPORARY_BOND_DEVICES = "temp_bond_device_list";
private static final String SETTINGS_PACKAGE_NAME = "com.android.settings";
private static final String SYSTEMUI_PACKAGE_NAME = "com.android.systemui";
private static final String SLICE_ACTION = "com.android.settings.SEARCH_RESULT_TRAMPOLINE";
@@ -130,8 +129,7 @@ public class ConnectedDeviceDashboardFragmentTest {
KEY_SAVED_DEVICE_SEE_ALL,
KEY_FAST_PAIR_DEVICE_SEE_ALL,
KEY_AUDIO_SHARING_DEVICES,
KEY_AUDIO_SHARING_SETTINGS,
KEY_TEMPORARY_BOND_DEVICES);
KEY_AUDIO_SHARING_SETTINGS);
}
@Test

View File

@@ -43,7 +43,6 @@ import android.content.ContentResolver;
import android.content.Context;
import android.database.ContentObserver;
import android.os.Looper;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
import android.view.View;
@@ -111,11 +110,8 @@ public class AudioSharingCallAudioPreferenceControllerTest {
private static final String PREF_KEY = "calls_and_alarms";
private static final String TEST_DEVICE_NAME1 = "test1";
private static final String TEST_DEVICE_NAME2 = "test2";
private static final String TEMP_BOND_METADATA =
"<TEMP_BOND_TYPE>le_audio_sharing</TEMP_BOND_TYPE>";
private static final int TEST_DEVICE_GROUP_ID1 = 1;
private static final int TEST_DEVICE_GROUP_ID2 = 2;
private static final int METADATA_FAST_PAIR_CUSTOMIZED_FIELDS = 25;
private static final String TEST_SETTINGS_KEY =
"bluetooth_le_broadcast_fallback_active_group_id";
@@ -447,23 +443,6 @@ public class AudioSharingCallAudioPreferenceControllerTest {
assertThat(mPreference.getSummary().toString()).isEmpty();
}
@Test
@EnableFlags(Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI)
public void displayPreference_hasTemporaryBondDevice_doNotShow() {
Settings.Secure.putInt(mContentResolver, TEST_SETTINGS_KEY, TEST_DEVICE_GROUP_ID1);
when(mCachedDevice1.isActiveDevice(BluetoothProfile.LE_AUDIO)).thenReturn(true);
when(mBroadcast.isEnabled(any())).thenReturn(true);
when(mAssistant.getAllConnectedDevices()).thenReturn(ImmutableList.of(mDevice1, mDevice2));
when(mAssistant.getAllSources(any())).thenReturn(ImmutableList.of(mState));
when(mDevice2.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS)).thenReturn(
TEMP_BOND_METADATA.getBytes());
mController.displayPreference(mScreen);
shadowOf(Looper.getMainLooper()).idle();
assertThat(mController.mGroupedConnectedDevices).hasSize(0);
}
@Test
public void displayPreference_clickToShowCorrectDialog() {
AlertDialog latestAlertDialog = ShadowAlertDialogCompat.getLatestAlertDialog();

View File

@@ -93,8 +93,14 @@ public class AudioSharingDialogFragmentTest {
private static final String METADATA_STR =
"BLUETOOTH:UUID:184F;BN:VGVzdA==;AT:1;AD:00A1A1A1A1A1;BI:1E240;BC:VGVzdENvZGU=;"
+ "MD:BgNwVGVzdA==;AS:1;PI:A0;NS:1;BS:3;NB:2;SM:BQNUZXN0BARlbmc=;;";
private static final String METADATA_STR_NO_PASSWORD =
"BLUETOOTH:UUID:184F;BN:SG9ja2V5;AT:0;AD:AABBCC001122;BI:DE51E9;SQ:1;AS:1;PI:FFFF;"
+ "NS:1;BS:1;NB:1;;";
private static final BluetoothLeBroadcastMetadata METADATA =
BluetoothLeBroadcastMetadataExt.INSTANCE.convertToBroadcastMetadata(METADATA_STR);
private static final BluetoothLeBroadcastMetadata METADATA_NO_PASSWORD =
BluetoothLeBroadcastMetadataExt.INSTANCE.convertToBroadcastMetadata(
METADATA_STR_NO_PASSWORD);
private Fragment mParent;
private FakeFeatureFactory mFeatureFactory;
@@ -290,6 +296,50 @@ public class AudioSharingDialogFragmentTest {
assertThat(dialog.isShowing()).isFalse();
}
@Test
public void onCreateDialog_noExtraConnectedDevice_hasMetadataNoPassword_showCancelButton() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);
AtomicBoolean isCancelBtnClicked = new AtomicBoolean(false);
AudioSharingDialogFragment.show(
mParent,
new ArrayList<>(),
METADATA_NO_PASSWORD,
new AudioSharingDialogFragment.DialogEventListener() {
@Override
public void onCancelClick() {
isCancelBtnClicked.set(true);
}
},
TEST_EVENT_DATA_LIST);
shadowMainLooper().idle();
AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
assertThat(dialog).isNotNull();
ImageView image = dialog.findViewById(R.id.description_image);
assertThat(image).isNotNull();
TextView text = dialog.findViewById(R.id.description_text);
assertThat(text).isNotNull();
assertThat(METADATA_NO_PASSWORD).isNotNull();
assertThat(text.getText().toString()).isEqualTo(
mParent.getString(R.string.audio_sharing_dialog_qr_code_content_no_password,
METADATA_NO_PASSWORD.getBroadcastName()));
TextView textBottom = dialog.findViewById(R.id.description_text_2);
assertThat(textBottom).isNotNull();
assertThat(textBottom.getText().toString()).isEqualTo(
mParent.getString(R.string.audio_sharing_dialog_pair_new_device_content));
Button cancelBtn = dialog.findViewById(R.id.negative_btn);
assertThat(cancelBtn).isNotNull();
cancelBtn.performClick();
shadowMainLooper().idle();
verify(mFeatureFactory.metricsFeatureProvider)
.action(
any(Context.class),
eq(SettingsEnums.ACTION_AUDIO_SHARING_DIALOG_NEGATIVE_BTN_CLICKED),
eq(TEST_EVENT_DATA));
assertThat(isCancelBtnClicked.get()).isTrue();
assertThat(dialog.isShowing()).isFalse();
}
@Test
public void onCreateDialog_flagOn_singleExtraConnectedDevice() {
mSetFlagsRule.enableFlags(Flags.FLAG_ENABLE_LE_AUDIO_SHARING);

View File

@@ -1,243 +0,0 @@
/*
* Copyright 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.connecteddevice.audiosharing;
import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothStatusCodes;
import android.content.Context;
import android.platform.test.annotations.RequiresFlagsDisabled;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import androidx.lifecycle.LifecycleOwner;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.bluetooth.Utils;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
import com.android.settingslib.bluetooth.BluetoothCallback;
import com.android.settingslib.bluetooth.BluetoothEventManager;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.core.lifecycle.Lifecycle;
import com.android.settingslib.flags.Flags;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
/** Tests for {@link TemporaryBondDeviceGroupController}. */
@RunWith(RobolectricTestRunner.class)
@Config(
shadows = {
ShadowBluetoothAdapter.class,
ShadowBluetoothUtils.class
})
public class TemporaryBondDeviceGroupControllerTest {
private static final String KEY = "temp_bond_device_list";
private static final String PREFERENCE_KEY_1 = "pref_key_1";
@Rule
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
@Mock
private TemporaryBondDeviceGroupUpdater mBluetoothDeviceUpdater;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private PreferenceManager mPreferenceManager;
@Mock
private LocalBluetoothManager mLocalBtManager;
@Mock
private BluetoothEventManager mEventManager;
@Mock private PreferenceScreen mScreen;
private PreferenceGroup mPreferenceGroup;
private Context mContext;
private Preference mPreference;
private TemporaryBondDeviceGroupController mTemporaryBondDeviceGroupController;
private LifecycleOwner mLifecycleOwner;
private Lifecycle mLifecycle;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = ApplicationProvider.getApplicationContext();
mPreference = new Preference(mContext);
mPreference.setKey(PREFERENCE_KEY_1);
mPreferenceGroup = spy(new PreferenceCategory(mContext));
when(mPreferenceGroup.getPreferenceManager()).thenReturn(mPreferenceManager);
mLifecycleOwner = () -> mLifecycle;
mLifecycle = new Lifecycle(mLifecycleOwner);
when(mScreen.getContext()).thenReturn(mContext);
when(mScreen.findPreference(KEY)).thenReturn(mPreferenceGroup);
ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBtManager;
mLocalBtManager = Utils.getLocalBtManager(mContext);
when(mLocalBtManager.getEventManager()).thenReturn(mEventManager);
ShadowBluetoothAdapter shadowBluetoothAdapter = Shadow.extract(
BluetoothAdapter.getDefaultAdapter());
shadowBluetoothAdapter.setEnabled(true);
shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
mTemporaryBondDeviceGroupController = spy(new TemporaryBondDeviceGroupController(mContext));
mTemporaryBondDeviceGroupController.setBluetoothDeviceUpdater(mBluetoothDeviceUpdater);
mTemporaryBondDeviceGroupController.setPreferenceGroup(mPreferenceGroup);
}
@Test
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI)
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
public void onStart_flagOff_doNothing() {
mTemporaryBondDeviceGroupController.onStart(mLifecycleOwner);
verify(mEventManager, never()).registerCallback(any(BluetoothCallback.class));
verify(mBluetoothDeviceUpdater, never()).registerCallback();
verify(mBluetoothDeviceUpdater, never()).refreshPreference();
}
@Test
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI)
public void onStart_audioSharingUINotAvailable_doNothing() {
mTemporaryBondDeviceGroupController.onStart(mLifecycleOwner);
verify(mEventManager, never()).registerCallback(any(BluetoothCallback.class));
verify(mBluetoothDeviceUpdater, never()).registerCallback();
verify(mBluetoothDeviceUpdater, never()).refreshPreference();
}
@Test
@RequiresFlagsEnabled({Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI,
Flags.FLAG_ENABLE_LE_AUDIO_SHARING})
public void onStart_registerCallbacks() {
mTemporaryBondDeviceGroupController.onStart(mLifecycleOwner);
verify(mEventManager).registerCallback(any(BluetoothCallback.class));
verify(mBluetoothDeviceUpdater).registerCallback();
verify(mBluetoothDeviceUpdater).refreshPreference();
}
@Test
@RequiresFlagsEnabled({Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI,
Flags.FLAG_ENABLE_LE_AUDIO_SHARING})
public void onStop_unregisterCallbacks() {
mTemporaryBondDeviceGroupController.onStop(mLifecycleOwner);
verify(mEventManager).unregisterCallback(any(BluetoothCallback.class));
verify(mBluetoothDeviceUpdater).unregisterCallback();
}
@Test
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI)
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
public void displayPreference_flagOff_doNothing() {
mTemporaryBondDeviceGroupController.displayPreference(mScreen);
assertThat(mPreferenceGroup.isVisible()).isFalse();
verify(mBluetoothDeviceUpdater, never()).forceUpdate();
}
@Test
@RequiresFlagsDisabled(Flags.FLAG_ENABLE_LE_AUDIO_SHARING)
@RequiresFlagsEnabled(Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI)
public void displayPreference_audioSharingUINotAvailable_doNothing() {
mTemporaryBondDeviceGroupController.displayPreference(mScreen);
assertThat(mPreferenceGroup.isVisible()).isFalse();
verify(mBluetoothDeviceUpdater, never()).forceUpdate();
}
@Test
@RequiresFlagsEnabled({Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI,
Flags.FLAG_ENABLE_LE_AUDIO_SHARING})
public void displayPreference_updateDeviceList() {
mTemporaryBondDeviceGroupController.displayPreference(mScreen);
assertThat(mPreferenceGroup.isVisible()).isFalse();
verify(mBluetoothDeviceUpdater).setPrefContext(mContext);
verify(mBluetoothDeviceUpdater).forceUpdate();
}
@Test
public void onDeviceAdded_firstAdd_becomeVisibleAndPreferenceAdded() {
mTemporaryBondDeviceGroupController.onDeviceAdded(mPreference);
assertThat(mPreferenceGroup.isVisible()).isTrue();
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
}
@Test
public void onDeviceRemoved_lastRemove_becomeInvisibleAndPreferenceRemoved() {
mPreferenceGroup.addPreference(mPreference);
mTemporaryBondDeviceGroupController.onDeviceRemoved(mPreference);
assertThat(mPreferenceGroup.isVisible()).isFalse();
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(0);
}
@Test
public void onDeviceRemoved_notLastRemove_stillVisible() {
mPreferenceGroup.setVisible(true);
mPreferenceGroup.addPreference(mPreference);
mPreferenceGroup.addPreference(new Preference(mContext));
mTemporaryBondDeviceGroupController.onDeviceRemoved(mPreference);
assertThat(mPreferenceGroup.isVisible()).isTrue();
assertThat(mPreferenceGroup.getPreferenceCount()).isEqualTo(1);
}
@Test
public void getPreferenceKey_returnsCorrectKey() {
assertThat(mTemporaryBondDeviceGroupController.getPreferenceKey()).isEqualTo(KEY);
}
@Test
@RequiresFlagsEnabled({Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI,
Flags.FLAG_ENABLE_LE_AUDIO_SHARING})
public void getAvailabilityStatus_returnsAvailable() {
assertThat(mTemporaryBondDeviceGroupController.getAvailabilityStatus()).isEqualTo(
AVAILABLE_UNSEARCHABLE);
}
}

View File

@@ -1,139 +0,0 @@
/*
* 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.connecteddevice.audiosharing;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothStatusCodes;
import android.content.Context;
import android.platform.test.annotations.RequiresFlagsEnabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.bluetooth.Utils;
import com.android.settings.connecteddevice.DevicePreferenceCallback;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.flags.Flags;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadow.api.Shadow;
import java.util.ArrayList;
import java.util.Collection;
/** Tests for {@link TemporaryBondDeviceGroupUpdater}. */
@RunWith(RobolectricTestRunner.class)
@Config(
shadows = {
ShadowBluetoothAdapter.class,
ShadowBluetoothUtils.class
})
public class TemporaryBondDeviceGroupUpdaterTest {
private static final String TAG = "TemporaryBondDeviceGroupUpdater";
private static final String PREF_KEY_PREFIX = "temp_bond_bt_";
private static final String TEMP_BOND_METADATA =
"<TEMP_BOND_TYPE>le_audio_sharing</TEMP_BOND_TYPE>";
private static final int METADATA_FAST_PAIR_CUSTOMIZED_FIELDS = 25;
@Rule
public final CheckFlagsRule mCheckFlagsRule = DeviceFlagsValueProvider.createCheckFlagsRule();
@Mock
private DevicePreferenceCallback mDevicePreferenceCallback;
@Mock
private CachedBluetoothDevice mCachedBluetoothDevice;
@Mock
private BluetoothDevice mBluetoothDevice;
@Mock
private LocalBluetoothManager mLocalBtManager;
@Mock
private CachedBluetoothDeviceManager mCachedDeviceManager;
private TemporaryBondDeviceGroupUpdater mDeviceUpdater;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
ShadowBluetoothAdapter shadowBluetoothAdapter = Shadow.extract(
BluetoothAdapter.getDefaultAdapter());
shadowBluetoothAdapter.setEnabled(true);
shadowBluetoothAdapter.setIsLeAudioBroadcastSourceSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
shadowBluetoothAdapter.setIsLeAudioBroadcastAssistantSupported(
BluetoothStatusCodes.FEATURE_SUPPORTED);
Context context = ApplicationProvider.getApplicationContext();
ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBtManager;
mLocalBtManager = Utils.getLocalBtManager(context);
when(mLocalBtManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager);
when(mCachedBluetoothDevice.getDevice()).thenReturn(mBluetoothDevice);
Collection<CachedBluetoothDevice> cachedDevices = new ArrayList<>();
cachedDevices.add(mCachedBluetoothDevice);
when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(cachedDevices);
mDeviceUpdater =
spy(
new TemporaryBondDeviceGroupUpdater(
context, mDevicePreferenceCallback, /* metricsCategory= */ 0));
mDeviceUpdater.setPrefContext(context);
}
@After
public void tearDown() {
ShadowBluetoothUtils.reset();
}
@Test
@RequiresFlagsEnabled({Flags.FLAG_ENABLE_TEMPORARY_BOND_DEVICES_UI,
Flags.FLAG_ENABLE_LE_AUDIO_SHARING})
public void isFilterMatched_isTemporaryBondDevice_returnsTrue() {
when(mBluetoothDevice.isConnected()).thenReturn(true);
when(mBluetoothDevice.getBondState()).thenReturn(BluetoothDevice.BOND_BONDED);
when(mBluetoothDevice.getMetadata(METADATA_FAST_PAIR_CUSTOMIZED_FIELDS))
.thenReturn(TEMP_BOND_METADATA.getBytes());
assertThat(mDeviceUpdater.isFilterMatched(mCachedBluetoothDevice)).isTrue();
}
@Test
public void getLogTag_returnsCorrectTag() {
assertThat(mDeviceUpdater.getLogTag()).isEqualTo(TAG);
}
@Test
public void getPreferenceKey_returnsCorrectKey() {
assertThat(mDeviceUpdater.getPreferenceKeyPrefix()).isEqualTo(PREF_KEY_PREFIX);
}
}

View File

@@ -20,6 +20,8 @@ import static android.bluetooth.BluetoothStatusCodes.FEATURE_SUPPORTED;
import static com.android.settings.development.BluetoothA2dpHwOffloadPreferenceController
.A2DP_OFFLOAD_DISABLED_PROPERTY;
import static com.android.settings.development.BluetoothA2dpHwOffloadPreferenceController
.A2DP_OFFLOAD_SUPPORTED_PROPERTY;
import static com.android.settings.development.BluetoothLeAudioHwOffloadPreferenceController
.LE_AUDIO_OFFLOAD_DISABLED_PROPERTY;
import static com.android.settings.development.BluetoothLeAudioHwOffloadPreferenceController
@@ -120,4 +122,17 @@ public class BluetoothLeAudioHwOffloadPreferenceControllerTest {
leAueioDisabled = SystemProperties.getBoolean(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, false);
assertThat(leAueioDisabled).isTrue();
}
@Test
public void asDisableDeveloperOption_ResetLEOffloadBasedOnA2dpLeAudioOffloadSupported() {
SystemProperties.set(LE_AUDIO_OFFLOAD_SUPPORTED_PROPERTY, Boolean.toString(true));
SystemProperties.set(A2DP_OFFLOAD_SUPPORTED_PROPERTY, Boolean.toString(true));
SystemProperties.set(
LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, Boolean.toString(true));
mController.onDeveloperOptionsSwitchDisabled();
boolean leAueioDisabled =
SystemProperties.getBoolean(LE_AUDIO_OFFLOAD_DISABLED_PROPERTY, false);
assertThat(leAueioDisabled).isFalse();
}
}

View File

@@ -102,7 +102,8 @@ public class DesktopExperiencePreferenceControllerTest {
// Set desktop mode available
when(mResources.getBoolean(com.android.internal.R.bool.config_isDesktopModeSupported))
.thenReturn(true);
when(mResources.getBoolean(com.android.internal.R.bool.config_canInternalDisplayHostDesktops))
when(mResources
.getBoolean(com.android.internal.R.bool.config_canInternalDisplayHostDesktops))
.thenReturn(true);
ShadowSystemProperties.override("persist.wm.debug.desktop_mode_enforce_device_restrictions",
"false");

View File

@@ -104,7 +104,8 @@ public class DesktopModePreferenceControllerTest {
// Set desktop mode available
when(mResources.getBoolean(R.bool.config_isDesktopModeSupported))
.thenReturn(true);
when(mResources.getBoolean(com.android.internal.R.bool.config_canInternalDisplayHostDesktops))
when(mResources
.getBoolean(com.android.internal.R.bool.config_canInternalDisplayHostDesktops))
.thenReturn(true);
ShadowSystemProperties.override("persist.wm.debug.desktop_mode_enforce_device_restrictions",
"false");

View File

@@ -97,7 +97,8 @@ public class DesktopModeSecondaryDisplayPreferenceControllerTest {
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
mController.displayPreference(mScreen);
when(mResources.getBoolean(R.bool.config_isDesktopModeSupported)).thenReturn(false);
when(mResources.getBoolean(com.android.internal.R.bool.config_canInternalDisplayHostDesktops))
when(mResources
.getBoolean(com.android.internal.R.bool.config_canInternalDisplayHostDesktops))
.thenReturn(false);
}

View File

@@ -91,6 +91,7 @@ public class FreeformWindowsPreferenceControllerTest {
doReturn(mFragmentManager).when(mActivity).getSupportFragmentManager();
doReturn(mActivity).when(mFragment).getActivity();
doReturn(true).when(mResources).getBoolean(R.bool.config_isDesktopModeSupported);
doReturn(true).when(mResources).getBoolean(R.bool.config_canInternalDisplayHostDesktops);
mController = new FreeformWindowsPreferenceController(mContext, mFragment);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mPreference);
when(mContext.getPackageManager()).thenReturn(mPackageManager);

View File

@@ -99,9 +99,9 @@ public final class PowerUsageTimeControllerTest {
/* anomalyHintText= */ null);
verifyOnePreferenceInvisible(mBackgroundTimePreference);
verify(mScreenTimePreference).setTimeTitle("Screen time");
verify(mScreenTimePreference).setTimeSummary("1 min");
verify(mScreenTimePreference, never()).setAnomalyHint(anyString());
verify(mScreenTimePreference).setTitle("Screen time");
verify(mScreenTimePreference).setSummary("1 min");
verify(mScreenTimePreference, never()).setHint(anyString());
}
@Test
@@ -117,9 +117,9 @@ public final class PowerUsageTimeControllerTest {
/* anomalyHintText= */ null);
verifyOnePreferenceInvisible(mScreenTimePreference);
verify(mBackgroundTimePreference).setTimeTitle("Background time");
verify(mBackgroundTimePreference).setTimeSummary("2 min");
verify(mBackgroundTimePreference, never()).setAnomalyHint(anyString());
verify(mBackgroundTimePreference).setTitle("Background time");
verify(mBackgroundTimePreference).setSummary("2 min");
verify(mBackgroundTimePreference, never()).setHint(anyString());
}
@Test
@@ -135,12 +135,12 @@ public final class PowerUsageTimeControllerTest {
/* anomalyHintText= */ null);
verifyAllPreferencesVisible(true);
verify(mScreenTimePreference).setTimeTitle("Screen time");
verify(mScreenTimePreference).setTimeSummary("1 min");
verify(mScreenTimePreference, never()).setAnomalyHint(anyString());
verify(mBackgroundTimePreference).setTimeTitle("Background time");
verify(mBackgroundTimePreference).setTimeSummary("2 min");
verify(mBackgroundTimePreference, never()).setAnomalyHint(anyString());
verify(mScreenTimePreference).setTitle("Screen time");
verify(mScreenTimePreference).setSummary("1 min");
verify(mScreenTimePreference, never()).setHint(anyString());
verify(mBackgroundTimePreference).setTitle("Background time");
verify(mBackgroundTimePreference).setSummary("2 min");
verify(mBackgroundTimePreference, never()).setHint(anyString());
verify(mPowerUsageTimeCategory).setTitle("App usage for 12 am-2 am");
}
@@ -173,8 +173,8 @@ public final class PowerUsageTimeControllerTest {
/* anomalyHintText= */ null);
verifyAllPreferencesVisible(true);
verify(mScreenTimePreference).setTimeSummary("1 min");
verify(mBackgroundTimePreference).setTimeSummary("Less than a minute");
verify(mScreenTimePreference).setSummary("1 min");
verify(mBackgroundTimePreference).setSummary("Less than a minute");
}
@Test
@@ -190,8 +190,8 @@ public final class PowerUsageTimeControllerTest {
/* anomalyHintText= */ null);
verifyAllPreferencesVisible(true);
verify(mScreenTimePreference).setTimeSummary("Less than a minute");
verify(mBackgroundTimePreference).setTimeSummary("2 min");
verify(mScreenTimePreference).setSummary("Less than a minute");
verify(mBackgroundTimePreference).setSummary("2 min");
}
@Test
@@ -207,8 +207,8 @@ public final class PowerUsageTimeControllerTest {
/* anomalyHintText= */ null);
verifyAllPreferencesVisible(true);
verify(mScreenTimePreference).setTimeSummary("Less than a minute");
verify(mBackgroundTimePreference).setTimeSummary("Less than a minute");
verify(mScreenTimePreference).setSummary("Less than a minute");
verify(mBackgroundTimePreference).setSummary("Less than a minute");
}
@Test
@@ -224,8 +224,8 @@ public final class PowerUsageTimeControllerTest {
TEST_ANOMALY_HINT_TEXT);
verifyAllPreferencesVisible(true);
verify(mScreenTimePreference).setAnomalyHint(TEST_ANOMALY_HINT_TEXT);
verify(mBackgroundTimePreference, never()).setAnomalyHint(anyString());
verify(mScreenTimePreference).setHint(TEST_ANOMALY_HINT_TEXT);
verify(mBackgroundTimePreference, never()).setHint(anyString());
}
@Test
@@ -241,8 +241,8 @@ public final class PowerUsageTimeControllerTest {
TEST_ANOMALY_HINT_TEXT);
verifyAllPreferencesVisible(true);
verify(mScreenTimePreference, never()).setAnomalyHint(anyString());
verify(mBackgroundTimePreference).setAnomalyHint(TEST_ANOMALY_HINT_TEXT);
verify(mScreenTimePreference, never()).setHint(anyString());
verify(mBackgroundTimePreference).setHint(TEST_ANOMALY_HINT_TEXT);
}
@Test
@@ -258,9 +258,9 @@ public final class PowerUsageTimeControllerTest {
TEST_ANOMALY_HINT_TEXT);
verifyAllPreferencesVisible(true);
verify(mScreenTimePreference).setTimeSummary("Less than a minute");
verify(mScreenTimePreference).setAnomalyHint(TEST_ANOMALY_HINT_TEXT);
verify(mBackgroundTimePreference, never()).setAnomalyHint(anyString());
verify(mScreenTimePreference).setSummary("Less than a minute");
verify(mScreenTimePreference).setHint(TEST_ANOMALY_HINT_TEXT);
verify(mBackgroundTimePreference, never()).setHint(anyString());
}
private void verifySetPrefToVisible(Preference pref, boolean isVisible) {

View File

@@ -67,7 +67,7 @@ public final class BatteryUsageBreakdownControllerTest {
@Mock private PreferenceGroup mRootPreferenceGroup;
@Mock private Drawable mDrawable;
@Mock private BatteryHistEntry mBatteryHistEntry;
@Mock private AnomalyAppItemPreference mAnomalyAppItemPreference;
@Mock private PowerGaugePreference mPowerGaugePreference;
private Context mContext;
private FakeFeatureFactory mFeatureFactory;
@@ -131,13 +131,13 @@ public final class BatteryUsageBreakdownControllerTest {
BatteryDiffEntry.sResourceCache.put(
"fakeBatteryDiffEntryKey",
new BatteryEntry.NameAndIcon("fakeName", /* icon= */ null, /* iconId= */ 1));
doReturn(mAnomalyAppItemPreference).when(mRootPreferenceGroup).findPreference(PREF_KEY);
doReturn(mPowerGaugePreference).when(mRootPreferenceGroup).findPreference(PREF_KEY);
}
@Test
public void onDestroy_clearPreferenceCacheAndPreferenceGroupRemoveAll() {
// Ensures the testing environment is correct.
mBatteryUsageBreakdownController.mPreferenceCache.put(PREF_KEY, mAnomalyAppItemPreference);
mBatteryUsageBreakdownController.mPreferenceCache.put(PREF_KEY, mPowerGaugePreference);
assertThat(mBatteryUsageBreakdownController.mPreferenceCache).hasSize(1);
mBatteryUsageBreakdownController.onDestroy();
@@ -204,25 +204,25 @@ public final class BatteryUsageBreakdownControllerTest {
@Test
public void removeAndCacheAllUnusedPreferences_removePref_buildCacheAndRemoveAllPreference() {
doReturn(1).when(mRootPreferenceGroup).getPreferenceCount();
doReturn(mAnomalyAppItemPreference).when(mRootPreferenceGroup).getPreference(0);
doReturn(mPowerGaugePreference).when(mRootPreferenceGroup).getPreference(0);
doReturn(PREF_KEY2).when(mBatteryHistEntry).getKey();
doReturn(PREF_KEY).when(mAnomalyAppItemPreference).getKey();
doReturn(PREF_KEY).when(mPowerGaugePreference).getKey();
// Ensures the testing data is correct.
assertThat(mBatteryUsageBreakdownController.mPreferenceCache).isEmpty();
mBatteryUsageBreakdownController.removeAndCacheAllUnusedPreferences();
assertThat(mBatteryUsageBreakdownController.mPreferenceCache.get(PREF_KEY))
.isEqualTo(mAnomalyAppItemPreference);
verify(mRootPreferenceGroup).removePreference(mAnomalyAppItemPreference);
.isEqualTo(mPowerGaugePreference);
verify(mRootPreferenceGroup).removePreference(mPowerGaugePreference);
}
@Test
public void removeAndCacheAllUnusedPreferences_keepPref_KeepAllPreference() {
doReturn(1).when(mRootPreferenceGroup).getPreferenceCount();
doReturn(mAnomalyAppItemPreference).when(mRootPreferenceGroup).getPreference(0);
doReturn(mPowerGaugePreference).when(mRootPreferenceGroup).getPreference(0);
doReturn(PREF_KEY).when(mBatteryDiffEntry).getKey();
doReturn(PREF_KEY).when(mAnomalyAppItemPreference).getKey();
doReturn(PREF_KEY).when(mPowerGaugePreference).getKey();
// Ensures the testing data is correct.
assertThat(mBatteryUsageBreakdownController.mPreferenceCache).isEmpty();
@@ -246,11 +246,11 @@ public final class BatteryUsageBreakdownControllerTest {
@Test
public void handlePreferenceTreeClick_forAppEntry_returnTrue() {
mBatteryDiffEntry.mConsumerType = ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY;
doReturn(mBatteryDiffEntry).when(mAnomalyAppItemPreference).getBatteryDiffEntry();
doReturn(mBatteryDiffEntry).when(mPowerGaugePreference).getBatteryDiffEntry();
assertThat(
mBatteryUsageBreakdownController.handlePreferenceTreeClick(
mAnomalyAppItemPreference))
mPowerGaugePreference))
.isTrue();
verify(mMetricsFeatureProvider)
.action(
@@ -264,11 +264,11 @@ public final class BatteryUsageBreakdownControllerTest {
@Test
public void handlePreferenceTreeClick_forSystemEntry_returnTrue() {
mBatteryDiffEntry.mConsumerType = ConvertUtils.CONSUMER_TYPE_UID_BATTERY;
doReturn(mBatteryDiffEntry).when(mAnomalyAppItemPreference).getBatteryDiffEntry();
doReturn(mBatteryDiffEntry).when(mPowerGaugePreference).getBatteryDiffEntry();
assertThat(
mBatteryUsageBreakdownController.handlePreferenceTreeClick(
mAnomalyAppItemPreference))
mPowerGaugePreference))
.isTrue();
verify(mMetricsFeatureProvider)
.action(

View File

@@ -19,19 +19,20 @@ import static com.google.common.truth.Truth.assertThat;
import android.content.Context;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.VectorDrawable;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.Space;
import androidx.preference.PreferenceViewHolder;
import com.android.settings.R;
import com.android.settingslib.widget.SettingsThemeHelper;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
@@ -48,17 +49,17 @@ public class PowerGaugePreferenceTest {
private View mWidgetView;
private PreferenceViewHolder mPreferenceViewHolder;
@Mock Drawable mMockIcon;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
mPowerGaugePreference = new PowerGaugePreference(mContext);
mRootView =
LayoutInflater.from(mContext)
.inflate(
com.android.settingslib.widget.preference.app.R.layout
.preference_app,
null);
.inflate(mPowerGaugePreference.getLayoutResource(), null);
mWidgetView =
LayoutInflater.from(mContext).inflate(R.layout.preference_widget_summary, null);
final LinearLayout widgetFrame = mRootView.findViewById(android.R.id.widget_frame);
@@ -66,31 +67,56 @@ public class PowerGaugePreferenceTest {
widgetFrame.addView(mWidgetView);
mPreferenceViewHolder = PreferenceViewHolder.createInstanceForTests(mRootView);
mPowerGaugePreference = new PowerGaugePreference(mContext);
assertThat(mPowerGaugePreference.getLayoutResource())
.isEqualTo(com.android.settingslib.widget.preference.app.R.layout.preference_app);
.isEqualTo(
SettingsThemeHelper.isExpressiveTheme(mContext)
? R.layout.expressive_warning_frame_preference
: R.layout.warning_frame_preference);
}
@Test
public void testOnBindViewHolder_showAnomaly_bindAnomalyIcon() {
mPowerGaugePreference.shouldShowAnomalyIcon(true);
public void testOnBindViewHolder_showHint_hasHintChip() {
mPowerGaugePreference.setHint("Hint Text");
mPowerGaugePreference.setIcon(mMockIcon);
mPowerGaugePreference.onBindViewHolder(mPreferenceViewHolder);
TextView widgetSummary = (TextView) mPreferenceViewHolder.findViewById(R.id.widget_summary);
final Drawable[] drawables = widgetSummary.getCompoundDrawablesRelative();
final LinearLayout warningChipFrame =
(LinearLayout) mPreferenceViewHolder.findViewById(R.id.warning_chip_frame);
final Space warningPaddingPlaceHolder =
warningChipFrame.findViewById(R.id.warning_padding_placeholder);
assertThat(drawables[0]).isInstanceOf(VectorDrawable.class);
assertThat(warningChipFrame.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(warningPaddingPlaceHolder.getVisibility()).isEqualTo(View.VISIBLE);
}
@Test
public void testOnBindViewHolder_notShowAnomaly_bindAnomalyIcon() {
mPowerGaugePreference.shouldShowAnomalyIcon(false);
public void testOnBindViewHolder_emptyHintText_withoutHintChip() {
mPowerGaugePreference.setHint("");
mPowerGaugePreference.setIcon(mMockIcon);
mPowerGaugePreference.onBindViewHolder(mPreferenceViewHolder);
TextView widgetSummary = (TextView) mPreferenceViewHolder.findViewById(R.id.widget_summary);
final Drawable[] drawables = widgetSummary.getCompoundDrawablesRelative();
final LinearLayout warningChipFrame =
(LinearLayout) mPreferenceViewHolder.findViewById(R.id.warning_chip_frame);
final Space warningPaddingPlaceholder =
warningChipFrame.findViewById(R.id.warning_padding_placeholder);
assertThat(drawables[0]).isNull();
assertThat(warningChipFrame.getVisibility()).isEqualTo(View.GONE);
assertThat(warningPaddingPlaceholder.getVisibility()).isEqualTo(View.VISIBLE);
}
@Test
public void testOnBindViewHolder_noAppIconWithHintText_hasChipWithoutPaddingPlaceholder() {
mPowerGaugePreference.setHint("Anomaly Hint Text");
mPowerGaugePreference.setIcon(null);
mPowerGaugePreference.onBindViewHolder(mPreferenceViewHolder);
final LinearLayout warningChipFrame =
(LinearLayout) mPreferenceViewHolder.findViewById(R.id.warning_chip_frame);
final Space warningPaddingPlaceHolder =
warningChipFrame.findViewById(R.id.warning_padding_placeholder);
assertThat(warningChipFrame.getVisibility()).isEqualTo(View.VISIBLE);
assertThat(warningPaddingPlaceHolder.getVisibility()).isEqualTo(View.GONE);
}
@Test

View File

@@ -102,7 +102,7 @@ public class DndConditionalCardControllerTest {
private ZenModeConfig getMutedAllConfig() {
final ZenModeConfig config = new ZenModeConfig();
config.applyNotificationPolicy(new NotificationManager.Policy(0, 0, 0));
config.areChannelsBypassingDnd = false;
config.hasPriorityChannels = false;
return config;
}
}

View File

@@ -26,10 +26,10 @@ import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.verify;
import android.app.Dialog;
import android.os.Bundle;
import android.window.OnBackInvokedDispatcher;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
@@ -92,17 +92,17 @@ public class LocaleDialogFragmentTest {
@Test
public void onBackInvoked_dialogIsStillDisplaying() {
mDialogFragment.setBackDispatcher(mOnBackInvokedDispatcher);
AlertDialog alertDialog = (AlertDialog) mDialogFragment.onCreateDialog(null);
alertDialog.show();
assertThat(alertDialog).isNotNull();
assertThat(alertDialog.isShowing()).isTrue();
Dialog dialog = mDialogFragment.onCreateDialog(null);
dialog.show();
assertThat(dialog).isNotNull();
assertThat(dialog.isShowing()).isTrue();
mOnBackInvokedDispatcher.registerOnBackInvokedCallback(
eq(OnBackInvokedDispatcher.PRIORITY_DEFAULT), any());
mDialogFragment.getBackInvokedCallback().onBackInvoked();
assertThat(alertDialog.isShowing()).isTrue();
assertThat(dialog.isShowing()).isTrue();
}
}

View File

@@ -33,6 +33,7 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.Activity;
import android.app.Dialog;
import android.app.IActivityManager;
import android.content.Context;
import android.content.DialogInterface;
@@ -53,10 +54,10 @@ import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.preference.Preference;
import androidx.test.core.app.ApplicationProvider;
import com.android.internal.app.LocaleStore;
@@ -78,6 +79,7 @@ import org.mockito.junit.MockitoRule;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowDialog;
import org.robolectric.shadows.ShadowLooper;
import org.robolectric.util.ReflectionHelpers;
@@ -87,6 +89,7 @@ import java.util.Locale;
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {
ShadowDialog.class,
ShadowAlertDialogCompat.class,
ShadowActivityManager.class,
com.android.settings.testutils.shadow.ShadowFragment.class,
@@ -143,6 +146,8 @@ public class LocaleListEditorTest {
private ImageView mDragHandle;
@Mock
private NotificationController mNotificationController;
@Mock
private Preference mAddLanguagePreference;
@Rule
public final CheckFlagsRule mCheckFlagsRule =
@@ -166,6 +171,8 @@ public class LocaleListEditorTest {
context.getSystemService(Context.USER_SERVICE));
ReflectionHelpers.setField(mLocaleListEditor, "mAdapter", mAdapter);
ReflectionHelpers.setField(mLocaleListEditor, "mAddLanguage", mAddLanguage);
ReflectionHelpers.setField(mLocaleListEditor, "mAddLanguagePreference",
mAddLanguagePreference);
ReflectionHelpers.setField(mLocaleListEditor, "mFragmentManager", mFragmentManager);
ReflectionHelpers.setField(mLocaleListEditor, "mMetricsFeatureProvider",
mMetricsFeatureProvider);
@@ -178,7 +185,7 @@ public class LocaleListEditorTest {
ReflectionHelpers.setField(mLocaleListEditor, "mRemoveMode", false);
ReflectionHelpers.setField(mLocaleListEditor, "mShowingRemoveDialog", false);
ReflectionHelpers.setField(mLocaleListEditor, "mLocaleAdditionMode", false);
ShadowAlertDialogCompat.reset();
ShadowDialog.reset();
}
@Test
@@ -209,14 +216,13 @@ public class LocaleListEditorTest {
//launch dialog
mLocaleListEditor.showRemoveLocaleWarningDialog();
final AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
final Dialog dialog = ShadowDialog.getLatestDialog();
assertThat(dialog).isNotNull();
final ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
assertThat(shadowDialog.getTitle()).isEqualTo(
mContext.getString(R.string.dlg_remove_locales_error_title));
TextView dialogTitle = dialog.findViewById(R.id.dialog_with_icon_title);
assertThat(dialogTitle.getText().toString())
.isEqualTo(mContext.getString(R.string.dlg_remove_locales_error_title));
}
@Test
@@ -231,14 +237,13 @@ public class LocaleListEditorTest {
//launch dialog
mLocaleListEditor.showRemoveLocaleWarningDialog();
final AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
final Dialog dialog = ShadowDialog.getLatestDialog();
assertThat(dialog).isNotNull();
final ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
assertThat(shadowDialog.getMessage()).isEqualTo(
mContext.getString(R.string.dlg_remove_locales_message));
TextView dialogMessage = dialog.findViewById(R.id.dialog_with_icon_message);
assertThat(dialogMessage.getText().toString())
.isEqualTo(mContext.getString(R.string.dlg_remove_locales_message));
}
@Test
@@ -253,13 +258,12 @@ public class LocaleListEditorTest {
//launch dialog
mLocaleListEditor.showRemoveLocaleWarningDialog();
final AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
final Dialog dialog = ShadowDialog.getLatestDialog();
assertThat(dialog).isNotNull();
final ShadowAlertDialogCompat shadowDialog = ShadowAlertDialogCompat.shadowOf(dialog);
assertThat(shadowDialog.getMessage()).isNull();
TextView dialogMessage = dialog.findViewById(R.id.dialog_with_icon_message);
assertThat(dialogMessage.getText().isEmpty()).isTrue();
}
@Test
@@ -280,12 +284,12 @@ public class LocaleListEditorTest {
//launch the first dialog
mLocaleListEditor.showRemoveLocaleWarningDialog();
final AlertDialog dialog = ShadowAlertDialogCompat.getLatestAlertDialog();
final Dialog dialog = ShadowDialog.getLatestDialog();
assertThat(dialog).isNotNull();
// click the remove button
dialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick();
dialog.findViewById(R.id.button_ok).performClick();
ShadowLooper.idleMainLooper();
assertThat(dialog.isShowing()).isFalse();

View File

@@ -21,14 +21,12 @@ import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_OPPORTUNI
import static android.net.ConnectivitySettingsManager.PRIVATE_DNS_MODE_PROVIDER_HOSTNAME;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import android.content.Context;
import android.content.DialogInterface;
import android.net.ConnectivitySettingsManager;
import android.view.LayoutInflater;
import android.view.View;
@@ -88,31 +86,31 @@ public class PrivateDnsModeDialogPreferenceTest {
}
@Test
public void testOnCheckedChanged_dnsModeOff_disableEditText() {
public void onCheckedChanged_dnsModeOff_disableHostnameText() {
mPreference.onCheckedChanged(null, R.id.private_dns_mode_off);
assertThat(mPreference.mMode).isEqualTo(PRIVATE_DNS_MODE_OFF);
assertThat(mPreference.mEditText.isEnabled()).isFalse();
assertThat(mPreference.mHostnameText.isEnabled()).isFalse();
}
@Test
public void testOnCheckedChanged_dnsModeOpportunistic_disableEditText() {
public void onCheckedChanged_dnsModeOpportunistic_disableHostnameText() {
mPreference.onCheckedChanged(null, R.id.private_dns_mode_opportunistic);
assertThat(mPreference.mMode).isEqualTo(PRIVATE_DNS_MODE_OPPORTUNISTIC);
assertThat(mPreference.mEditText.isEnabled()).isFalse();
assertThat(mPreference.mHostnameText.isEnabled()).isFalse();
}
@Test
public void testOnCheckedChanged_dnsModeProvider_enableEditText() {
public void onCheckedChanged_dnsModeProvider_enableHostnameText() {
mPreference.onCheckedChanged(null, R.id.private_dns_mode_provider);
assertThat(mPreference.mMode).isEqualTo(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
assertThat(mPreference.mEditText.isEnabled()).isTrue();
assertThat(mPreference.mHostnameText.isEnabled()).isTrue();
}
@Test
public void testOnBindDialogView_containsCorrectData() {
public void onBindDialogView_containsCorrectData() {
// Don't set settings to the default value ("opportunistic") as that
// risks masking failure to read the mode from settings.
ConnectivitySettingsManager.setPrivateDnsMode(mContext, PRIVATE_DNS_MODE_OFF);
@@ -123,57 +121,74 @@ public class PrivateDnsModeDialogPreferenceTest {
new LinearLayout(mContext), false);
mPreference.onBindDialogView(view);
assertThat(mPreference.mEditText.getText().toString()).isEqualTo(HOST_NAME);
assertThat(mPreference.mHostnameText.getText().toString()).isEqualTo(HOST_NAME);
assertThat(mPreference.mRadioGroup.getCheckedRadioButtonId()).isEqualTo(
R.id.private_dns_mode_off);
}
@Test
public void testOnCheckedChanged_switchMode_saveButtonHasCorrectState() {
final String[] INVALID_HOST_NAMES = new String[] {
INVALID_HOST_NAME,
"2001:db8::53", // IPv6 string literal
"192.168.1.1", // IPv4 string literal
};
public void doSaveButton_changeToOffMode_saveData() {
// Set the default settings to OPPORTUNISTIC
ConnectivitySettingsManager.setPrivateDnsMode(mContext, PRIVATE_DNS_MODE_OPPORTUNISTIC);
for (String invalid : INVALID_HOST_NAMES) {
// Set invalid hostname
mPreference.mEditText.setText(invalid);
mPreference.onCheckedChanged(null, R.id.private_dns_mode_off);
assertWithMessage("off: " + invalid).that(mSaveButton.isEnabled()).isTrue();
mPreference.onCheckedChanged(null, R.id.private_dns_mode_opportunistic);
assertWithMessage("opportunistic: " + invalid).that(mSaveButton.isEnabled()).isTrue();
mPreference.onCheckedChanged(null, R.id.private_dns_mode_provider);
assertWithMessage("provider: " + invalid).that(mSaveButton.isEnabled()).isFalse();
}
}
@Test
public void testOnClick_positiveButtonClicked_saveData() {
// Set the default settings to OFF
ConnectivitySettingsManager.setPrivateDnsMode(mContext, PRIVATE_DNS_MODE_OFF);
mPreference.mMode = PRIVATE_DNS_MODE_OPPORTUNISTIC;
mPreference.onClick(null, DialogInterface.BUTTON_POSITIVE);
mPreference.mMode = PRIVATE_DNS_MODE_OFF;
mPreference.doSaveButton();
// Change to OPPORTUNISTIC
assertThat(ConnectivitySettingsManager.getPrivateDnsMode(mContext)).isEqualTo(
PRIVATE_DNS_MODE_OPPORTUNISTIC);
assertThat(ConnectivitySettingsManager.getPrivateDnsMode(mContext))
.isEqualTo(PRIVATE_DNS_MODE_OFF);
}
@Test
public void testOnClick_negativeButtonClicked_doNothing() {
public void doSaveButton_changeToOpportunisticMode_saveData() {
// Set the default settings to OFF
ConnectivitySettingsManager.setPrivateDnsMode(mContext, PRIVATE_DNS_MODE_OFF);
mPreference.mMode = PRIVATE_DNS_MODE_OPPORTUNISTIC;
mPreference.onClick(null, DialogInterface.BUTTON_NEGATIVE);
mPreference.doSaveButton();
// Still equal to OFF
assertThat(ConnectivitySettingsManager.getPrivateDnsMode(mContext)).isEqualTo(
PRIVATE_DNS_MODE_OFF);
// Change to OPPORTUNISTIC
assertThat(ConnectivitySettingsManager.getPrivateDnsMode(mContext))
.isEqualTo(PRIVATE_DNS_MODE_OPPORTUNISTIC);
}
@Test
public void doSaveButton_changeToProviderHostnameMode_saveData() {
// Set the default settings to OFF
ConnectivitySettingsManager.setPrivateDnsMode(mContext, PRIVATE_DNS_MODE_OFF);
mPreference.onCheckedChanged(null, R.id.private_dns_mode_provider);
mPreference.mHostnameText.setText(HOST_NAME);
mPreference.doSaveButton();
// Change to PROVIDER_HOSTNAME
assertThat(ConnectivitySettingsManager.getPrivateDnsMode(mContext))
.isEqualTo(PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
assertThat(ConnectivitySettingsManager.getPrivateDnsHostname(mContext))
.isEqualTo(HOST_NAME);
}
@Test
public void doSaveButton_providerHostnameIsEmpty_setHostnameError() {
ConnectivitySettingsManager.setPrivateDnsMode(mContext, PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
ConnectivitySettingsManager.setPrivateDnsHostname(mContext, HOST_NAME);
mPreference.onCheckedChanged(null, R.id.private_dns_mode_provider);
mPreference.mHostnameText.setText("");
mPreference.doSaveButton();
assertThat(mPreference.mHostnameLayout.isErrorEnabled()).isTrue();
}
@Test
public void doSaveButton_providerHostnameIsInvalid_setHostnameError() {
ConnectivitySettingsManager.setPrivateDnsMode(mContext, PRIVATE_DNS_MODE_PROVIDER_HOSTNAME);
ConnectivitySettingsManager.setPrivateDnsHostname(mContext, HOST_NAME);
mPreference.onCheckedChanged(null, R.id.private_dns_mode_provider);
mPreference.mHostnameText.setText(INVALID_HOST_NAME);
mPreference.doSaveButton();
assertThat(mPreference.mHostnameLayout.isErrorEnabled()).isTrue();
}
}

View File

@@ -85,7 +85,7 @@ public class ZenModeSetCalendarPreferenceControllerTest {
}
@Test
@EnableFlags({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI})
@EnableFlags(Flags.FLAG_MODES_UI)
public void updateEventMode_updatesConditionAndTriggerDescription() {
ZenMode mode = new TestModeBuilder()
.setPackage(SystemZenRules.PACKAGE_ANDROID)

View File

@@ -80,7 +80,7 @@ public class ZenModeSetSchedulePreferenceControllerTest {
}
@Test
@EnableFlags({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI})
@EnableFlags(Flags.FLAG_MODES_UI)
public void updateScheduleRule_updatesConditionAndTriggerDescription() {
ZenMode mode = new TestModeBuilder()
.setPackage(SystemZenRules.PACKAGE_ANDROID)

View File

@@ -213,11 +213,7 @@ public class ZenModeBackendTest {
mBackend.saveConversationSenders(CONVERSATION_SENDERS_NONE);
ArgumentCaptor<Policy> captor = ArgumentCaptor.forClass(Policy.class);
if (android.app.Flags.modesApi()) {
verify(mNotificationManager).setNotificationPolicy(captor.capture(), eq(true));
} else {
verify(mNotificationManager).setNotificationPolicy(captor.capture());
}
verify(mNotificationManager).setNotificationPolicy(captor.capture(), eq(true));
Policy expected = new Policy(
PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_MESSAGES | PRIORITY_CATEGORY_ALARMS,
@@ -241,11 +237,7 @@ public class ZenModeBackendTest {
mBackend.saveConversationSenders(CONVERSATION_SENDERS_ANYONE);
ArgumentCaptor<Policy> captor = ArgumentCaptor.forClass(Policy.class);
if (android.app.Flags.modesApi()) {
verify(mNotificationManager).setNotificationPolicy(captor.capture(), eq(true));
} else {
verify(mNotificationManager).setNotificationPolicy(captor.capture());
}
verify(mNotificationManager).setNotificationPolicy(captor.capture(), eq(true));
Policy expected = new Policy(PRIORITY_CATEGORY_CONVERSATIONS
| PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_MESSAGES | PRIORITY_CATEGORY_ALARMS,
@@ -270,11 +262,7 @@ public class ZenModeBackendTest {
mBackend.saveSenders(PRIORITY_CATEGORY_CALLS, PRIORITY_SENDERS_ANY);
ArgumentCaptor<Policy> captor = ArgumentCaptor.forClass(Policy.class);
if (android.app.Flags.modesApi()) {
verify(mNotificationManager).setNotificationPolicy(captor.capture(), eq(true));
} else {
verify(mNotificationManager).setNotificationPolicy(captor.capture());
}
verify(mNotificationManager).setNotificationPolicy(captor.capture(), eq(true));
Policy expected = new Policy(PRIORITY_CATEGORY_CONVERSATIONS
| PRIORITY_CATEGORY_CALLS | PRIORITY_CATEGORY_MESSAGES | PRIORITY_CATEGORY_ALARMS,

View File

@@ -107,7 +107,7 @@ public class ZenModeEventRuleSettingsTest {
}
@Test
@EnableFlags({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI})
@EnableFlags(Flags.FLAG_MODES_UI)
public void updateEventRule_updatesConditionAndTriggerDescription() {
mFragment.setBackend(mBackend);
mFragment.mId = "id";

View File

@@ -107,7 +107,7 @@ public class ZenModeScheduleRuleSettingsTest {
}
@Test
@EnableFlags({Flags.FLAG_MODES_API, Flags.FLAG_MODES_UI})
@EnableFlags(Flags.FLAG_MODES_UI)
public void updateScheduleRule_updatesConditionAndTriggerDescription() {
mFragment.setBackend(mBackend);
mFragment.mId = "id";

View File

@@ -117,11 +117,7 @@ public class ZenModeSliceBuilderTest {
ZenModeSliceBuilder.handleUriChange(mContext, intent);
if (android.app.Flags.modesApi()) {
verify(mNm).setZenMode(eq(ZEN_MODE_IMPORTANT_INTERRUPTIONS), any(), any(), eq(true));
} else {
verify(mNm).setZenMode(eq(ZEN_MODE_IMPORTANT_INTERRUPTIONS), any(), any());
}
verify(mNm).setZenMode(eq(ZEN_MODE_IMPORTANT_INTERRUPTIONS), any(), any(), eq(true));
}
@Test
@@ -131,10 +127,6 @@ public class ZenModeSliceBuilderTest {
ZenModeSliceBuilder.handleUriChange(mContext, intent);
if (android.app.Flags.modesApi()) {
verify(mNm).setZenMode(eq(ZEN_MODE_OFF), any(), any(), eq(true));
} else {
verify(mNm).setZenMode(eq(ZEN_MODE_OFF), any(), any());
}
verify(mNm).setZenMode(eq(ZEN_MODE_OFF), any(), any(), eq(true));
}
}

View File

@@ -17,6 +17,7 @@
package com.android.settings.deviceinfo
import android.content.Context
import android.os.UserManager
import android.telephony.SubscriptionInfo
import android.telephony.SubscriptionManager
import android.telephony.TelephonyManager
@@ -25,30 +26,39 @@ import androidx.preference.PreferenceCategory
import androidx.preference.PreferenceManager
import androidx.test.core.app.ApplicationProvider
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.dx.mockito.inline.extended.ExtendedMockito
import com.android.settings.R
import com.android.settings.core.BasePreferenceController
import com.android.settings.network.SubscriptionUtil
import com.android.settingslib.Utils
import com.google.common.truth.Truth.assertThat
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.MockitoSession
import org.mockito.kotlin.any
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.spy
import org.mockito.kotlin.stub
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever
import org.mockito.quality.Strictness
@RunWith(AndroidJUnit4::class)
class PhoneNumberPreferenceControllerTest {
private lateinit var mockSession: MockitoSession
private val mockUserManager = mock<UserManager>()
private val mockTelephonyManager = mock<TelephonyManager>()
private val mockSubscriptionManager = mock<SubscriptionManager>()
private val context: Context =
spy(ApplicationProvider.getApplicationContext()) {
on { getSystemService(SubscriptionManager::class.java) } doReturn
mockSubscriptionManager
on { getSystemService(SubscriptionManager::class.java) } doReturn mockSubscriptionManager
on { getSystemService(TelephonyManager::class.java) } doReturn mockTelephonyManager
on { getSystemService(UserManager::class.java) } doReturn mockUserManager
}
private val subscriptionInfo = mock<SubscriptionInfo>()
@@ -61,6 +71,20 @@ class PhoneNumberPreferenceControllerTest {
@Before
fun setup() {
mockSession =
ExtendedMockito.mockitoSession()
.mockStatic(SubscriptionUtil::class.java)
.mockStatic(Utils::class.java)
.strictness(Strictness.LENIENT)
.startMocking()
// By default, available
whenever(SubscriptionUtil.isSimHardwareVisible(context)).thenReturn(true)
whenever(Utils.isWifiOnly(context)).thenReturn(false)
mockUserManager.stub {
on { isAdminUser } doReturn true
}
preference.setKey(controller.preferenceKey)
preference.isVisible = true
preferenceScreen.addPreference(preference)
@@ -70,6 +94,11 @@ class PhoneNumberPreferenceControllerTest {
doReturn(secondPreference).whenever(controller).createNewPreference(context)
}
@After
fun teardown() {
mockSession.finishMocking()
}
@Test
fun displayPreference_multiSim_shouldAddSecondPreference() {
whenever(mockTelephonyManager.phoneCount).thenReturn(2)
@@ -132,4 +161,37 @@ class PhoneNumberPreferenceControllerTest {
verify(preference).summary = context.getString(R.string.device_info_not_available)
}
@Test
fun getAvailabilityStatus_simHardwareVisible_userAdmin_notWifiOnly_displayed() {
// Use defaults from setup()
val availabilityStatus = controller.availabilityStatus
assertThat(availabilityStatus).isEqualTo(BasePreferenceController.AVAILABLE)
}
@Test
fun getAvailabilityStatus_notSimHardwareVisible_userAdmin_notWifiOnly_notDisplayed() {
whenever(SubscriptionUtil.isSimHardwareVisible(context)).thenReturn(false)
val availabilityStatus = controller.availabilityStatus
assertThat(availabilityStatus).isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE)
}
@Test
fun getAvailabilityStatus_simHardwareVisible_notUserAdmin_notWifiOnly_notDisplayed() {
mockUserManager.stub {
on { isAdminUser } doReturn false
}
val availabilityStatus = controller.availabilityStatus
assertThat(availabilityStatus).isEqualTo(BasePreferenceController.DISABLED_FOR_USER)
}
@Test
fun getAvailabilityStatus_simHardwareVisible_userAdmin_wifiOnly_notDisplayed() {
whenever(Utils.isWifiOnly(context)).thenReturn(true)
val availabilityStatus = controller.availabilityStatus
assertThat(availabilityStatus).isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE)
}
}

View File

@@ -17,6 +17,7 @@
package com.android.settings.network.telephony
import android.content.Context
import android.os.UserManager
import androidx.lifecycle.testing.TestLifecycleOwner
import androidx.preference.Preference
import androidx.preference.PreferenceManager
@@ -26,6 +27,7 @@ import com.android.dx.mockito.inline.extended.ExtendedMockito
import com.android.settings.R
import com.android.settings.core.BasePreferenceController
import com.android.settings.network.SubscriptionUtil
import com.android.settingslib.Utils
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.flowOf
@@ -37,6 +39,7 @@ import org.junit.runner.RunWith
import org.mockito.MockitoSession
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.mock
import org.mockito.kotlin.spy
import org.mockito.kotlin.stub
import org.mockito.kotlin.whenever
import org.mockito.quality.Strictness
@@ -45,9 +48,14 @@ import org.mockito.quality.Strictness
class MobileNetworkPhoneNumberPreferenceControllerTest {
private lateinit var mockSession: MockitoSession
private val context: Context = ApplicationProvider.getApplicationContext()
private val mockUserManager = mock<UserManager>()
private val mockSubscriptionRepository = mock<SubscriptionRepository>()
private val context: Context =
spy(ApplicationProvider.getApplicationContext()) {
on { getSystemService(UserManager::class.java) } doReturn mockUserManager
}
private val controller =
MobileNetworkPhoneNumberPreferenceController(context, TEST_KEY, mockSubscriptionRepository)
private val preference = Preference(context).apply { key = TEST_KEY }
@@ -58,9 +66,17 @@ class MobileNetworkPhoneNumberPreferenceControllerTest {
mockSession =
ExtendedMockito.mockitoSession()
.mockStatic(SubscriptionUtil::class.java)
.mockStatic(Utils::class.java)
.strictness(Strictness.LENIENT)
.startMocking()
// By default, available
whenever(SubscriptionUtil.isSimHardwareVisible(context)).thenReturn(true)
whenever(Utils.isWifiOnly(context)).thenReturn(false)
mockUserManager.stub {
on { isAdminUser } doReturn true
}
preferenceScreen.addPreference(preference)
controller.init(SUB_ID)
controller.displayPreference(preferenceScreen)
@@ -73,7 +89,6 @@ class MobileNetworkPhoneNumberPreferenceControllerTest {
@Test
fun onViewCreated_cannotGetPhoneNumber_displayUnknown() = runBlocking {
whenever(SubscriptionUtil.isSimHardwareVisible(context)).thenReturn(true)
mockSubscriptionRepository.stub {
on { phoneNumberFlow(SUB_ID) } doReturn flowOf(null)
}
@@ -86,7 +101,6 @@ class MobileNetworkPhoneNumberPreferenceControllerTest {
@Test
fun onViewCreated_canGetPhoneNumber_displayPhoneNumber() = runBlocking {
whenever(SubscriptionUtil.isSimHardwareVisible(context)).thenReturn(true)
mockSubscriptionRepository.stub {
on { phoneNumberFlow(SUB_ID) } doReturn flowOf(PHONE_NUMBER)
}
@@ -98,11 +112,35 @@ class MobileNetworkPhoneNumberPreferenceControllerTest {
}
@Test
fun getAvailabilityStatus_notSimHardwareVisible() {
fun getAvailabilityStatus_simHardwareVisible_userAdmin_notWifiOnly_displayed() {
// Use defaults from setup()
val availabilityStatus = controller.availabilityStatus
assertThat(availabilityStatus).isEqualTo(BasePreferenceController.AVAILABLE)
}
@Test
fun getAvailabilityStatus_notSimHardwareVisible_userAdmin_notWifiOnly_notDisplayed() {
whenever(SubscriptionUtil.isSimHardwareVisible(context)).thenReturn(false)
val availabilityStatus = controller.availabilityStatus
assertThat(availabilityStatus).isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE)
}
@Test
fun getAvailabilityStatus_simHardwareVisible_notUserAdmin_notWifiOnly_notDisplayed() {
mockUserManager.stub {
on { isAdminUser } doReturn false
}
val availabilityStatus = controller.availabilityStatus
assertThat(availabilityStatus).isEqualTo(BasePreferenceController.DISABLED_FOR_USER)
}
@Test
fun getAvailabilityStatus_simHardwareVisible_userAdmin_wifiOnly_notDisplayed() {
whenever(Utils.isWifiOnly(context)).thenReturn(true)
val availabilityStatus = controller.availabilityStatus
assertThat(availabilityStatus).isEqualTo(BasePreferenceController.CONDITIONALLY_UNAVAILABLE)
}

View File

@@ -28,14 +28,12 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.AppOpsManager;
import android.app.Flags;
import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.RequiresFlagsDisabled;
import android.platform.test.flag.junit.CheckFlagsRule;
import android.platform.test.flag.junit.DeviceFlagsValueProvider;
@@ -50,7 +48,6 @@ import com.android.settingslib.RestrictedSwitchPreference;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -188,7 +185,6 @@ public class ApprovalPreferenceControllerTest {
}
@Test
@EnableFlags(Flags.FLAG_MODES_API)
public void disable() {
when(mNm.isNotificationPolicyAccessGrantedForPackage(anyString())).thenReturn(false);
mController.disable(mCn);

View File

@@ -22,6 +22,8 @@ import static com.android.settings.connecteddevice.display.ExternalDisplayPrefer
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_SETTINGS_RESOURCE;
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.EXTERNAL_DISPLAY_SIZE_SUMMARY_RESOURCE;
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.PREVIOUSLY_SHOWN_LIST_KEY;
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.displayListDisplayCategoryKey;
import static com.android.settings.connecteddevice.display.ExternalDisplayPreferenceFragment.resolutionRotationPreferenceKey;
import static com.android.settings.flags.Flags.FLAG_DISPLAY_SIZE_CONNECTED_DISPLAY_SETTING;
import static com.android.settings.flags.Flags.FLAG_DISPLAY_TOPOLOGY_PANE_IN_DISPLAY_LIST;
import static com.android.settingslib.widget.FooterPreference.KEY_FOOTER;
@@ -79,6 +81,19 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa
assertThat(mPreferenceIdFromResource).isEqualTo(EXTERNAL_DISPLAY_SETTINGS_RESOURCE);
}
private void assertDisplayList(boolean present, int displayId) {
// In display list fragment, there is a combined resolution/rotation preference key.
var category = mPreferenceScreen.findPreference(displayListDisplayCategoryKey(displayId));
var pref = mPreferenceScreen.findPreference(resolutionRotationPreferenceKey(displayId));
if (present) {
assertThat(category).isNotNull();
assertThat(pref).isNotNull();
} else {
assertThat(category).isNull();
assertThat(pref).isNull();
}
}
@Test
@UiThreadTest
public void testShowDisplayList() {
@@ -89,19 +104,26 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa
fragment.onSaveInstanceStateCallback(outState);
assertThat(outState.getBoolean(PREVIOUSLY_SHOWN_LIST_KEY)).isFalse();
assertThat(mHandler.getPendingMessages().size()).isEqualTo(1);
PreferenceCategory pref = mPreferenceScreen.findPreference(PrefBasics.DISPLAYS_LIST.key);
assertThat(pref).isNull();
// Combined resolution/refresh rate are not available in displays list because the pane is
// disabled (v1 UI).
assertDisplayList(false, EXTERNAL_DISPLAY_ID);
assertDisplayList(false, OVERLAY_DISPLAY_ID);
// Individual resolution preference is not available in displays list.
assertThat(mPreferenceScreen.<Preference>findPreference(
PrefBasics.EXTERNAL_DISPLAY_RESOLUTION.key))
.isNull();
verify(mMockedInjector, never()).getAllDisplays();
mHandler.flush();
assertThat(mHandler.getPendingMessages().size()).isEqualTo(0);
verify(mMockedInjector).getAllDisplays();
pref = mPreferenceScreen.findPreference(PrefBasics.DISPLAYS_LIST.key);
assertThat(pref).isNotNull();
assertThat(pref.getPreferenceCount()).isEqualTo(2);
assertDisplayList(true, EXTERNAL_DISPLAY_ID);
assertDisplayList(true, OVERLAY_DISPLAY_ID);
fragment.onSaveInstanceStateCallback(outState);
assertThat(outState.getBoolean(PREVIOUSLY_SHOWN_LIST_KEY)).isTrue();
pref = mPreferenceScreen.findPreference(PrefBasics.DISPLAY_TOPOLOGY.key);
Preference pref = mPreferenceScreen.findPreference(PrefBasics.DISPLAY_TOPOLOGY.key);
assertThat(pref).isNull();
pref = mPreferenceScreen.findPreference(PrefBasics.BUILTIN_DISPLAY_LIST.key);
@@ -122,8 +144,7 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa
pref = mPreferenceScreen.findPreference(PrefBasics.MIRROR.key);
assertThat(pref).isNotNull();
pref = mPreferenceScreen.findPreference(PrefBasics.DISPLAYS_LIST.key);
assertThat(pref).isNull();
assertDisplayList(false, mDisplays[1].getDisplayId());
PreferenceCategory listPref =
mPreferenceScreen.findPreference(PrefBasics.BUILTIN_DISPLAY_LIST.key);
@@ -148,11 +169,10 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa
pref = mPreferenceScreen.findPreference(PrefBasics.MIRROR.key);
assertThat(pref).isNull();
PreferenceCategory listPref =
mPreferenceScreen.findPreference(PrefBasics.DISPLAYS_LIST.key);
assertThat(listPref).isNull();
assertDisplayList(false, EXTERNAL_DISPLAY_ID);
assertDisplayList(false, OVERLAY_DISPLAY_ID);
listPref = mPreferenceScreen.findPreference(PrefBasics.BUILTIN_DISPLAY_LIST.key);
var listPref = mPreferenceScreen.findPreference(PrefBasics.BUILTIN_DISPLAY_LIST.key);
assertThat(listPref).isNull();
}
@@ -161,19 +181,23 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa
public void testLaunchDisplaySettingFromList() {
initFragment();
mHandler.flush();
PreferenceCategory pref = mPreferenceScreen.findPreference(PrefBasics.DISPLAYS_LIST.key);
assertThat(pref).isNotNull();
var display1Category = (PreferenceCategory) pref.getPreference(0);
assertDisplayList(true, EXTERNAL_DISPLAY_ID);
assertDisplayList(true, OVERLAY_DISPLAY_ID);
PreferenceCategory display1Category = mPreferenceScreen.findPreference(
displayListDisplayCategoryKey(EXTERNAL_DISPLAY_ID));
var display1Pref = (DisplayPreference) display1Category.getPreference(0);
var display2Category = (PreferenceCategory) pref.getPreference(1);
PreferenceCategory display2Category = mPreferenceScreen.findPreference(
displayListDisplayCategoryKey(OVERLAY_DISPLAY_ID));
var display2Pref = (DisplayPreference) display2Category.getPreference(0);
assertThat(display1Pref.getKey()).isEqualTo("display_id_" + 1);
assertThat(display1Pref.getKey()).isEqualTo(
resolutionRotationPreferenceKey(EXTERNAL_DISPLAY_ID));
assertThat("" + display1Category.getTitle()).isEqualTo("HDMI");
assertThat("" + display1Pref.getSummary()).isEqualTo("1920 x 1080");
display1Pref.onPreferenceClick(display1Pref);
assertThat(mDisplayIdArg).isEqualTo(1);
verify(mMockedMetricsLogger).writePreferenceClickMetric(display1Pref);
assertThat(display2Pref.getKey()).isEqualTo("display_id_" + 2);
assertThat(display2Pref.getKey()).isEqualTo(
resolutionRotationPreferenceKey(OVERLAY_DISPLAY_ID));
assertThat("" + display2Category.getTitle()).isEqualTo("Overlay #1");
assertThat("" + display2Pref.getSummary()).isEqualTo("1240 x 780");
display2Pref.onPreferenceClick(display2Pref);
@@ -190,9 +214,12 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa
// Only one display available
doReturn(new Display[] {mDisplays[1]}).when(mMockedInjector).getAllDisplays();
mHandler.flush();
PreferenceCategory pref = mPreferenceScreen.findPreference(PrefBasics.DISPLAYS_LIST.key);
assertThat(pref).isNotNull();
assertThat(pref.getPreferenceCount()).isEqualTo(1);
int attachedId = mDisplays[1].getDisplayId();
assertDisplayList(true, attachedId);
assertThat(mPreferenceScreen.<Preference>findPreference(
resolutionRotationPreferenceKey(attachedId)))
.isNotNull();
assertDisplayList(false, mDisplays[2].getDisplayId());
}
@Test
@@ -205,8 +232,7 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa
// Init
initFragment();
mHandler.flush();
PreferenceCategory list = mPreferenceScreen.findPreference(PrefBasics.DISPLAYS_LIST.key);
assertThat(list).isNull();
assertDisplayList(false, mDisplays[1].getDisplayId());
var pref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_RESOLUTION.key);
assertThat(pref).isNotNull();
pref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_ROTATION.key);
@@ -227,8 +253,8 @@ public class ExternalDisplayPreferenceFragmentTest extends ExternalDisplayTestBa
// Init
initFragment();
mHandler.flush();
PreferenceCategory list = mPreferenceScreen.findPreference(PrefBasics.DISPLAYS_LIST.key);
assertThat(list).isNull();
assertDisplayList(false, mDisplays[1].getDisplayId());
assertDisplayList(false, mDisplays[2].getDisplayId());
var pref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_RESOLUTION.key);
assertThat(pref).isNotNull();
pref = mPreferenceScreen.findPreference(PrefBasics.EXTERNAL_DISPLAY_ROTATION.key);

View File

@@ -49,6 +49,9 @@ import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
public class ExternalDisplayTestBase {
static final int EXTERNAL_DISPLAY_ID = 1;
static final int OVERLAY_DISPLAY_ID = 2;
@Mock
ExternalDisplaySettingsConfiguration.Injector mMockedInjector;
@Mock
@@ -115,7 +118,7 @@ public class ExternalDisplayTestBase {
}
Display createExternalDisplay() throws RemoteException {
int displayId = 1;
int displayId = EXTERNAL_DISPLAY_ID;
var displayInfo = new DisplayInfo();
doReturn(displayInfo).when(mMockedIDisplayManager).getDisplayInfo(displayId);
displayInfo.displayId = displayId;
@@ -134,7 +137,7 @@ public class ExternalDisplayTestBase {
}
Display createOverlayDisplay() throws RemoteException {
int displayId = 2;
int displayId = OVERLAY_DISPLAY_ID;
var displayInfo = new DisplayInfo();
doReturn(displayInfo).when(mMockedIDisplayManager).getDisplayInfo(displayId);
displayInfo.displayId = displayId;

View File

@@ -35,6 +35,7 @@ import androidx.test.annotation.UiThreadTest;
import androidx.test.core.app.ApplicationProvider;
import com.android.internal.app.LocaleStore;
import com.android.settings.R;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.ResourcesUtils;
@@ -82,11 +83,9 @@ public class LocaleDialogFragmentTest {
LocaleDialogFragment.LocaleDialogController.DialogContent dialogContent =
controller.getDialogContent();
assertEquals(ResourcesUtils.getResourcesString(
mContext, "button_label_confirmation_of_system_locale_change"),
assertEquals(R.string.button_label_confirmation_of_system_locale_change,
dialogContent.mPositiveButton);
assertEquals(ResourcesUtils.getResourcesString(mContext, "cancel"),
dialogContent.mNegativeButton);
assertEquals(R.string.cancel, dialogContent.mNegativeButton);
}
@Test
@@ -99,9 +98,8 @@ public class LocaleDialogFragmentTest {
LocaleDialogFragment.LocaleDialogController.DialogContent dialogContent =
controller.getDialogContent();
assertEquals(ResourcesUtils.getResourcesString(mContext, "okay"),
dialogContent.mPositiveButton);
assertTrue(dialogContent.mNegativeButton.isEmpty());
assertEquals(R.string.okay, dialogContent.mPositiveButton);
assertTrue(dialogContent.mNegativeButton == 0);
}
@Test