Merge "Fix lcr icon direction in RTL layout" into main
diff --git a/aconfig/settings_datetime_flag_declarations.aconfig b/aconfig/settings_datetime_flag_declarations.aconfig
index 93d41d6..9951243 100644
--- a/aconfig/settings_datetime_flag_declarations.aconfig
+++ b/aconfig/settings_datetime_flag_declarations.aconfig
@@ -8,12 +8,3 @@
description: "Enable the time feedback feature, a button to launch feedback in Date & Time Settings"
bug: "283239837"
}
-
-flag {
- name: "revamp_toggles"
- # "location" is used by the Android System Time team for feature flags.
- namespace: "location"
- description: "Makes the use location toggle dependent on automatic time zone detection"
- bug: "296835792"
-}
-
diff --git a/res/layout/apn_preference_layout.xml b/res/layout/apn_preference_layout.xml
deleted file mode 100644
index 9b6efe7..0000000
--- a/res/layout/apn_preference_layout.xml
+++ /dev/null
@@ -1,76 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 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:minHeight="?android:attr/listPreferredItemHeight"
- android:focusable="false"
- android:gravity="center_vertical">
-
- <RelativeLayout
- android:id="@+id/text_layout"
- android:layout_width="0dip"
- android:layout_height="wrap_content"
- android:gravity="center_vertical"
- android:layout_weight="1"
- android:focusable="true"
- android:clickable="true"
- android:background="?android:attr/selectableItemBackground">
-
- <TextView
- android:id="@android:id/title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:focusable="false"
- android:labelFor="@id/apn_radio_button_frame"
- android:singleLine="true"
- android:textAppearance="?android:attr/textAppearanceListItem" />
-
- <TextView
- android:id="@android:id/summary"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@android:id/title"
- android:layout_alignStart="@android:id/title"
- android:textAppearance="?android:attr/textAppearanceListItemSecondary"
- android:textColor="?android:attr/textColorSecondary"
- android:focusable="false"
- android:hyphenationFrequency="normalFast"
- android:lineBreakWordStyle="phrase"
- android:maxLines="2" />
-
- </RelativeLayout>
-
- <FrameLayout
- android:id="@+id/apn_radio_button_frame"
- android:layout_width="@dimen/min_tap_target_size"
- android:layout_height="@dimen/min_tap_target_size"
- android:layout_margin="8dp">
-
- <RadioButton
- android:id="@+id/apn_radiobutton"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:clickable="false"
- android:focusable="false" />
- </FrameLayout>
-
-</LinearLayout>
diff --git a/res/layout/battery_chart_graph.xml b/res/layout/battery_chart_graph.xml
index 9e816ed..b84f38a 100644
--- a/res/layout/battery_chart_graph.xml
+++ b/res/layout/battery_chart_graph.xml
@@ -36,8 +36,7 @@
android:id="@+id/battery_chart_group"
android:layout_width="match_parent"
android:layout_height="wrap_content"
- android:orientation="vertical"
- android:alpha="0">
+ android:orientation="vertical">
<com.android.settings.fuelgauge.batteryusage.BatteryChartView
android:id="@+id/daily_battery_chart"
android:layout_width="match_parent"
@@ -53,7 +52,7 @@
android:layout_width="match_parent"
android:layout_height="@dimen/chartview_layout_height"
android:layout_marginBottom="16dp"
- android:visibility="visible"
+ android:visibility="gone"
android:contentDescription="@string/hourly_battery_usage_chart"
android:textAppearance="?android:attr/textAppearanceSmall"
settings:textColor="?android:attr/textColorSecondary" />
diff --git a/res/layout/display_topology_preference.xml b/res/layout/display_topology_preference.xml
index d2e4300..beaf816 100644
--- a/res/layout/display_topology_preference.xml
+++ b/res/layout/display_topology_preference.xml
@@ -16,8 +16,9 @@
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/display_topology_pane_holder"
android:importantForAccessibility="no"
- android:layout_height="160dp"
+ android:layout_height="wrap_content"
android:layout_width="match_parent"
android:paddingHorizontal="@dimen/display_topology_pane_margin"
android:orientation="horizontal">
@@ -27,14 +28,14 @@
android:layout_width="match_parent"
android:src="@drawable/display_topology_background"/>
<FrameLayout
- android:id="@+id/display_topology_container"
+ android:id="@+id/display_topology_pane_content"
android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
+ android:layout_height="match_parent"/>
<TextView
android:id="@+id/topology_hint"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_gravity="top|center_horizontal"
- android:paddingTop="10dp"
- android:text="@string/external_display_topology_hint"/>
+ android:paddingBottom="10dp"
+ android:paddingTop="10dp" />
</FrameLayout>
diff --git a/res/values/attrs.xml b/res/values/attrs.xml
index 200253a..87c3ce9 100644
--- a/res/values/attrs.xml
+++ b/res/values/attrs.xml
@@ -50,8 +50,6 @@
<attr name="android:textAppearance" />
</declare-styleable>
- <attr name="apnPreferenceStyle" format="reference" />
-
<attr name="slicePreferenceStyle" format="reference" />
<attr name="cardPreferenceStyle" format="reference" />
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 8faf62a..89f6d8f 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4514,6 +4514,8 @@
<string name="language_settings">Languages & input</string>
<!-- Title of setting on main settings screen. This item will take the user to the screen to tweak settings related to languages -->
<string name="languages_settings">Languages</string>
+ <!-- Title of setting on main settings screen. This item will take the user to the screen to tweak settings related to language and region-->
+ <string name="language_and_region_settings">Language & region</string>
<!-- Title of setting on main settings screen. This item will take the user to the screen to tweak settings related to keyboards -->
<string name="keyboard_settings">Keyboard</string>
<!-- Text displayed when user has restriction DISALLOW_CONFIG_LOCALE [CHAR LIMIT=NONE]-->
diff --git a/res/values/styles_preference.xml b/res/values/styles_preference.xml
index ec0a747..c7638d3 100644
--- a/res/values/styles_preference.xml
+++ b/res/values/styles_preference.xml
@@ -20,7 +20,6 @@
<resources>
<style name="SettingsPreferenceTheme" parent="@style/PreferenceTheme.SettingsLib">
- <item name="apnPreferenceStyle">@style/ApnPreference</item>
<item name="cardPreferenceStyle">@style/CardPreference</item>
<item name="slicePreferenceStyle">@style/SlicePreference</item>
<item name="seekBarPreferenceStyle">@style/SettingsSeekBarPreference</item>
@@ -32,10 +31,6 @@
<item name="preferenceFragmentCompatStyle">@style/SetupWizardPreferenceFragmentStyle</item>
</style>
- <style name="ApnPreference" parent="@style/Preference.Material">
- <item name="android:layout">@layout/apn_preference_layout</item>
- </style>
-
<style name="CardPreference" parent="@style/Preference.Material">
<item name="android:layout">@layout/card_preference_layout</item>
</style>
diff --git a/res/values/styles_preference_expressive.xml b/res/values/styles_preference_expressive.xml
index a6fe2f1..278fe00 100644
--- a/res/values/styles_preference_expressive.xml
+++ b/res/values/styles_preference_expressive.xml
@@ -20,7 +20,6 @@
<resources>
<style name="SettingsPreferenceTheme.Expressive" parent="@style/PreferenceTheme.SettingsLib.Expressive">
- <item name="apnPreferenceStyle">@style/ApnPreference</item>
<item name="cardPreferenceStyle">@style/CardPreference</item>
<item name="slicePreferenceStyle">@style/SlicePreference</item>
<item name="seekBarPreferenceStyle">@style/SettingsSeekBarPreference</item>
diff --git a/res/xml/connected_devices_advanced.xml b/res/xml/connected_devices_advanced.xml
index 779555b..f491055 100644
--- a/res/xml/connected_devices_advanced.xml
+++ b/res/xml/connected_devices_advanced.xml
@@ -42,7 +42,7 @@
android:order="-7"
android:title="@string/nfc_quick_toggle_title"
settings:controller="com.android.settings.connecteddevice.NfcAndPaymentFragmentController"
- settings:searchable="false"
+ settings:searchable="true"
settings:useAdminDisabledSummary="true"
settings:userRestriction="no_near_field_communication_radio" />
diff --git a/res/xml/date_time_prefs.xml b/res/xml/date_time_prefs.xml
index d8643be..fe0fd7e 100644
--- a/res/xml/date_time_prefs.xml
+++ b/res/xml/date_time_prefs.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2008 The Android Open Source Project
+<!-- Copyright (C) 2024 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -94,10 +94,6 @@
android:key="time_format_preference_category"
android:title="@string/time_format_category_title"
settings:keywords="@string/keywords_time_format">
- <SwitchPreferenceCompat
- android:key="auto_24hour"
- android:title="@string/date_time_24hour_auto"
- settings:controller="com.android.settings.datetime.AutoTimeFormatPreferenceController" />
<SwitchPreferenceCompat
android:key="24 hour"
diff --git a/res/xml/date_time_prefs_revamped.xml b/res/xml/date_time_prefs_revamped.xml
deleted file mode 100644
index fe0fd7e..0000000
--- a/res/xml/date_time_prefs_revamped.xml
+++ /dev/null
@@ -1,104 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2024 The Android Open Source Project
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
--->
-
-<PreferenceScreen
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:settings="http://schemas.android.com/apk/res-auto"
- android:title="@string/date_and_time"
- settings:keywords="@string/keywords_date_and_time">
-
- <com.android.settingslib.RestrictedSwitchPreference
- android:key="auto_time"
- android:title="@string/date_time_auto"
- android:summary="@string/summary_placeholder"
- settings:userRestriction="no_config_date_time"
- settings:controller="com.android.settings.datetime.AutoTimePreferenceController" />
-
- <com.android.settingslib.RestrictedPreference
- android:key="date"
- android:title="@string/date_time_set_date_title"
- android:summary="@string/summary_placeholder"
- settings:userRestriction="no_config_date_time"
- settings:controller="com.android.settings.datetime.DatePreferenceController" />
-
- <com.android.settingslib.RestrictedPreference
- android:key="time"
- android:title="@string/date_time_set_time_title"
- android:summary="@string/summary_placeholder"
- settings:userRestriction="no_config_date_time"
- settings:controller="com.android.settings.datetime.TimePreferenceController" />
-
- <PreferenceCategory
- android:key="timezone_preference_category"
- android:title="@string/date_time_set_timezone_title">
-
- <com.android.settingslib.RestrictedSwitchPreference
- android:key="auto_zone"
- android:title="@string/zone_auto_title"
- android:summary="@string/summary_placeholder"
- settings:userRestriction="no_config_date_time"
- settings:controller="com.android.settings.datetime.AutoTimeZonePreferenceController" />
-
- <com.android.settingslib.widget.BannerMessagePreference
- android:key="location_time_zone_detection_status"
- android:title="@string/location_time_zone_detection_status_title"
- settings:controller="com.android.settings.datetime.LocationProviderStatusPreferenceController"/>
-
- <!-- This preference gets removed if location-based time zone detection is not supported -->
- <SwitchPreferenceCompat
- android:key="location_time_zone_detection"
- android:title="@string/location_time_zone_detection_toggle_title"
- android:summary="@string/summary_placeholder"
- settings:controller="com.android.settings.datetime.LocationTimeZoneDetectionPreferenceController"/>
-
- <com.android.settingslib.RestrictedPreference
- android:key="timezone"
- android:title="@string/date_time_set_timezone_title"
- android:summary="@string/summary_placeholder"
- android:fragment="com.android.settings.datetime.timezone.TimeZoneSettings"
- settings:userRestriction="no_config_date_time"
- settings:keywords="@string/keywords_time_zone"
- settings:controller="com.android.settings.datetime.TimeZonePreferenceController" />
-
- </PreferenceCategory>
-
- <!-- An optional preference category for feedback. Only displayed up if enabled via flags and config. -->
- <PreferenceCategory
- android:key="time_feedback_preference_category"
- android:title="@string/time_feedback_category_title"
- settings:keywords="@string/keywords_time_feedback_category"
- settings:controller="com.android.settings.datetime.TimeFeedbackPreferenceCategoryController">
-
- <Preference
- android:key="time_feedback"
- android:title="@string/time_feedback_title"
- settings:keywords="@string/keywords_time_feedback"
- settings:controller="com.android.settings.datetime.TimeFeedbackPreferenceController" />
-
- </PreferenceCategory>
-
- <PreferenceCategory
- android:key="time_format_preference_category"
- android:title="@string/time_format_category_title"
- settings:keywords="@string/keywords_time_format">
-
- <SwitchPreferenceCompat
- android:key="24 hour"
- android:title="@string/date_time_24hour"
- settings:controller="com.android.settings.datetime.TimeFormatPreferenceController" />
- </PreferenceCategory>
-
-</PreferenceScreen>
diff --git a/res/xml/language_and_region_settings.xml b/res/xml/language_and_region_settings.xml
new file mode 100644
index 0000000..5626f22
--- /dev/null
+++ b/res/xml/language_and_region_settings.xml
@@ -0,0 +1,127 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2024 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:title="@string/language_and_region_settings"
+ android:key="language_and_region_settings">
+ <PreferenceCategory
+ android:key="languages_category"
+ android:title="@string/locale_picker_category_title">
+ <Preference
+ android:key="phone_language"
+ android:title="@string/system_language"
+ android:fragment="com.android.settings.localepicker.LocaleListEditor"
+ settings:controller="com.android.settings.language.PhoneLanguagePreferenceController" />
+ </PreferenceCategory>
+
+ <PreferenceCategory
+ android:key="more_language_settings_category"
+ android:title="@string/more_language_settings_category"
+ settings:controller="com.android.settings.language.MoreLanguagesSettingsCategoryController">
+ <Preference
+ android:key="apps_language_in_more_language_settings"
+ android:title="@string/app_locales_picker_menu_title"
+ android:summary="@string/app_locale_picker_summary"
+ android:fragment="com.android.settings.applications.manageapplications.ManageApplications"
+ settings:controller="com.android.settings.applications.appinfo.NewAppsLocalePreferenceController">
+ <extra
+ android:name="classname"
+ android:value="com.android.settings.applications.appinfo.AppLocaleDetails" />
+ </Preference>
+ </PreferenceCategory>
+
+ <PreferenceCategory
+ android:key="regional_preferences_category"
+ android:title="@string/regional_preferences_category_title"
+ settings:controller="com.android.settings.regionalpreferences.RegionalPreferencesCategoryController">
+
+ <Preference
+ android:key="temperature_preference"
+ android:title="@string/temperature_preferences_title"
+ android:summary="@string/default_string_of_regional_preference"
+ settings:controller="com.android.settings.regionalpreferences.NewTemperatureUnitController"
+ settings:fragment="com.android.settings.regionalpreferences.TemperatureUnitFragment">
+ <extra
+ android:name="arg_key_regional_preference"
+ android:value="mu"/>
+ </Preference>
+
+ <Preference
+ android:key="key_measurement_system"
+ android:title="@string/measurement_system_preferences_title"
+ android:summary="@string/default_string_of_regional_preference"
+ settings:controller="com.android.settings.regionalpreferences.MeasurementSystemController"
+ settings:fragment="com.android.settings.regionalpreferences.MeasurementSystemItemFragment">
+ <extra
+ android:name="arg_key_regional_preference"
+ android:value="ms"/>
+ </Preference>
+
+ <Preference
+ android:key="first_day_of_week_preference"
+ android:title="@string/first_day_of_week_preferences_title"
+ android:summary="@string/default_string_of_regional_preference"
+ settings:controller="com.android.settings.regionalpreferences.NewFirstDayOfWeekController"
+ settings:fragment="com.android.settings.regionalpreferences.FirstDayOfWeekItemFragment">
+ <extra
+ android:name="arg_key_regional_preference"
+ android:value="fw"/>
+ </Preference>
+
+ <Preference
+ android:key="numbering_system_preference"
+ android:title="@string/numbers_preferences_title"
+ android:summary="@string/default_string_of_regional_preference"
+ settings:controller="com.android.settings.regionalpreferences.NewNumberingSystemController"
+ settings:fragment="com.android.settings.regionalpreferences.NumberingPreferencesFragment">
+ <extra
+ android:name="arg_key_regional_preference"
+ android:value="arg_value_language_select"/>
+ </Preference>
+ </PreferenceCategory>
+
+ <PreferenceCategory
+ android:key="speech_category"
+ android:title="@string/speech_category_title">
+ <com.android.settings.widget.GearPreference
+ android:key="voice_input_settings"
+ android:title="@string/voice_input_settings_title"
+ android:fragment="com.android.settings.language.DefaultVoiceInputPicker" />
+
+ <Preference
+ android:key="on_device_recognition_settings"
+ android:title="@string/on_device_recognition_settings_title"
+ android:summary="@string/on_device_recognition_settings_summary"
+ settings:controller=
+ "com.android.settings.language.OnDeviceRecognitionPreferenceController" />
+
+ <Preference
+ android:key="tts_settings_summary"
+ android:title="@string/tts_settings_title"
+ android:fragment="com.android.settings.tts.TextToSpeechSettings"
+ settings:searchable="false"/>
+ </PreferenceCategory>
+
+ <com.android.settingslib.widget.FooterPreference
+ android:key="new_regional_pref_footer"
+ android:title="@string/title_regional_pref_footer"
+ android:selectable="false"
+ settings:searchable="false"
+ settings:controller="com.android.settings.regionalpreferences.NewRegionalFooterPreferenceController"/>
+</PreferenceScreen>
diff --git a/res/xml/language_settings.xml b/res/xml/language_settings.xml
index 44a195c..eccbbc1 100644
--- a/res/xml/language_settings.xml
+++ b/res/xml/language_settings.xml
@@ -50,72 +50,6 @@
</PreferenceCategory>
<PreferenceCategory
- android:key="more_language_settings_category"
- android:title="@string/more_language_settings_category"
- settings:controller="com.android.settings.language.MoreLanguagesSettingsCategoryController">
- <Preference
- android:key="apps_language_in_more_language_settings"
- android:title="@string/app_locales_picker_menu_title"
- android:summary="@string/app_locale_picker_summary"
- android:fragment="com.android.settings.applications.manageapplications.ManageApplications"
- settings:controller="com.android.settings.applications.appinfo.NewAppsLocalePreferenceController">
- <extra
- android:name="classname"
- android:value="com.android.settings.applications.appinfo.AppLocaleDetails" />
- </Preference>
- </PreferenceCategory>
-
- <PreferenceCategory
- android:key="regional_preferences_category"
- android:title="@string/regional_preferences_category_title"
- settings:controller="com.android.settings.regionalpreferences.RegionalPreferencesCategoryController">
-
- <Preference
- android:key="temperature_preference"
- android:title="@string/temperature_preferences_title"
- android:summary="@string/default_string_of_regional_preference"
- settings:controller="com.android.settings.regionalpreferences.NewTemperatureUnitController"
- settings:fragment="com.android.settings.regionalpreferences.TemperatureUnitFragment">
- <extra
- android:name="arg_key_regional_preference"
- android:value="mu"/>
- </Preference>
-
- <Preference
- android:key="key_measurement_system"
- android:title="@string/measurement_system_preferences_title"
- android:summary="@string/default_string_of_regional_preference"
- settings:controller="com.android.settings.regionalpreferences.MeasurementSystemController"
- settings:fragment="com.android.settings.regionalpreferences.MeasurementSystemItemFragment">
- <extra
- android:name="arg_key_regional_preference"
- android:value="ms"/>
- </Preference>
-
- <Preference
- android:key="first_day_of_week_preference"
- android:title="@string/first_day_of_week_preferences_title"
- android:summary="@string/default_string_of_regional_preference"
- settings:controller="com.android.settings.regionalpreferences.NewFirstDayOfWeekController"
- settings:fragment="com.android.settings.regionalpreferences.FirstDayOfWeekItemFragment">
- <extra
- android:name="arg_key_regional_preference"
- android:value="fw"/>
- </Preference>
-
- <Preference
- android:key="numbering_system_preference"
- android:title="@string/numbers_preferences_title"
- android:summary="@string/default_string_of_regional_preference"
- settings:controller="com.android.settings.regionalpreferences.NewNumberingSystemController"
- settings:fragment="com.android.settings.regionalpreferences.NumberingPreferencesFragment">
- <extra
- android:name="arg_key_regional_preference"
- android:value="arg_value_language_select"/>
- </Preference>
- </PreferenceCategory>
-
- <PreferenceCategory
android:key="speech_category"
android:title="@string/speech_category_title">
<com.android.settings.widget.GearPreference
@@ -136,11 +70,4 @@
android:fragment="com.android.settings.tts.TextToSpeechSettings"
settings:searchable="false"/>
</PreferenceCategory>
-
- <com.android.settingslib.widget.FooterPreference
- android:key="new_regional_pref_footer"
- android:title="@string/title_regional_pref_footer"
- android:selectable="false"
- settings:searchable="false"
- settings:controller="com.android.settings.regionalpreferences.NewRegionalFooterPreferenceController"/>
</PreferenceScreen>
diff --git a/res/xml/system_dashboard_fragment.xml b/res/xml/system_dashboard_fragment.xml
index 9c7f001..a9d7444 100644
--- a/res/xml/system_dashboard_fragment.xml
+++ b/res/xml/system_dashboard_fragment.xml
@@ -30,6 +30,15 @@
settings:controller="com.android.settings.language.LanguagePreferenceController"/>
<Preference
+ android:key="language_and_region_settings"
+ android:title="@string/language_and_region_settings"
+ android:summary="@string/languages_setting_summary"
+ android:icon="@drawable/ic_settings_languages"
+ android:order="-260"
+ android:fragment="com.android.settings.language.LanguageAndRegionSettings"
+ settings:controller="com.android.settings.language.LanguageAndRegionPreferenceController"/>
+
+ <Preference
android:key="Keyboard_settings"
android:title="@string/keyboard_settings"
android:icon="@drawable/ic_settings_keyboards"
diff --git a/src/com/android/settings/accessibility/AccessibilityHearingAidsFragment.java b/src/com/android/settings/accessibility/AccessibilityHearingAidsFragment.java
index 09e2d97..3bda864 100644
--- a/src/com/android/settings/accessibility/AccessibilityHearingAidsFragment.java
+++ b/src/com/android/settings/accessibility/AccessibilityHearingAidsFragment.java
@@ -97,17 +97,6 @@
}
@Override
- protected ComponentName getTileComponentName() {
- return AccessibilityShortcutController.ACCESSIBILITY_HEARING_AIDS_TILE_COMPONENT_NAME;
- }
-
- @Override
- protected CharSequence getTileTooltipContent(int type) {
- // No tooltip to be shown
- return null;
- }
-
- @Override
protected boolean showGeneralCategory() {
// Have static preference under dynamically created PreferenceCategory KEY_GENERAL_CATEGORY.
// In order to modify that, we need to use our own PreferenceCategory for this page.
diff --git a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java
index 23c3fd4..2a22902 100644
--- a/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragment.java
@@ -20,10 +20,8 @@
import static com.android.settings.accessibility.AccessibilityDialogUtils.DialogEnums;
import static com.android.settings.accessibility.AccessibilityUtil.getShortcutSummaryList;
import static com.android.settings.accessibility.ToggleFeaturePreferenceFragment.KEY_GENERAL_CATEGORY;
-import static com.android.settings.accessibility.ToggleFeaturePreferenceFragment.KEY_SAVED_QS_TOOLTIP_TYPE;
import android.annotation.SuppressLint;
-import android.app.Activity;
import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.content.ComponentName;
@@ -44,7 +42,6 @@
import com.android.internal.accessibility.common.ShortcutConstants;
import com.android.settings.R;
-import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType;
import com.android.settings.accessibility.shortcuts.EditShortcutsPreferenceFragment;
import com.android.settings.dashboard.RestrictedDashboardFragment;
@@ -60,16 +57,12 @@
public abstract class AccessibilityShortcutPreferenceFragment extends RestrictedDashboardFragment
implements ShortcutPreference.OnClickCallback {
private static final String KEY_SHORTCUT_PREFERENCE = "shortcut_preference";
- protected static final String KEY_SAVED_QS_TOOLTIP_RESHOW = "qs_tooltip_reshow";
protected ShortcutPreference mShortcutPreference;
protected Dialog mDialog;
private AccessibilityManager.TouchExplorationStateChangeListener
mTouchExplorationStateChangeListener;
private AccessibilitySettingsContentObserver mSettingsContentObserver;
- private AccessibilityQuickSettingsTooltipWindow mTooltipWindow;
- private boolean mNeedsQSTooltipReshow = false;
- private int mNeedsQSTooltipType = QuickSettingsTooltipType.GUIDE_TO_EDIT;
public AccessibilityShortcutPreferenceFragment(String restrictionKey) {
super(restrictionKey);
@@ -81,26 +74,10 @@
/** Returns the accessibility feature name. */
protected abstract CharSequence getLabelName();
- /** Returns the accessibility tile component name. */
- protected abstract ComponentName getTileComponentName();
-
- /** Returns the accessibility tile tooltip content. */
- protected abstract CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type);
-
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- // Restore the user shortcut type and tooltip.
- if (savedInstanceState != null) {
- if (savedInstanceState.containsKey(KEY_SAVED_QS_TOOLTIP_RESHOW)) {
- mNeedsQSTooltipReshow = savedInstanceState.getBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW);
- }
- if (savedInstanceState.containsKey(KEY_SAVED_QS_TOOLTIP_TYPE)) {
- mNeedsQSTooltipType = savedInstanceState.getInt(KEY_SAVED_QS_TOOLTIP_TYPE);
- }
- }
-
final int resId = getPreferenceScreenResId();
if (resId <= 0) {
final PreferenceScreen preferenceScreen = getPreferenceManager().createPreferenceScreen(
@@ -142,21 +119,6 @@
}
@Override
- public void onViewCreated(View view, Bundle savedInstanceState) {
- super.onViewCreated(view, savedInstanceState);
-
- // Reshow tooltip when activity recreate, such as rotate device.
- if (mNeedsQSTooltipReshow) {
- view.post(() -> {
- final Activity activity = getActivity();
- if (activity != null && !activity.isFinishing()) {
- showQuickSettingsTooltipIfNeeded();
- }
- });
- }
- }
-
- @Override
public void onResume() {
super.onResume();
@@ -178,16 +140,6 @@
}
@Override
- public void onSaveInstanceState(Bundle outState) {
- final boolean isTooltipWindowShowing = mTooltipWindow != null && mTooltipWindow.isShowing();
- if (mNeedsQSTooltipReshow || isTooltipWindowShowing) {
- outState.putBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW, /* value= */ true);
- outState.putInt(KEY_SAVED_QS_TOOLTIP_TYPE, mNeedsQSTooltipType);
- }
- super.onSaveInstanceState(outState);
- }
-
- @Override
public Dialog onCreateDialog(int dialogId) {
switch (dialogId) {
case DialogEnums.LAUNCH_ACCESSIBILITY_TUTORIAL:
@@ -289,7 +241,6 @@
*/
private void callOnTutorialDialogButtonClicked(DialogInterface dialog, int which) {
dialog.dismiss();
- showQuickSettingsTooltipIfNeeded();
}
@VisibleForTesting
@@ -363,26 +314,6 @@
}
/**
- * Shows the quick settings tooltip if the quick settings feature is assigned. The tooltip only
- * shows once.
- *
- * @param type The quick settings tooltip type
- */
- protected void showQuickSettingsTooltipIfNeeded(@QuickSettingsTooltipType int type) {
- mNeedsQSTooltipType = type;
- showQuickSettingsTooltipIfNeeded();
- }
-
- /**
- * @deprecated made obsolete by quick settings rollout.
- *
- * (TODO 367414968: finish removal.)
- */
- @Deprecated
- private void showQuickSettingsTooltipIfNeeded() {
- }
-
- /**
* Returns the user preferred shortcut types or the default shortcut types if not set
*/
@ShortcutConstants.UserShortcutType
diff --git a/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java b/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java
index e49078b..f729cc7 100644
--- a/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/LaunchAccessibilityActivityPreferenceFragment.java
@@ -72,11 +72,6 @@
}
@Override
- protected void onPreferenceToggled(String preferenceKey, boolean enabled) {
- // Do nothing.
- }
-
- @Override
protected void onProcessArguments(Bundle arguments) {
super.onProcessArguments(arguments);
mComponentName = arguments.getParcelable(AccessibilitySettings.EXTRA_COMPONENT_NAME);
diff --git a/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java
index e286225..b779f9d 100644
--- a/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleColorInversionPreferenceFragment.java
@@ -107,10 +107,6 @@
if (enabled == isEnabled) {
return;
}
-
- if (enabled) {
- showQuickSettingsTooltipIfNeeded(QuickSettingsTooltipType.GUIDE_TO_DIRECT_USE);
- }
logAccessibilityServiceEnabled(mComponentName, enabled);
Settings.Secure.putInt(getContentResolver(), ENABLED, enabled ? ON : OFF);
}
diff --git a/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java
index 5b2df5a..fe51e69 100644
--- a/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleDaltonizerPreferenceFragment.java
@@ -158,10 +158,6 @@
if (enabled == isEnabled) {
return;
}
-
- if (enabled) {
- showQuickSettingsTooltipIfNeeded(QuickSettingsTooltipType.GUIDE_TO_DIRECT_USE);
- }
logAccessibilityServiceEnabled(mComponentName, enabled);
Settings.Secure.putInt(getContentResolver(), ENABLED, enabled ? ON : OFF);
}
diff --git a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
index 65a1cd4..49f22bf 100644
--- a/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragment.java
@@ -21,7 +21,6 @@
import static com.android.settings.accessibility.AccessibilityDialogUtils.DialogEnums;
import static com.android.settings.accessibility.AccessibilityUtil.getShortcutSummaryList;
-import android.app.Activity;
import android.app.Dialog;
import android.app.settings.SettingsEnums;
import android.content.ComponentName;
@@ -85,8 +84,6 @@
public static final String KEY_SHORTCUT_PREFERENCE = "shortcut_preference";
protected static final String KEY_TOP_INTRO_PREFERENCE = "top_intro";
protected static final String KEY_HTML_DESCRIPTION_PREFERENCE = "html_description";
- protected static final String KEY_SAVED_QS_TOOLTIP_RESHOW = "qs_tooltip_reshow";
- protected static final String KEY_SAVED_QS_TOOLTIP_TYPE = "qs_tooltip_type";
protected static final String KEY_ANIMATED_IMAGE = "animated_image";
// For html description of accessibility service, must follow the rule, such as
// <img src="R.drawable.fileName"/>, a11y settings will get the resources successfully.
@@ -112,10 +109,6 @@
private CharSequence mDescription;
private TouchExplorationStateChangeListener mTouchExplorationStateChangeListener;
private AccessibilitySettingsContentObserver mSettingsContentObserver;
-
- private AccessibilityQuickSettingsTooltipWindow mTooltipWindow;
- private boolean mNeedsQSTooltipReshow = false;
- private int mNeedsQSTooltipType = QuickSettingsTooltipType.GUIDE_TO_EDIT;
private ImageView mImageGetterCacheView;
protected final Html.ImageGetter mImageGetter = (String str) -> {
if (str != null && str.startsWith(IMG_PREFIX)) {
@@ -133,16 +126,6 @@
super.onCreate(savedInstanceState);
onProcessArguments(getArguments());
- // Restore the user shortcut type and tooltip.
- if (savedInstanceState != null) {
- if (savedInstanceState.containsKey(KEY_SAVED_QS_TOOLTIP_RESHOW)) {
- mNeedsQSTooltipReshow = savedInstanceState.getBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW);
- }
- if (savedInstanceState.containsKey(KEY_SAVED_QS_TOOLTIP_TYPE)) {
- mNeedsQSTooltipType = savedInstanceState.getInt(KEY_SAVED_QS_TOOLTIP_TYPE);
- }
- }
-
final int resId = getPreferenceScreenResId();
if (resId <= 0) {
final PreferenceScreen preferenceScreen = getPreferenceManager().createPreferenceScreen(
@@ -227,16 +210,6 @@
final SettingsMainSwitchBar switchBar = settingsActivity.getSwitchBar();
switchBar.hide();
- // Reshow tooltip when activity recreate, such as rotate device.
- if (mNeedsQSTooltipReshow) {
- view.post(() -> {
- final Activity activity = getActivity();
- if (activity != null && !activity.isFinishing()) {
- showQuickSettingsTooltipIfNeeded();
- }
- });
- }
-
writeConfigDefaultAccessibilityServiceIntoShortcutTargetServiceIfNeeded(getContext());
}
@@ -262,23 +235,9 @@
}
@Override
- public void onSaveInstanceState(Bundle outState) {
- final boolean isTooltipWindowShowing = mTooltipWindow != null && mTooltipWindow.isShowing();
- if (mNeedsQSTooltipReshow || isTooltipWindowShowing) {
- outState.putBoolean(KEY_SAVED_QS_TOOLTIP_RESHOW, /* value= */ true);
- outState.putInt(KEY_SAVED_QS_TOOLTIP_TYPE, mNeedsQSTooltipType);
- }
- super.onSaveInstanceState(outState);
- }
-
- @Override
public void onDestroyView() {
super.onDestroyView();
removeActionBarToggleSwitch();
- final boolean isTooltipWindowShowing = mTooltipWindow != null && mTooltipWindow.isShowing();
- if (isTooltipWindowShowing) {
- mTooltipWindow.dismiss();
- }
}
@Override
@@ -314,7 +273,12 @@
/** Returns the accessibility tile component name. */
abstract ComponentName getTileComponentName();
- /** Returns the accessibility tile tooltip content. */
+ /** Returns the accessibility tile component name.
+ *
+ * @deprecated unused, as this class no longer displays tile tooltips.
+ *
+ * (TODO 367414968: finish removal.)*/
+ @Deprecated
abstract CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type);
protected void updateToggleServiceTitle(SettingsMainSwitchPreference switchPreference) {
@@ -332,9 +296,6 @@
}
protected void onPreferenceToggled(String preferenceKey, boolean enabled) {
- if (enabled) {
- showQuickSettingsTooltipIfNeeded();
- }
}
protected void onInstallSwitchPreferenceToggleSwitch() {
@@ -646,7 +607,6 @@
*/
private void callOnTutorialDialogButtonClicked(DialogInterface dialog, int which) {
dialog.dismiss();
- showQuickSettingsTooltipIfNeeded();
}
protected void updateShortcutPreferenceData() {
@@ -737,26 +697,6 @@
}
}
- /**
- * Shows the quick settings tooltip if the quick settings feature is assigned. The tooltip only
- * shows once.
- *
- * @param type The quick settings tooltip type
- */
- protected void showQuickSettingsTooltipIfNeeded(@QuickSettingsTooltipType int type) {
- mNeedsQSTooltipType = type;
- showQuickSettingsTooltipIfNeeded();
- }
-
- /**
- * @deprecated made obsolete by quick settings rollout.
- *
- * (TODO 367414968: finish removal.)
- */
- @Deprecated
- private void showQuickSettingsTooltipIfNeeded() {
- }
-
/** Returns user visible name of the tile by given {@link ComponentName}. */
protected CharSequence loadTileLabel(Context context, ComponentName componentName) {
final PackageManager packageManager = context.getPackageManager();
diff --git a/src/com/android/settings/accessibility/ToggleReduceBrightColorsPreferenceFragment.java b/src/com/android/settings/accessibility/ToggleReduceBrightColorsPreferenceFragment.java
index 16911f6..ff14021 100644
--- a/src/com/android/settings/accessibility/ToggleReduceBrightColorsPreferenceFragment.java
+++ b/src/com/android/settings/accessibility/ToggleReduceBrightColorsPreferenceFragment.java
@@ -149,9 +149,6 @@
@Override
protected void onPreferenceToggled(String preferenceKey, boolean enabled) {
- if (enabled) {
- showQuickSettingsTooltipIfNeeded(QuickSettingsTooltipType.GUIDE_TO_DIRECT_USE);
- }
logAccessibilityServiceEnabled(mComponentName, enabled);
mColorDisplayManager.setReduceBrightColorsActivated(enabled);
}
diff --git a/src/com/android/settings/connecteddevice/display/DisplayTopology.kt b/src/com/android/settings/connecteddevice/display/DisplayTopology.kt
index 76abc03..9cac772 100644
--- a/src/com/android/settings/connecteddevice/display/DisplayTopology.kt
+++ b/src/com/android/settings/connecteddevice/display/DisplayTopology.kt
@@ -16,14 +16,32 @@
package com.android.settings.connecteddevice.display
+import android.app.WallpaperManager
import com.android.settings.R
import android.content.Context
+import android.graphics.Color
import android.graphics.Point
import android.graphics.PointF
import android.graphics.RectF
+import android.graphics.drawable.Drawable
+import android.graphics.drawable.ColorDrawable
+import android.hardware.display.DisplayManager
+import android.hardware.display.DisplayTopology
+import android.hardware.display.DisplayTopology.TreeNode.POSITION_BOTTOM
+import android.hardware.display.DisplayTopology.TreeNode.POSITION_LEFT
+import android.hardware.display.DisplayTopology.TreeNode.POSITION_RIGHT
+import android.hardware.display.DisplayTopology.TreeNode.POSITION_TOP
+import android.util.Log
+import android.view.ViewGroup
+import android.view.ViewTreeObserver
+import android.widget.Button
+import android.widget.FrameLayout
+import android.widget.TextView
+import androidx.annotation.VisibleForTesting
import androidx.preference.Preference
+import androidx.preference.PreferenceViewHolder
import java.util.Locale
@@ -143,11 +161,27 @@
const val PREFERENCE_KEY = "display_topology_preference"
+/** dp of padding on each side of a display block. */
+const val BLOCK_PADDING = 2
+
/**
* DisplayTopologyPreference allows the user to change the display topology
* when there is one or more extended display attached.
*/
-class DisplayTopologyPreference(context : Context) : Preference(context) {
+class DisplayTopologyPreference(context : Context)
+ : Preference(context), ViewTreeObserver.OnGlobalLayoutListener {
+ @VisibleForTesting lateinit var mPaneContent : FrameLayout
+ @VisibleForTesting lateinit var mPaneHolder : FrameLayout
+ @VisibleForTesting lateinit var mTopologyHint : TextView
+
+ @VisibleForTesting var injector : Injector
+
+ /**
+ * This is needed to prevent a repopulation of the pane causing another
+ * relayout and vice-versa ad infinitum.
+ */
+ private var mPaneNeedsRefresh = false
+
init {
layoutResource = R.layout.display_topology_preference
@@ -155,5 +189,108 @@
isSelectable = false
key = PREFERENCE_KEY
+
+ injector = Injector()
+ }
+
+ override fun onBindViewHolder(holder: PreferenceViewHolder) {
+ super.onBindViewHolder(holder)
+
+ val newPane = holder.findViewById(R.id.display_topology_pane_content) as FrameLayout
+ if (this::mPaneContent.isInitialized) {
+ if (newPane == mPaneContent) {
+ return
+ }
+ mPaneContent.viewTreeObserver.removeOnGlobalLayoutListener(this)
+ }
+ mPaneContent = newPane
+ mPaneHolder = holder.itemView as FrameLayout
+ mTopologyHint = holder.findViewById(R.id.topology_hint) as TextView
+ mPaneContent.viewTreeObserver.addOnGlobalLayoutListener(this)
+ }
+
+ override fun onAttached() {
+ // We don't know if topology changes happened when we were detached, as it is impossible to
+ // listen at that time (we must remove listeners when detaching). Setting this flag makes
+ // the following onGlobalLayout call refresh the pane.
+ mPaneNeedsRefresh = true
+ }
+
+ override fun onGlobalLayout() {
+ if (mPaneNeedsRefresh) {
+ mPaneNeedsRefresh = false
+ refreshPane()
+ }
+ }
+
+ open class Injector {
+ open fun displayTopology(context : Context) : DisplayTopology? {
+ val displayManager = context.getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
+ return displayManager.displayTopology
+ }
+
+ open fun wallpaper(context : Context) : Drawable {
+ return WallpaperManager.getInstance(context).drawable ?: ColorDrawable(Color.BLACK)
+ }
+ }
+
+ private fun calcAbsRects(
+ dest : MutableMap<Int, RectF>, n : DisplayTopology.TreeNode, x : Float, y : Float) {
+ dest.put(n.displayId, RectF(x, y, x + n.width, y + n.height))
+
+ for (c in n.children) {
+ val (xoff, yoff) = when (c.position) {
+ POSITION_LEFT -> Pair(-c.width, +c.offset)
+ POSITION_RIGHT -> Pair(+n.width, +c.offset)
+ POSITION_TOP -> Pair(+c.offset, -c.height)
+ POSITION_BOTTOM -> Pair(+c.offset, +n.height)
+ else -> throw IllegalStateException("invalid position for display: ${c}")
+ }
+ calcAbsRects(dest, c, x + xoff, y + yoff)
+ }
+ }
+
+ private fun refreshPane() {
+ mPaneContent.removeAllViews()
+
+ val root = injector.displayTopology(context)?.root
+ if (root == null) {
+ // This occurs when no topology is active.
+ // TODO(b/352648432): show main display or mirrored displays rather than an empty pane.
+ mTopologyHint.text = ""
+ return
+ }
+ mTopologyHint.text = context.getString(R.string.external_display_topology_hint)
+
+ val blocksPos = buildMap { calcAbsRects(this, root, x = 0f, y = 0f) }
+
+ val scaling = TopologyScale(
+ mPaneContent.width, minEdgeLength = 60, maxBlockRatio = 0.12f, blocksPos.values)
+ mPaneHolder.layoutParams.let {
+ if (it.height != scaling.paneHeight) {
+ it.height = scaling.paneHeight
+ mPaneHolder.layoutParams = it
+ }
+ }
+ val wallpaper = injector.wallpaper(context)
+ blocksPos.values.forEach { p ->
+ Button(context).apply {
+ isScrollContainer = false
+ isVerticalScrollBarEnabled = false
+ isHorizontalScrollBarEnabled = false
+ background = wallpaper
+ val topLeft = scaling.displayToPaneCoor(PointF(p.left, p.top))
+ val bottomRight = scaling.displayToPaneCoor(PointF(p.right, p.bottom))
+
+ mPaneContent.addView(this)
+
+ val layout = layoutParams
+ layout.width = bottomRight.x - topLeft.x - BLOCK_PADDING * 2
+ layout.height = bottomRight.y - topLeft.y - BLOCK_PADDING * 2
+ layoutParams = layout
+ x = (topLeft.x + BLOCK_PADDING).toFloat()
+ y = (topLeft.y + BLOCK_PADDING).toFloat()
+ }
+ }
}
}
diff --git a/src/com/android/settings/datetime/AutoTimeFormatPreferenceController.java b/src/com/android/settings/datetime/AutoTimeFormatPreferenceController.java
deleted file mode 100644
index 44e7cc6..0000000
--- a/src/com/android/settings/datetime/AutoTimeFormatPreferenceController.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2017 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.datetime;
-
-import android.content.Context;
-import android.provider.Settings;
-import android.provider.Settings.System;
-import android.text.format.DateFormat;
-
-import com.android.settings.R;
-import com.android.settings.core.TogglePreferenceController;
-
-import java.util.Locale;
-
-public class AutoTimeFormatPreferenceController extends TogglePreferenceController {
-
- public AutoTimeFormatPreferenceController(Context context, String preferenceKey) {
- super(context, preferenceKey);
- }
-
- @Override
- public int getAvailabilityStatus() {
- return AVAILABLE;
- }
-
- @Override
- public boolean isChecked() {
- return isAutoTimeFormatSelection(mContext);
- }
-
- @Override
- public boolean setChecked(boolean isChecked) {
- Boolean is24Hour;
- if (isChecked) {
- is24Hour = null;
- } else {
- is24Hour = is24HourLocale(mContext.getResources().getConfiguration().locale);
- }
- TimeFormatPreferenceController.update24HourFormat(mContext, is24Hour);
- return true;
- }
-
- @Override
- public int getSliceHighlightMenuRes() {
- return R.string.menu_key_system;
- }
-
- boolean is24HourLocale(Locale locale) {
- return DateFormat.is24HourLocale(locale);
- }
-
- /**
- * Returns if the system is currently configured to pick the time format automatically based on
- * the locale.
- */
- static boolean isAutoTimeFormatSelection(Context context) {
- return Settings.System.getString(context.getContentResolver(), System.TIME_12_24) == null;
- }
-}
diff --git a/src/com/android/settings/datetime/AutoTimeZonePreferenceController.java b/src/com/android/settings/datetime/AutoTimeZonePreferenceController.java
index 3d8f801..ecd416d 100644
--- a/src/com/android/settings/datetime/AutoTimeZonePreferenceController.java
+++ b/src/com/android/settings/datetime/AutoTimeZonePreferenceController.java
@@ -32,7 +32,6 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
-import com.android.settings.flags.Flags;
public class AutoTimeZonePreferenceController extends TogglePreferenceController {
@@ -107,19 +106,17 @@
TimeZoneConfiguration.Builder configuration = new TimeZoneConfiguration.Builder()
.setAutoDetectionEnabled(isChecked);
- if (Flags.revampToggles()) {
- // "Use location for time zone" is only used if "Automatic time zone" is enabled. If
- // the user toggles off automatic time zone, set the toggle off and disable the toggle.
- int geoDetectionCapability = mTimeManager
- .getTimeZoneCapabilitiesAndConfig()
- .getCapabilities()
- .getConfigureGeoDetectionEnabledCapability();
+ // "Use location for time zone" is only used if "Automatic time zone" is enabled. If
+ // the user toggles off automatic time zone, set the toggle off and disable the toggle.
+ int geoDetectionCapability = mTimeManager
+ .getTimeZoneCapabilitiesAndConfig()
+ .getCapabilities()
+ .getConfigureGeoDetectionEnabledCapability();
- if (!isChecked
- && (geoDetectionCapability == CAPABILITY_NOT_APPLICABLE
- || geoDetectionCapability == CAPABILITY_POSSESSED)) {
- configuration.setGeoDetectionEnabled(false);
- }
+ if (!isChecked
+ && (geoDetectionCapability == CAPABILITY_NOT_APPLICABLE
+ || geoDetectionCapability == CAPABILITY_POSSESSED)) {
+ configuration.setGeoDetectionEnabled(false);
}
boolean result = mTimeManager.updateTimeZoneConfiguration(configuration.build());
diff --git a/src/com/android/settings/datetime/DateTimeSettings.java b/src/com/android/settings/datetime/DateTimeSettings.java
index e5c13bf..f3c11d4 100644
--- a/src/com/android/settings/datetime/DateTimeSettings.java
+++ b/src/com/android/settings/datetime/DateTimeSettings.java
@@ -23,7 +23,6 @@
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.flags.Flags;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.search.SearchIndexable;
@@ -50,9 +49,6 @@
@Override
protected int getPreferenceScreenResId() {
- if (Flags.revampToggles()) {
- return R.xml.date_time_prefs_revamped;
- }
return R.xml.date_time_prefs;
}
@@ -123,6 +119,5 @@
}
public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
- new BaseSearchIndexProvider(
- Flags.revampToggles() ? R.xml.date_time_prefs_revamped : R.xml.date_time_prefs);
+ new BaseSearchIndexProvider(R.xml.date_time_prefs);
}
diff --git a/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceController.java b/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceController.java
index 52d49ac..d475d9d 100644
--- a/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceController.java
+++ b/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceController.java
@@ -32,7 +32,6 @@
import com.android.settings.R;
import com.android.settings.core.InstrumentedPreferenceFragment;
import com.android.settings.core.TogglePreferenceController;
-import com.android.settings.flags.Flags;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
import com.android.settingslib.core.lifecycle.events.OnStart;
import com.android.settingslib.core.lifecycle.events.OnStop;
@@ -68,7 +67,7 @@
// forceRefresh set to true as the location toggle may have been turned off by switching off
// automatic time zone
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
- getTimeZoneCapabilitiesAndConfig(/*forceRefresh=*/ Flags.revampToggles());
+ getTimeZoneCapabilitiesAndConfig(/*forceRefresh=*/ true);
TimeZoneConfiguration configuration = capabilitiesAndConfig.getConfiguration();
return configuration.isGeoDetectionEnabled();
}
@@ -137,11 +136,7 @@
if (capability == CAPABILITY_NOT_SUPPORTED || capability == CAPABILITY_NOT_ALLOWED) {
return UNSUPPORTED_ON_DEVICE;
} else if (capability == CAPABILITY_NOT_APPLICABLE || capability == CAPABILITY_POSSESSED) {
- if (Flags.revampToggles()) {
- return isAutoTimeZoneEnabled() ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
- } else {
- return AVAILABLE;
- }
+ return isAutoTimeZoneEnabled() ? AVAILABLE : DISABLED_DEPENDENT_SETTING;
} else {
throw new IllegalStateException("Unknown capability=" + capability);
}
@@ -151,10 +146,8 @@
public void updateState(Preference preference) {
super.updateState(preference);
- if (Flags.revampToggles()) {
- // enable / disable the toggle based on automatic time zone being enabled or not
- preference.setEnabled(isAutoTimeZoneEnabled());
- }
+ // enable / disable the toggle based on automatic time zone being enabled or not
+ preference.setEnabled(isAutoTimeZoneEnabled());
}
@Override
diff --git a/src/com/android/settings/datetime/TimeFormatPreferenceController.java b/src/com/android/settings/datetime/TimeFormatPreferenceController.java
index 2dee76e..c400f4e 100644
--- a/src/com/android/settings/datetime/TimeFormatPreferenceController.java
+++ b/src/com/android/settings/datetime/TimeFormatPreferenceController.java
@@ -25,7 +25,6 @@
import com.android.settings.R;
import com.android.settings.core.TogglePreferenceController;
-import com.android.settings.flags.Flags;
import java.util.Calendar;
import java.util.Date;
@@ -73,11 +72,6 @@
if (mIsFromSUW) {
return DISABLED_DEPENDENT_SETTING;
}
- if (!Flags.revampToggles()) {
- if (AutoTimeFormatPreferenceController.isAutoTimeFormatSelection(mContext)) {
- return DISABLED_DEPENDENT_SETTING;
- }
- }
return AVAILABLE;
}
@@ -120,12 +114,12 @@
return DateFormat.is24HourFormat(mContext);
}
- static void update24HourFormat(Context context, Boolean is24Hour) {
+ private static void update24HourFormat(Context context, Boolean is24Hour) {
set24Hour(context, is24Hour);
timeUpdated(context, is24Hour);
}
- static void timeUpdated(Context context, Boolean is24Hour) {
+ private static void timeUpdated(Context context, Boolean is24Hour) {
Intent timeChanged = new Intent(Intent.ACTION_TIME_CHANGED);
timeChanged.addFlags(Intent.FLAG_RECEIVER_INCLUDE_BACKGROUND);
int timeFormatPreference;
@@ -139,9 +133,8 @@
context.sendBroadcast(timeChanged);
}
- static void set24Hour(Context context, Boolean is24Hour) {
- String value = is24Hour == null ? null :
- is24Hour ? HOURS_24 : HOURS_12;
+ private static void set24Hour(Context context, boolean is24Hour) {
+ String value = is24Hour ? HOURS_24 : HOURS_12;
Settings.System.putString(context.getContentResolver(),
Settings.System.TIME_12_24, value);
}
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
index 5e17f4b..2edbf99 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
@@ -274,7 +274,6 @@
}
if (mDailyChartView != dailyChartView || mHourlyChartView != hourlyChartView) {
mHandler.post(() -> setBatteryChartViewInner(dailyChartView, hourlyChartView));
- animateBatteryChartViewGroup();
}
if (mBatteryChartViewGroup != null) {
final View grandparentView = (View) mBatteryChartViewGroup.getParent();
diff --git a/src/com/android/settings/gestures/OneHandedSettings.java b/src/com/android/settings/gestures/OneHandedSettings.java
index 0378888..0a2599e 100644
--- a/src/com/android/settings/gestures/OneHandedSettings.java
+++ b/src/com/android/settings/gestures/OneHandedSettings.java
@@ -22,9 +22,9 @@
import android.content.Context;
import android.os.Bundle;
import android.os.UserHandle;
-import android.util.Log;
import android.view.LayoutInflater;
import android.view.ViewGroup;
+import android.widget.CompoundButton;
import androidx.recyclerview.widget.RecyclerView;
@@ -33,7 +33,6 @@
import com.android.settings.R;
import com.android.settings.accessibility.AccessibilityFragmentUtils;
import com.android.settings.accessibility.AccessibilityShortcutPreferenceFragment;
-import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settingslib.search.SearchIndexable;
import com.android.settingslib.search.SearchIndexableRaw;
@@ -82,12 +81,7 @@
final MainSwitchPreference mainSwitchPreference =
getPreferenceScreen().findPreference(ONE_HANDED_MAIN_SWITCH_KEY);
- mainSwitchPreference.addOnSwitchChangeListener((switchView, isChecked) -> {
- switchView.setChecked(isChecked);
- if (isChecked) {
- showQuickSettingsTooltipIfNeeded(QuickSettingsTooltipType.GUIDE_TO_DIRECT_USE);
- }
- });
+ mainSwitchPreference.addOnSwitchChangeListener(CompoundButton::setChecked);
}
@Override
@@ -146,24 +140,6 @@
}
@Override
- protected ComponentName getTileComponentName() {
- return AccessibilityShortcutController.ONE_HANDED_TILE_COMPONENT_NAME;
- }
-
- @Override
- protected CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type) {
- final Context context = getContext();
- if (context == null) {
- Log.w(TAG, "OneHandedSettings not attached to a context.");
- return null;
- }
- return type == QuickSettingsTooltipType.GUIDE_TO_EDIT
- ? context.getText(R.string.accessibility_one_handed_mode_qs_tooltip_content)
- : context.getText(
- R.string.accessibility_one_handed_mode_auto_added_qs_tooltip_content);
- }
-
- @Override
protected int getPreferenceScreenResId() {
return R.xml.one_handed_settings;
}
diff --git a/src/com/android/settings/language/DefaultVoiceInputPreferenceController.java b/src/com/android/settings/language/DefaultVoiceInputPreferenceController.java
index 74c156c..c0b65df 100644
--- a/src/com/android/settings/language/DefaultVoiceInputPreferenceController.java
+++ b/src/com/android/settings/language/DefaultVoiceInputPreferenceController.java
@@ -22,9 +22,12 @@
import android.content.pm.PackageManager;
import android.text.TextUtils;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
+import com.android.internal.annotations.Initializer;
import com.android.settings.applications.defaultapps.DefaultAppPreferenceController;
import com.android.settingslib.applications.DefaultAppInfo;
import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -43,7 +46,8 @@
private Preference mPreference;
private Context mContext;
- public DefaultVoiceInputPreferenceController(Context context, Lifecycle lifecycle) {
+ public DefaultVoiceInputPreferenceController(
+ @NonNull Context context, @Nullable Lifecycle lifecycle) {
super(context);
mContext = context;
mHelper = new VoiceInputHelper(context);
@@ -65,6 +69,7 @@
}
@Override
+ @Initializer
public void displayPreference(PreferenceScreen screen) {
mScreen = screen;
mPreference = screen.findPreference(getPreferenceKey());
diff --git a/src/com/android/settings/language/LanguageAndRegionPreferenceController.java b/src/com/android/settings/language/LanguageAndRegionPreferenceController.java
new file mode 100644
index 0000000..4e554ed
--- /dev/null
+++ b/src/com/android/settings/language/LanguageAndRegionPreferenceController.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.language;
+
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.flags.Flags;
+
+/**
+ * This is a display controller for new language activity entry.
+ * TODO(b/379962955): When new layout is on board, all old layouts should be removed.
+ */
+public class LanguageAndRegionPreferenceController extends BasePreferenceController {
+
+ public LanguageAndRegionPreferenceController(@NonNull Context context, @NonNull String key) {
+ super(context, key);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ if (!Flags.regionalPreferencesApiEnabled()) {
+ return CONDITIONALLY_UNAVAILABLE;
+ }
+ // TODO: Add setComponentEnabledSetting after LanguageAndRegionSettingsActivity is created.
+ return AVAILABLE;
+ }
+}
diff --git a/src/com/android/settings/language/LanguageAndRegionSettings.java b/src/com/android/settings/language/LanguageAndRegionSettings.java
new file mode 100644
index 0000000..a405878
--- /dev/null
+++ b/src/com/android/settings/language/LanguageAndRegionSettings.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.language;
+
+import android.app.Activity;
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.flags.Flags;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.widget.PreferenceCategoryController;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.search.SearchIndexable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@SearchIndexable
+public class LanguageAndRegionSettings extends DashboardFragment {
+
+ private static final String KEY_SPEECH_CATEGORY = "speech_category";
+ private static final String KEY_ON_DEVICE_RECOGNITION = "on_device_recognition_settings";
+ private static final String KEY_TEXT_TO_SPEECH = "tts_settings_summary";
+
+ private static final String TAG = "LanguageAndRegionSettings";
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.SETTINGS_LANGUAGES_CATEGORY;
+ }
+
+ @Override
+ protected String getLogTag() {
+ return TAG;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ // Hack to update action bar title. It's necessary to refresh title because this page user
+ // can change locale from here and fragment won't relaunch. Once language changes, title
+ // must display in the new language.
+ final Activity activity = getActivity();
+ if (activity == null) {
+ return;
+ }
+ activity.setTitle(R.string.languages_settings);
+ }
+
+ @Override
+ public @Nullable String getPreferenceScreenBindingKey(@NonNull Context context) {
+ return LanguageSettingScreen.KEY;
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.language_and_region_settings;
+ }
+
+ protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
+ return buildPreferenceControllers(context, getSettingsLifecycle());
+ }
+
+ private static List<AbstractPreferenceController> buildPreferenceControllers(
+ @NonNull Context context, @Nullable Lifecycle lifecycle) {
+ final List<AbstractPreferenceController> controllers = new ArrayList<>();
+
+ final DefaultVoiceInputPreferenceController defaultVoiceInputPreferenceController =
+ new DefaultVoiceInputPreferenceController(context, lifecycle);
+ final TtsPreferenceController ttsPreferenceController =
+ new TtsPreferenceController(context, KEY_TEXT_TO_SPEECH);
+ final OnDeviceRecognitionPreferenceController onDeviceRecognitionPreferenceController =
+ new OnDeviceRecognitionPreferenceController(context, KEY_ON_DEVICE_RECOGNITION);
+
+ controllers.add(defaultVoiceInputPreferenceController);
+ controllers.add(ttsPreferenceController);
+ List<AbstractPreferenceController> speechCategoryChildren = new ArrayList<>(
+ List.of(defaultVoiceInputPreferenceController, ttsPreferenceController));
+
+ if (onDeviceRecognitionPreferenceController.isAvailable()) {
+ controllers.add(onDeviceRecognitionPreferenceController);
+ speechCategoryChildren.add(onDeviceRecognitionPreferenceController);
+ }
+
+ controllers.add(new PreferenceCategoryController(context, KEY_SPEECH_CATEGORY)
+ .setChildren(speechCategoryChildren));
+
+ return controllers;
+ }
+
+ public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider(R.xml.language_and_region_settings) {
+
+ @Override
+ @NonNull
+ public List<AbstractPreferenceController> createPreferenceControllers(
+ @NonNull Context context) {
+ return buildPreferenceControllers(context, null);
+ }
+
+ @Override
+ protected boolean isPageSearchEnabled(Context context) {
+ if (Flags.regionalPreferencesApiEnabled()) {
+ return true;
+ }
+ return false;
+ }
+ };
+}
diff --git a/src/com/android/settings/language/LanguagePreferenceController.java b/src/com/android/settings/language/LanguagePreferenceController.java
index 84624a2..90aaec4 100644
--- a/src/com/android/settings/language/LanguagePreferenceController.java
+++ b/src/com/android/settings/language/LanguagePreferenceController.java
@@ -22,6 +22,7 @@
import com.android.settings.Settings;
import com.android.settings.core.BasePreferenceController;
+import com.android.settings.flags.Flags;
/**
* This is a display controller for new language activity entry.
@@ -34,6 +35,10 @@
@Override
public int getAvailabilityStatus() {
+ if (Flags.regionalPreferencesApiEnabled()) {
+ setActivityEnabled(mContext, Settings.LanguageSettingsActivity.class, false);
+ return CONDITIONALLY_UNAVAILABLE;
+ }
setActivityEnabled(mContext, Settings.LanguageSettingsActivity.class, true);
return AVAILABLE;
}
diff --git a/src/com/android/settings/language/LanguageSettings.java b/src/com/android/settings/language/LanguageSettings.java
index d992ff2..58df053 100644
--- a/src/com/android/settings/language/LanguageSettings.java
+++ b/src/com/android/settings/language/LanguageSettings.java
@@ -25,6 +25,7 @@
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.flags.Flags;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.widget.PreferenceCategoryController;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -116,6 +117,9 @@
}
@Override
protected boolean isPageSearchEnabled(Context context) {
+ if (Flags.regionalPreferencesApiEnabled()) {
+ return false;
+ }
return true;
}
};
diff --git a/src/com/android/settings/network/apn/ApnPreference.java b/src/com/android/settings/network/apn/ApnPreference.java
index 55258c1..3ba3508 100644
--- a/src/com/android/settings/network/apn/ApnPreference.java
+++ b/src/com/android/settings/network/apn/ApnPreference.java
@@ -24,31 +24,29 @@
import android.net.Uri;
import android.provider.Telephony;
import android.telephony.SubscriptionManager;
-import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.RadioButton;
-import android.widget.RelativeLayout;
import android.widget.Toast;
-import androidx.annotation.Nullable;
+import androidx.annotation.NonNull;
import androidx.preference.Preference;
import androidx.preference.PreferenceViewHolder;
import com.android.settings.R;
import com.android.settings.flags.Flags;
import com.android.settings.spa.SpaActivity;
+import com.android.settingslib.widget.TwoTargetPreference;
/**
* Preference of APN UI entry
*/
-public class ApnPreference extends Preference
- implements CompoundButton.OnCheckedChangeListener, View.OnClickListener {
+public class ApnPreference extends TwoTargetPreference
+ implements CompoundButton.OnCheckedChangeListener, Preference.OnPreferenceClickListener {
private static final String TAG = "ApnPreference";
private boolean mIsChecked = false;
- @Nullable
- private RadioButton mRadioButton = null;
+ private RadioButton mRadioButton;
private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
private boolean mProtectFromCheckedChange = false;
private boolean mDefaultSelectable = true;
@@ -57,50 +55,36 @@
/**
* Constructor of Preference
*/
- public ApnPreference(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- // Primary target and radio button could be selectable, but entire preference itself is not
- // selectable.
- setSelectable(false);
- }
-
- /**
- * Constructor of Preference
- */
- public ApnPreference(Context context, AttributeSet attrs) {
- this(context, attrs, R.attr.apnPreferenceStyle);
- }
-
- /**
- * Constructor of Preference
- */
public ApnPreference(Context context) {
- this(context, null);
+ super(context);
+ setOnPreferenceClickListener(this);
}
@Override
- public void onBindViewHolder(PreferenceViewHolder view) {
- super.onBindViewHolder(view);
+ public void onBindViewHolder(PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
- final RelativeLayout textArea = (RelativeLayout) view.findViewById(R.id.text_layout);
- textArea.setOnClickListener(this);
-
- final View radioButtonFrame = view.itemView.requireViewById(R.id.apn_radio_button_frame);
- final RadioButton rb = view.itemView.requireViewById(R.id.apn_radiobutton);
- mRadioButton = rb;
- if (mDefaultSelectable) {
- radioButtonFrame.setOnClickListener((v) -> {
- rb.performClick();
- });
- rb.setOnCheckedChangeListener(this);
-
- mProtectFromCheckedChange = true;
- rb.setChecked(mIsChecked);
- mProtectFromCheckedChange = false;
- radioButtonFrame.setVisibility(View.VISIBLE);
- } else {
- radioButtonFrame.setVisibility(View.GONE);
+ final RadioButton rb = (RadioButton) holder.findViewById(android.R.id.checkbox);
+ final View radioButtonFrame = holder.findViewById(android.R.id.widget_frame);
+ if (rb == null || radioButtonFrame == null) {
+ throw new RuntimeException("Failed to load system layout.");
}
+
+ mRadioButton = rb;
+ radioButtonFrame.setOnClickListener(v -> rb.performClick());
+ rb.setOnCheckedChangeListener(this);
+ setIsChecked(mIsChecked);
+ rb.setVisibility(View.VISIBLE);
+ }
+
+ @Override
+ protected boolean shouldHideSecondTarget() {
+ return !mDefaultSelectable;
+ }
+
+ @Override
+ protected int getSecondTargetResId() {
+ return R.layout.preference_widget_radiobutton;
}
/**
@@ -118,6 +102,7 @@
/**
* Change the preference status.
*/
+ @Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
Log.i(TAG, "ID: " + getKey() + " :" + isChecked);
if (mProtectFromCheckedChange) {
@@ -130,19 +115,14 @@
}
@Override
- public void onClick(View layoutView) {
- super.onClick();
+ public boolean onPreferenceClick(@NonNull Preference preference) {
final Context context = getContext();
final int pos = Integer.parseInt(getKey());
- if (context == null) {
- Log.w(TAG, "No context available for pos=" + pos);
- return;
- }
if (mHideDetails) {
Toast.makeText(context, context.getString(R.string.cannot_change_apn_toast),
Toast.LENGTH_LONG).show();
- return;
+ return true;
}
final Uri url = ContentUris.withAppendedId(Telephony.Carriers.CONTENT_URI, pos);
@@ -156,6 +136,7 @@
editIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(editIntent);
}
+ return true;
}
public void setDefaultSelectable(boolean defaultSelectable) {
diff --git a/src/com/android/settings/network/telephony/SubscriptionRepository.kt b/src/com/android/settings/network/telephony/SubscriptionRepository.kt
index 43bba07..33c1e655 100644
--- a/src/com/android/settings/network/telephony/SubscriptionRepository.kt
+++ b/src/com/android/settings/network/telephony/SubscriptionRepository.kt
@@ -40,6 +40,7 @@
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.flow.shareIn
+import java.util.stream.Collectors
private const val TAG = "SubscriptionRepository"
@@ -154,6 +155,18 @@
.conflate()
.flowOn(Dispatchers.Default)
+ fun removableSubscriptionInfoListFlow(): Flow<List<SubscriptionInfo>> {
+ return subscriptionsChangedFlow()
+ .map {
+ subscriptionManager.availableSubscriptionInfoList?.stream()
+ ?.filter { sub: SubscriptionInfo -> !sub.isEmbedded }
+ ?.collect(Collectors.toList()) ?: emptyList()
+ }
+ .conflate()
+ .onEach { Log.d(TAG, "getRemovableSubscriptionVisibleFlow: $it") }
+ .flowOn(Dispatchers.Default)
+ }
+
@OptIn(ExperimentalCoroutinesApi::class)
fun phoneNumberFlow(subId: Int): Flow<String?> =
activeSubscriptionInfoFlow(subId).flatMapLatest { subInfo ->
diff --git a/src/com/android/settings/regionalpreferences/MeasurementSystemItemFragment.java b/src/com/android/settings/regionalpreferences/MeasurementSystemItemFragment.java
index 9f15cf4..231a34e 100644
--- a/src/com/android/settings/regionalpreferences/MeasurementSystemItemFragment.java
+++ b/src/com/android/settings/regionalpreferences/MeasurementSystemItemFragment.java
@@ -63,7 +63,7 @@
new BaseSearchIndexProvider(R.xml.regional_preferences_measurement_system) {
@Override
protected boolean isPageSearchEnabled(Context context) {
- if (Flags.regionalPreferencesApiEnabled()) {
+ if (!Flags.regionalPreferencesApiEnabled()) {
return false;
}
return true;
diff --git a/src/com/android/settings/service/PreferenceService.kt b/src/com/android/settings/service/PreferenceService.kt
index d07e78d..81ab584 100644
--- a/src/com/android/settings/service/PreferenceService.kt
+++ b/src/com/android/settings/service/PreferenceService.kt
@@ -19,7 +19,6 @@
import android.app.Application
import android.os.Binder
import android.os.OutcomeReceiver
-import android.os.Process
import android.service.settings.preferences.GetValueRequest
import android.service.settings.preferences.GetValueResult
import android.service.settings.preferences.MetadataRequest
@@ -37,7 +36,6 @@
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.launch
-import java.lang.Exception
class PreferenceService : SettingsPreferenceService() {
@@ -49,14 +47,22 @@
override fun onGetAllPreferenceMetadata(
request: MetadataRequest,
- callback: OutcomeReceiver<MetadataResult, Exception>
+ callback: OutcomeReceiver<MetadataResult, Exception>,
) {
+ // MUST get pid/uid in binder thread
+ val callingPid = Binder.getCallingPid()
+ val callingUid = Binder.getCallingUid()
scope.launch {
- val graphProto = graphApi.invoke(application, Process.myUid(), Binder.getCallingUid(),
- GetPreferenceGraphRequest(
- includeValue = false,
- flags = PreferenceGetterFlags.METADATA
- ))
+ val graphProto =
+ graphApi.invoke(
+ application,
+ callingPid,
+ callingUid,
+ GetPreferenceGraphRequest(
+ includeValue = false,
+ flags = PreferenceGetterFlags.METADATA,
+ ),
+ )
val result = transformCatalystGetMetadataResponse(this@PreferenceService, graphProto)
callback.onResult(result)
}
@@ -64,17 +70,16 @@
override fun onGetPreferenceValue(
request: GetValueRequest,
- callback: OutcomeReceiver<GetValueResult, Exception>
+ callback: OutcomeReceiver<GetValueResult, Exception>,
) {
+ // MUST get pid/uid in binder thread
+ val callingPid = Binder.getCallingPid()
+ val callingUid = Binder.getCallingUid()
scope.launch {
val apiRequest = transformFrameworkGetValueRequest(request)
- val response = getApiHandler.invoke(application, Process.myUid(),
- Binder.getCallingUid(), apiRequest)
- val result = transformCatalystGetValueResponse(
- this@PreferenceService,
- request,
- response
- )
+ val response = getApiHandler.invoke(application, callingPid, callingUid, apiRequest)
+ val result =
+ transformCatalystGetValueResponse(this@PreferenceService, request, response)
if (result == null) {
callback.onError(IllegalStateException("No response"))
} else {
@@ -85,8 +90,11 @@
override fun onSetPreferenceValue(
request: SetValueRequest,
- callback: OutcomeReceiver<SetValueResult, Exception>
+ callback: OutcomeReceiver<SetValueResult, Exception>,
) {
+ // MUST get pid/uid in binder thread
+ val callingPid = Binder.getCallingPid()
+ val callingUid = Binder.getCallingUid()
scope.launch {
val apiRequest = transformFrameworkSetValueRequest(request)
if (apiRequest == null) {
@@ -94,8 +102,7 @@
SetValueResult.Builder(SetValueResult.RESULT_INVALID_REQUEST).build()
)
} else {
- val response = setApiHandler.invoke(application, Process.myUid(),
- Binder.getCallingUid(), apiRequest)
+ val response = setApiHandler.invoke(application, callingPid, callingUid, apiRequest)
callback.onResult(transformCatalystSetValueResponse(response))
}
@@ -106,9 +113,9 @@
private class GraphProvider(override val id: Int) : GetPreferenceGraphApiHandler(emptySet()) {
override fun hasPermission(
application: Application,
- myUid: Int,
+ callingPid: Int,
callingUid: Int,
- request: GetPreferenceGraphRequest
+ request: GetPreferenceGraphRequest,
) = true
}
}
diff --git a/src/com/android/settings/sim/receivers/SimSlotChangeHandler.java b/src/com/android/settings/sim/receivers/SimSlotChangeHandler.java
deleted file mode 100644
index f808924..0000000
--- a/src/com/android/settings/sim/receivers/SimSlotChangeHandler.java
+++ /dev/null
@@ -1,432 +0,0 @@
-/*
- * Copyright (C) 2020 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.sim.receivers;
-
-import static android.content.Context.MODE_PRIVATE;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.os.Looper;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.telephony.SubscriptionInfo;
-import android.telephony.SubscriptionManager;
-import android.telephony.TelephonyManager;
-import android.telephony.UiccCardInfo;
-import android.telephony.UiccPortInfo;
-import android.telephony.UiccSlotInfo;
-import android.util.Log;
-
-import com.android.settings.flags.Flags;
-import com.android.settings.network.SubscriptionUtil;
-import com.android.settings.network.UiccSlotUtil;
-import com.android.settings.network.UiccSlotsException;
-import com.android.settings.sim.ChooseSimActivity;
-import com.android.settings.sim.DsdsDialogActivity;
-import com.android.settings.sim.SimActivationNotifier;
-import com.android.settings.sim.SimNotificationService;
-import com.android.settings.sim.SwitchToEsimConfirmDialogActivity;
-
-import com.google.common.collect.ImmutableList;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-import javax.annotation.Nullable;
-
-/** Perform actions after a slot change event is triggered. */
-public class SimSlotChangeHandler {
- private static final String TAG = "SimSlotChangeHandler";
-
- private static final String EUICC_PREFS = "euicc_prefs";
- // Shared preference keys
- private static final String KEY_REMOVABLE_SLOT_STATE = "removable_slot_state";
- private static final String KEY_SUW_PSIM_ACTION = "suw_psim_action";
- // User's last removable SIM insertion / removal action during SUW.
- private static final int LAST_USER_ACTION_IN_SUW_NONE = 0;
- private static final int LAST_USER_ACTION_IN_SUW_INSERT = 1;
- private static final int LAST_USER_ACTION_IN_SUW_REMOVE = 2;
-
- private static volatile SimSlotChangeHandler sSlotChangeHandler;
-
- /** Returns a SIM slot change handler singleton. */
- public static SimSlotChangeHandler get() {
- if (sSlotChangeHandler == null) {
- synchronized (SimSlotChangeHandler.class) {
- if (sSlotChangeHandler == null) {
- sSlotChangeHandler = new SimSlotChangeHandler();
- }
- }
- }
- return sSlotChangeHandler;
- }
-
- private SubscriptionManager mSubMgr;
- private TelephonyManager mTelMgr;
- private Context mContext;
-
- void onSlotsStatusChange(Context context) {
- init(context);
-
- if (Looper.myLooper() == Looper.getMainLooper()) {
- throw new IllegalStateException("Cannot be called from main thread.");
- }
-
- UiccSlotInfo removableSlotInfo = getRemovableUiccSlotInfo();
- if (removableSlotInfo == null) {
- Log.e(TAG, "Unable to find the removable slot. Do nothing.");
- return;
- }
- Log.i(TAG, "The removableSlotInfo: " + removableSlotInfo);
- int lastRemovableSlotState = getLastRemovableSimSlotState(mContext);
- int currentRemovableSlotState = removableSlotInfo.getCardStateInfo();
- Log.d(TAG,
- "lastRemovableSlotState: " + lastRemovableSlotState + ",currentRemovableSlotState: "
- + currentRemovableSlotState);
- boolean isRemovableSimInserted =
- lastRemovableSlotState == UiccSlotInfo.CARD_STATE_INFO_ABSENT
- && currentRemovableSlotState == UiccSlotInfo.CARD_STATE_INFO_PRESENT;
- boolean isRemovableSimRemoved =
- lastRemovableSlotState == UiccSlotInfo.CARD_STATE_INFO_PRESENT
- && currentRemovableSlotState == UiccSlotInfo.CARD_STATE_INFO_ABSENT;
-
- // Sets the current removable slot state.
- setRemovableSimSlotState(mContext, currentRemovableSlotState);
-
- if (mTelMgr.getActiveModemCount() > 1) {
- if (!isRemovableSimInserted) {
- Log.d(TAG, "Removable Sim is not inserted in DSDS mode. Do nothing.");
- return;
- }
-
- if (Flags.isDualSimOnboardingEnabled()) {
- // ForNewUi, when the user inserts the psim, showing the sim onboarding for the user
- // to setup the sim switching or the default data subscription in DSDS.
- // Will show dialog for below case.
- // 1. the psim slot is not active.
- // 2. there are one or more active sim.
- handleRemovableSimInsertWhenDsds(removableSlotInfo);
- return;
- } else if (!isMultipleEnabledProfilesSupported()) {
- Log.d(TAG, "The device is already in DSDS mode and no MEP. Do nothing.");
- return;
- } else if (isMultipleEnabledProfilesSupported()) {
- handleRemovableSimInsertUnderDsdsMep(removableSlotInfo);
- return;
- }
- }
-
- if (isRemovableSimInserted) {
- handleSimInsert(removableSlotInfo);
- return;
- }
- if (isRemovableSimRemoved) {
- handleSimRemove(removableSlotInfo);
- return;
- }
- Log.i(TAG, "Do nothing on slot status changes.");
- }
-
- void onSuwFinish(Context context) {
- init(context);
-
- if (Looper.myLooper() == Looper.getMainLooper()) {
- throw new IllegalStateException("Cannot be called from main thread.");
- }
-
- if (mTelMgr.getActiveModemCount() > 1) {
- Log.i(TAG, "The device is already in DSDS mode. Do nothing.");
- return;
- }
-
- UiccSlotInfo removableSlotInfo = getRemovableUiccSlotInfo();
- if (removableSlotInfo == null) {
- Log.e(TAG, "Unable to find the removable slot. Do nothing.");
- return;
- }
-
- boolean embeddedSimExist = getGroupedEmbeddedSubscriptions().size() != 0;
- int removableSlotAction = getSuwRemovableSlotAction(mContext);
- setSuwRemovableSlotAction(mContext, LAST_USER_ACTION_IN_SUW_NONE);
-
- if (embeddedSimExist
- && removableSlotInfo.getCardStateInfo() == UiccSlotInfo.CARD_STATE_INFO_PRESENT) {
- if (mTelMgr.isMultiSimSupported() == TelephonyManager.MULTISIM_ALLOWED) {
- Log.i(TAG, "DSDS condition satisfied. Show notification.");
- SimNotificationService.scheduleSimNotification(
- mContext, SimActivationNotifier.NotificationType.ENABLE_DSDS);
- } else if (removableSlotAction == LAST_USER_ACTION_IN_SUW_INSERT) {
- Log.i(
- TAG,
- "Both removable SIM and eSIM are present. DSDS condition doesn't"
- + " satisfied. User inserted pSIM during SUW. Show choose SIM"
- + " screen.");
- startChooseSimActivity(true);
- }
- } else if (removableSlotAction == LAST_USER_ACTION_IN_SUW_REMOVE) {
- handleSimRemove(removableSlotInfo);
- }
- }
-
- private void init(Context context) {
- mSubMgr =
- (SubscriptionManager)
- context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
- mTelMgr = context.getSystemService(TelephonyManager.class);
- mContext = context;
- }
-
- private void handleSimInsert(UiccSlotInfo removableSlotInfo) {
- Log.i(TAG, "Handle SIM inserted.");
- if (!isSuwFinished(mContext)) {
- Log.i(TAG, "Still in SUW. Handle SIM insertion after SUW is finished");
- setSuwRemovableSlotAction(mContext, LAST_USER_ACTION_IN_SUW_INSERT);
- return;
- }
- if (removableSlotInfo.getPorts().stream().findFirst().get().isActive()) {
- Log.i(TAG, "The removable slot is already active. Do nothing.");
- return;
- }
-
- if (hasActiveEsimSubscription()) {
- if (mTelMgr.isMultiSimSupported() == TelephonyManager.MULTISIM_ALLOWED) {
- Log.i(TAG, "Enabled profile exists. DSDS condition satisfied.");
- if (Flags.isDualSimOnboardingEnabled()) {
- // enable dsds by sim onboarding flow
- handleRemovableSimInsertWhenDsds(removableSlotInfo);
- } else {
- startDsdsDialogActivity();
- }
- } else {
- Log.i(TAG, "Enabled profile exists. DSDS condition not satisfied.");
- startChooseSimActivity(true);
- }
- return;
- }
-
- Log.i(
- TAG,
- "No enabled eSIM profile. Ready to switch to removable slot and show"
- + " notification.");
- try {
- UiccSlotUtil.switchToRemovableSlot(
- UiccSlotUtil.INVALID_PHYSICAL_SLOT_ID, mContext.getApplicationContext());
- } catch (UiccSlotsException e) {
- Log.e(TAG, "Failed to switch to removable slot.");
- return;
- }
- SimNotificationService.scheduleSimNotification(
- mContext, SimActivationNotifier.NotificationType.SWITCH_TO_REMOVABLE_SLOT);
- }
-
- private void handleSimRemove(UiccSlotInfo removableSlotInfo) {
- Log.i(TAG, "Handle SIM removed.");
-
- if (!isSuwFinished(mContext)) {
- Log.i(TAG, "Still in SUW. Handle SIM removal after SUW is finished");
- setSuwRemovableSlotAction(mContext, LAST_USER_ACTION_IN_SUW_REMOVE);
- return;
- }
-
- List<SubscriptionInfo> groupedEmbeddedSubscriptions = getGroupedEmbeddedSubscriptions();
- if (groupedEmbeddedSubscriptions.size() == 0 || !removableSlotInfo.getPorts().stream()
- .findFirst().get().isActive()) {
- Log.i(TAG, "eSIM slot is active or no subscriptions exist. Do nothing."
- + " The removableSlotInfo: " + removableSlotInfo
- + ", groupedEmbeddedSubscriptions: " + groupedEmbeddedSubscriptions);
- return;
- }
-
- // If there is only 1 eSIM profile exists, we ask the user if they want to switch to that
- // profile.
- if (groupedEmbeddedSubscriptions.size() == 1) {
- Log.i(TAG, "Only 1 eSIM profile found. Ask user's consent to switch.");
- startSwitchSlotConfirmDialogActivity(groupedEmbeddedSubscriptions.get(0));
- return;
- }
-
- // If there are more than 1 eSIM profiles installed, we show a screen to let users to choose
- // the number they want to use.
- Log.i(TAG, "Multiple eSIM profiles found. Ask user which subscription to use.");
- startChooseSimActivity(false);
- }
-
- private boolean hasOtherActiveSubInfo(int psimSubId) {
- List<SubscriptionInfo> activeSubs = SubscriptionUtil.getActiveSubscriptions(mSubMgr);
- return activeSubs.stream()
- .anyMatch(subscriptionInfo -> subscriptionInfo.getSubscriptionId() != psimSubId);
- }
-
- private boolean hasAnyPortActiveInSlot(UiccSlotInfo removableSlotInfo) {
- return removableSlotInfo.getPorts().stream().anyMatch(UiccPortInfo::isActive);
- }
-
- private void handleRemovableSimInsertWhenDsds(UiccSlotInfo removableSlotInfo) {
- Log.i(TAG, "ForNewUi: Handle Removable SIM inserted");
- List<SubscriptionInfo> subscriptionInfos = getAvailableRemovableSubscription();
- if (subscriptionInfos.isEmpty()) {
- Log.e(TAG, "Unable to find the removable subscriptionInfo. Do nothing.");
- return;
- }
- Log.d(TAG, "getAvailableRemovableSubscription:" + subscriptionInfos);
- int psimSubId = subscriptionInfos.get(0).getSubscriptionId();
- if (!hasAnyPortActiveInSlot(removableSlotInfo) || hasOtherActiveSubInfo(psimSubId)) {
- Log.d(TAG, "ForNewUi Start Setup flow");
- startSimConfirmDialogActivity(psimSubId);
- }
- }
-
- private void handleRemovableSimInsertUnderDsdsMep(UiccSlotInfo removableSlotInfo) {
- Log.i(TAG, "Handle Removable SIM inserted under DSDS+Mep.");
-
- if (removableSlotInfo.getPorts().stream().findFirst().get().isActive()) {
- Log.i(TAG, "The removable slot is already active. Do nothing. removableSlotInfo: "
- + removableSlotInfo);
- return;
- }
-
- List<SubscriptionInfo> subscriptionInfos = getAvailableRemovableSubscription();
- if (subscriptionInfos.isEmpty()) {
- Log.e(TAG, "Unable to find the removable subscriptionInfo. Do nothing.");
- return;
- }
- Log.d(TAG, "getAvailableRemovableSubscription:" + subscriptionInfos);
- startSimConfirmDialogActivity(subscriptionInfos.get(0).getSubscriptionId());
- }
-
- private int getLastRemovableSimSlotState(Context context) {
- final SharedPreferences prefs = context.getSharedPreferences(EUICC_PREFS, MODE_PRIVATE);
- return prefs.getInt(KEY_REMOVABLE_SLOT_STATE, UiccSlotInfo.CARD_STATE_INFO_ABSENT);
- }
-
- private void setRemovableSimSlotState(Context context, int state) {
- final SharedPreferences prefs = context.getSharedPreferences(EUICC_PREFS, MODE_PRIVATE);
- prefs.edit().putInt(KEY_REMOVABLE_SLOT_STATE, state).apply();
- Log.d(TAG, "setRemovableSimSlotState: " + state);
- }
-
- private int getSuwRemovableSlotAction(Context context) {
- final SharedPreferences prefs = context.getSharedPreferences(EUICC_PREFS, MODE_PRIVATE);
- return prefs.getInt(KEY_SUW_PSIM_ACTION, LAST_USER_ACTION_IN_SUW_NONE);
- }
-
- private void setSuwRemovableSlotAction(Context context, int action) {
- final SharedPreferences prefs = context.getSharedPreferences(EUICC_PREFS, MODE_PRIVATE);
- prefs.edit().putInt(KEY_SUW_PSIM_ACTION, action).apply();
- }
-
- @Nullable
- private UiccSlotInfo getRemovableUiccSlotInfo() {
- UiccSlotInfo[] slotInfos = mTelMgr.getUiccSlotsInfo();
- if (slotInfos == null) {
- Log.e(TAG, "slotInfos is null. Unable to get slot infos.");
- return null;
- }
- for (UiccSlotInfo slotInfo : slotInfos) {
- if (slotInfo != null && slotInfo.isRemovable()) {
- return slotInfo;
- }
- }
- return null;
- }
-
- private static boolean isSuwFinished(Context context) {
- try {
- // DEVICE_PROVISIONED is 0 if still in setup wizard. 1 if setup completed.
- return Settings.Global.getInt(
- context.getContentResolver(), Settings.Global.DEVICE_PROVISIONED)
- == 1;
- } catch (Settings.SettingNotFoundException e) {
- Log.e(TAG, "Cannot get DEVICE_PROVISIONED from the device.", e);
- return false;
- }
- }
-
- private boolean hasActiveEsimSubscription() {
- List<SubscriptionInfo> activeSubs = SubscriptionUtil.getActiveSubscriptions(mSubMgr);
- return activeSubs.stream().anyMatch(SubscriptionInfo::isEmbedded);
- }
-
- private List<SubscriptionInfo> getGroupedEmbeddedSubscriptions() {
- List<SubscriptionInfo> groupedSubscriptions =
- SubscriptionUtil.getSelectableSubscriptionInfoList(mContext);
- if (groupedSubscriptions == null) {
- return ImmutableList.of();
- }
- return ImmutableList.copyOf(
- groupedSubscriptions.stream()
- .filter(sub -> sub.isEmbedded())
- .collect(Collectors.toList()));
- }
-
- protected List<SubscriptionInfo> getAvailableRemovableSubscription() {
- List<SubscriptionInfo> removableSubscriptions =
- SubscriptionUtil.getAvailableSubscriptions(mContext);
- return ImmutableList.copyOf(
- removableSubscriptions.stream()
- // ToDo: This condition is for psim only. If device supports removable
- // esim, it needs an new condition.
- .filter(sub -> !sub.isEmbedded())
- .collect(Collectors.toList()));
- }
-
- private void startChooseSimActivity(boolean psimInserted) {
- Intent intent = ChooseSimActivity.getIntent(mContext);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.putExtra(ChooseSimActivity.KEY_HAS_PSIM, psimInserted);
- mContext.startActivityAsUser(intent, UserHandle.SYSTEM);
- }
-
- private void startSwitchSlotConfirmDialogActivity(SubscriptionInfo subscriptionInfo) {
- Intent intent = new Intent(mContext, SwitchToEsimConfirmDialogActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- intent.putExtra(SwitchToEsimConfirmDialogActivity.KEY_SUB_TO_ENABLE, subscriptionInfo);
- mContext.startActivityAsUser(intent, UserHandle.SYSTEM);
- }
-
- private void startDsdsDialogActivity() {
- Intent intent = new Intent(mContext, DsdsDialogActivity.class);
- intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivityAsUser(intent, UserHandle.SYSTEM);
- }
-
- private void startSimConfirmDialogActivity(int subId) {
- if (!isSuwFinished(mContext)) {
- Log.d(TAG, "Still in SUW. Do nothing");
- return;
- }
- if (!SubscriptionManager.isUsableSubscriptionId(subId)) {
- Log.i(TAG, "Unable to enable subscription due to invalid subscription ID.");
- return;
- }
- Log.d(TAG, "Start ToggleSubscriptionDialogActivity with " + subId + " under DSDS+Mep.");
- SubscriptionUtil.startToggleSubscriptionDialogActivity(mContext, subId, true, true);
- }
-
- private boolean isMultipleEnabledProfilesSupported() {
- List<UiccCardInfo> cardInfos = mTelMgr.getUiccCardsInfo();
- if (cardInfos == null) {
- Log.d(TAG, "UICC cards info list is empty.");
- return false;
- }
- return cardInfos.stream().anyMatch(
- cardInfo -> cardInfo.isMultipleEnabledProfilesSupported());
- }
-
- private SimSlotChangeHandler() {}
-}
diff --git a/src/com/android/settings/sim/receivers/SimSlotChangeHandler.kt b/src/com/android/settings/sim/receivers/SimSlotChangeHandler.kt
new file mode 100644
index 0000000..940184a
--- /dev/null
+++ b/src/com/android/settings/sim/receivers/SimSlotChangeHandler.kt
@@ -0,0 +1,480 @@
+/*
+ * Copyright (C) 2020 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.sim.receivers
+
+import android.content.Context
+import android.content.Intent
+import android.os.Looper
+import android.os.UserHandle
+import android.provider.Settings
+import android.provider.Settings.SettingNotFoundException
+import android.telephony.SubscriptionInfo
+import android.telephony.SubscriptionManager
+import android.telephony.TelephonyManager
+import android.telephony.UiccCardInfo
+import android.telephony.UiccSlotInfo
+import android.util.Log
+import com.android.settings.flags.Flags
+import com.android.settings.network.SubscriptionUtil
+import com.android.settings.network.UiccSlotUtil
+import com.android.settings.network.UiccSlotsException
+import com.android.settings.network.telephony.SubscriptionRepository
+import com.android.settings.sim.ChooseSimActivity
+import com.android.settings.sim.DsdsDialogActivity
+import com.android.settings.sim.SimActivationNotifier
+import com.android.settings.sim.SimNotificationService
+import com.android.settings.sim.SwitchToEsimConfirmDialogActivity
+import com.google.common.collect.ImmutableList
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.flow.firstOrNull
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.withContext
+import kotlinx.coroutines.withTimeoutOrNull
+import java.util.stream.Collectors
+import kotlin.concurrent.Volatile
+
+/** Perform actions after a slot change event is triggered. */
+class SimSlotChangeHandler private constructor() {
+ private var mSubMgr: SubscriptionManager? = null
+ private var mTelMgr: TelephonyManager? = null
+ private var mContext: Context? = null
+
+ fun onSlotsStatusChange(context: Context) {
+ init(context)
+
+ check(Looper.myLooper() != Looper.getMainLooper()) { "Cannot be called from main thread." }
+
+ val removableSlotInfo = removableUiccSlotInfo
+ if (removableSlotInfo == null) {
+ Log.e(TAG, "Unable to find the removable slot. Do nothing.")
+ return
+ }
+ Log.i(
+ TAG,
+ "The removableSlotInfo: $removableSlotInfo"
+ )
+ val lastRemovableSlotState = getLastRemovableSimSlotState(mContext!!)
+ val currentRemovableSlotState = removableSlotInfo.cardStateInfo
+ Log.d(
+ TAG,
+ ("lastRemovableSlotState: " + lastRemovableSlotState + ",currentRemovableSlotState: "
+ + currentRemovableSlotState)
+ )
+ val isRemovableSimInserted =
+ lastRemovableSlotState == UiccSlotInfo.CARD_STATE_INFO_ABSENT
+ && currentRemovableSlotState == UiccSlotInfo.CARD_STATE_INFO_PRESENT
+ val isRemovableSimRemoved =
+ lastRemovableSlotState == UiccSlotInfo.CARD_STATE_INFO_PRESENT
+ && currentRemovableSlotState == UiccSlotInfo.CARD_STATE_INFO_ABSENT
+
+ // Sets the current removable slot state.
+ setRemovableSimSlotState(mContext!!, currentRemovableSlotState)
+
+ if (mTelMgr!!.activeModemCount > 1) {
+ if (!isRemovableSimInserted) {
+ Log.d(TAG, "Removable Sim is not inserted in DSDS mode. Do nothing.")
+ return
+ }
+
+ if (Flags.isDualSimOnboardingEnabled()) {
+ // ForNewUi, when the user inserts the psim, showing the sim onboarding for the user
+ // to setup the sim switching or the default data subscription in DSDS.
+ // Will show dialog for below case.
+ // 1. the psim slot is not active.
+ // 2. there are one or more active sim.
+ handleRemovableSimInsertWhenDsds(removableSlotInfo)
+ return
+ } else if (!isMultipleEnabledProfilesSupported) {
+ Log.d(TAG, "The device is already in DSDS mode and no MEP. Do nothing.")
+ return
+ } else if (isMultipleEnabledProfilesSupported) {
+ handleRemovableSimInsertUnderDsdsMep(removableSlotInfo)
+ return
+ }
+ }
+
+ if (isRemovableSimInserted) {
+ handleSimInsert(removableSlotInfo)
+ return
+ }
+ if (isRemovableSimRemoved) {
+ handleSimRemove(removableSlotInfo)
+ return
+ }
+ Log.i(TAG, "Do nothing on slot status changes.")
+ }
+
+ fun onSuwFinish(context: Context) {
+ init(context)
+
+ check(Looper.myLooper() != Looper.getMainLooper()) { "Cannot be called from main thread." }
+
+ if (mTelMgr!!.activeModemCount > 1) {
+ Log.i(TAG, "The device is already in DSDS mode. Do nothing.")
+ return
+ }
+
+ val removableSlotInfo = removableUiccSlotInfo
+ if (removableSlotInfo == null) {
+ Log.e(TAG, "Unable to find the removable slot. Do nothing.")
+ return
+ }
+
+ val embeddedSimExist = groupedEmbeddedSubscriptions.size != 0
+ val removableSlotAction = getSuwRemovableSlotAction(mContext!!)
+ setSuwRemovableSlotAction(mContext!!, LAST_USER_ACTION_IN_SUW_NONE)
+
+ if (embeddedSimExist
+ && removableSlotInfo.cardStateInfo == UiccSlotInfo.CARD_STATE_INFO_PRESENT
+ ) {
+ if (mTelMgr!!.isMultiSimSupported() == TelephonyManager.MULTISIM_ALLOWED) {
+ Log.i(TAG, "DSDS condition satisfied. Show notification.")
+ SimNotificationService.scheduleSimNotification(
+ mContext, SimActivationNotifier.NotificationType.ENABLE_DSDS
+ )
+ } else if (removableSlotAction == LAST_USER_ACTION_IN_SUW_INSERT) {
+ Log.i(
+ TAG,
+ ("Both removable SIM and eSIM are present. DSDS condition doesn't"
+ + " satisfied. User inserted pSIM during SUW. Show choose SIM"
+ + " screen.")
+ )
+ startChooseSimActivity(true)
+ }
+ } else if (removableSlotAction == LAST_USER_ACTION_IN_SUW_REMOVE) {
+ handleSimRemove(removableSlotInfo)
+ }
+ }
+
+ private fun init(context: Context) {
+ mSubMgr =
+ context.getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE) as SubscriptionManager
+ mTelMgr = context.getSystemService(TelephonyManager::class.java)
+ mContext = context
+ }
+
+ private fun handleSimInsert(removableSlotInfo: UiccSlotInfo) {
+ Log.i(TAG, "Handle SIM inserted.")
+ if (!isSuwFinished(mContext!!)) {
+ Log.i(TAG, "Still in SUW. Handle SIM insertion after SUW is finished")
+ setSuwRemovableSlotAction(mContext!!, LAST_USER_ACTION_IN_SUW_INSERT)
+ return
+ }
+ if (removableSlotInfo.ports.stream().findFirst().get().isActive) {
+ Log.i(TAG, "The removable slot is already active. Do nothing.")
+ return
+ }
+
+ if (hasActiveEsimSubscription()) {
+ if (mTelMgr!!.isMultiSimSupported() == TelephonyManager.MULTISIM_ALLOWED) {
+ Log.i(TAG, "Enabled profile exists. DSDS condition satisfied.")
+ if (Flags.isDualSimOnboardingEnabled()) {
+ // enable dsds by sim onboarding flow
+ handleRemovableSimInsertWhenDsds(removableSlotInfo)
+ } else {
+ startDsdsDialogActivity()
+ }
+ } else {
+ Log.i(TAG, "Enabled profile exists. DSDS condition not satisfied.")
+ startChooseSimActivity(true)
+ }
+ return
+ }
+
+ Log.i(
+ TAG,
+ "No enabled eSIM profile. Ready to switch to removable slot and show"
+ + " notification."
+ )
+ try {
+ UiccSlotUtil.switchToRemovableSlot(
+ UiccSlotUtil.INVALID_PHYSICAL_SLOT_ID, mContext!!.applicationContext
+ )
+ } catch (e: UiccSlotsException) {
+ Log.e(TAG, "Failed to switch to removable slot.")
+ return
+ }
+ SimNotificationService.scheduleSimNotification(
+ mContext, SimActivationNotifier.NotificationType.SWITCH_TO_REMOVABLE_SLOT
+ )
+ }
+
+ private fun handleSimRemove(removableSlotInfo: UiccSlotInfo) {
+ Log.i(TAG, "Handle SIM removed.")
+
+ if (!isSuwFinished(mContext!!)) {
+ Log.i(TAG, "Still in SUW. Handle SIM removal after SUW is finished")
+ setSuwRemovableSlotAction(mContext!!, LAST_USER_ACTION_IN_SUW_REMOVE)
+ return
+ }
+
+ val groupedEmbeddedSubscriptions =
+ groupedEmbeddedSubscriptions
+ if (groupedEmbeddedSubscriptions.isEmpty() || !removableSlotInfo.ports.stream()
+ .findFirst().get().isActive
+ ) {
+ Log.i(
+ TAG, ("eSIM slot is active or no subscriptions exist. Do nothing."
+ + " The removableSlotInfo: " + removableSlotInfo
+ + ", groupedEmbeddedSubscriptions: " + groupedEmbeddedSubscriptions)
+ )
+ return
+ }
+
+ // If there is only 1 eSIM profile exists, we ask the user if they want to switch to that
+ // profile.
+ if (groupedEmbeddedSubscriptions.size == 1) {
+ Log.i(TAG, "Only 1 eSIM profile found. Ask user's consent to switch.")
+ startSwitchSlotConfirmDialogActivity(groupedEmbeddedSubscriptions[0])
+ return
+ }
+
+ // If there are more than 1 eSIM profiles installed, we show a screen to let users to choose
+ // the number they want to use.
+ Log.i(TAG, "Multiple eSIM profiles found. Ask user which subscription to use.")
+ startChooseSimActivity(false)
+ }
+
+ private fun hasOtherActiveSubInfo(psimSubId: Int): Boolean {
+ val activeSubs = SubscriptionUtil.getActiveSubscriptions(mSubMgr)
+ return activeSubs.stream()
+ .anyMatch { subscriptionInfo -> subscriptionInfo.subscriptionId != psimSubId }
+ }
+
+ private fun hasAnyPortActiveInSlot(removableSlotInfo: UiccSlotInfo): Boolean {
+ return removableSlotInfo.ports.stream().anyMatch { slot -> slot.isActive }
+ }
+
+ private fun handleRemovableSimInsertWhenDsds(removableSlotInfo: UiccSlotInfo) {
+ Log.i(TAG, "ForNewUi: Handle Removable SIM inserted")
+ CoroutineScope(Dispatchers.Default + SupervisorJob()).launch {
+ withContext(Dispatchers.Default) {
+ val subscriptionInfos =
+ withTimeoutOrNull(DEFAULT_WAIT_AFTER_SIM_INSERTED_TIMEOUT_MILLIS) {
+ SubscriptionRepository(mContext!!)
+ .removableSubscriptionInfoListFlow()
+ .firstOrNull { it.isNotEmpty() }
+ }
+
+ if (subscriptionInfos.isNullOrEmpty()) {
+ Log.e(TAG, "Unable to find the removable subscriptionInfo. Do nothing.")
+ return@withContext
+ }
+ Log.d(
+ TAG,
+ "getAvailableRemovableSubscription:$subscriptionInfos"
+ )
+ val psimSubId = subscriptionInfos[0].subscriptionId
+ if (!hasAnyPortActiveInSlot(removableSlotInfo)
+ || hasOtherActiveSubInfo(psimSubId)) {
+ Log.d(TAG, "ForNewUi Start Setup flow")
+ startSimConfirmDialogActivity(psimSubId)
+ }
+ }
+ }
+ }
+
+ private fun handleRemovableSimInsertUnderDsdsMep(removableSlotInfo: UiccSlotInfo) {
+ Log.i(TAG, "Handle Removable SIM inserted under DSDS+Mep.")
+
+ if (removableSlotInfo.ports.stream().findFirst().get().isActive) {
+ Log.i(
+ TAG, "The removable slot is already active. Do nothing. removableSlotInfo: "
+ + removableSlotInfo
+ )
+ return
+ }
+
+ val subscriptionInfos =
+ availableRemovableSubscription
+ if (subscriptionInfos.isEmpty()) {
+ Log.e(TAG, "Unable to find the removable subscriptionInfo. Do nothing.")
+ return
+ }
+ Log.d(
+ TAG,
+ "getAvailableRemovableSubscription:$subscriptionInfos"
+ )
+ startSimConfirmDialogActivity(subscriptionInfos[0].subscriptionId)
+ }
+
+ private fun getLastRemovableSimSlotState(context: Context): Int {
+ val prefs = context.getSharedPreferences(EUICC_PREFS, Context.MODE_PRIVATE)
+ return prefs.getInt(KEY_REMOVABLE_SLOT_STATE, UiccSlotInfo.CARD_STATE_INFO_ABSENT)
+ }
+
+ private fun setRemovableSimSlotState(context: Context, state: Int) {
+ val prefs = context.getSharedPreferences(EUICC_PREFS, Context.MODE_PRIVATE)
+ prefs.edit().putInt(KEY_REMOVABLE_SLOT_STATE, state).apply()
+ Log.d(TAG, "setRemovableSimSlotState: $state")
+ }
+
+ private fun getSuwRemovableSlotAction(context: Context): Int {
+ val prefs = context.getSharedPreferences(EUICC_PREFS, Context.MODE_PRIVATE)
+ return prefs.getInt(KEY_SUW_PSIM_ACTION, LAST_USER_ACTION_IN_SUW_NONE)
+ }
+
+ private fun setSuwRemovableSlotAction(context: Context, action: Int) {
+ val prefs = context.getSharedPreferences(EUICC_PREFS, Context.MODE_PRIVATE)
+ prefs.edit().putInt(KEY_SUW_PSIM_ACTION, action).apply()
+ }
+
+ private val removableUiccSlotInfo: UiccSlotInfo?
+ get() {
+ val slotInfos = mTelMgr!!.uiccSlotsInfo
+ if (slotInfos == null) {
+ Log.e(
+ TAG,
+ "slotInfos is null. Unable to get slot infos."
+ )
+ return null
+ }
+ for (slotInfo in slotInfos) {
+ if (slotInfo != null && slotInfo.isRemovable) {
+ return slotInfo
+ }
+ }
+ return null
+ }
+
+ private fun hasActiveEsimSubscription(): Boolean {
+ val activeSubs = SubscriptionUtil.getActiveSubscriptions(mSubMgr)
+ return activeSubs.stream().anyMatch { subscriptionInfo -> subscriptionInfo.isEmbedded }
+ }
+
+ private val groupedEmbeddedSubscriptions: List<SubscriptionInfo>
+ get() {
+ val groupedSubscriptions =
+ SubscriptionUtil.getSelectableSubscriptionInfoList(mContext)
+ ?: return ImmutableList.of()
+ return ImmutableList.copyOf(
+ groupedSubscriptions.stream()
+ .filter { sub: SubscriptionInfo -> sub.isEmbedded }
+ .collect(Collectors.toList()))
+ }
+
+ protected val availableRemovableSubscription: List<SubscriptionInfo>
+ get() {
+ val removableSubscriptions =
+ SubscriptionUtil.getAvailableSubscriptions(mContext)
+ return ImmutableList.copyOf(
+ removableSubscriptions.stream()
+ // ToDo: This condition is for psim only. If device supports removable
+ // esim, it needs an new condition.
+ .filter { sub: SubscriptionInfo -> !sub.isEmbedded }
+ .collect(Collectors.toList()))
+ }
+
+ private fun startChooseSimActivity(psimInserted: Boolean) {
+ val intent = ChooseSimActivity.getIntent(mContext)
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ intent.putExtra(ChooseSimActivity.KEY_HAS_PSIM, psimInserted)
+ mContext!!.startActivityAsUser(intent, UserHandle.SYSTEM)
+ }
+
+ private fun startSwitchSlotConfirmDialogActivity(subscriptionInfo: SubscriptionInfo) {
+ val intent = Intent(
+ mContext,
+ SwitchToEsimConfirmDialogActivity::class.java
+ )
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ intent.putExtra(SwitchToEsimConfirmDialogActivity.KEY_SUB_TO_ENABLE, subscriptionInfo)
+ mContext!!.startActivityAsUser(intent, UserHandle.SYSTEM)
+ }
+
+ private fun startDsdsDialogActivity() {
+ val intent = Intent(mContext, DsdsDialogActivity::class.java)
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
+ mContext!!.startActivityAsUser(intent, UserHandle.SYSTEM)
+ }
+
+ private fun startSimConfirmDialogActivity(subId: Int) {
+ if (!isSuwFinished(mContext!!)) {
+ Log.d(TAG, "Still in SUW. Do nothing")
+ return
+ }
+ if (!SubscriptionManager.isUsableSubscriptionId(subId)) {
+ Log.i(TAG, "Unable to enable subscription due to invalid subscription ID.")
+ return
+ }
+ Log.d(
+ TAG,
+ "Start ToggleSubscriptionDialogActivity with $subId under DSDS+Mep."
+ )
+ SubscriptionUtil.startToggleSubscriptionDialogActivity(mContext, subId, true, true)
+ }
+
+ private val isMultipleEnabledProfilesSupported: Boolean
+ get() {
+ val cardInfos = mTelMgr!!.uiccCardsInfo
+ if (cardInfos == null) {
+ Log.d(
+ TAG,
+ "UICC cards info list is empty."
+ )
+ return false
+ }
+ return cardInfos.stream()
+ .anyMatch { cardInfo: UiccCardInfo -> cardInfo.isMultipleEnabledProfilesSupported }
+ }
+
+ private fun isSuwFinished(context: Context): Boolean {
+ try {
+ // DEVICE_PROVISIONED is 0 if still in setup wizard. 1 if setup completed.
+ return (Settings.Global.getInt(
+ context.contentResolver, Settings.Global.DEVICE_PROVISIONED)
+ == 1)
+ } catch (e: SettingNotFoundException) {
+ Log.e(TAG, "Cannot get DEVICE_PROVISIONED from the device.", e)
+ return false
+ }
+ }
+
+ companion object {
+ private const val TAG = "SimSlotChangeHandler"
+
+ private const val EUICC_PREFS = "euicc_prefs"
+
+ // Shared preference keys
+ private const val KEY_REMOVABLE_SLOT_STATE = "removable_slot_state"
+ private const val KEY_SUW_PSIM_ACTION = "suw_psim_action"
+
+ // User's last removable SIM insertion / removal action during SUW.
+ private const val LAST_USER_ACTION_IN_SUW_NONE = 0
+ private const val LAST_USER_ACTION_IN_SUW_INSERT = 1
+ private const val LAST_USER_ACTION_IN_SUW_REMOVE = 2
+
+ private const val DEFAULT_WAIT_AFTER_SIM_INSERTED_TIMEOUT_MILLIS: Long = 25 * 1000L
+
+ @Volatile
+ private var slotChangeHandler: SimSlotChangeHandler? = null
+
+ /** Returns a SIM slot change handler singleton. */
+ @JvmStatic
+ fun get(): SimSlotChangeHandler? {
+ if (slotChangeHandler == null) {
+ synchronized(SimSlotChangeHandler::class.java) {
+ if (slotChangeHandler == null) {
+ slotChangeHandler = SimSlotChangeHandler()
+ }
+ }
+ }
+ return slotChangeHandler
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragmentTest.java
index 5973d26..552a4a7 100644
--- a/tests/robotests/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilityShortcutPreferenceFragmentTest.java
@@ -19,7 +19,6 @@
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.HARDWARE;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.QUICK_SETTINGS;
import static com.android.internal.accessibility.common.ShortcutConstants.UserShortcutType.SOFTWARE;
-import static com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType;
import static com.google.common.truth.Truth.assertThat;
@@ -37,7 +36,6 @@
import android.content.Intent;
import android.icu.text.CaseMap;
import android.os.Bundle;
-import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
import android.view.LayoutInflater;
import android.view.View;
@@ -57,7 +55,6 @@
import com.android.settings.testutils.shadow.ShadowFragment;
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
@@ -83,18 +80,11 @@
PLACEHOLDER_PACKAGE_NAME + "tile.placeholder";
private static final ComponentName PLACEHOLDER_COMPONENT_NAME = new ComponentName(
PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_CLASS_NAME);
- private static final ComponentName PLACEHOLDER_TILE_COMPONENT_NAME = new ComponentName(
- PLACEHOLDER_PACKAGE_NAME, PLACEHOLDER_TILE_CLASS_NAME);
- private static final String PLACEHOLDER_TILE_TOOLTIP_CONTENT =
- PLACEHOLDER_PACKAGE_NAME + "tooltip_content";
- private static final String PLACEHOLDER_DIALOG_TITLE = "title";
private static final String SOFTWARE_SHORTCUT_KEY =
Settings.Secure.ACCESSIBILITY_BUTTON_TARGETS;
private static final String HARDWARE_SHORTCUT_KEY =
Settings.Secure.ACCESSIBILITY_SHORTCUT_TARGET_SERVICE;
- @Rule
- public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
private TestAccessibilityShortcutPreferenceFragment mFragment;
private PreferenceScreen mScreen;
private Context mContext = ApplicationProvider.getApplicationContext();
@@ -153,14 +143,6 @@
@Test
@Config(shadows = ShadowFragment.class)
- public void showQuickSettingsTooltipIfNeeded_dontShowTooltipView() {
- mFragment.showQuickSettingsTooltipIfNeeded(QuickSettingsTooltipType.GUIDE_TO_EDIT);
-
- assertThat(getLatestPopupWindow()).isNull();
- }
-
- @Test
- @Config(shadows = ShadowFragment.class)
public void showGeneralCategory_shouldInitCategory() {
final Bundle savedInstanceState = new Bundle();
when(mFragment.showGeneralCategory()).thenReturn(true);
@@ -261,16 +243,6 @@
}
@Override
- protected ComponentName getTileComponentName() {
- return PLACEHOLDER_TILE_COMPONENT_NAME;
- }
-
- @Override
- protected CharSequence getTileTooltipContent(@QuickSettingsTooltipType int type) {
- return PLACEHOLDER_TILE_TOOLTIP_CONTENT;
- }
-
- @Override
public int getUserShortcutTypes() {
return 0;
}
diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
index 86322f9..6dbb8b5 100644
--- a/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/ToggleFeaturePreferenceFragmentTest.java
@@ -316,14 +316,6 @@
}
@Test
- @Config(shadows = ShadowFragment.class)
- public void showQuickSettingsTooltipIfNeeded_dontShowTooltipView() {
- mFragment.showQuickSettingsTooltipIfNeeded(QuickSettingsTooltipType.GUIDE_TO_EDIT);
-
- assertThat(getLatestPopupWindow()).isNull();
- }
-
- @Test
public void getShortcutTypeSummary_shortcutSummaryIsCorrectlySet() {
final PreferredShortcut userPreferredShortcut = new PreferredShortcut(
PLACEHOLDER_COMPONENT_NAME.flattenToString(),
diff --git a/tests/robotests/src/com/android/settings/connecteddevice/display/DisplayTopologyPreferenceTest.kt b/tests/robotests/src/com/android/settings/connecteddevice/display/DisplayTopologyPreferenceTest.kt
new file mode 100644
index 0000000..ad633cc
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/connecteddevice/display/DisplayTopologyPreferenceTest.kt
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2024 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.connecteddevice.display
+
+import android.hardware.display.DisplayTopology.TreeNode.POSITION_LEFT
+
+import android.content.Context
+import android.graphics.Color
+import android.graphics.drawable.Drawable
+import android.graphics.drawable.ColorDrawable
+import android.hardware.display.DisplayTopology
+import android.view.View
+import android.widget.FrameLayout
+import androidx.preference.PreferenceViewHolder
+import androidx.test.core.app.ApplicationProvider
+
+import com.android.settings.R
+import com.google.common.truth.Truth.assertThat
+
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.robolectric.RobolectricTestRunner
+
+@RunWith(RobolectricTestRunner::class)
+class DisplayTopologyPreferenceTest {
+ val context = ApplicationProvider.getApplicationContext<Context>()
+ val preference = DisplayTopologyPreference(context)
+ val injector = TestInjector()
+ val rootView = View.inflate(context, preference.layoutResource, /*parent=*/ null)
+ val holder = PreferenceViewHolder.createInstanceForTests(rootView)
+ val wallpaper = ColorDrawable(Color.MAGENTA)
+
+ init {
+ preference.injector = injector
+ injector.systemWallpaper = wallpaper
+ preference.onBindViewHolder(holder)
+ }
+
+ class TestInjector : DisplayTopologyPreference.Injector() {
+ var topology : DisplayTopology? = null
+ var systemWallpaper : Drawable? = null
+
+ override fun displayTopology(context : Context) : DisplayTopology? { return topology }
+
+ override fun wallpaper(context : Context) : Drawable { return systemWallpaper!! }
+ }
+
+ @Test
+ fun disabledTopology() {
+ preference.onAttached()
+ preference.onGlobalLayout()
+
+ assertThat(preference.mPaneContent.childCount).isEqualTo(0)
+ // TODO(b/352648432): update test when we show the main display even when
+ // a topology is not active.
+ assertThat(preference.mTopologyHint.text).isEqualTo("")
+ }
+
+ @Test
+ fun twoDisplaysGenerateBlocks() {
+ val child = DisplayTopology.TreeNode(
+ /* displayId= */ 42, /* width= */ 100f, /* height= */ 80f,
+ POSITION_LEFT, /* offset= */ 42f)
+ val root = DisplayTopology.TreeNode(
+ /* displayId= */ 0, /* width= */ 200f, /* height= */ 160f,
+ POSITION_LEFT, /* offset= */ 0f)
+ root.addChild(child)
+ injector.topology = DisplayTopology(root, /*primaryDisplayId=*/ 0)
+
+ // This layoutParams needs to be non-null for the global layout handler.
+ preference.mPaneHolder.layoutParams = FrameLayout.LayoutParams(
+ /* width= */ 640, /* height= */ 480)
+
+ // Force pane width to have a reasonable value (hundreds of dp) so the TopologyScale is
+ // calculated reasonably.
+ preference.mPaneContent.left = 0
+ preference.mPaneContent.right = 640
+
+ preference.onAttached()
+ preference.onGlobalLayout()
+
+ assertThat(preference.mPaneContent.childCount).isEqualTo(2)
+ val block0 = preference.mPaneContent.getChildAt(0)
+ val block1 = preference.mPaneContent.getChildAt(1)
+
+ // Block of child display is on the left.
+ val (childBlock, rootBlock) = if (block0.x < block1.x)
+ listOf(block0, block1)
+ else
+ listOf(block1, block0)
+
+ // After accounting for padding, child should be half the length of root in each dimension.
+ assertThat(childBlock.layoutParams.width + BLOCK_PADDING)
+ .isEqualTo(rootBlock.layoutParams.width / 2)
+ assertThat(childBlock.layoutParams.height + BLOCK_PADDING)
+ .isEqualTo(rootBlock.layoutParams.height / 2)
+ assertThat(childBlock.y).isGreaterThan(rootBlock.y)
+ assertThat(block0.background).isEqualTo(wallpaper)
+ assertThat(block1.background).isEqualTo(wallpaper)
+ assertThat(rootBlock.x - BLOCK_PADDING * 2)
+ .isEqualTo(childBlock.x + childBlock.layoutParams.width)
+
+ assertThat(preference.mTopologyHint.text)
+ .isEqualTo(context.getString(R.string.external_display_topology_hint))
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/datetime/AutoTimeFormatPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/datetime/AutoTimeFormatPreferenceControllerTest.java
deleted file mode 100644
index f9b566e..0000000
--- a/tests/robotests/src/com/android/settings/datetime/AutoTimeFormatPreferenceControllerTest.java
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * Copyright (C) 2017 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.datetime;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.content.Context;
-import android.content.Intent;
-import android.provider.Settings;
-import android.text.format.DateFormat;
-
-import androidx.preference.SwitchPreference;
-
-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;
-import org.robolectric.shadows.ShadowApplication;
-
-import java.util.List;
-import java.util.Locale;
-
-@RunWith(RobolectricTestRunner.class)
-public class AutoTimeFormatPreferenceControllerTest {
-
- @Mock
- private UpdateTimeAndDateCallback mCallback;
-
- private ShadowApplication mApplication;
- private Context mContext;
- private SwitchPreference mPreference;
- private TestAutoTimeFormatPreferenceController mController;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mApplication = ShadowApplication.getInstance();
- mContext = RuntimeEnvironment.application;
- mController = new TestAutoTimeFormatPreferenceController(mContext, "test_key");
- mPreference = new SwitchPreference(mContext);
- mPreference.setKey("test_key");
- }
-
- @Test
- public void updateState_24HourSet_shouldCheckPreference() {
- Settings.System.putString(mContext.getContentResolver(), Settings.System.TIME_12_24,
- TimeFormatPreferenceController.HOURS_24);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isChecked()).isFalse();
- }
-
- @Test
- public void updateState_12HourSet_shouldCheckPreference() {
- Settings.System.putString(mContext.getContentResolver(), Settings.System.TIME_12_24,
- TimeFormatPreferenceController.HOURS_12);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isChecked()).isFalse();
- }
-
- @Test
- public void updateState_autoSet_shouldNotCheckPreference() {
- Settings.System.putString(mContext.getContentResolver(), Settings.System.TIME_12_24, null);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isChecked()).isTrue();
- }
-
- @Test
- public void updatePreference_autoSet_shouldSendIntent_12HourLocale() {
- mController.setChecked(false);
-
- List<Intent> intentsFired = mApplication.getBroadcastIntents();
- assertThat(intentsFired.size()).isEqualTo(1);
- Intent intentFired = intentsFired.get(0);
- assertThat(intentFired.getAction()).isEqualTo(Intent.ACTION_TIME_CHANGED);
- assertThat(intentFired.getIntExtra(Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT, -1))
- .isEqualTo(Intent.EXTRA_TIME_PREF_VALUE_USE_12_HOUR);
- }
-
- @Test
- public void updatePreference_autoSet_shouldSendIntent_24HourLocale() {
- mController.setIs24HourLocale(true);
-
- mController.setChecked(false);
-
- List<Intent> intentsFired = mApplication.getBroadcastIntents();
- assertThat(intentsFired.size()).isEqualTo(1);
- Intent intentFired = intentsFired.get(0);
- assertThat(intentFired.getAction()).isEqualTo(Intent.ACTION_TIME_CHANGED);
- assertThat(intentFired.getIntExtra(Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT, -1))
- .isEqualTo(Intent.EXTRA_TIME_PREF_VALUE_USE_24_HOUR);
- }
-
- @Test
- public void updatePreference_24HourSet_shouldSendIntent() {
- mController.setIs24HourLocale(false);
-
- mController.setChecked(true);
-
- List<Intent> intentsFired = mApplication.getBroadcastIntents();
- assertThat(intentsFired.size()).isEqualTo(1);
- Intent intentFired = intentsFired.get(0);
- assertThat(intentFired.getAction()).isEqualTo(Intent.ACTION_TIME_CHANGED);
- assertThat(intentFired.getIntExtra(Intent.EXTRA_TIME_PREF_24_HOUR_FORMAT, -1))
- .isEqualTo(Intent.EXTRA_TIME_PREF_VALUE_USE_LOCALE_DEFAULT);
- }
-
- /**
- * Extend class under test to change {@link #is24HourLocale} to not call
- * {@link DateFormat#is24HourLocale(Locale)} because that's not available in roboelectric.
- */
- private static class TestAutoTimeFormatPreferenceController
- extends AutoTimeFormatPreferenceController {
-
- private boolean is24HourLocale = false;
-
- TestAutoTimeFormatPreferenceController(Context context, String preferenceKey) {
- super(context, preferenceKey);
- }
-
- void setIs24HourLocale(boolean value) {
- is24HourLocale = value;
- }
-
- @Override
- boolean is24HourLocale(Locale locale) {
- return is24HourLocale;
- }
- }
-}
diff --git a/tests/robotests/src/com/android/settings/datetime/AutoTimeZonePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/datetime/AutoTimeZonePreferenceControllerTest.java
index 7bf8d52..2961935 100644
--- a/tests/robotests/src/com/android/settings/datetime/AutoTimeZonePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/datetime/AutoTimeZonePreferenceControllerTest.java
@@ -40,17 +40,12 @@
import android.app.time.TimeZoneDetectorStatus;
import android.content.Context;
import android.os.UserHandle;
-import android.platform.test.annotations.DisableFlags;
-import android.platform.test.annotations.EnableFlags;
-import android.platform.test.flag.junit.SetFlagsRule;
import androidx.preference.Preference;
import com.android.settings.R;
-import com.android.settings.flags.Flags;
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -62,9 +57,6 @@
@RunWith(RobolectricTestRunner.class)
public class AutoTimeZonePreferenceControllerTest {
- @Rule
- public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
-
@Mock
private UpdateTimeAndDateCallback mCallback;
private Context mContext;
@@ -247,7 +239,6 @@
}
@Test
- @EnableFlags({Flags.FLAG_REVAMP_TOGGLES})
public void toggleOff_revampFlagOn_shouldToggleOffUseLocation() {
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = createCapabilitiesAndConfig(
/* autoSupported= */ true,
@@ -266,25 +257,6 @@
verify(mTimeManager).updateTimeZoneConfiguration(configuration);
}
- @Test
- @DisableFlags({Flags.FLAG_REVAMP_TOGGLES})
- public void toggleOff_revampFlagOff_shouldToggleOffUseLocation() {
- TimeZoneCapabilitiesAndConfig capabilitiesAndConfig = createCapabilitiesAndConfig(
- /* autoSupported= */ true,
- /* autoEnabled= */ true,
- /* telephonySupported= */ true,
- /* locationSupported= */ true);
- when(mTimeManager.getTimeZoneCapabilitiesAndConfig()).thenReturn(capabilitiesAndConfig);
-
- mController.setChecked(false);
-
- TimeZoneConfiguration configuration = new TimeZoneConfiguration.Builder()
- .setAutoDetectionEnabled(false)
- .build();
-
- verify(mTimeManager).updateTimeZoneConfiguration(configuration);
- }
-
private static TimeZoneCapabilitiesAndConfig createCapabilitiesAndConfig(
boolean autoSupported, boolean autoEnabled, boolean telephonySupported) {
return createCapabilitiesAndConfig(autoSupported, autoEnabled, telephonySupported, false);
diff --git a/tests/robotests/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceControllerTest.java
index 40794d2..2f23257 100644
--- a/tests/robotests/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/datetime/LocationTimeZoneDetectionPreferenceControllerTest.java
@@ -45,17 +45,13 @@
import android.app.time.TimeZoneDetectorStatus;
import android.content.Context;
import android.os.UserHandle;
-import android.platform.test.annotations.EnableFlags;
-import android.platform.test.flag.junit.SetFlagsRule;
import androidx.preference.SwitchPreference;
import com.android.settings.R;
import com.android.settings.core.InstrumentedPreferenceFragment;
-import com.android.settings.flags.Flags;
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
@@ -71,9 +67,6 @@
})
public class LocationTimeZoneDetectionPreferenceControllerTest {
- @Rule
- public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
-
@Mock
private TimeManager mTimeManager;
private Context mContext;
@@ -131,8 +124,7 @@
}
@Test
- @EnableFlags({Flags.FLAG_REVAMP_TOGGLES})
- public void flagRevampTogglesOn_toggleOff_automaticTimeZone_disablesLocationToggle() {
+ public void toggleOff_automaticTimeZone_disablesLocationToggle() {
TimeZoneCapabilitiesAndConfig capabilitiesAndConfig =
createTimeZoneCapabilitiesAndConfig(/* useLocationEnabled= */ true,
CAPABILITY_POSSESSED, /* setAutoDetectionEnabled= */ false);
diff --git a/tests/robotests/src/com/android/settings/datetime/TimeFormatPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/datetime/TimeFormatPreferenceControllerTest.java
index c5aac84..a341922 100644
--- a/tests/robotests/src/com/android/settings/datetime/TimeFormatPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/datetime/TimeFormatPreferenceControllerTest.java
@@ -23,16 +23,11 @@
import android.content.Context;
import android.content.Intent;
-import android.platform.test.annotations.DisableFlags;
-import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
import androidx.preference.SwitchPreference;
-import com.android.settings.flags.Flags;
-
import org.junit.Before;
-import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -46,9 +41,6 @@
@RunWith(RobolectricTestRunner.class)
public class TimeFormatPreferenceControllerTest {
- @Rule
- public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
-
@Mock
private UpdateTimeAndDateCallback mCallback;
@@ -105,16 +97,6 @@
}
@Test
- @DisableFlags({Flags.FLAG_REVAMP_TOGGLES})
- public void updateState_autoSet_shouldNotEnablePreference() {
- Settings.System.putString(mContext.getContentResolver(), Settings.System.TIME_12_24, null);
-
- mController.updateState(mPreference);
-
- assertThat(mPreference.isEnabled()).isFalse();
- }
-
- @Test
public void updatePreference_12HourSet_shouldSendIntent() {
mController.setChecked(false);
diff --git a/tests/robotests/src/com/android/settings/gestures/OneHandedSettingsTest.java b/tests/robotests/src/com/android/settings/gestures/OneHandedSettingsTest.java
index a03ca61..1ce6c3f 100644
--- a/tests/robotests/src/com/android/settings/gestures/OneHandedSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/gestures/OneHandedSettingsTest.java
@@ -21,7 +21,6 @@
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
import android.content.Context;
import android.os.SystemProperties;
@@ -32,8 +31,6 @@
import androidx.test.core.app.ApplicationProvider;
-import com.android.settings.R;
-import com.android.settings.accessibility.AccessibilityUtil.QuickSettingsTooltipType;
import com.android.settingslib.search.SearchIndexableRaw;
import org.junit.Before;
@@ -63,21 +60,6 @@
}
@Test
- public void getTileTooltipContent_returnsExpectedValues() {
- // Simulate to call getTileTooltipContent after onDetach
- assertThat(mSettings.getTileTooltipContent(QuickSettingsTooltipType.GUIDE_TO_EDIT))
- .isNull();
- // Simulate to call getTileTooltipContent after onAttach
- when(mSettings.getContext()).thenReturn(mContext);
- assertThat(mSettings.getTileTooltipContent(QuickSettingsTooltipType.GUIDE_TO_EDIT))
- .isEqualTo(mContext.getText(
- R.string.accessibility_one_handed_mode_qs_tooltip_content));
- assertThat(mSettings.getTileTooltipContent(QuickSettingsTooltipType.GUIDE_TO_DIRECT_USE))
- .isEqualTo(mContext.getText(
- R.string.accessibility_one_handed_mode_auto_added_qs_tooltip_content));
- }
-
- @Test
public void getLogTag_returnsCorrectTag() {
assertThat(mSettings.getLogTag()).isEqualTo("OneHandedSettings");
}
diff --git a/tests/unit/src/com/android/settings/accessibility/ReduceBrightColorsIntensityPreferenceControllerTest.java b/tests/unit/src/com/android/settings/accessibility/ReduceBrightColorsIntensityPreferenceControllerTest.java
index c3ccf34..96d9583 100644
--- a/tests/unit/src/com/android/settings/accessibility/ReduceBrightColorsIntensityPreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/accessibility/ReduceBrightColorsIntensityPreferenceControllerTest.java
@@ -24,20 +24,29 @@
import android.content.Context;
import android.content.res.Resources;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.provider.Settings;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import com.android.internal.R;
+import com.android.server.display.feature.flags.Flags;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+/** Tests for {@link ReduceBrightColorsIntensityPreferenceController} */
@RunWith(AndroidJUnit4.class)
public class ReduceBrightColorsIntensityPreferenceControllerTest {
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
private Context mContext;
private Resources mResources;
private ReduceBrightColorsIntensityPreferenceController mPreferenceController;
@@ -52,27 +61,119 @@
}
@Test
- public void isAvailable_configuredRbcAvailable_enabledRbc_shouldReturnTrue() {
+ @DisableFlags(Flags.FLAG_EVEN_DIMMER)
+ public void isAvailable_whenEvenDimmerOffAndDisabled_RbcOnAndAvailable_returnTrue() {
+ doReturn(false).when(mResources).getBoolean(
+ com.android.internal.R.bool.config_evenDimmerEnabled);
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, 1);
doReturn(true).when(mResources).getBoolean(
R.bool.config_reduceBrightColorsAvailable);
+
assertThat(mPreferenceController.isAvailable()).isTrue();
}
+
@Test
- public void isAvailable_configuredRbcAvailable_disabledRbc_shouldReturnTrue() {
+ @DisableFlags(Flags.FLAG_EVEN_DIMMER)
+ public void isAvailable_whenEvenDimmerOffAndDisabled_RbcOffAndAvailable_returnTrue() {
+ doReturn(false).when(mResources).getBoolean(
+ com.android.internal.R.bool.config_evenDimmerEnabled);
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, 0);
doReturn(true).when(mResources).getBoolean(
R.bool.config_reduceBrightColorsAvailable);
+
assertThat(mPreferenceController.isAvailable()).isTrue();
}
+
@Test
- public void isAvailable_configuredRbcUnavailable_enabledRbc_shouldReturnFalse() {
+ @DisableFlags(Flags.FLAG_EVEN_DIMMER)
+ public void isAvailable_whenEvenDimmerOffAndDisabled_RbcOnAndUnavailable_returnFalse() {
+ doReturn(false).when(mResources).getBoolean(
+ com.android.internal.R.bool.config_evenDimmerEnabled);
Settings.Secure.putInt(mContext.getContentResolver(),
Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, 1);
doReturn(false).when(mResources).getBoolean(
R.bool.config_reduceBrightColorsAvailable);
+
+ assertThat(mPreferenceController.isAvailable()).isFalse();
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_EVEN_DIMMER)
+ public void isAvailable_whenEvenDimmerOnAndDisabled_RbcOnAndAvailable_returnTrue() {
+ doReturn(false).when(mResources).getBoolean(
+ com.android.internal.R.bool.config_evenDimmerEnabled);
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, 1);
+ doReturn(true).when(mResources).getBoolean(
+ R.bool.config_reduceBrightColorsAvailable);
+
+ assertThat(mPreferenceController.isAvailable()).isTrue();
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_EVEN_DIMMER)
+ public void isAvailable_whenEvenDimmerOnAndDisabled_RbcOffAndAvailable_returnTrue() {
+ doReturn(false).when(mResources).getBoolean(
+ com.android.internal.R.bool.config_evenDimmerEnabled);
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, 0);
+ doReturn(true).when(mResources).getBoolean(
+ R.bool.config_reduceBrightColorsAvailable);
+
+ assertThat(mPreferenceController.isAvailable()).isTrue();
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_EVEN_DIMMER)
+ public void isAvailable_whenEvenDimmerOnAndDisabled_RbcOnAndUnavailable_returnFalse() {
+ doReturn(false).when(mResources).getBoolean(
+ com.android.internal.R.bool.config_evenDimmerEnabled);
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, 1);
+ doReturn(false).when(mResources).getBoolean(
+ R.bool.config_reduceBrightColorsAvailable);
+
+ assertThat(mPreferenceController.isAvailable()).isFalse();
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_EVEN_DIMMER)
+ public void isAvailable_whenEvenDimmerOnAndEnabled_RbcOnAndAvailable_returnFalse() {
+ doReturn(true).when(mResources).getBoolean(
+ com.android.internal.R.bool.config_evenDimmerEnabled);
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, 1);
+ doReturn(true).when(mResources).getBoolean(
+ R.bool.config_reduceBrightColorsAvailable);
+
+ assertThat(mPreferenceController.isAvailable()).isFalse();
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_EVEN_DIMMER)
+ public void isAvailable_whenEvenDimmerOnAndEnabled_RbcOffAndAvailable_returnFalse() {
+ doReturn(true).when(mResources).getBoolean(
+ com.android.internal.R.bool.config_evenDimmerEnabled);
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, 0);
+ doReturn(true).when(mResources).getBoolean(
+ R.bool.config_reduceBrightColorsAvailable);
+
+ assertThat(mPreferenceController.isAvailable()).isFalse();
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_EVEN_DIMMER)
+ public void isAvailable_whenEvenDimmerOnAndEnabled_RbcOnAndUnavailable_returnFalse() {
+ doReturn(true).when(mResources).getBoolean(
+ com.android.internal.R.bool.config_evenDimmerEnabled);
+ Settings.Secure.putInt(mContext.getContentResolver(),
+ Settings.Secure.REDUCE_BRIGHT_COLORS_ACTIVATED, 1);
+ doReturn(false).when(mResources).getBoolean(
+ R.bool.config_reduceBrightColorsAvailable);
+
assertThat(mPreferenceController.isAvailable()).isFalse();
}
diff --git a/tests/unit/src/com/android/settings/language/LanguagePreferenceControllerTest.java b/tests/unit/src/com/android/settings/language/LanguagePreferenceControllerTest.java
index 656fa27..2209355 100644
--- a/tests/unit/src/com/android/settings/language/LanguagePreferenceControllerTest.java
+++ b/tests/unit/src/com/android/settings/language/LanguagePreferenceControllerTest.java
@@ -21,18 +21,24 @@
import android.content.ComponentName;
import android.content.Context;
import android.content.pm.PackageManager;
+import android.platform.test.annotations.DisableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.Settings;
+import com.android.settings.flags.Flags;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
public class LanguagePreferenceControllerTest {
private Context mContext;
private LanguagePreferenceController mController;
+ @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
@Before
public void setup() {
mContext = ApplicationProvider.getApplicationContext();
@@ -40,6 +46,7 @@
}
@Test
+ @DisableFlags(Flags.FLAG_REGIONAL_PREFERENCES_API_ENABLED)
public void getAvailabilityStatus_featureFlagOff_LanguageSettingsActivitydisabled() {
mController.getAvailabilityStatus();
diff --git a/tests/unit/src/com/android/settings/network/telephony/CellInfoUtilTest.kt b/tests/unit/src/com/android/settings/network/telephony/CellInfoUtilTest.kt
index 27b5c38..c6974ab 100644
--- a/tests/unit/src/com/android/settings/network/telephony/CellInfoUtilTest.kt
+++ b/tests/unit/src/com/android/settings/network/telephony/CellInfoUtilTest.kt
@@ -24,6 +24,7 @@
import com.android.settings.network.telephony.CellInfoUtil.getNetworkTitle
import com.android.settings.network.telephony.CellInfoUtil.getOperatorNumeric
import com.google.common.truth.Truth.assertThat
+import org.junit.Ignore
import org.junit.Test
import org.junit.runner.RunWith
@@ -95,6 +96,7 @@
}
@Test
+ @Ignore("b/383858953")
fun cellInfoListToString() {
val cellInfoList =
listOf(