Merge "Redirect AdvancedSecuritySettings to MoreSettings"
diff --git a/res/drawable/ic_fast_pair_24dp.xml b/res/drawable/ic_fast_pair_24dp.xml
deleted file mode 100644
index 17bfdd9..0000000
--- a/res/drawable/ic_fast_pair_24dp.xml
+++ /dev/null
@@ -1,36 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
- ~ Copyright (C) 2022 The Android Open Source Project
- ~
- ~ Licensed under the Apache License, Version 2.0 (the "License");
- ~ you may not use this file except in compliance with the License.
- ~ You may obtain a copy of the License at
- ~
- ~ http://www.apache.org/licenses/LICENSE-2.0
- ~
- ~ Unless required by applicable law or agreed to in writing, software
- ~ distributed under the License is distributed on an "AS IS" BASIS,
- ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- ~ See the License for the specific language governing permissions and
- ~ limitations under the License.
- -->
-<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24"
- android:tint="?android:attr/colorControlNormal">
-
- <path
- android:fillColor="#FF000000"
- android:pathData="M20.65,19.27c-0.35,0-0.69-0.13-0.96-0.4l-8.66-8.66c-0.53-0.53-0.53-1.38,0-1.91 c0.53-0.53,1.38-0.53,1.91,0l8.66,8.66c0.53,0.53,0.53,1.38,0,1.91C21.34,19.14,20.99,19.27,20.65,19.27z" />
- <path
- android:fillColor="#FF000000"
- android:pathData="M12.01,16.09c-0.35,0-0.69-0.13-0.96-0.4L2.4,7.04c-0.53-0.53-0.53-1.38,0-1.91s1.38-0.53,1.91,0l8.66,8.66 c0.53,0.53,0.53,1.38,0,1.91C12.7,15.96,12.36,16.09,12.01,16.09z" />
- <path
- android:fillColor="#FF000000"
- android:pathData="M6.32,19.06c0-0.34,0.13-0.69,0.4-0.95l1.85-1.85c0.53-0.53,1.38-0.53,1.91,0c0.53,0.53,0.53,1.38,0,1.91 l-1.85,1.85c-0.53,0.53-1.38,0.53-1.91,0C6.45,19.75,6.32,19.4,6.32,19.06z" />
- <path
- android:fillColor="#FF000000"
- android:pathData="M13.13,6.79c0-0.34,0.13-0.69,0.4-0.95l1.85-1.85c0.53-0.53,1.38-0.53,1.91,0c0.53,0.53,0.53,1.38,0,1.91 l-1.85,1.85c-0.53,0.53-1.38,0.53-1.91,0C13.27,7.48,13.13,7.13,13.13,6.79z" />
-</vector>
\ No newline at end of file
diff --git a/res/values/config.xml b/res/values/config.xml
index df2bae3..628699a 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -689,4 +689,7 @@
58.0001 29.2229,56.9551 26.8945,55.195
</string>
+ <!-- Whether auto data switching on secondary SIM enables cross-SIM calling on both SIMs. -->
+ <bool name="config_auto_data_switch_enables_cross_sim_calling">false</bool>
+
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 5d32022..23f7a9f 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -4080,6 +4080,18 @@
<string name="experimental_category_title">Experimental</string>
<!-- Title for feature flags dashboard where developers can turn on experimental features [CHAR LIMIT=50] -->
<string name="feature_flags_dashboard_title">Feature flags</string>
+ <!-- Title for snoop logger filters dashboard where developers can turn on filters [CHAR LIMIT=50] -->
+ <string name="snoop_logger_filters_dashboard_title">Snoop Logger Filters</string>
+ <!-- Summary for the snoop logger filters [CHAR LIMIT=50] -->
+ <string name="bt_hci_snoop_log_filters_dashboard_summary">Set filters (Toggle Bluetooth after changing this setting)</string>
+ <!-- Title for the snoop logger pbap filter [CHAR LIMIT=50] -->
+ <string name="bt_hci_snoop_log_filter_pbap_title">Snoop Logger Filter PBAP</string>
+ <!-- Title for the snoop logger map filter [CHAR LIMIT=50] -->
+ <string name="bt_hci_snoop_log_filter_map_title">Snoop Logger Filter MAP</string>
+ <!-- Summary for the snoop logger filters [CHAR LIMIT=50] -->
+ <string name="bt_hci_snoop_log_filter_summary">Set filtering mode. (Toggle Bluetooth after changing this setting)</string>
+ <!-- Summary for the snoop logger profile filters while disabled [CHAR LIMIT=50] -->
+ <string name="bt_hci_snoop_log_filtered_mode_disabled_summary">Enable Snoop Log Mode Filtered to change this option.</string>
<!-- Title for the Talkback Accessibility Service. Displayed on the Accessibility Settings screen in Setup Wizard. [CHAR_LIMIT=25] -->
<string name="talkback_title">Talkback</string>
<!-- Summary for the Talkback Accessibility Service. Lets the user know that Talkback is a screenreader and that it is usually most helpful to blind and low vision users and whether the service is on. [CHAR_LIMIT=none] -->
@@ -4828,19 +4840,6 @@
<!-- List of synonyms used in the settings search bar to find the “Voice Access”. [CHAR LIMIT=NONE] -->
<string name="keywords_voice_access"></string>
- <!-- Fast Pair settings -->
- <skip />
-
- <!-- Title in main settings screen for Fast Pair settings [CHAR LIMIT=15] -->
- <string name="fast_pair_settings">Fast Pair</string>
-
- <!-- Fast Pair setting summary in settings screen [CHAR LIMIT=50] -->
- <string name="fast_pair_settings_summary">Nearby detection of Fast Pair bluetooth devices.</string>
- <!-- Title for Fast Pair main switch preferences. [CHAR LIMIT=50] -->
- <string name="fast_pair_main_switch_title">Scan for nearby devices</string>
- <!-- Title for Fast Pair saved devices preferences. [CHAR LIMIT=50] -->
- <string name="fast_pair_saved_devices_title">Saved devices</string>
- <!-- Printing settings -->
<skip />
<!-- Title in main settings screen for printing settings [CHAR LIMIT=15] -->
@@ -6457,6 +6456,7 @@
<string name="help_url_privacy_dashboard" translatable="false"></string>
<string name="help_url_memtag" translatable="false"></string>
+ <string name="help_url_development_memtag" translatable="false"></string>
<string name="help_url_network_dashboard" translatable="false"></string>
<string name="help_url_connected_devices" translatable="false"></string>
<string name="help_url_apps_and_notifications" translatable="false"></string>
@@ -6885,9 +6885,6 @@
<!-- List of synonyms for the Bluetooth setting, used to match in settings search [CHAR LIMIT=NONE] -->
<string name="keywords_bluetooth_settings">connected, device, headphones, headset, speaker, wireless, pair, earbuds, music, media </string>
- <!-- List of synonyms for the Fast Pair setting, used to match in settings search [CHAR LIMIT=NONE] -->
- <string name="keywords_fast_pair">pair, earbuds, bluetooth</string>
-
<!-- List of synonyms for the Wallpaper picker setting, used to match in settings search [CHAR LIMIT=NONE] -->
<string name="keywords_wallpaper">background, theme, grid, customize, personalize</string>
@@ -8583,11 +8580,11 @@
<!-- Label for list that shows all permissions -->
<string name="app_permissions">Permission manager</string>
- <!-- Label for the list that shows all data sharing updates. TODO b/261914980 finalize string [CHAR LIMIT=30]-->
- <string name="app_data_sharing_updates_title">Data sharing updates</string>
+ <!-- Title for the entrypoint that navigates to the App Data Sharing Updates page. [CHAR LIMIT=70]-->
+ <string name="app_data_sharing_updates_title">Data sharing updates for location</string>
- <!-- Label for the list that shows all data sharing updates TODO b/261914980 finalize string [CHAR LIMIT=NONE]-->
- <string name="app_data_sharing_updates_summary">Show which apps recently updated data sharing policy</string>
+ <!-- Summary for the entrypoint that navigates to the App Data Sharing Updates page. [CHAR LIMIT=130]-->
+ <string name="app_data_sharing_updates_summary">Review apps that changed the way they may share your location data</string>
<!-- Label for tap to wake setting [CHAR LIMIT=30] -->
<string name="tap_to_wake">Tap to wake</string>
@@ -10871,14 +10868,26 @@
<!-- Title for the button to initiate a heap dump for the system server. [CHAR LIMIT=NONE] -->
<string name="capture_system_heap_dump_title">Capture system heap dump</string>
+
+ <!-- [CHAR LIMIT=32] Name of MTE page in "Developer Options" and heading of page. -->
+ <string name="development_memtag_page_title">Memory Tagging Extension</string>
+ <!-- [CHAR LIMIT=52] Label for button to turn on / off MTE protection.-->
+ <string name="development_memtag_intro">Memory Tagging Extension (MTE) makes it easier to find memory safety issues in your app and make native code in it more secure.</string>
+ <string name="development_memtag_footer">Turning on MTE might cause slower device performance.</string>
+ <string name="development_memtag_learn_more">Learn more about MTE</string>
+ <string name="development_memtag_toggle">Enable MTE until you turn it off</string>
+ <!-- [CHAR LIMIT=NONE] Message shown in dialog prompting user to reboot device to turn on MTE.-->
+ <string name="development_memtag_reboot_message_on">You\u0027ll need to restart your device to turn on MTE.</string>
+ <!-- [CHAR LIMIT=NONE] Message shown in dialog prompting user to reboot device to turn off MTE.-->
+ <string name="development_memtag_reboot_message_off">You\u0027ll need to restart your device to turn off MTE.</string>
<!-- Title for the button to reboot with MTE enabled. [CHAR LIMIT=NONE] -->
- <string name="reboot_with_mte_title">Reboot with MTE</string>
- <string name="reboot_with_mte_message">System will reboot and allow to experiment with Memory Tagging Extension (MTE). MTE may negatively impact system performance and stability. Will be reset on next subsequent reboot.</string>
+ <string name="reboot_with_mte_title">Enable MTE for a single session</string>
+ <string name="reboot_with_mte_message">System will restart and allow to experiment with Memory Tagging Extension (MTE). MTE may negatively impact system performance and stability. Will be reset on next subsequent reboot.</string>
<!-- Subtext for button if MTE is not enabled through Advanced memory protection. -->
- <string name="reboot_with_mte_summary">Try MTE for a single boot for app development</string>
+ <string name="reboot_with_mte_summary">Restart for a single session with MTE enabled</string>
<!-- Subtext for button if MTE is already enabled through Advanced memory protection.
The string for "Advanced memory protection" needs to match "memtag_toggle" above -->
- <string name="reboot_with_mte_already_enabled">MTE is enabled through Advanced memory protection</string>
+ <string name="reboot_with_mte_already_enabled">MTE is already enabled</string>
<!-- Toast that is shown when the user initiates capturing a heap dump for the system server. [CHAR LIMIT=NONE] -->
<string name="capturing_system_heap_dump_message">Capturing system heap dump</string>
<!-- Toast that is shown if there's an error capturing the user initiated heap dump. [CHAR LIMIT=NONE] -->
diff --git a/res/xml/bluetooth_audio_routing_fragment.xml b/res/xml/bluetooth_audio_routing_fragment.xml
index 18f18f2..79494c4 100644
--- a/res/xml/bluetooth_audio_routing_fragment.xml
+++ b/res/xml/bluetooth_audio_routing_fragment.xml
@@ -30,7 +30,8 @@
android:summary="%s"
android:key="audio_routing_ringtone"
android:persistent="false"
- android:title="@string/bluetooth_ringtone_title" />
+ android:title="@string/bluetooth_ringtone_title"
+ settings:controller="com.android.settings.bluetooth.HearingDeviceRingtoneRoutingPreferenceController" />
<ListPreference
android:entries="@array/bluetooth_audio_routing_titles"
@@ -38,7 +39,8 @@
android:summary="%s"
android:key="audio_routing_call"
android:persistent="false"
- android:title="@string/bluetooth_call_title" />
+ android:title="@string/bluetooth_call_title"
+ settings:controller="com.android.settings.bluetooth.HearingDeviceCallRoutingPreferenceController" />
<ListPreference
android:entries="@array/bluetooth_audio_routing_titles"
@@ -46,7 +48,8 @@
android:summary="%s"
android:key="audio_routing_media"
android:persistent="false"
- android:title="@string/bluetooth_media_title" />
+ android:title="@string/bluetooth_media_title"
+ settings:controller="com.android.settings.bluetooth.HearingDeviceMediaRoutingPreferenceController" />
<ListPreference
android:entries="@array/bluetooth_audio_routing_titles"
@@ -54,6 +57,7 @@
android:summary="%s"
android:key="audio_routing_system_sounds"
android:persistent="false"
- android:title="@string/bluetooth_system_sounds_title" />
+ android:title="@string/bluetooth_system_sounds_title"
+ settings:controller="com.android.settings.bluetooth.HearingDeviceSystemSoundsRoutingPreferenceController" />
</PreferenceScreen>
diff --git a/res/xml/connected_devices_advanced.xml b/res/xml/connected_devices_advanced.xml
index bd8eafb..46d1a0a 100644
--- a/res/xml/connected_devices_advanced.xml
+++ b/res/xml/connected_devices_advanced.xml
@@ -69,15 +69,6 @@
settings:userRestriction="no_ultra_wideband_radio"
settings:useAdminDisabledSummary="true"/>
- <Preference
- android:key="connected_device_fast_pair"
- android:title="@string/fast_pair_settings"
- android:summary="@string/fast_pair_settings_summary"
- android:icon="@drawable/ic_fast_pair_24dp"
- android:fragment="com.android.settings.nearby.FastPairSettingsFragment"
- settings:controller="com.android.settings.nearby.FastPairPreferenceController"
- android:order="-2"/>
-
<PreferenceCategory
android:key="dashboard_tile_placeholder"
android:order="-8"/>
diff --git a/res/xml/development_memtag_page.xml b/res/xml/development_memtag_page.xml
new file mode 100644
index 0000000..e230821
--- /dev/null
+++ b/res/xml/development_memtag_page.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2023 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:title="@string/development_memtag_page_title">
+
+ <com.android.settingslib.widget.TopIntroPreference
+ android:title="@string/development_memtag_intro"
+ settings:searchable="false"/>
+
+ <com.android.settingslib.RestrictedSwitchPreference
+ android:key="development_memtag"
+ android:title="@string/development_memtag_toggle"
+ settings:controller="com.android.settings.development.DevelopmentMemtagPreferenceController" />
+
+ <Preference
+ android:key="reboot_with_mte"
+ android:title="@string/reboot_with_mte_title"
+ settings:controller="com.android.settings.development.RebootWithMtePreferenceController" />
+
+ <com.android.settingslib.widget.FooterPreference
+ android:title="@string/development_memtag_footer"
+ android:key="memtag_footer"
+ settings:searchable="false"
+ settings:controller="com.android.settings.development.DevelopmentMemtagFooterPreferenceController" />
+</PreferenceScreen>
diff --git a/res/xml/development_settings.xml b/res/xml/development_settings.xml
index 82d7e43..ae93eed 100644
--- a/res/xml/development_settings.xml
+++ b/res/xml/development_settings.xml
@@ -45,8 +45,9 @@
android:title="@string/capture_system_heap_dump_title" />
<Preference
- android:key="reboot_with_mte"
- android:title="@string/reboot_with_mte_title" />
+ android:key="development_memtag_page"
+ android:title="@string/development_memtag_page_title"
+ android:fragment="com.android.settings.development.DevelopmentMemtagPage" />
<Preference
android:key="local_backup_password"
@@ -80,6 +81,26 @@
android:entries="@array/bt_hci_snoop_log_entries"
android:entryValues="@array/bt_hci_snoop_log_values" />
+ <Preference
+ android:key="snoop_logger_filters_dashboard"
+ android:title="@string/snoop_logger_filters_dashboard_title"
+ android:fragment=
+ "com.android.settings.development.snooplogger.SnoopLoggerFiltersDashboard" />
+
+ <ListPreference
+ android:key="bt_hci_snoop_log_filter_pbap"
+ android:title="@string/bt_hci_snoop_log_filter_pbap_title"
+ android:dialogTitle="@string/bt_hci_snoop_log_filter_summary"
+ android:entries="@array/bt_hci_snoop_log_profile_filter_entries"
+ android:entryValues="@array/bt_hci_snoop_log_profile_filter_values" />
+
+ <ListPreference
+ android:key="bt_hci_snoop_log_filter_map"
+ android:title="@string/bt_hci_snoop_log_filter_map_title"
+ android:dialogTitle="@string/bt_hci_snoop_log_filter_summary"
+ android:entries="@array/bt_hci_snoop_log_profile_filter_entries"
+ android:entryValues="@array/bt_hci_snoop_log_profile_filter_values" />
+
<com.android.settingslib.RestrictedSwitchPreference
android:key="oem_unlock_enable"
android:title="@string/oem_unlock_enable"
diff --git a/res/xml/fast_pair_settings.xml b/res/xml/fast_pair_settings.xml
deleted file mode 100644
index 95662fc..0000000
--- a/res/xml/fast_pair_settings.xml
+++ /dev/null
@@ -1,32 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-~ Copyright (C) 2022 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/fast_pair_settings"
- settings:keywords="@string/keywords_fast_pair">
-
- <com.android.settingslib.widget.MainSwitchPreference
- android:key="fast_pair_scan_switch"
- android:title="@string/fast_pair_main_switch_title" />
-
- <Preference
- android:key="saved_devices"
- android:title="@string/fast_pair_saved_devices_title" />
-
-</PreferenceScreen>
diff --git a/res/xml/more_security_privacy_settings.xml b/res/xml/more_security_privacy_settings.xml
index 00957f7..5fce68f 100644
--- a/res/xml/more_security_privacy_settings.xml
+++ b/res/xml/more_security_privacy_settings.xml
@@ -22,9 +22,10 @@
android:title="@string/more_security_privacy_settings">
<!-- work profile security section. See also: security_advanced_settings.xml and
- privacy_advanced_settings.xml. That page also has some duplicate entries -->
+ privacy_advanced_settings.xml. That page also has these same entries.
+ The order is -10 to make sure it is always at the top. -->
<PreferenceCategory
- android:order="10"
+ android:order="-10"
android:key="work_profile_category"
android:title="@string/work_profile_category_header">
@@ -45,141 +46,27 @@
android:key="visiblepattern_profile"
android:title="@string/lockpattern_settings_enable_visible_pattern_title_profile" />
- <com.android.settingslib.RestrictedPreference
- android:key="fingerprint_settings_profile"
- android:title="@string/security_settings_work_fingerprint_preference_title"
- android:summary="@string/summary_placeholder" />
-
- <com.android.settingslib.RestrictedPreference
- android:key="face_settings_profile"
- android:title="@string/security_settings_face_profile_preference_title"
- android:summary="@string/summary_placeholder" />
-
- <com.android.settingslib.RestrictedPreference
- android:key="biometric_settings_profile"
- android:title="@string/security_settings_work_biometric_preference_title"
- android:summary="@string/summary_placeholder" />
-
- </PreferenceCategory>
-
- <PreferenceCategory
- android:key="privacy_work_profile_notifications_category"
- android:title="@string/profile_section_header_for_advanced_privacy"
- android:layout="@layout/preference_category_no_label"
- android:order="20">
-
<com.android.settings.RestrictedListPreference
android:key="privacy_lock_screen_work_profile_notifications"
android:title="@string/locked_work_profile_notification_title"
android:summary="@string/summary_placeholder"
- android:order="21"
settings:searchable="false"/>
- </PreferenceCategory>
- <!-- Connected work and personal apps -->
- <Preference
- android:key="interact_across_profiles_privacy"
- android:title="@string/interact_across_profiles_title"
- android:order="25"
- android:fragment="com.android.settings.applications.specialaccess.interactacrossprofiles.InteractAcrossProfilesSettings"
- settings:searchable="false"
- settings:controller="com.android.settings.applications.specialaccess.interactacrossprofiles.InteractAcrossProfilesController" />
-
- <!-- Main security section - for trust agents added in code. -->
- <PreferenceCategory
- android:order="30"
- android:key="security_category"
- android:title="@string/security_header" />
-
- <PreferenceCategory
- android:order="40"
- android:key="security_settings_device_admin_category"
- android:layout="@layout/preference_category_no_label">
-
+ <!-- Connected work and personal apps -->
<Preference
- android:key="manage_device_admin"
- android:title="@string/manage_device_admin"
- android:summary="@string/summary_placeholder"
- android:fragment=
- "com.android.settings.applications.specialaccess.deviceadmin.DeviceAdminSettings"
- settings:controller=
- "com.android.settings.enterprise.ManageDeviceAdminPreferenceController" />
-
- <Preference
- android:key="enterprise_privacy"
- android:title="@string/enterprise_privacy_settings"
- android:summary="@string/summary_placeholder"
- android:fragment="com.android.settings.enterprise.EnterprisePrivacySettings"
- settings:controller="com.android.settings.enterprise.EnterprisePrivacyPreferenceController"/>
-
- <Preference
- android:key="financed_privacy"
- android:title="@string/financed_privacy_settings"
- android:summary="@string/summary_placeholder"
- android:fragment="com.android.settings.enterprise.EnterprisePrivacySettings"
- settings:controller="com.android.settings.enterprise.FinancedPrivacyPreferenceController"/>
+ android:key="interact_across_profiles_privacy"
+ android:title="@string/interact_across_profiles_title"
+ android:fragment="com.android.settings.applications.specialaccess.interactacrossprofiles.InteractAcrossProfilesSettings"
+ settings:searchable="false"
+ settings:controller="com.android.settings.applications.specialaccess.interactacrossprofiles.InteractAcrossProfilesController" />
</PreferenceCategory>
- <Preference
- android:order="50"
- android:key="sim_lock_settings"
- android:title="@string/sim_lock_settings_category"
- settings:isPreferenceVisible="@bool/config_show_sim_info"
- settings:controller="com.android.settings.security.SimLockPreferenceController">
-
- <intent
- android:action="android.intent.action.MAIN"
- android:targetPackage="com.android.settings"
- android:targetClass="com.android.settings.Settings$IccLockSettingsActivity" />
-
- </Preference>
-
- <Preference
- android:order="60"
- android:key="encryption_and_credential"
- android:title="@string/encryption_and_credential_settings_title"
- android:summary="@string/encryption_and_credential_settings_summary"
- android:fragment="com.android.settings.security.EncryptionAndCredential"
- settings:controller="com.android.settings.security.EncryptionStatusPreferenceController" />
-
- <Preference
- android:order="70"
- android:key="manage_trust_agents"
- android:title="@string/manage_trust_agents"
- android:summary="@string/summary_placeholder"
- android:fragment="com.android.settings.security.trustagent.TrustAgentSettings"
- settings:controller="com.android.settings.security.trustagent.ManageTrustAgentsPreferenceController" />
-
- <Preference
- android:order="80"
- android:key="screen_pinning_settings"
- android:title="@string/screen_pinning_title"
- android:summary="@string/summary_placeholder"
- android:fragment="com.android.settings.security.ScreenPinningSettings"
- settings:keywords="@string/keywords_app_pinning"
- settings:controller="com.android.settings.security.ScreenPinningPreferenceController" />
-
- <SwitchPreference
- android:order="90"
- android:key="confirm_sim_deletion"
- android:title="@string/confirm_sim_deletion_title"
- android:summary="@string/confirm_sim_deletion_description"
- settings:isPreferenceVisible="@bool/config_show_sim_info"
- settings:controller="com.android.settings.security.ConfirmSimDeletionPreferenceController" />
-
- <Preference
- android:order="100"
- android:id="@+id/memtag_page"
- android:key="memtag_page"
- android:title="@string/memtag_title"
- android:fragment="com.android.settings.security.MemtagPage"
- settings:controller="com.android.settings.security.MemtagPagePreferenceController" />
-
<!-- Privacy section -->
+ <!-- The order is -1 to make sure it is above all the privacy entries. Some dynamically injected entries have order 0. -->
<PreferenceCategory
- android:order="200"
+ android:order="-1"
android:key="privacy_category"
android:title="@string/privacy_header">
<!-- Accessibility usage -->
@@ -224,4 +111,98 @@
</PreferenceCategory>
+ <!-- Security section. -->
+ <!-- "security_category" is used to add trust agents by TrustAgentListPreferenceController -->
+ <PreferenceCategory
+ android:order="200"
+ android:key="security_category"
+ android:title="@string/security_header" />
+
+ <PreferenceCategory
+ android:order="240"
+ android:key="security_settings_device_admin_category"
+ android:layout="@layout/preference_category_no_label">
+
+ <Preference
+ android:key="manage_device_admin"
+ android:title="@string/manage_device_admin"
+ android:summary="@string/summary_placeholder"
+ android:fragment=
+ "com.android.settings.applications.specialaccess.deviceadmin.DeviceAdminSettings"
+ settings:controller=
+ "com.android.settings.enterprise.ManageDeviceAdminPreferenceController" />
+
+ <Preference
+ android:key="enterprise_privacy"
+ android:title="@string/enterprise_privacy_settings"
+ android:summary="@string/summary_placeholder"
+ android:fragment="com.android.settings.enterprise.EnterprisePrivacySettings"
+ settings:controller="com.android.settings.enterprise.EnterprisePrivacyPreferenceController"/>
+
+ <Preference
+ android:key="financed_privacy"
+ android:title="@string/financed_privacy_settings"
+ android:summary="@string/summary_placeholder"
+ android:fragment="com.android.settings.enterprise.EnterprisePrivacySettings"
+ settings:controller="com.android.settings.enterprise.FinancedPrivacyPreferenceController"/>
+
+ </PreferenceCategory>
+
+ <Preference
+ android:order="250"
+ android:key="sim_lock_settings"
+ android:title="@string/sim_lock_settings_category"
+ settings:isPreferenceVisible="@bool/config_show_sim_info"
+ settings:controller="com.android.settings.security.SimLockPreferenceController">
+
+ <intent
+ android:action="android.intent.action.MAIN"
+ android:targetPackage="com.android.settings"
+ android:targetClass="com.android.settings.Settings$IccLockSettingsActivity" />
+
+ </Preference>
+
+ <Preference
+ android:order="260"
+ android:key="encryption_and_credential"
+ android:title="@string/encryption_and_credential_settings_title"
+ android:summary="@string/encryption_and_credential_settings_summary"
+ android:fragment="com.android.settings.security.EncryptionAndCredential"
+ settings:controller="com.android.settings.security.EncryptionStatusPreferenceController" />
+
+ <Preference
+ android:order="270"
+ android:key="manage_trust_agents"
+ android:title="@string/manage_trust_agents"
+ android:summary="@string/summary_placeholder"
+ android:fragment="com.android.settings.security.trustagent.TrustAgentSettings"
+ settings:controller="com.android.settings.security.trustagent.ManageTrustAgentsPreferenceController" />
+
+ <Preference
+ android:order="280"
+ android:key="screen_pinning_settings"
+ android:title="@string/screen_pinning_title"
+ android:summary="@string/summary_placeholder"
+ android:fragment="com.android.settings.security.ScreenPinningSettings"
+ settings:keywords="@string/keywords_app_pinning"
+ settings:controller="com.android.settings.security.ScreenPinningPreferenceController" />
+
+ <SwitchPreference
+ android:order="290"
+ android:key="confirm_sim_deletion"
+ android:title="@string/confirm_sim_deletion_title"
+ android:summary="@string/confirm_sim_deletion_description"
+ settings:isPreferenceVisible="@bool/config_show_sim_info"
+ settings:controller="com.android.settings.security.ConfirmSimDeletionPreferenceController" />
+
+ <Preference
+ android:order="300"
+ android:id="@+id/memtag_page"
+ android:key="memtag_page"
+ android:title="@string/memtag_title"
+ android:fragment="com.android.settings.security.MemtagPage"
+ settings:controller="com.android.settings.security.MemtagPagePreferenceController" />
+
+
+
</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/snoop_logger_filters_settings.xml b/res/xml/snoop_logger_filters_settings.xml
new file mode 100644
index 0000000..c804ec6
--- /dev/null
+++ b/res/xml/snoop_logger_filters_settings.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2022 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/snoop_logger_filters_dashboard_title" >
+
+ <PreferenceCategory
+ android:key="snoop_logger_filters_category"
+ android:layout="@layout/preference_category_no_label"
+ android:title="@string/bt_hci_snoop_log_filters_dashboard_summary"
+ settings:controller=
+ "com.android.settings.development.snooplogger.SnoopLoggerFiltersPreferenceController" />
+</PreferenceScreen>
diff --git a/src/com/android/settings/TestingSettings.java b/src/com/android/settings/TestingSettings.java
index c1df705..48b5be3 100644
--- a/src/com/android/settings/TestingSettings.java
+++ b/src/com/android/settings/TestingSettings.java
@@ -17,27 +17,41 @@
package com.android.settings;
import android.app.settings.SettingsEnums;
+import android.content.Context;
import android.os.Bundle;
import android.os.UserManager;
+import androidx.annotation.VisibleForTesting;
import androidx.preference.PreferenceScreen;
+import com.android.settings.network.telephony.MobileNetworkUtils;
+
public class TestingSettings extends SettingsPreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
-
+
addPreferencesFromResource(R.xml.testing_settings);
- final UserManager um = UserManager.get(getContext());
- if (!um.isAdminUser()) {
+ if (!isRadioInfoVisible(getContext())) {
PreferenceScreen preferenceScreen = (PreferenceScreen)
findPreference("radio_info_settings");
getPreferenceScreen().removePreference(preferenceScreen);
}
}
+ @VisibleForTesting
+ protected boolean isRadioInfoVisible(Context context) {
+ UserManager um = context.getSystemService(UserManager.class);
+ if (um != null) {
+ if (!um.isAdminUser()) {
+ return false;
+ }
+ }
+ return !MobileNetworkUtils.isMobileNetworkUserRestricted(context);
+ }
+
@Override
public int getMetricsCategory() {
return SettingsEnums.TESTING;
diff --git a/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizard.java b/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizard.java
index 6c32edd..f452737 100644
--- a/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizard.java
+++ b/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizard.java
@@ -16,6 +16,8 @@
package com.android.settings.accessibility;
+import static android.app.Activity.RESULT_CANCELED;
+
import static com.android.settings.Utils.getAdaptiveIcon;
import static com.android.settingslib.widget.TwoTargetPreference.ICON_SIZE_MEDIUM;
@@ -41,6 +43,7 @@
import com.android.settings.dashboard.DashboardFragment;
import com.android.settingslib.RestrictedPreference;
+import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupdesign.GlifPreferenceLayout;
import java.util.List;
@@ -90,6 +93,12 @@
final Drawable icon = getContext().getDrawable(R.drawable.ic_accessibility_visibility);
AccessibilitySetupWizardUtils.updateGlifPreferenceLayout(getContext(), layout, title,
description, icon);
+
+ final FooterBarMixin mixin = layout.getMixin(FooterBarMixin.class);
+ AccessibilitySetupWizardUtils.setPrimaryButton(getContext(), mixin, R.string.done, () -> {
+ setResult(RESULT_CANCELED);
+ finish();
+ });
}
@Override
diff --git a/src/com/android/settings/accessibility/AccessibilitySetupWizardUtils.java b/src/com/android/settings/accessibility/AccessibilitySetupWizardUtils.java
index c530214..b7a3439 100644
--- a/src/com/android/settings/accessibility/AccessibilitySetupWizardUtils.java
+++ b/src/com/android/settings/accessibility/AccessibilitySetupWizardUtils.java
@@ -19,8 +19,13 @@
import android.graphics.drawable.Drawable;
import android.widget.LinearLayout;
+import androidx.annotation.StringRes;
+
import com.android.settings.R;
+import com.google.android.setupcompat.template.FooterBarMixin;
+import com.google.android.setupcompat.template.FooterButton;
+import com.google.android.setupcompat.template.Mixin;
import com.google.android.setupdesign.GlifPreferenceLayout;
import com.google.android.setupdesign.util.ThemeHelper;
@@ -30,7 +35,7 @@
private AccessibilitySetupWizardUtils(){}
/**
- * Update the {@link GlifPreferenceLayout} attributes if they have previously been initialized.
+ * Updates the {@link GlifPreferenceLayout} attributes if they have previously been initialized.
* When the SetupWizard supports the extended partner configs, it means the material layout
* would be applied. It should set a different padding/margin in views to align Settings style
* for accessibility feature pages.
@@ -55,4 +60,46 @@
}
}
}
+
+ /**
+ * Sets primary button for footer of the {@link GlifPreferenceLayout}.
+ *
+ * <p> This will be the initial by given material theme style.
+ *
+ * @param context A {@link Context}
+ * @param mixin A {@link Mixin} for managing buttons.
+ * @param text The {@code text} by resource.
+ * @param runnable The {@link Runnable} to run.
+ */
+ public static void setPrimaryButton(Context context, FooterBarMixin mixin, @StringRes int text,
+ Runnable runnable) {
+ mixin.setPrimaryButton(
+ new FooterButton.Builder(context)
+ .setText(text)
+ .setListener(l -> runnable.run())
+ .setButtonType(FooterButton.ButtonType.DONE)
+ .setTheme(R.style.SudGlifButton_Primary)
+ .build());
+ }
+
+ /**
+ * Sets secondary button for the footer of the {@link GlifPreferenceLayout}.
+ *
+ * <p> This will be the initial by given material theme style.
+ *
+ * @param context A {@link Context}
+ * @param mixin A {@link Mixin} for managing buttons.
+ * @param text The {@code text} by resource.
+ * @param runnable The {@link Runnable} to run.
+ */
+ public static void setSecondaryButton(Context context, FooterBarMixin mixin,
+ @StringRes int text, Runnable runnable) {
+ mixin.setSecondaryButton(
+ new FooterButton.Builder(context)
+ .setText(text)
+ .setListener(l -> runnable.run())
+ .setButtonType(FooterButton.ButtonType.CLEAR)
+ .setTheme(R.style.SudGlifButton_Secondary)
+ .build());
+ }
}
diff --git a/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizard.java b/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizard.java
index cdbfe5f..f2edf8e 100644
--- a/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizard.java
+++ b/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizard.java
@@ -33,7 +33,6 @@
import com.android.settingslib.Utils;
import com.google.android.setupcompat.template.FooterBarMixin;
-import com.google.android.setupcompat.template.FooterButton;
import com.google.android.setupdesign.GlifPreferenceLayout;
/**
@@ -55,26 +54,14 @@
/* description= */ null, icon);
final FooterBarMixin mixin = layout.getMixin(FooterBarMixin.class);
- mixin.setSecondaryButton(
- new FooterButton.Builder(getContext())
- .setText(R.string.accessibility_text_reading_reset_button_title)
- .setListener(l -> showDialog(DIALOG_RESET_SETTINGS))
- .setButtonType(FooterButton.ButtonType.CLEAR)
- .setTheme(R.style.SudGlifButton_Secondary)
- .build());
-
- if (isCallingFromAnythingElseEntryPoint()) {
- mixin.setPrimaryButton(
- new FooterButton.Builder(getContext())
- .setText(R.string.done)
- .setListener(l -> {
- setResult(RESULT_CANCELED);
- finish();
- })
- .setButtonType(FooterButton.ButtonType.DONE)
- .setTheme(R.style.SudGlifButton_Primary)
- .build());
- }
+ AccessibilitySetupWizardUtils.setPrimaryButton(getContext(), mixin, R.string.done, () -> {
+ setResult(RESULT_CANCELED);
+ finish();
+ });
+ AccessibilitySetupWizardUtils.setSecondaryButton(getContext(), mixin,
+ R.string.accessibility_text_reading_reset_button_title,
+ () -> showDialog(DIALOG_RESET_SETTINGS)
+ );
}
@Override
diff --git a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizard.java b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizard.java
index 12a9886..a726d81 100644
--- a/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizard.java
+++ b/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizard.java
@@ -16,6 +16,8 @@
package com.android.settings.accessibility;
+import static android.app.Activity.RESULT_CANCELED;
+
import android.app.settings.SettingsEnums;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
@@ -27,6 +29,7 @@
import com.android.settings.R;
+import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupdesign.GlifPreferenceLayout;
public class ToggleScreenMagnificationPreferenceFragmentForSetupWizard
@@ -44,6 +47,13 @@
final Drawable icon = getContext().getDrawable(R.drawable.ic_accessibility_visibility);
AccessibilitySetupWizardUtils.updateGlifPreferenceLayout(getContext(), layout, title,
description, icon);
+
+ final FooterBarMixin mixin = layout.getMixin(FooterBarMixin.class);
+ AccessibilitySetupWizardUtils.setPrimaryButton(getContext(), mixin, R.string.done, () -> {
+ setResult(RESULT_CANCELED);
+ finish();
+ });
+
hidePreferenceSettingComponents();
}
diff --git a/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizard.java b/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizard.java
index f9a1113..89dc437 100644
--- a/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizard.java
+++ b/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizard.java
@@ -16,6 +16,8 @@
package com.android.settings.accessibility;
+import static android.app.Activity.RESULT_CANCELED;
+
import android.app.settings.SettingsEnums;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
@@ -27,6 +29,7 @@
import com.android.settings.R;
+import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupdesign.GlifPreferenceLayout;
public class ToggleScreenReaderPreferenceFragmentForSetupWizard
@@ -45,6 +48,12 @@
AccessibilitySetupWizardUtils.updateGlifPreferenceLayout(getContext(), layout, title,
description, icon);
+ final FooterBarMixin mixin = layout.getMixin(FooterBarMixin.class);
+ AccessibilitySetupWizardUtils.setPrimaryButton(getContext(), mixin, R.string.done, () -> {
+ setResult(RESULT_CANCELED);
+ finish();
+ });
+
mToggleSwitchWasInitiallyChecked = mToggleServiceSwitchPreference.isChecked();
if (mTopIntroPreference != null) {
mTopIntroPreference.setVisible(false);
diff --git a/src/com/android/settings/accessibility/ToggleSelectToSpeakPreferenceFragmentForSetupWizard.java b/src/com/android/settings/accessibility/ToggleSelectToSpeakPreferenceFragmentForSetupWizard.java
index a460419..ff9182e 100644
--- a/src/com/android/settings/accessibility/ToggleSelectToSpeakPreferenceFragmentForSetupWizard.java
+++ b/src/com/android/settings/accessibility/ToggleSelectToSpeakPreferenceFragmentForSetupWizard.java
@@ -16,6 +16,8 @@
package com.android.settings.accessibility;
+import static android.app.Activity.RESULT_CANCELED;
+
import android.app.settings.SettingsEnums;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
@@ -27,6 +29,7 @@
import com.android.settings.R;
+import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupdesign.GlifPreferenceLayout;
public class ToggleSelectToSpeakPreferenceFragmentForSetupWizard
@@ -45,6 +48,12 @@
AccessibilitySetupWizardUtils.updateGlifPreferenceLayout(getContext(), layout, title,
description, icon);
+ final FooterBarMixin mixin = layout.getMixin(FooterBarMixin.class);
+ AccessibilitySetupWizardUtils.setPrimaryButton(getContext(), mixin, R.string.done, () -> {
+ setResult(RESULT_CANCELED);
+ finish();
+ });
+
mToggleSwitchWasInitiallyChecked = mToggleServiceSwitchPreference.isChecked();
if (mTopIntroPreference != null) {
mTopIntroPreference.setVisible(false);
diff --git a/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java b/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
index 7160b0d..873be17 100644
--- a/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
+++ b/src/com/android/settings/applications/credentials/CredentialManagerPreferenceController.java
@@ -293,8 +293,19 @@
return true;
} else {
- // Disable the provider.
- togglePackageNameDisabled(packageName);
+ // If we are disabling the last enabled provider then show a warning.
+ if (mEnabledPackageNames.size() <= 1) {
+ final DialogFragment fragment =
+ newConfirmationDialogFragment(packageName, title, pref);
+
+ if (fragment == null || mFragmentManager == null) {
+ return true;
+ }
+
+ fragment.show(mFragmentManager, ConfirmationDialogFragment.TAG);
+ } else {
+ togglePackageNameDisabled(packageName);
+ }
}
return true;
@@ -337,6 +348,29 @@
return new ErrorDialogFragment(host);
}
+ private @Nullable ConfirmationDialogFragment newConfirmationDialogFragment(
+ @NonNull String packageName,
+ @NonNull CharSequence appName,
+ @NonNull SwitchPreference pref) {
+ DialogHost host =
+ new DialogHost() {
+ @Override
+ public void onDialogClick(int whichButton) {
+ if (whichButton == DialogInterface.BUTTON_POSITIVE) {
+ // Since the package is now enabled then we
+ // should remove it from the enabled list.
+ togglePackageNameDisabled(packageName);
+ } else if (whichButton == DialogInterface.BUTTON_NEGATIVE) {
+ // Set the checked back to true because we
+ // backed out of turning this off.
+ pref.setChecked(true);
+ }
+ }
+ };
+
+ return new ConfirmationDialogFragment(host, packageName, appName);
+ }
+
private int getUser() {
UserHandle workUser = getWorkProfileUser();
return workUser != null ? workUser.getIdentifier() : UserHandle.myUserId();
@@ -386,4 +420,44 @@
@Override
public void onClick(DialogInterface dialog, int which) {}
}
+
+ /**
+ * Confirmation dialog fragment shows a dialog to the user to confirm that they are disabling a
+ * provider.
+ */
+ public static class ConfirmationDialogFragment extends CredentialManagerDialogFragment {
+
+ ConfirmationDialogFragment(
+ DialogHost dialogHost, @NonNull String packageName, @NonNull CharSequence appName) {
+ super(dialogHost);
+
+ final Bundle argument = new Bundle();
+ argument.putString(PACKAGE_NAME_KEY, packageName);
+ argument.putCharSequence(APP_NAME_KEY, appName);
+ setArguments(argument);
+ }
+
+ @Override
+ public Dialog onCreateDialog(Bundle savedInstanceState) {
+ final Bundle bundle = getArguments();
+ final String title =
+ getContext()
+ .getString(
+ R.string.credman_confirmation_message_title,
+ bundle.getCharSequence(
+ CredentialManagerDialogFragment.APP_NAME_KEY));
+
+ return new AlertDialog.Builder(getActivity())
+ .setTitle(title)
+ .setMessage(getContext().getString(R.string.credman_confirmation_message))
+ .setPositiveButton(R.string.credman_confirmation_message_positive_button, this)
+ .setNegativeButton(android.R.string.cancel, this)
+ .create();
+ }
+
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ getDialogHost().onDialogClick(which);
+ }
+ }
}
diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingRfpsFragment.java b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingRfpsFragment.java
index f72e6c4..842bf42 100644
--- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingRfpsFragment.java
+++ b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingRfpsFragment.java
@@ -27,6 +27,7 @@
import android.graphics.drawable.AnimatedVectorDrawable;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
+import android.hardware.fingerprint.FingerprintManager;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
@@ -40,7 +41,7 @@
import android.widget.ProgressBar;
import android.widget.TextView;
-import androidx.annotation.IdRes;
+import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
@@ -52,7 +53,6 @@
import com.android.settings.biometrics.fingerprint.FingerprintErrorDialog;
import com.android.settings.biometrics2.ui.model.EnrollmentProgress;
import com.android.settings.biometrics2.ui.model.EnrollmentStatusMessage;
-import com.android.settings.biometrics2.ui.viewmodel.DeviceRotationViewModel;
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel;
import com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollProgressViewModel;
@@ -80,7 +80,6 @@
private static final int HINT_TIMEOUT_DURATION = 2500;
private FingerprintEnrollEnrollingViewModel mEnrollingViewModel;
- private DeviceRotationViewModel mRotationViewModel;
private FingerprintEnrollProgressViewModel mProgressViewModel;
private Interpolator mFastOutSlowInInterpolator;
@@ -92,13 +91,13 @@
private ProgressBar mProgressBar;
private ObjectAnimator mProgressAnim;
private TextView mErrorText;
- private FooterBarMixin mFooterBarMixin;
private AnimatedVectorDrawable mIconAnimationDrawable;
private AnimatedVectorDrawable mIconBackgroundBlinksDrawable;
+ private int mIconTouchCount;
private final View.OnClickListener mOnSkipClickListener = v -> {
- mProgressViewModel.cancelEnrollment();
- mEnrollingViewModel.onSkipButtonClick();
+ mEnrollingViewModel.setOnSkipPressed();
+ cancelEnrollment();
};
private final Observer<EnrollmentProgress> mProgressObserver = progress -> {
@@ -128,16 +127,21 @@
}
};
- private int mIconTouchCount;
-
@Override
public void onAttach(@NonNull Context context) {
final FragmentActivity activity = getActivity();
final ViewModelProvider provider = new ViewModelProvider(activity);
mEnrollingViewModel = provider.get(FingerprintEnrollEnrollingViewModel.class);
- mRotationViewModel = provider.get(DeviceRotationViewModel.class);
mProgressViewModel = provider.get(FingerprintEnrollProgressViewModel.class);
super.onAttach(context);
+ requireActivity().getOnBackPressedDispatcher().addCallback(new OnBackPressedCallback(true) {
+ @Override
+ public void handleOnBackPressed() {
+ setEnabled(false);
+ mEnrollingViewModel.setOnBackPressed();
+ cancelEnrollment();
+ }
+ });
}
@Nullable
@@ -198,8 +202,7 @@
mErrorText = containView.findViewById(R.id.error_text);
mProgressBar = containView.findViewById(R.id.fingerprint_progress_bar);
- mFooterBarMixin = containView.getMixin(FooterBarMixin.class);
- mFooterBarMixin.setSecondaryButton(
+ containView.getMixin(FooterBarMixin.class).setSecondaryButton(
new FooterButton.Builder(activity)
.setText(R.string.security_settings_fingerprint_enroll_enrolling_skip)
.setListener(mOnSkipClickListener)
@@ -263,39 +266,28 @@
}
}
- private void onCancelEnrollment(@IdRes int errorMsgId) {
- // TODO
- // showErrorDialog() will cause onWindowFocusChanged(false), set mIsCanceled to false
- // before showErrorDialog() to prevent that another error dialog is triggered again.
-// TODO mIsCanceled = true;
-// TODO mIsOrientationChanged = false;
- mEnrollingViewModel.showErrorDialog(new FingerprintEnrollEnrollingViewModel.ErrorDialogData(
- mView.getContext().getString(FingerprintErrorDialog.getErrorMessage(errorMsgId)),
- mView.getContext().getString(FingerprintErrorDialog.getErrorTitle(errorMsgId)),
- errorMsgId
- ));
- cancelEnrollment();
- stopIconAnimation();
- }
-
@Override
public void onStop() {
stopIconAnimation();
- removeEnrollmentObserver();
- if (!getActivity().isChangingConfigurations()) {
+ removeEnrollmentObservers();
+ if (!getActivity().isChangingConfigurations() && mProgressViewModel.isEnrolling()) {
mProgressViewModel.cancelEnrollment();
}
super.onStop();
}
- private void removeEnrollmentObserver() {
- mProgressViewModel.getProgressLiveData().removeObserver(mProgressObserver);
- mProgressViewModel.getHelpMessageLiveData().removeObserver(mHelpMessageObserver);
+ private void removeEnrollmentObservers() {
+ preRemoveEnrollmentObservers();
mProgressViewModel.getErrorMessageLiveData().removeObserver(mErrorMessageObserver);
}
+ private void preRemoveEnrollmentObservers() {
+ mProgressViewModel.getProgressLiveData().removeObserver(mProgressObserver);
+ mProgressViewModel.getHelpMessageLiveData().removeObserver(mHelpMessageObserver);
+ }
+
private void cancelEnrollment() {
- removeEnrollmentObserver();
+ preRemoveEnrollmentObservers();
mProgressViewModel.cancelEnrollment();
}
@@ -318,7 +310,27 @@
}
private void onEnrollmentError(@NonNull EnrollmentStatusMessage errorMessage) {
- onCancelEnrollment(errorMessage.getMsgId());
+ stopIconAnimation();
+ removeEnrollmentObservers();
+
+ if (mEnrollingViewModel.getOnBackPressed()
+ && errorMessage.getMsgId() == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
+ mEnrollingViewModel.onCancelledDueToOnBackPressed();
+ } else if (mEnrollingViewModel.getOnSkipPressed()
+ && errorMessage.getMsgId() == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
+ mEnrollingViewModel.onCancelledDueToOnSkipPressed();
+ } else {
+ final int errMsgId = errorMessage.getMsgId();
+ mEnrollingViewModel.showErrorDialog(
+ new FingerprintEnrollEnrollingViewModel.ErrorDialogData(
+ mView.getContext().getString(
+ FingerprintErrorDialog.getErrorMessage(errMsgId)),
+ mView.getContext().getString(
+ FingerprintErrorDialog.getErrorTitle(errMsgId)),
+ errMsgId
+ ));
+ mProgressViewModel.cancelEnrollment();
+ }
}
private void onEnrollmentProgressChange(@NonNull EnrollmentProgress progress) {
@@ -398,7 +410,6 @@
}
}
-
@Override
public void onDestroy() {
// TODO stopListenOrientationEvent();
@@ -444,7 +455,6 @@
private void showIconTouchDialog() {
mIconTouchCount = 0;
- //TODO EnrollingActivity should observe live data and add dialog fragment
mEnrollingViewModel.onIconTouchDialogShow();
}
diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingSfpsFragment.java b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingSfpsFragment.java
index 57b8665..7d2ef9f 100644
--- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingSfpsFragment.java
+++ b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingSfpsFragment.java
@@ -113,7 +113,7 @@
private boolean mHaveShownSfpsRightEdgeLottie;
private final View.OnClickListener mOnSkipClickListener =
- (v) -> mEnrollingViewModel.onSkipButtonClick();
+ (v) -> mEnrollingViewModel.onCancelledDueToOnSkipPressed();
private final Observer<EnrollmentProgress> mProgressObserver = progress -> {
// TODO
};
diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingUdfpsFragment.java b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingUdfpsFragment.java
index 18a7c25..ad6abf1 100644
--- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingUdfpsFragment.java
+++ b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollEnrollingUdfpsFragment.java
@@ -107,7 +107,7 @@
private boolean mIsAccessibilityEnabled;
private final View.OnClickListener mOnSkipClickListener =
- (v) -> mEnrollingViewModel.onSkipButtonClick();
+ (v) -> mEnrollingViewModel.onCancelledDueToOnSkipPressed();
private final Observer<EnrollmentProgress> mProgressObserver = progress -> {
// TODO
};
diff --git a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollmentActivity.java b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollmentActivity.java
index c0b0b4d..7448678 100644
--- a/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollmentActivity.java
+++ b/src/com/android/settings/biometrics2/ui/view/FingerprintEnrollmentActivity.java
@@ -31,6 +31,7 @@
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FINGERPRINT_ENROLL_ENROLLING_ACTION_DONE;
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FINGERPRINT_ENROLL_ENROLLING_ACTION_SHOW_ICON_TOUCH_DIALOG;
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FINGERPRINT_ENROLL_ENROLLING_ACTION_SKIP;
+import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_BACK_PRESSED;
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_FINISH;
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FINGERPRINT_ERROR_DIALOG_ACTION_SET_RESULT_TIMEOUT;
import static com.android.settings.biometrics2.ui.viewmodel.FingerprintEnrollEnrollingViewModel.FingerprintEnrollEnrollingAction;
@@ -453,8 +454,7 @@
private void onFindSensorAction(@FingerprintEnrollFindSensorAction int action) {
switch (action) {
case FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_SKIP: {
- onSetActivityResult(
- new ActivityResult(BiometricEnrollBase.RESULT_SKIP, null));
+ onSetActivityResult(new ActivityResult(BiometricEnrollBase.RESULT_SKIP, null));
return;
}
case FINGERPRINT_ENROLL_FIND_SENSOR_ACTION_DIALOG: {
@@ -487,6 +487,10 @@
onSetActivityResult(new ActivityResult(BiometricEnrollBase.RESULT_TIMEOUT, null));
break;
}
+ case FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_BACK_PRESSED: {
+ getSupportFragmentManager().popBackStack();
+ break;
+ }
}
}
diff --git a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollEnrollingViewModel.java b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollEnrollingViewModel.java
index 08109ca..bf7b0ac 100644
--- a/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollEnrollingViewModel.java
+++ b/src/com/android/settings/biometrics2/ui/viewmodel/FingerprintEnrollEnrollingViewModel.java
@@ -71,11 +71,17 @@
*/
public static final int FINGERPRINT_ENROLL_ENROLLING_ACTION_DISMISS_ICON_TOUCH_DIALOG = 3;
+ /**
+ * Has got latest cancelled event due to back key
+ */
+ public static final int FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_BACK_PRESSED = 4;
+
@IntDef(prefix = { "FINGERPRINT_ENROLL_ENROLLING_ACTION_" }, value = {
FINGERPRINT_ENROLL_ENROLLING_ACTION_SKIP,
FINGERPRINT_ENROLL_ENROLLING_ACTION_DONE,
FINGERPRINT_ENROLL_ENROLLING_ACTION_SHOW_ICON_TOUCH_DIALOG,
- FINGERPRINT_ENROLL_ENROLLING_ACTION_DISMISS_ICON_TOUCH_DIALOG
+ FINGERPRINT_ENROLL_ENROLLING_ACTION_DISMISS_ICON_TOUCH_DIALOG,
+ FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_BACK_PRESSED
})
@Retention(RetentionPolicy.SOURCE)
public @interface FingerprintEnrollEnrollingAction {}
@@ -103,8 +109,9 @@
@Retention(RetentionPolicy.SOURCE)
public @interface FingerprintErrorDialogAction {}
-
private final int mUserId;
+ private boolean mOnBackPressed;
+ private boolean mOnSkipPressed;
private final FingerprintRepository mFingerprintRepository;
private final AccessibilityRepository mAccessibilityRepository;
private final VibratorRepository mVibratorRepository;
@@ -162,14 +169,26 @@
mErrorDialogActionLiveData.postValue(action);
}
+ public boolean getOnSkipPressed() {
+ return mOnSkipPressed;
+ }
+
/**
* User clicks skip button
*/
- public void onSkipButtonClick() {
+ public void setOnSkipPressed() {
+ mOnSkipPressed = true;
+ }
+
+ /**
+ * Enrolling is cacelled because user clicks skip
+ */
+ public void onCancelledDueToOnSkipPressed() {
final int action = FINGERPRINT_ENROLL_ENROLLING_ACTION_SKIP;
if (DEBUG) {
Log.d(TAG, "onSkipButtonClick, post action " + action);
}
+ mOnSkipPressed = false;
mActionLiveData.postValue(action);
}
@@ -184,6 +203,29 @@
mActionLiveData.postValue(action);
}
+ public boolean getOnBackPressed() {
+ return mOnBackPressed;
+ }
+
+ /**
+ * Back key is pressed.
+ */
+ public void setOnBackPressed() {
+ mOnBackPressed = true;
+ }
+
+ /**
+ * Enrollment is cancelled because back key is pressed.
+ */
+ public void onCancelledDueToOnBackPressed() {
+ final int action = FINGERPRINT_ENROLL_ENROLLING_CANCELED_BECAUSE_BACK_PRESSED;
+ if (DEBUG) {
+ Log.d(TAG, "onCancelledEventReceivedAfterOnBackPressed, post action " + action);
+ }
+ mOnBackPressed = false;
+ mActionLiveData.postValue(action);
+ }
+
/**
* Icon touch dialog show
*/
diff --git a/src/com/android/settings/bluetooth/BluetoothBroadcastDialog.java b/src/com/android/settings/bluetooth/BluetoothBroadcastDialog.java
index 62a66cf..b9cc29e 100644
--- a/src/com/android/settings/bluetooth/BluetoothBroadcastDialog.java
+++ b/src/com/android/settings/bluetooth/BluetoothBroadcastDialog.java
@@ -125,8 +125,7 @@
@Override
public int getMetricsCategory() {
- //TODO(b/228255796) : add new enum for find broadcast fragment
- return SettingsEnums.PAGE_UNKNOWN;
+ return SettingsEnums.DIALOG_LE_AUDIO_BROADCAST;
}
private void launchFindBroadcastsActivity() {
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsAudioRoutingFragment.java b/src/com/android/settings/bluetooth/BluetoothDetailsAudioRoutingFragment.java
index 691acee..ea89053 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsAudioRoutingFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsAudioRoutingFragment.java
@@ -65,7 +65,10 @@
return;
}
- // TODO: mCachedDevice will pass to control in next CLs.
+ use(HearingDeviceRingtoneRoutingPreferenceController.class).init(mCachedDevice);
+ use(HearingDeviceCallRoutingPreferenceController.class).init(mCachedDevice);
+ use(HearingDeviceMediaRoutingPreferenceController.class).init(mCachedDevice);
+ use(HearingDeviceSystemSoundsRoutingPreferenceController.class).init(mCachedDevice);
}
@Override
diff --git a/src/com/android/settings/bluetooth/BluetoothFindBroadcastsFragment.java b/src/com/android/settings/bluetooth/BluetoothFindBroadcastsFragment.java
index e08a244..a365b42 100644
--- a/src/com/android/settings/bluetooth/BluetoothFindBroadcastsFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothFindBroadcastsFragment.java
@@ -239,8 +239,7 @@
@Override
public int getMetricsCategory() {
- //TODO(b/228255796) : add new enum for find broadcast fragment
- return SettingsEnums.PAGE_UNKNOWN;
+ return SettingsEnums.LE_AUDIO_BROADCAST_FIND_BROADCAST;
}
/**
diff --git a/src/com/android/settings/bluetooth/BluetoothPairingRequest.java b/src/com/android/settings/bluetooth/BluetoothPairingRequest.java
index ed7a1fc..ed477c8 100644
--- a/src/com/android/settings/bluetooth/BluetoothPairingRequest.java
+++ b/src/com/android/settings/bluetooth/BluetoothPairingRequest.java
@@ -50,10 +50,8 @@
PowerManager powerManager = context.getSystemService(PowerManager.class);
int pairingVariant = intent.getIntExtra(BluetoothDevice.EXTRA_PAIRING_VARIANT,
BluetoothDevice.ERROR);
- String deviceAddress = device != null ? device.getAddress() : null;
- String deviceName = device != null ? device.getName() : null;
boolean shouldShowDialog = LocalBluetoothPreferences.shouldShowDialogInForeground(
- context, deviceAddress, deviceName);
+ context, device);
// Skips consent pairing dialog if the device was recently associated with CDM
if (pairingVariant == BluetoothDevice.PAIRING_VARIANT_CONSENT
diff --git a/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java b/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java
index a62bbe1..2212e23 100644
--- a/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java
+++ b/src/com/android/settings/bluetooth/BluetoothPermissionRequest.java
@@ -109,8 +109,6 @@
mRequestType);
connectionAccessIntent.putExtra(BluetoothDevice.EXTRA_DEVICE, mDevice);
- String deviceAddress = mDevice != null ? mDevice.getAddress() : null;
- String deviceName = mDevice != null ? mDevice.getName() : null;
String title = null;
String message = null;
PowerManager powerManager =
@@ -118,7 +116,7 @@
if (powerManager.isScreenOn()
&& LocalBluetoothPreferences.shouldShowDialogInForeground(
- context, deviceAddress, deviceName)) {
+ context, mDevice)) {
context.startActivity(connectionAccessIntent);
} else {
// Put up a notification that leads to the dialog
diff --git a/src/com/android/settings/bluetooth/HearingDeviceAudioRoutingBasePreferenceController.java b/src/com/android/settings/bluetooth/HearingDeviceAudioRoutingBasePreferenceController.java
new file mode 100644
index 0000000..84412da
--- /dev/null
+++ b/src/com/android/settings/bluetooth/HearingDeviceAudioRoutingBasePreferenceController.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.bluetooth;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.media.AudioAttributes;
+import android.media.AudioDeviceAttributes;
+import android.media.AudioDeviceInfo;
+import android.media.AudioManager;
+import android.media.audiopolicy.AudioProductStrategy;
+import android.util.Log;
+
+import androidx.annotation.IntDef;
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+
+import com.google.common.primitives.Ints;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Abstract class for providing audio routing {@link ListPreference} common control for hearing
+ * device specifically.
+ */
+public abstract class HearingDeviceAudioRoutingBasePreferenceController extends
+ BasePreferenceController implements Preference.OnPreferenceChangeListener {
+
+ private static final String TAG = "HARoutingBasePreferenceController";
+
+ private static final AudioDeviceAttributes DEVICE_SPEAKER_OUT = new AudioDeviceAttributes(
+ AudioDeviceAttributes.ROLE_OUTPUT, AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, "");
+
+ private final AudioManager mAudioManager;
+
+ public HearingDeviceAudioRoutingBasePreferenceController(Context context,
+ String preferenceKey) {
+ super(context, preferenceKey);
+ mAudioManager = mContext.getSystemService(AudioManager.class);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+
+ final ListPreference listPreference = (ListPreference) preference;
+ final int routingValue = restoreRoutingValue(mContext);
+ listPreference.setValue(String.valueOf(routingValue));
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ final ListPreference listPreference = (ListPreference) preference;
+ final Integer routingValue = Ints.tryParse((String) newValue);
+ final AudioDeviceAttributes hearingDeviceAttribute = new AudioDeviceAttributes(
+ AudioDeviceAttributes.ROLE_OUTPUT,
+ AudioDeviceInfo.TYPE_HEARING_AID,
+ getHearingDevice().getAddress());
+ final List<AudioProductStrategy> supportedStrategies = getSupportedStrategies(
+ getSupportedAttributeList());
+
+ boolean status = false;
+ if (routingValue != null) {
+ switch (routingValue) {
+ case RoutingValue.AUTO:
+ status = removePreferredDeviceForStrategies(supportedStrategies);
+ break;
+ case RoutingValue.HEARING_DEVICE:
+ removePreferredDeviceForStrategies(supportedStrategies);
+ status = setPreferredDeviceForStrategies(supportedStrategies,
+ hearingDeviceAttribute);
+ break;
+ case RoutingValue.DEVICE_SPEAKER:
+ removePreferredDeviceForStrategies(supportedStrategies);
+ status = setPreferredDeviceForStrategies(supportedStrategies,
+ DEVICE_SPEAKER_OUT);
+ break;
+ default:
+ throw new IllegalArgumentException("Unexpected routingValue: " + routingValue);
+ }
+ }
+ if (!status) {
+ Log.w(TAG, "routingMode: " + listPreference.getKey() + "routingValue: " + routingValue
+ + " fail to configure AudioProductStrategy");
+ }
+
+ saveRoutingValue(mContext, routingValue);
+ updateState(listPreference);
+ return true;
+ }
+
+ /**
+ * Gets a list of usage value defined in {@link AudioAttributes} that is used to configure
+ * audio routing via {@link AudioProductStrategy}.
+ */
+ protected abstract int[] getSupportedAttributeList();
+
+ /**
+ * Gets the {@link CachedBluetoothDevice} hearing device that is used to configure audio
+ * routing.
+ */
+ protected abstract CachedBluetoothDevice getHearingDevice();
+
+ /**
+ * Saves the {@link RoutingValue}.
+ *
+ * @param context the valid context used to get the {@link ContentResolver}
+ * @param routingValue the value defined in {@link RoutingValue}
+ */
+ protected abstract void saveRoutingValue(Context context, int routingValue);
+
+ /**
+ * Restores the {@link RoutingValue} and used to reflect status on ListPreference.
+ *
+ * @param context the valid context used to get the {@link ContentResolver}
+ * @return one of {@link RoutingValue}
+ */
+ protected abstract int restoreRoutingValue(Context context);
+
+ private List<AudioProductStrategy> getSupportedStrategies(int[] attributeSdkUsageList) {
+ final List<AudioAttributes> audioAttrList = new ArrayList<>(attributeSdkUsageList.length);
+ for (int attributeSdkUsage : attributeSdkUsageList) {
+ audioAttrList.add(new AudioAttributes.Builder().setUsage(attributeSdkUsage).build());
+ }
+
+ final List<AudioProductStrategy> allStrategies = getAudioProductStrategies();
+ final List<AudioProductStrategy> supportedStrategies = new ArrayList<>();
+ for (AudioProductStrategy strategy : allStrategies) {
+ for (AudioAttributes audioAttr : audioAttrList) {
+ if (strategy.supportsAudioAttributes(audioAttr)) {
+ supportedStrategies.add(strategy);
+ }
+ }
+ }
+
+ return supportedStrategies.stream().distinct().collect(Collectors.toList());
+ }
+
+ @VisibleForTesting
+ List<AudioProductStrategy> getAudioProductStrategies() {
+ return AudioManager.getAudioProductStrategies();
+ }
+
+ @VisibleForTesting
+ boolean setPreferredDeviceForStrategies(List<AudioProductStrategy> strategies,
+ AudioDeviceAttributes audioDevice) {
+ boolean status = true;
+ for (AudioProductStrategy strategy : strategies) {
+ status &= mAudioManager.setPreferredDeviceForStrategy(strategy, audioDevice);
+ }
+
+ return status;
+ }
+
+ @VisibleForTesting
+ boolean removePreferredDeviceForStrategies(List<AudioProductStrategy> strategies) {
+ boolean status = true;
+ for (AudioProductStrategy strategy : strategies) {
+ status &= mAudioManager.removePreferredDeviceForStrategy(strategy);
+ }
+
+ return status;
+ }
+
+ @Retention(RetentionPolicy.SOURCE)
+ @IntDef({
+ RoutingValue.AUTO,
+ RoutingValue.HEARING_DEVICE,
+ RoutingValue.DEVICE_SPEAKER,
+ })
+
+ @VisibleForTesting
+ protected @interface RoutingValue {
+ int AUTO = 0;
+ int HEARING_DEVICE = 1;
+ int DEVICE_SPEAKER = 2;
+ }
+}
diff --git a/src/com/android/settings/bluetooth/HearingDeviceCallRoutingPreferenceController.java b/src/com/android/settings/bluetooth/HearingDeviceCallRoutingPreferenceController.java
new file mode 100644
index 0000000..8daa738
--- /dev/null
+++ b/src/com/android/settings/bluetooth/HearingDeviceCallRoutingPreferenceController.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.bluetooth;
+
+import android.content.Context;
+import android.media.AudioAttributes;
+import android.provider.Settings;
+
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+
+/**
+ * The controller of the hearing device call routing list preference.
+ */
+public class HearingDeviceCallRoutingPreferenceController extends
+ HearingDeviceAudioRoutingBasePreferenceController {
+
+ private CachedBluetoothDevice mHearingDevice;
+
+ public HearingDeviceCallRoutingPreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ /**
+ * Initializes objects in this controller. Need to call this before using the controller.
+ *
+ * @param cachedBluetoothDevice the hearing device to configure audio routing
+ */
+ public void init(CachedBluetoothDevice cachedBluetoothDevice) {
+ mHearingDevice = cachedBluetoothDevice;
+ }
+
+ @Override
+ protected int[] getSupportedAttributeList() {
+ return new int[]{
+ AudioAttributes.USAGE_VOICE_COMMUNICATION,
+ AudioAttributes.USAGE_VOICE_COMMUNICATION_SIGNALLING};
+ }
+
+ @Override
+ protected CachedBluetoothDevice getHearingDevice() {
+ return mHearingDevice;
+ }
+
+ @Override
+ protected void saveRoutingValue(Context context, int routingValue) {
+ Settings.Secure.putInt(context.getContentResolver(),
+ Settings.Secure.HEARING_AID_CALL_ROUTING, routingValue);
+ }
+
+ @Override
+ protected int restoreRoutingValue(Context context) {
+ return Settings.Secure.getInt(context.getContentResolver(),
+ Settings.Secure.HEARING_AID_CALL_ROUTING, RoutingValue.AUTO);
+ }
+}
diff --git a/src/com/android/settings/bluetooth/HearingDeviceMediaRoutingPreferenceController.java b/src/com/android/settings/bluetooth/HearingDeviceMediaRoutingPreferenceController.java
new file mode 100644
index 0000000..4e61346
--- /dev/null
+++ b/src/com/android/settings/bluetooth/HearingDeviceMediaRoutingPreferenceController.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.bluetooth;
+
+import android.content.Context;
+import android.media.AudioAttributes;
+import android.provider.Settings;
+
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+
+/**
+ * The controller of the hearing device media routing list preference.
+ */
+public class HearingDeviceMediaRoutingPreferenceController extends
+ HearingDeviceAudioRoutingBasePreferenceController {
+
+ private CachedBluetoothDevice mHearingDevice;
+
+ public HearingDeviceMediaRoutingPreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ /**
+ * Initializes objects in this controller. Need to call this before using the controller.
+ *
+ * @param cachedBluetoothDevice the hearing device to configure audio routing
+ */
+ public void init(CachedBluetoothDevice cachedBluetoothDevice) {
+ mHearingDevice = cachedBluetoothDevice;
+ }
+
+ @Override
+ protected int[] getSupportedAttributeList() {
+ return new int[]{
+ AudioAttributes.USAGE_MEDIA,
+ AudioAttributes.USAGE_GAME};
+ }
+
+ @Override
+ protected CachedBluetoothDevice getHearingDevice() {
+ return mHearingDevice;
+ }
+
+ @Override
+ protected void saveRoutingValue(Context context, int routingValue) {
+ Settings.Secure.putInt(context.getContentResolver(),
+ Settings.Secure.HEARING_AID_MEDIA_ROUTING, routingValue);
+ }
+
+ @Override
+ protected int restoreRoutingValue(Context context) {
+ return Settings.Secure.getInt(context.getContentResolver(),
+ Settings.Secure.HEARING_AID_MEDIA_ROUTING, RoutingValue.AUTO);
+ }
+}
diff --git a/src/com/android/settings/bluetooth/HearingDeviceRingtoneRoutingPreferenceController.java b/src/com/android/settings/bluetooth/HearingDeviceRingtoneRoutingPreferenceController.java
new file mode 100644
index 0000000..325d394
--- /dev/null
+++ b/src/com/android/settings/bluetooth/HearingDeviceRingtoneRoutingPreferenceController.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.bluetooth;
+
+import android.content.Context;
+import android.media.AudioAttributes;
+import android.provider.Settings;
+
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+
+/**
+ * The controller of the hearing device ringtone routing list preference.
+ */
+public class HearingDeviceRingtoneRoutingPreferenceController extends
+ HearingDeviceAudioRoutingBasePreferenceController {
+
+ private CachedBluetoothDevice mHearingDevice;
+
+ public HearingDeviceRingtoneRoutingPreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ /**
+ * Initializes objects in this controller. Need to call this before using the controller.
+ *
+ * @param cachedBluetoothDevice the hearing device to configure audio routing
+ */
+ public void init(CachedBluetoothDevice cachedBluetoothDevice) {
+ mHearingDevice = cachedBluetoothDevice;
+ }
+
+ @Override
+ protected int[] getSupportedAttributeList() {
+ return new int[] {AudioAttributes.USAGE_NOTIFICATION_RINGTONE};
+ }
+
+ @Override
+ protected CachedBluetoothDevice getHearingDevice() {
+ return mHearingDevice;
+ }
+
+ @Override
+ protected void saveRoutingValue(Context context, int routingValue) {
+ Settings.Secure.putInt(context.getContentResolver(),
+ Settings.Secure.HEARING_AID_RINGTONE_ROUTING, routingValue);
+ }
+
+ @Override
+ protected int restoreRoutingValue(Context context) {
+ return Settings.Secure.getInt(context.getContentResolver(),
+ Settings.Secure.HEARING_AID_RINGTONE_ROUTING, RoutingValue.AUTO);
+ }
+}
diff --git a/src/com/android/settings/bluetooth/HearingDeviceSystemSoundsRoutingPreferenceController.java b/src/com/android/settings/bluetooth/HearingDeviceSystemSoundsRoutingPreferenceController.java
new file mode 100644
index 0000000..19de713
--- /dev/null
+++ b/src/com/android/settings/bluetooth/HearingDeviceSystemSoundsRoutingPreferenceController.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.bluetooth;
+
+import android.content.Context;
+import android.media.AudioAttributes;
+import android.provider.Settings;
+
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+
+/**
+ * The controller of the hearing device system sounds routing list preference.
+ */
+public class HearingDeviceSystemSoundsRoutingPreferenceController extends
+ HearingDeviceAudioRoutingBasePreferenceController {
+
+ private CachedBluetoothDevice mHearingDevice;
+
+ public HearingDeviceSystemSoundsRoutingPreferenceController(Context context,
+ String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ /**
+ * Initializes objects in this controller. Need to call this before using the controller.
+ *
+ * @param cachedBluetoothDevice the hearing device to configure audio routing
+ */
+ public void init(CachedBluetoothDevice cachedBluetoothDevice) {
+ mHearingDevice = cachedBluetoothDevice;
+ }
+
+ @Override
+ protected int[] getSupportedAttributeList() {
+ return new int[]{
+ AudioAttributes.USAGE_ALARM,
+ AudioAttributes.USAGE_NOTIFICATION,
+ AudioAttributes.USAGE_NOTIFICATION_EVENT,
+ AudioAttributes.USAGE_ASSISTANCE_ACCESSIBILITY,
+ AudioAttributes.USAGE_ASSISTANCE_NAVIGATION_GUIDANCE,
+ AudioAttributes.USAGE_ASSISTANCE_SONIFICATION,
+ AudioAttributes.USAGE_ASSISTANT};
+ }
+
+ @Override
+ protected CachedBluetoothDevice getHearingDevice() {
+ return mHearingDevice;
+ }
+
+ @Override
+ protected void saveRoutingValue(Context context, int routingValue) {
+ Settings.Secure.putInt(context.getContentResolver(),
+ Settings.Secure.HEARING_AID_SYSTEM_SOUNDS_ROUTING, routingValue);
+
+ }
+
+ @Override
+ protected int restoreRoutingValue(Context context) {
+ return Settings.Secure.getInt(context.getContentResolver(),
+ Settings.Secure.HEARING_AID_SYSTEM_SOUNDS_ROUTING, RoutingValue.AUTO);
+ }
+}
diff --git a/src/com/android/settings/bluetooth/LocalBluetoothPreferences.java b/src/com/android/settings/bluetooth/LocalBluetoothPreferences.java
index faed1c3..4dcc868 100644
--- a/src/com/android/settings/bluetooth/LocalBluetoothPreferences.java
+++ b/src/com/android/settings/bluetooth/LocalBluetoothPreferences.java
@@ -16,7 +16,10 @@
package com.android.settings.bluetooth;
+import android.annotation.Nullable;
+import android.app.ActivityManager;
import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
@@ -57,8 +60,9 @@
KEY_DISCOVERABLE_END_TIMESTAMP, 0);
}
- static boolean shouldShowDialogInForeground(Context context,
- String deviceAddress, String deviceName) {
+ static boolean shouldShowDialogInForeground(Context context, @Nullable BluetoothDevice device) {
+ String deviceAddress = device != null ? device.getAddress() : null;
+ String deviceName = device != null ? device.getName() : null;
LocalBluetoothManager manager = Utils.getLocalBtManager(context);
if (manager == null) {
if (DEBUG) Log.v(TAG, "manager == null - do not show dialog.");
@@ -126,6 +130,20 @@
}
}
+ if (device != null) {
+ ActivityManager activityManager = context.getSystemService(ActivityManager.class);
+ String packageName = device.getCreateBondCaller();
+
+ if (packageName != null && activityManager.getPackageImportance(packageName)
+ == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
+ if (DEBUG) {
+ Log.v(TAG, "showing dialog because the initiating application "
+ + "is in foreground");
+ }
+ return true;
+ }
+ }
+
if (DEBUG) Log.v(TAG, "Found no reason to show the dialog - do not show dialog.");
return false;
}
diff --git a/src/com/android/settings/dashboard/CategoryManager.java b/src/com/android/settings/dashboard/CategoryManager.java
index b6ec4ca..8ea5cf4 100644
--- a/src/com/android/settings/dashboard/CategoryManager.java
+++ b/src/com/android/settings/dashboard/CategoryManager.java
@@ -26,6 +26,7 @@
import androidx.annotation.VisibleForTesting;
import com.android.settings.homepage.HighlightableMenu;
+import com.android.settings.safetycenter.SafetyCenterManagerWrapper;
import com.android.settingslib.applications.InterestingConfigChanges;
import com.android.settingslib.drawer.CategoryKey;
import com.android.settingslib.drawer.DashboardCategory;
@@ -38,6 +39,7 @@
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
+import java.util.Objects;
import java.util.Set;
public class CategoryManager {
@@ -151,6 +153,7 @@
mCategoryByKeyMap.put(category.key, category);
}
backwardCompatCleanupForCategory(mTileByComponentCache, mCategoryByKeyMap);
+ mergeSecurityPrivacyKeys(context, mTileByComponentCache, mCategoryByKeyMap);
sortCategories(context, mCategoryByKeyMap);
filterDuplicateTiles(mCategoryByKeyMap);
if (firstLoading) {
@@ -225,6 +228,36 @@
}
/**
+ * Merges {@link CategoryKey#CATEGORY_SECURITY_ADVANCED_SETTINGS} and {@link
+ * CategoryKey#CATEGORY_PRIVACY} into {@link
+ * CategoryKey#CATEGORY_MORE_SECURITY_PRIVACY_SETTINGS}
+ */
+ @VisibleForTesting
+ synchronized void mergeSecurityPrivacyKeys(
+ Context context,
+ Map<Pair<String, String>, Tile> tileByComponentCache,
+ Map<String, DashboardCategory> categoryByKeyMap) {
+ if (!SafetyCenterManagerWrapper.get().isEnabled(context)) {
+ return;
+ }
+ for (Entry<Pair<String, String>, Tile> tileEntry : tileByComponentCache.entrySet()) {
+ Tile tile = tileEntry.getValue();
+ if (Objects.equals(tile.getCategory(), CategoryKey.CATEGORY_SECURITY_ADVANCED_SETTINGS)
+ || Objects.equals(tile.getCategory(), CategoryKey.CATEGORY_PRIVACY)) {
+ final String newCategoryKey = CategoryKey.CATEGORY_MORE_SECURITY_PRIVACY_SETTINGS;
+ tile.setCategory(newCategoryKey);
+ // move tile to new category.
+ DashboardCategory newCategory = categoryByKeyMap.get(newCategoryKey);
+ if (newCategory == null) {
+ newCategory = new DashboardCategory(newCategoryKey);
+ categoryByKeyMap.put(newCategoryKey, newCategory);
+ }
+ newCategory.addTile(tile);
+ }
+ }
+ }
+
+ /**
* Sort the tiles injected from all apps such that if they have the same priority value,
* they wil lbe sorted by package name.
* <p/>
diff --git a/src/com/android/settings/development/BluetoothSnoopLogFilterProfileMapPreferenceController.java b/src/com/android/settings/development/BluetoothSnoopLogFilterProfileMapPreferenceController.java
new file mode 100644
index 0000000..8ace9bb
--- /dev/null
+++ b/src/com/android/settings/development/BluetoothSnoopLogFilterProfileMapPreferenceController.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2022 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.development;
+
+import android.content.Context;
+import android.sysprop.BluetoothProperties;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.development.DeveloperOptionsPreferenceController;
+
+import java.util.Locale;
+
+/** Bluetooth Snoop Logger Map Profile Filter Preference Controller */
+public class BluetoothSnoopLogFilterProfileMapPreferenceController
+ extends DeveloperOptionsPreferenceController
+ implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
+
+ private static final String TAG = "BluetoothSnoopLogFilterProfileMapPreferenceController";
+ private static final String PREFERENCE_KEY = "bt_hci_snoop_log_filter_map";
+ @VisibleForTesting static final int BTSNOOP_LOG_PROFILE_FILTER_MODE_DISABLED_INDEX = 0;
+ @VisibleForTesting static final int BTSNOOP_LOG_PROFILE_FILTER_MODE_MAGIC_INDEX = 1;
+ @VisibleForTesting static final int BTSNOOP_LOG_PROFILE_FILTER_MODE_HEADER_INDEX = 2;
+ @VisibleForTesting static final int BTSNOOP_LOG_PROFILE_FILTER_MODE_FULL_FILTER_INDEX = 3;
+
+ private final String[] mListValues;
+ private final String[] mListEntries;
+ private final String mProfilesFilterDisabledEntry;
+
+ @VisibleForTesting
+ static boolean isSnoopLogModeFilteredEnabled() {
+ return (BluetoothProperties.snoop_log_mode()
+ .orElse(BluetoothProperties.snoop_log_mode_values.DISABLED)
+ == BluetoothProperties.snoop_log_mode_values.FILTERED);
+ }
+
+ public BluetoothSnoopLogFilterProfileMapPreferenceController(Context context) {
+ super(context);
+ mListValues =
+ context.getResources()
+ .getStringArray(R.array.bt_hci_snoop_log_profile_filter_values);
+ mListEntries =
+ context.getResources()
+ .getStringArray(R.array.bt_hci_snoop_log_profile_filter_entries);
+ mProfilesFilterDisabledEntry =
+ context.getResources()
+ .getString(R.string.bt_hci_snoop_log_filtered_mode_disabled_summary);
+ }
+
+ // Default mode is DISABLED.
+ public int getDefaultModeIndex() {
+ return BTSNOOP_LOG_PROFILE_FILTER_MODE_DISABLED_INDEX;
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return PREFERENCE_KEY;
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ BluetoothProperties.snoop_log_filter_profile_map(
+ BluetoothProperties.snoop_log_filter_profile_map_values.valueOf(
+ newValue.toString().toUpperCase(Locale.US)));
+ updateState(mPreference);
+ return true;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ final ListPreference listPreference = (ListPreference) preference;
+ if (isSnoopLogModeFilteredEnabled()) {
+ mPreference.setEnabled(true);
+
+ BluetoothProperties.snoop_log_filter_profile_map_values currentValue =
+ BluetoothProperties.snoop_log_filter_profile_map()
+ .orElse(
+ BluetoothProperties.snoop_log_filter_profile_map_values
+ .DISABLED);
+
+ int index = getDefaultModeIndex();
+ for (int i = 0; i < mListValues.length; i++) {
+ if (currentValue
+ == BluetoothProperties.snoop_log_filter_profile_map_values.valueOf(
+ mListValues[i].toUpperCase(Locale.US))) {
+ index = i;
+ break;
+ }
+ }
+ listPreference.setValue(mListValues[index]);
+ listPreference.setSummary(mListEntries[index]);
+ } else {
+ mPreference.setEnabled(false);
+ listPreference.setSummary(mProfilesFilterDisabledEntry);
+ }
+ }
+
+ /** Called when the Bluetooth Snoop Log Mode changes. */
+ public void onSettingChanged() {
+ updateState(mPreference);
+ }
+
+ @Override
+ protected void onDeveloperOptionsSwitchEnabled() {
+ super.onDeveloperOptionsSwitchEnabled();
+ mPreference.setEnabled(isSnoopLogModeFilteredEnabled());
+ }
+
+ @Override
+ protected void onDeveloperOptionsSwitchDisabled() {
+ super.onDeveloperOptionsSwitchDisabled();
+ BluetoothProperties.snoop_log_filter_profile_map(
+ BluetoothProperties.snoop_log_filter_profile_map_values.DISABLED);
+ ((ListPreference) mPreference).setValue(mListValues[getDefaultModeIndex()]);
+ ((ListPreference) mPreference).setSummary(mListEntries[getDefaultModeIndex()]);
+ mPreference.setEnabled(false);
+ }
+}
diff --git a/src/com/android/settings/development/BluetoothSnoopLogFilterProfilePbapPreferenceController.java b/src/com/android/settings/development/BluetoothSnoopLogFilterProfilePbapPreferenceController.java
new file mode 100644
index 0000000..c17291c
--- /dev/null
+++ b/src/com/android/settings/development/BluetoothSnoopLogFilterProfilePbapPreferenceController.java
@@ -0,0 +1,136 @@
+/*
+ * Copyright (C) 2022 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.development;
+
+import android.content.Context;
+import android.sysprop.BluetoothProperties;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.development.DeveloperOptionsPreferenceController;
+
+import java.util.Locale;
+
+/** Bluetooth Snoop Logger Pbap Profile Filter Preference Controller */
+public class BluetoothSnoopLogFilterProfilePbapPreferenceController
+ extends DeveloperOptionsPreferenceController
+ implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
+
+ private static final String TAG = "BluetoothSnoopLogFilterProfilePbapPreferenceController";
+ private static final String PREFERENCE_KEY = "bt_hci_snoop_log_filter_pbap";
+ @VisibleForTesting static final int BTSNOOP_LOG_PROFILE_FILTER_MODE_DISABLED_INDEX = 0;
+ @VisibleForTesting static final int BTSNOOP_LOG_PROFILE_FILTER_MODE_MAGIC_INDEX = 1;
+ @VisibleForTesting static final int BTSNOOP_LOG_PROFILE_FILTER_MODE_HEADER_INDEX = 2;
+ @VisibleForTesting static final int BTSNOOP_LOG_PROFILE_FILTER_MODE_FULL_FILTER_INDEX = 3;
+
+ private final String[] mListValues;
+ private final String[] mListEntries;
+ private final String mProfilesFilterDisabledEntry;
+
+ @VisibleForTesting
+ static boolean isSnoopLogModeFilteredEnabled() {
+ return (BluetoothProperties.snoop_log_mode()
+ .orElse(BluetoothProperties.snoop_log_mode_values.DISABLED)
+ == BluetoothProperties.snoop_log_mode_values.FILTERED);
+ }
+
+ public BluetoothSnoopLogFilterProfilePbapPreferenceController(Context context) {
+ super(context);
+ mListValues =
+ context.getResources()
+ .getStringArray(R.array.bt_hci_snoop_log_profile_filter_values);
+ mListEntries =
+ context.getResources()
+ .getStringArray(R.array.bt_hci_snoop_log_profile_filter_entries);
+ mProfilesFilterDisabledEntry =
+ context.getResources()
+ .getString(R.string.bt_hci_snoop_log_filtered_mode_disabled_summary);
+ }
+
+ // Default mode is DISABLED.
+ public int getDefaultModeIndex() {
+ return BTSNOOP_LOG_PROFILE_FILTER_MODE_DISABLED_INDEX;
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return PREFERENCE_KEY;
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ BluetoothProperties.snoop_log_filter_profile_pbap(
+ BluetoothProperties.snoop_log_filter_profile_pbap_values.valueOf(
+ newValue.toString().toUpperCase(Locale.US)));
+ updateState(mPreference);
+ return true;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ final ListPreference listPreference = (ListPreference) preference;
+ if (isSnoopLogModeFilteredEnabled()) {
+ mPreference.setEnabled(true);
+ BluetoothProperties.snoop_log_filter_profile_pbap_values currentValue =
+ BluetoothProperties.snoop_log_filter_profile_pbap()
+ .orElse(
+ BluetoothProperties.snoop_log_filter_profile_pbap_values
+ .DISABLED);
+
+ int index = getDefaultModeIndex();
+ for (int i = 0; i < mListValues.length; i++) {
+ if (currentValue
+ == BluetoothProperties.snoop_log_filter_profile_pbap_values.valueOf(
+ mListValues[i].toUpperCase(Locale.US))) {
+ index = i;
+ break;
+ }
+ }
+ listPreference.setValue(mListValues[index]);
+ listPreference.setSummary(mListEntries[index]);
+ } else {
+ mPreference.setEnabled(false);
+ listPreference.setSummary(mProfilesFilterDisabledEntry);
+ }
+ }
+
+ /** Called when the Bluetooth Snoop Log Mode changes. */
+ public void onSettingChanged() {
+ updateState(mPreference);
+ }
+
+ @Override
+ protected void onDeveloperOptionsSwitchEnabled() {
+ super.onDeveloperOptionsSwitchEnabled();
+ mPreference.setEnabled(isSnoopLogModeFilteredEnabled());
+ }
+
+ @Override
+ protected void onDeveloperOptionsSwitchDisabled() {
+ super.onDeveloperOptionsSwitchDisabled();
+ BluetoothProperties.snoop_log_filter_profile_pbap(
+ BluetoothProperties.snoop_log_filter_profile_pbap_values.DISABLED);
+ ((ListPreference) mPreference).setValue(mListValues[getDefaultModeIndex()]);
+ ((ListPreference) mPreference).setSummary(mListEntries[getDefaultModeIndex()]);
+ mPreference.setEnabled(false);
+ }
+}
diff --git a/src/com/android/settings/development/BluetoothSnoopLogHost.java b/src/com/android/settings/development/BluetoothSnoopLogHost.java
new file mode 100644
index 0000000..1e53e73
--- /dev/null
+++ b/src/com/android/settings/development/BluetoothSnoopLogHost.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+/**
+ * Interface for BluetoothSnoopLogPreferenceController callbacks.
+ */
+public interface BluetoothSnoopLogHost {
+
+ /**
+ * Called when the Bluetooth Snoop Log Mode changes.
+ */
+ void onSettingChanged();
+}
diff --git a/src/com/android/settings/development/BluetoothSnoopLogPreferenceController.java b/src/com/android/settings/development/BluetoothSnoopLogPreferenceController.java
index d698436..31ed652 100644
--- a/src/com/android/settings/development/BluetoothSnoopLogPreferenceController.java
+++ b/src/com/android/settings/development/BluetoothSnoopLogPreferenceController.java
@@ -22,12 +22,9 @@
import android.provider.Settings;
import android.text.TextUtils;
-import android.util.Log;
-
import androidx.annotation.VisibleForTesting;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
-import androidx.preference.SwitchPreference;
import com.android.settings.R;
import com.android.settings.core.PreferenceControllerMixin;
@@ -37,22 +34,23 @@
implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
private static final String PREFERENCE_KEY = "bt_hci_snoop_log";
- @VisibleForTesting
- static final int BTSNOOP_LOG_MODE_DISABLED_INDEX = 0;
- @VisibleForTesting
- static final int BTSNOOP_LOG_MODE_FILTERED_INDEX = 1;
- @VisibleForTesting
- static final int BTSNOOP_LOG_MODE_FULL_INDEX = 2;
+ @VisibleForTesting static final int BTSNOOP_LOG_MODE_DISABLED_INDEX = 0;
+ @VisibleForTesting static final int BTSNOOP_LOG_MODE_FILTERED_INDEX = 1;
+ @VisibleForTesting static final int BTSNOOP_LOG_MODE_FULL_INDEX = 2;
+
@VisibleForTesting
static final String BLUETOOTH_BTSNOOP_LOG_MODE_PROPERTY = "persist.bluetooth.btsnooplogmode";
private final String[] mListValues;
private final String[] mListEntries;
+ private DevelopmentSettingsDashboardFragment mFragment;
- public BluetoothSnoopLogPreferenceController(Context context) {
+ public BluetoothSnoopLogPreferenceController(
+ Context context, DevelopmentSettingsDashboardFragment fragment) {
super(context);
mListValues = context.getResources().getStringArray(R.array.bt_hci_snoop_log_values);
mListEntries = context.getResources().getStringArray(R.array.bt_hci_snoop_log_entries);
+ mFragment = fragment;
}
// Default mode is DISABLED. It can also be changed by modifying the global setting.
@@ -61,8 +59,10 @@
return BTSNOOP_LOG_MODE_DISABLED_INDEX;
}
- final String default_mode = Settings.Global.getString(mContext.getContentResolver(),
- Settings.Global.BLUETOOTH_BTSNOOP_DEFAULT_MODE);
+ final String default_mode =
+ Settings.Global.getString(
+ mContext.getContentResolver(),
+ Settings.Global.BLUETOOTH_BTSNOOP_DEFAULT_MODE);
for (int i = 0; i < mListValues.length; i++) {
if (TextUtils.equals(default_mode, mListValues[i])) {
@@ -82,6 +82,9 @@
public boolean onPreferenceChange(Preference preference, Object newValue) {
SystemProperties.set(BLUETOOTH_BTSNOOP_LOG_MODE_PROPERTY, newValue.toString());
updateState(mPreference);
+ if (mFragment != null) {
+ mFragment.onSettingChanged();
+ }
return true;
}
diff --git a/src/com/android/settings/development/DevelopmentMemtagFooterPreferenceController.java b/src/com/android/settings/development/DevelopmentMemtagFooterPreferenceController.java
new file mode 100644
index 0000000..a5612ca
--- /dev/null
+++ b/src/com/android/settings/development/DevelopmentMemtagFooterPreferenceController.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 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.security;
+
+import android.content.Context;
+import android.text.TextUtils;
+
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settingslib.HelpUtils;
+import com.android.settingslib.widget.FooterPreference;
+
+/** Footer for face settings showing the help text and help link. */
+public class DevelopmentMemtagFooterPreferenceController extends BasePreferenceController {
+
+ public DevelopmentMemtagFooterPreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AVAILABLE_UNSEARCHABLE;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ // Set up learn more link.
+ FooterPreference prefFooter = screen.findPreference(getPreferenceKey());
+ String helpUrl = mContext.getString(R.string.help_url_development_memtag);
+ if (prefFooter != null && !TextUtils.isEmpty(helpUrl)) {
+ prefFooter.setLearnMoreAction(
+ v ->
+ mContext.startActivity(
+ HelpUtils.getHelpIntent(
+ mContext, helpUrl, /* backupContext= */ "")));
+ prefFooter.setLearnMoreText(mContext.getString(R.string.development_memtag_learn_more));
+ }
+ }
+}
diff --git a/src/com/android/settings/development/DevelopmentMemtagPage.java b/src/com/android/settings/development/DevelopmentMemtagPage.java
new file mode 100644
index 0000000..df983f3
--- /dev/null
+++ b/src/com/android/settings/development/DevelopmentMemtagPage.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.search.SearchIndexable;
+
+@SearchIndexable
+public class DevelopmentMemtagPage extends DashboardFragment {
+ private static final String TAG = "DevelopmentMemtagPage";
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.SETTINGS_DEVELOPMENT_MEMTAG_CATEGORY;
+ }
+
+ @Override
+ protected String getLogTag() {
+ return TAG;
+ }
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+
+ use(RebootWithMtePreferenceController.class).setFragment(this);
+ use(DevelopmentMemtagPreferenceController.class).setFragment(this);
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.development_memtag_page;
+ }
+
+ public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider(R.xml.development_memtag_page);
+}
diff --git a/src/com/android/settings/development/DevelopmentMemtagPagePreferenceController.java b/src/com/android/settings/development/DevelopmentMemtagPagePreferenceController.java
new file mode 100644
index 0000000..240079b
--- /dev/null
+++ b/src/com/android/settings/development/DevelopmentMemtagPagePreferenceController.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import android.content.Context;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.security.MemtagHelper;
+import com.android.settingslib.development.DeveloperOptionsPreferenceController;
+
+public class DevelopmentMemtagPagePreferenceController extends DeveloperOptionsPreferenceController
+ implements PreferenceControllerMixin {
+ private static final String KEY_DEVELOPMENT_MEMTAG_PAGE = "development_memtag_page";
+
+ public DevelopmentMemtagPagePreferenceController(
+ Context context, DevelopmentSettingsDashboardFragment fragment) {
+ super(context);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return android.os.SystemProperties.getBoolean("ro.arm64.memtag.bootctl_supported", false);
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY_DEVELOPMENT_MEMTAG_PAGE;
+ }
+
+ @Override
+ protected void onDeveloperOptionsSwitchDisabled() {
+ super.onDeveloperOptionsSwitchDisabled();
+ MemtagHelper.setChecked(false);
+ }
+}
diff --git a/src/com/android/settings/development/DevelopmentMemtagPreferenceController.java b/src/com/android/settings/development/DevelopmentMemtagPreferenceController.java
new file mode 100644
index 0000000..751ccba
--- /dev/null
+++ b/src/com/android/settings/development/DevelopmentMemtagPreferenceController.java
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import static com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
+
+import android.content.Context;
+import android.os.SystemProperties;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+import com.android.settings.core.TogglePreferenceController;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.security.MemtagHelper;
+import com.android.settings.security.MemtagRebootDialog;
+import com.android.settingslib.RestrictedLockUtilsInternal;
+import com.android.settingslib.RestrictedSwitchPreference;
+import com.android.settingslib.development.DevelopmentSettingsEnabler;
+
+public class DevelopmentMemtagPreferenceController extends TogglePreferenceController {
+ private Preference mPreference;
+ private DashboardFragment mFragment;
+
+ public DevelopmentMemtagPreferenceController(Context context, String key) {
+ super(context, key);
+ }
+
+ public void setFragment(DashboardFragment fragment) {
+ mFragment = fragment;
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)
+ && SystemProperties.getBoolean("ro.arm64.memtag.bootctl_supported", false)
+ ? BasePreferenceController.AVAILABLE
+ : BasePreferenceController.UNSUPPORTED_ON_DEVICE;
+ }
+
+ @Override
+ public boolean isChecked() {
+ return MemtagHelper.isChecked();
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ MemtagHelper.setChecked(isChecked);
+ if (mPreference != null) {
+ refreshSummary(mPreference);
+ }
+ if (isChecked != MemtagHelper.isOn()) {
+ int msg =
+ isChecked
+ ? R.string.development_memtag_reboot_message_on
+ : R.string.development_memtag_reboot_message_off;
+ MemtagRebootDialog.show(mContext, mFragment, msg);
+ }
+ mFragment.forceUpdatePreferences();
+ return true;
+ }
+
+ @Override
+ public int getSliceHighlightMenuRes() {
+ return R.string.menu_key_system;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = screen.findPreference(getPreferenceKey());
+ refreshSummary(mPreference);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ EnforcedAdmin admin = RestrictedLockUtilsInternal.checkIfMteIsDisabled(mContext);
+ if (admin != null) {
+ // Make sure this is disabled even if the user directly goes to this
+ // page via the android.settings.ADVANCED_MEMORY_PROTECTION_SETTINGS intent.
+ ((RestrictedSwitchPreference) preference).setDisabledByAdmin(admin);
+ }
+ refreshSummary(preference);
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ return mContext.getResources().getString(MemtagHelper.getSummary());
+ }
+}
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index 8ff2336..c732c0a 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -83,7 +83,7 @@
AdbClearKeysDialogHost, LogPersistDialogHost,
BluetoothRebootDialog.OnRebootDialogListener,
AbstractBluetoothPreferenceController.Callback,
- NfcRebootDialog.OnNfcRebootDialogConfirmedListener {
+ NfcRebootDialog.OnNfcRebootDialogConfirmedListener, BluetoothSnoopLogHost {
private static final String TAG = "DevSettingsDashboard";
@@ -431,6 +431,18 @@
}
@Override
+ public void onSettingChanged() {
+ final BluetoothSnoopLogFilterProfileMapPreferenceController controllerMap =
+ getDevelopmentOptionsController(
+ BluetoothSnoopLogFilterProfileMapPreferenceController.class);
+ final BluetoothSnoopLogFilterProfilePbapPreferenceController controllerPbap =
+ getDevelopmentOptionsController(
+ BluetoothSnoopLogFilterProfilePbapPreferenceController.class);
+ controllerMap.onSettingChanged();
+ controllerPbap.onSettingChanged();
+ }
+
+ @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
boolean handledResult = false;
for (AbstractPreferenceController controller : mPreferenceControllers) {
@@ -544,11 +556,15 @@
controllers.add(new BugReportPreferenceController(context));
controllers.add(new BugReportHandlerPreferenceController(context));
controllers.add(new SystemServerHeapDumpPreferenceController(context));
- controllers.add(new RebootWithMtePreferenceController(context, fragment));
+ controllers.add(new DevelopmentMemtagPagePreferenceController(context, fragment));
controllers.add(new LocalBackupPasswordPreferenceController(context));
controllers.add(new StayAwakePreferenceController(context, lifecycle));
controllers.add(new HdcpCheckingPreferenceController(context));
- controllers.add(new BluetoothSnoopLogPreferenceController(context));
+ controllers.add(new BluetoothSnoopLogPreferenceController(context, fragment));
+ controllers.add(new DefaultLaunchPreferenceController(context,
+ "snoop_logger_filters_dashboard"));
+ controllers.add(new BluetoothSnoopLogFilterProfilePbapPreferenceController(context));
+ controllers.add(new BluetoothSnoopLogFilterProfileMapPreferenceController(context));
controllers.add(new OemUnlockPreferenceController(context, activity, fragment));
controllers.add(new PictureColorModePreferenceController(context, lifecycle));
controllers.add(new WebViewAppPreferenceController(context));
diff --git a/src/com/android/settings/development/RebootWithMtePreferenceController.java b/src/com/android/settings/development/RebootWithMtePreferenceController.java
index f7bd726..76ad2ce 100644
--- a/src/com/android/settings/development/RebootWithMtePreferenceController.java
+++ b/src/com/android/settings/development/RebootWithMtePreferenceController.java
@@ -17,32 +17,35 @@
package com.android.settings.development;
import android.content.Context;
+import android.os.SystemProperties;
import android.text.TextUtils;
+import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import com.android.settings.R;
import com.android.settings.Utils;
+import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.security.MemtagHelper;
-import com.android.settingslib.development.DeveloperOptionsPreferenceController;
+import com.android.settingslib.development.DevelopmentSettingsEnabler;
-public class RebootWithMtePreferenceController extends DeveloperOptionsPreferenceController
+public class RebootWithMtePreferenceController extends BasePreferenceController
implements PreferenceControllerMixin {
-
private static final String KEY_REBOOT_WITH_MTE = "reboot_with_mte";
- private final DevelopmentSettingsDashboardFragment mFragment;
+ private Fragment mFragment;
- public RebootWithMtePreferenceController(
- Context context, DevelopmentSettingsDashboardFragment fragment) {
- super(context);
- mFragment = fragment;
+ public RebootWithMtePreferenceController(Context context) {
+ super(context, KEY_REBOOT_WITH_MTE);
}
@Override
- public boolean isAvailable() {
- return android.os.SystemProperties.getBoolean("ro.arm64.memtag.bootctl_supported", false);
+ public int getAvailabilityStatus() {
+ return DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(mContext)
+ && SystemProperties.getBoolean("ro.arm64.memtag.bootctl_supported", false)
+ ? BasePreferenceController.AVAILABLE
+ : BasePreferenceController.UNSUPPORTED_ON_DEVICE;
}
@Override
@@ -64,6 +67,10 @@
return KEY_REBOOT_WITH_MTE;
}
+ public void setFragment(Fragment fragment) {
+ mFragment = fragment;
+ }
+
@Override
public boolean handlePreferenceTreeClick(Preference preference) {
if (Utils.isMonkeyRunning()) {
diff --git a/src/com/android/settings/development/snooplogger/SnoopLoggerFiltersDashboard.java b/src/com/android/settings/development/snooplogger/SnoopLoggerFiltersDashboard.java
new file mode 100644
index 0000000..6f1ede2
--- /dev/null
+++ b/src/com/android/settings/development/snooplogger/SnoopLoggerFiltersDashboard.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2022 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.development.snooplogger;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.provider.SearchIndexableResource;
+
+import com.android.settings.R;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.development.DevelopmentSettingsEnabler;
+import com.android.settingslib.search.SearchIndexable;
+
+import java.util.List;
+
+/**
+ * Bluetooth Snoop Logger Filters Dashboard
+ */
+@SearchIndexable
+public class SnoopLoggerFiltersDashboard extends DashboardFragment {
+
+ private static final String TAG = "SnoopLoggerFiltersDashboard";
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.SETTINGS_SNOOP_LOGGER_DASHBOARD;
+ }
+
+ @Override
+ protected String getLogTag() {
+ return TAG;
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.snoop_logger_filters_settings;
+ }
+
+ @Override
+ public void onAttach(Context context) {
+ super.onAttach(context);
+ }
+
+ @Override
+ public int getHelpResource() {
+ return 0;
+ }
+
+ public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider() {
+ @Override
+ public List<SearchIndexableResource> getXmlResourcesToIndex(
+ Context context, boolean enabled) {
+ final SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = R.xml.snoop_logger_filters_settings;
+ return List.of(sir);
+ }
+
+ @Override
+ protected boolean isPageSearchEnabled(Context context) {
+ return DevelopmentSettingsEnabler.isDevelopmentSettingsEnabled(context);
+ }
+ };
+}
diff --git a/src/com/android/settings/development/snooplogger/SnoopLoggerFiltersPreference.java b/src/com/android/settings/development/snooplogger/SnoopLoggerFiltersPreference.java
new file mode 100644
index 0000000..f0c9ff4
--- /dev/null
+++ b/src/com/android/settings/development/snooplogger/SnoopLoggerFiltersPreference.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2022 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.development.snooplogger;
+
+import android.content.Context;
+import android.os.SystemProperties;
+
+import androidx.preference.SwitchPreference;
+
+/**
+ * Bluetooth Snoop Logger Filters Preference
+ */
+public class SnoopLoggerFiltersPreference extends SwitchPreference {
+
+ private final String mKey;
+ private static final String TAG = "SnoopLoggerFiltersPreference";
+ private static final String SNOOP_LOG_FILTERS_PREFIX = "persist.bluetooth.snooplogfilter.";
+ private static final String SNOOP_LOG_FILTERS_SUFFIX = ".enabled";
+
+ public SnoopLoggerFiltersPreference(Context context, String key, String entry) {
+ super(context);
+ mKey = key;
+ setKey(key);
+ setTitle(entry);
+
+ String filterProp = SNOOP_LOG_FILTERS_PREFIX.concat(mKey).concat(SNOOP_LOG_FILTERS_SUFFIX);
+
+ boolean isFilterEnabled = SystemProperties.get(filterProp).equals("true");
+
+ super.setChecked(isFilterEnabled);
+ }
+
+ @Override
+ public void setChecked(boolean isChecked) {
+ super.setChecked(isChecked);
+ String filterProp = SNOOP_LOG_FILTERS_PREFIX.concat(mKey).concat(SNOOP_LOG_FILTERS_SUFFIX);
+ SystemProperties.set(filterProp, isChecked ? "true" : "false");
+ }
+}
diff --git a/src/com/android/settings/development/snooplogger/SnoopLoggerFiltersPreferenceController.java b/src/com/android/settings/development/snooplogger/SnoopLoggerFiltersPreferenceController.java
new file mode 100644
index 0000000..8262182
--- /dev/null
+++ b/src/com/android/settings/development/snooplogger/SnoopLoggerFiltersPreferenceController.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2022 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.development.snooplogger;
+
+import android.content.Context;
+import android.sysprop.BluetoothProperties;
+
+import androidx.preference.PreferenceGroup;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+
+/** A {@link BasePreferenceController} used in {@link SnoopLoggerFiltersDashboard} */
+public class SnoopLoggerFiltersPreferenceController extends BasePreferenceController {
+ private static final String TAG = "SnoopLoggerFiltersPreferenceController";
+
+ private final String[] mListValues;
+ private final String[] mListEntries;
+
+ public SnoopLoggerFiltersPreferenceController(Context context, String key) {
+ super(context, key);
+ mListValues =
+ context.getResources().getStringArray(R.array.bt_hci_snoop_log_filters_values);
+ mListEntries =
+ context.getResources().getStringArray(R.array.bt_hci_snoop_log_filters_entries);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ BluetoothProperties.snoop_log_mode_values snoopLogMode =
+ BluetoothProperties.snoop_log_mode()
+ .orElse(BluetoothProperties.snoop_log_mode_values.DISABLED);
+ if (snoopLogMode == BluetoothProperties.snoop_log_mode_values.FILTERED) {
+ return AVAILABLE;
+ }
+ return DISABLED_DEPENDENT_SETTING;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ PreferenceGroup mGroup = screen.findPreference(getPreferenceKey());
+ mGroup.removeAll();
+ final Context prefContext = mGroup.getContext();
+ for (int i = 0; i < mListValues.length; i++) {
+ mGroup.addPreference(
+ new SnoopLoggerFiltersPreference(prefContext, mListValues[i], mListEntries[i]));
+ }
+ }
+}
diff --git a/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java b/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
index f91b98f..d1bf808 100644
--- a/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
@@ -30,7 +30,6 @@
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.network.SubscriptionUtil;
-import com.android.settingslib.DeviceInfoUtils;
import java.util.ArrayList;
import java.util.List;
@@ -157,7 +156,7 @@
@VisibleForTesting
protected CharSequence getFormattedPhoneNumber(SubscriptionInfo subscriptionInfo) {
- final String phoneNumber = DeviceInfoUtils.getBidiFormattedPhoneNumber(mContext,
+ final String phoneNumber = SubscriptionUtil.getBidiFormattedPhoneNumber(mContext,
subscriptionInfo);
return TextUtils.isEmpty(phoneNumber) ? mContext.getString(R.string.device_info_default)
: phoneNumber;
diff --git a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java
index e6f7a0e..d3058ce 100644
--- a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java
+++ b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java
@@ -59,7 +59,7 @@
import androidx.lifecycle.OnLifecycleEvent;
import com.android.settings.R;
-import com.android.settingslib.DeviceInfoUtils;
+import com.android.settings.network.SubscriptionUtil;
import com.android.settingslib.Utils;
import com.android.settingslib.core.lifecycle.Lifecycle;
@@ -329,7 +329,7 @@
public void updatePhoneNumber() {
// If formattedNumber is null or empty, it'll display as "Unknown".
mDialog.setText(PHONE_NUMBER_VALUE_ID,
- DeviceInfoUtils.getBidiFormattedPhoneNumber(mContext, mSubscriptionInfo));
+ SubscriptionUtil.getBidiFormattedPhoneNumber(mContext, mSubscriptionInfo));
}
private void updateDataState(int state) {
diff --git a/src/com/android/settings/emergency/EmergencyGestureSettings.java b/src/com/android/settings/emergency/EmergencyGestureSettings.java
index 7826872..3803ce1 100644
--- a/src/com/android/settings/emergency/EmergencyGestureSettings.java
+++ b/src/com/android/settings/emergency/EmergencyGestureSettings.java
@@ -54,8 +54,8 @@
final EmergencyGestureEntrypointPreferenceController controller =
new EmergencyGestureEntrypointPreferenceController(context,
"dummy_emergency_gesture_pref_key");
- return !controller.isAvailable()
- || controller.shouldSuppressFromSearch();
+ return controller.isAvailable()
+ && !controller.shouldSuppressFromSearch();
}
};
}
diff --git a/src/com/android/settings/nearby/FastPairPreferenceController.java b/src/com/android/settings/nearby/FastPairPreferenceController.java
deleted file mode 100644
index a115202..0000000
--- a/src/com/android/settings/nearby/FastPairPreferenceController.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (C) 2022 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.nearby;
-
-import android.content.Context;
-
-import androidx.lifecycle.LifecycleObserver;
-
-import com.android.settings.core.BasePreferenceController;
-
-/**
- * {@link BasePreferenceController} for Fast Pair settings.
- */
-public class FastPairPreferenceController extends BasePreferenceController implements
- LifecycleObserver {
- public static final String TAG = "FastPairPrefController";
- public static final String KEY_FAST_PAIR_SETTINGS = "connected_device_fast_pair";
-
- public FastPairPreferenceController(Context context) {
- super(context, KEY_FAST_PAIR_SETTINGS);
- }
-
- @Override
- public int getAvailabilityStatus() {
- return AVAILABLE;
- }
-}
diff --git a/src/com/android/settings/nearby/FastPairSettingsFragment.java b/src/com/android/settings/nearby/FastPairSettingsFragment.java
deleted file mode 100644
index 2fff7a0..0000000
--- a/src/com/android/settings/nearby/FastPairSettingsFragment.java
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * Copyright (C) 2022 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.nearby;
-
-import android.app.settings.SettingsEnums;
-import android.content.ComponentName;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.nearby.NearbyManager;
-import android.os.Bundle;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.Log;
-
-import androidx.annotation.Nullable;
-import androidx.preference.Preference;
-
-import com.android.settings.R;
-import com.android.settings.SettingsPreferenceFragment;
-import com.android.settings.search.BaseSearchIndexProvider;
-import com.android.settingslib.search.SearchIndexable;
-import com.android.settingslib.widget.MainSwitchPreference;
-import com.android.settingslib.widget.OnMainSwitchChangeListener;
-
-import java.util.Objects;
-
-/**
- * Fragment with the top level fast pair settings.
- */
-@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
-public class FastPairSettingsFragment extends SettingsPreferenceFragment {
-
- private static final String TAG = "FastPairSettingsFrag";
-
- private static final String SCAN_SWITCH_KEY = "fast_pair_scan_switch";
- private static final String SAVED_DEVICES_PREF_KEY = "saved_devices";
-
- private MainSwitchPreference mMainSwitchPreference;
- private OnMainSwitchChangeListener mMainSwitchChangeListener;
-
- @Override
- public void onCreate(Bundle icicle) {
- super.onCreate(icicle);
-
- mMainSwitchPreference = Objects.requireNonNull(
- findPreference(SCAN_SWITCH_KEY));
- mMainSwitchChangeListener = (switchView, isChecked) ->
- NearbyManager.setFastPairScanEnabled(getContext(), isChecked);
- Preference savedDevicePref = Objects.requireNonNull(
- findPreference(SAVED_DEVICES_PREF_KEY));
- savedDevicePref.setOnPreferenceClickListener(preference -> {
- Intent savedDevicesIntent = getSavedDevicesIntent();
- if (savedDevicesIntent != null && getActivity() != null) {
- getActivity().startActivity(savedDevicesIntent);
- }
- return true;
- });
- }
-
- @Override
- public void onResume() {
- super.onResume();
- mMainSwitchPreference.addOnSwitchChangeListener(mMainSwitchChangeListener);
- mMainSwitchPreference.setChecked(NearbyManager.isFastPairScanEnabled(getContext()));
- }
-
- @Override
- public void onPause() {
- super.onPause();
- mMainSwitchPreference.removeOnSwitchChangeListener(mMainSwitchChangeListener);
- }
-
- @Override
- public int getMetricsCategory() {
- return SettingsEnums.CONNECTION_DEVICE_ADVANCED_FAST_PAIR;
- }
-
- @Override
- public int getHelpResource() {
- return 0;
- }
-
- @Override
- protected int getPreferenceScreenResId() {
- return R.xml.fast_pair_settings;
- }
-
- public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
- new BaseSearchIndexProvider(R.xml.fast_pair_settings);
-
- @Nullable
- private ComponentName getSavedDevicesComponent() {
- String savedDevicesComponent = Settings.Secure.getString(
- getContentResolver(),
- Settings.Secure.NEARBY_FAST_PAIR_SETTINGS_DEVICES_COMPONENT);
- if (TextUtils.isEmpty(savedDevicesComponent)) {
- savedDevicesComponent = getString(
- com.android.internal.R.string.config_defaultNearbyFastPairSettingsDevicesComponent);
- }
-
- if (TextUtils.isEmpty(savedDevicesComponent)) {
- return null;
- }
-
- return ComponentName.unflattenFromString(savedDevicesComponent);
- }
-
- @Nullable
- private Intent getSavedDevicesIntent() {
- ComponentName componentName = getSavedDevicesComponent();
- if (componentName == null) {
- return null;
- }
-
- PackageManager pm = getPackageManager();
- Intent intent = getIntent();
- intent.setAction(Intent.ACTION_VIEW);
- intent.setComponent(componentName);
-
- final ResolveInfo resolveInfo = pm.resolveActivity(intent, PackageManager.GET_META_DATA);
- if (resolveInfo == null || resolveInfo.activityInfo == null) {
- Log.e(TAG, "Device-specified fast pair component (" + componentName
- + ") not available");
- return null;
- }
- return intent;
- }
-}
diff --git a/src/com/android/settings/network/ActiveSubscriptionsListener.java b/src/com/android/settings/network/ActiveSubscriptionsListener.java
index b23b723..dce441b 100644
--- a/src/com/android/settings/network/ActiveSubscriptionsListener.java
+++ b/src/com/android/settings/network/ActiveSubscriptionsListener.java
@@ -16,6 +16,7 @@
package com.android.settings.network;
+import android.annotation.NonNull;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -278,6 +279,15 @@
}
/**
+ * Gets a list of active, visible subscription Id(s) of the currently active SIM(s).
+ *
+ * @return the list of subId's that are active and visible; the length may be 0.
+ */
+ public @NonNull int[] getActiveSubscriptionIdList() {
+ return getSubscriptionManager().getActiveSubscriptionIdList();
+ }
+
+ /**
* Clear data cached within listener
*/
public void clearCache() {
diff --git a/src/com/android/settings/network/EraseEuiccDataController.java b/src/com/android/settings/network/EraseEuiccDataController.java
index 091b6d7..3dc3ab5 100644
--- a/src/com/android/settings/network/EraseEuiccDataController.java
+++ b/src/com/android/settings/network/EraseEuiccDataController.java
@@ -24,6 +24,7 @@
import com.android.settings.core.BasePreferenceController;
import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.network.telephony.MobileNetworkUtils;
import com.android.settings.system.ResetDashboardFragment;
/**
@@ -52,6 +53,7 @@
@Override
public int getAvailabilityStatus() {
return SubscriptionUtil.isSimHardwareVisible(mContext) &&
+ (!MobileNetworkUtils.isMobileNetworkUserRestricted(mContext)) &&
mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TELEPHONY_EUICC) ? AVAILABLE_UNSEARCHABLE
: UNSUPPORTED_ON_DEVICE;
diff --git a/src/com/android/settings/network/ProxySubscriptionManager.java b/src/com/android/settings/network/ProxySubscriptionManager.java
index 614491a..51fafb1 100644
--- a/src/com/android/settings/network/ProxySubscriptionManager.java
+++ b/src/com/android/settings/network/ProxySubscriptionManager.java
@@ -20,6 +20,7 @@
import static androidx.lifecycle.Lifecycle.Event.ON_START;
import static androidx.lifecycle.Lifecycle.Event.ON_STOP;
+import android.annotation.NonNull;
import android.content.Context;
import android.os.Looper;
import android.provider.Settings;
@@ -242,6 +243,15 @@
}
/**
+ * Gets a list of active, visible subscription Id(s) of the currently active SIM(s).
+ *
+ * @return the list of subId's that are active and visible; the length may be 0.
+ */
+ public @NonNull int[] getActiveSubscriptionIdList() {
+ return mSubscriptionMonitor.getActiveSubscriptionIdList();
+ }
+
+ /**
* Clear data cached within proxy
*/
public void clearCache() {
diff --git a/src/com/android/settings/network/SubscriptionUtil.java b/src/com/android/settings/network/SubscriptionUtil.java
index d6cac10..a562990 100644
--- a/src/com/android/settings/network/SubscriptionUtil.java
+++ b/src/com/android/settings/network/SubscriptionUtil.java
@@ -31,6 +31,8 @@
import android.telephony.TelephonyManager;
import android.telephony.UiccCardInfo;
import android.telephony.UiccSlotInfo;
+import android.text.BidiFormatter;
+import android.text.TextDirectionHeuristics;
import android.text.TextUtils;
import android.util.Log;
@@ -42,7 +44,6 @@
import com.android.settings.network.helper.SubscriptionAnnotation;
import com.android.settings.network.telephony.DeleteEuiccSubscriptionDialogActivity;
import com.android.settings.network.telephony.ToggleSubscriptionDialogActivity;
-import com.android.settingslib.DeviceInfoUtils;
import java.util.ArrayList;
import java.util.Collections;
@@ -292,7 +293,7 @@
final Supplier<Stream<DisplayInfo>> uniqueInfos = () -> originalInfos.get().map(info -> {
if (duplicateOriginalNames.contains(info.originalName)) {
// This may return null, if the user cannot view the phone number itself.
- final String phoneNumber = DeviceInfoUtils.getBidiFormattedPhoneNumber(context,
+ final String phoneNumber = getBidiFormattedPhoneNumber(context,
info.subscriptionInfo);
String lastFourDigits = "";
if (phoneNumber != null) {
@@ -564,6 +565,20 @@
}
/**
+ * To get the formatting text for display in a potentially opposite-directionality context
+ * without garbling.
+ * @param subscriptionInfo {@link SubscriptionInfo} subscription information.
+ * @return Returns phone number with Bidi format.
+ */
+ @Nullable
+ public static String getBidiFormattedPhoneNumber(Context context,
+ SubscriptionInfo subscriptionInfo) {
+ String phoneNumber = getFormattedPhoneNumber(context, subscriptionInfo);
+ return (phoneNumber == null) ? phoneNumber :
+ BidiFormatter.getInstance().unicodeWrap(phoneNumber, TextDirectionHeuristics.LTR);
+ }
+
+ /**
* Returns the subscription on a removable sim card. The device does not need to be on removable
* slot.
*/
diff --git a/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java b/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java
index f4543f5..1c20f59 100644
--- a/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java
+++ b/src/com/android/settings/network/telephony/AutoDataSwitchPreferenceController.java
@@ -19,12 +19,20 @@
import static androidx.lifecycle.Lifecycle.Event.ON_PAUSE;
import static androidx.lifecycle.Lifecycle.Event.ON_RESUME;
+import android.app.settings.SettingsEnums;
import android.content.Context;
import android.os.Handler;
import android.os.Looper;
+import android.os.PersistableBundle;
+import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.telephony.ims.ImsException;
+import android.telephony.ims.ImsManager;
+import android.telephony.ims.ImsMmTelManager;
+import android.util.Log;
+import androidx.annotation.NonNull;
import androidx.lifecycle.LifecycleObserver;
import androidx.lifecycle.OnLifecycleEvent;
import androidx.preference.Preference;
@@ -32,9 +40,14 @@
import androidx.preference.SwitchPreference;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.R;
import com.android.settings.datausage.DataUsageUtils;
import com.android.settings.network.MobileDataContentObserver;
+import com.android.settings.network.ProxySubscriptionManager;
import com.android.settings.network.SubscriptionsChangeListener;
+import com.android.settings.network.ims.WifiCallingQueryImsState;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
/**
* Controls whether switch mobile data to the non-default SIM if the non-default SIM has better
@@ -49,6 +62,7 @@
public class AutoDataSwitchPreferenceController extends TelephonyTogglePreferenceController
implements LifecycleObserver,
SubscriptionsChangeListener.SubscriptionsChangeListenerClient {
+ private static final String LOG_TAG = "AutoDataSwitchPrefCtrl";
private SwitchPreference mPreference;
private SubscriptionsChangeListener mChangeListener;
@@ -56,9 +70,12 @@
private MobileDataContentObserver mMobileDataContentObserver;
private PreferenceScreen mScreen;
+ private final MetricsFeatureProvider mMetricsFeatureProvider;
+
public AutoDataSwitchPreferenceController(Context context,
String preferenceKey) {
super(context, preferenceKey);
+ mMetricsFeatureProvider = FeatureFactory.getFactory(context).getMetricsFeatureProvider();
}
void init(int subId) {
@@ -103,11 +120,36 @@
TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH);
}
+ private int getOtherSubId(@NonNull int[] subIds) {
+ if (subIds.length > 1) {
+ for (int subId : subIds) {
+ if (subId != mSubId) {
+ return subId;
+ }
+ }
+ }
+ return SubscriptionManager.INVALID_SUBSCRIPTION_ID;
+ }
+
+ private boolean isEnabled(int subId) {
+ if (subId == SubscriptionManager.INVALID_SUBSCRIPTION_ID) {
+ return false;
+ }
+ TelephonyManager telephonyManager = mContext.getSystemService(
+ TelephonyManager.class).createForSubscriptionId(subId);
+ return telephonyManager != null && telephonyManager.isMobileDataPolicyEnabled(
+ TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH);
+ }
+
@Override
public boolean setChecked(boolean isChecked) {
mManager.setMobileDataPolicyEnabled(
TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH,
isChecked);
+ if (mContext.getResources().getBoolean(
+ R.bool.config_auto_data_switch_enables_cross_sim_calling)) {
+ trySetCrossSimCalling(mContext, getActiveSubscriptionIdList(), isChecked /* enabled */);
+ }
return true;
}
@@ -116,6 +158,40 @@
return DataUsageUtils.hasMobileData(mContext);
}
+ private boolean isCrossSimCallingAllowedByPlatform(Context context, int subId) {
+ if ((new WifiCallingQueryImsState(context, subId)).isWifiCallingSupported()) {
+ PersistableBundle bundle = getCarrierConfigForSubId(subId);
+ return (bundle != null) && bundle.getBoolean(
+ CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL,
+ false /*default*/);
+ }
+ return false;
+ }
+
+ protected ImsMmTelManager getImsMmTelManager(Context context, int subId) {
+ ImsManager imsMgr = context.getSystemService(ImsManager.class);
+ return (imsMgr == null) ? null : imsMgr.getImsMmTelManager(subId);
+ }
+
+ private void trySetCrossSimCallingPerSub(Context context, int subId, boolean enabled) {
+ try {
+ getImsMmTelManager(context, subId).setCrossSimCallingEnabled(enabled);
+ } catch (ImsException | IllegalArgumentException | NullPointerException exception) {
+ Log.w(LOG_TAG, "failed to change cross SIM calling configuration to " + enabled
+ + " for subID " + subId + "with exception: ", exception);
+ }
+ }
+
+ private void trySetCrossSimCalling(Context context, int[] subIds, boolean enabled) {
+ mMetricsFeatureProvider.action(mContext,
+ SettingsEnums.ACTION_UPDATE_CROSS_SIM_CALLING_ON_AUTO_DATA_SWITCH_EVENT, enabled);
+ for (int subId : subIds) {
+ if (isCrossSimCallingAllowedByPlatform(context, subId)) {
+ trySetCrossSimCallingPerSub(context, subId, enabled);
+ }
+ }
+ }
+
@Override
public int getAvailabilityStatus(int subId) {
if (!SubscriptionManager.isValidSubscriptionId(subId)
@@ -143,11 +219,20 @@
updateState(mPreference);
}
+ private int[] getActiveSubscriptionIdList() {
+ return ProxySubscriptionManager.getInstance(mContext).getActiveSubscriptionIdList();
+ }
+
/**
- * Trigger displaying preference when Mobilde data content changed.
+ * Trigger displaying preference when Mobile data content changed.
*/
@VisibleForTesting
public void refreshPreference() {
+ if (mContext.getResources().getBoolean(
+ R.bool.config_auto_data_switch_enables_cross_sim_calling)) {
+ int[] subIds = getActiveSubscriptionIdList();
+ trySetCrossSimCalling(mContext, subIds, isEnabled(getOtherSubId(subIds)));
+ }
if (mScreen != null) {
super.displayPreference(mScreen);
}
diff --git a/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java b/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java
index ec48c82..8823353 100644
--- a/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java
+++ b/src/com/android/settings/network/telephony/RenameMobileNetworkDialogFragment.java
@@ -47,7 +47,6 @@
import com.android.settings.R;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
import com.android.settings.network.SubscriptionUtil;
-import com.android.settingslib.DeviceInfoUtils;
import com.google.common.collect.ImmutableMap;
@@ -184,7 +183,7 @@
phoneTitle.setVisibility(info.isOpportunistic() ? View.GONE : View.VISIBLE);
final TextView phoneNumber = view.findViewById(R.id.number_value);
- final String pn = DeviceInfoUtils.getBidiFormattedPhoneNumber(getContext(), info);
+ final String pn = SubscriptionUtil.getBidiFormattedPhoneNumber(getContext(), info);
if (!TextUtils.isEmpty(pn)) {
phoneNumber.setText(pn);
}
diff --git a/src/com/android/settings/notification/NotificationBackend.java b/src/com/android/settings/notification/NotificationBackend.java
index c63a294..7b7d41a 100644
--- a/src/com/android/settings/notification/NotificationBackend.java
+++ b/src/com/android/settings/notification/NotificationBackend.java
@@ -413,18 +413,6 @@
}
}
- public void allowAssistantAdjustment(String capability, boolean allowed) {
- try {
- if (allowed) {
- sINM.allowAssistantAdjustment(capability);
- } else {
- sINM.disallowAssistantAdjustment(capability);
- }
- } catch (Exception e) {
- Log.w(TAG, "Error calling NoMan", e);
- }
- }
-
public List<String> getAssistantAdjustments(String pkg) {
try {
return sINM.getAllowedAssistantAdjustments(pkg);
diff --git a/src/com/android/settings/security/ConfirmSimDeletionPreferenceController.java b/src/com/android/settings/security/ConfirmSimDeletionPreferenceController.java
index 3bf1563..2712a02 100644
--- a/src/com/android/settings/security/ConfirmSimDeletionPreferenceController.java
+++ b/src/com/android/settings/security/ConfirmSimDeletionPreferenceController.java
@@ -57,7 +57,8 @@
@Override
public int getAvailabilityStatus() {
// hide if eSim is not supported on the device
- return MobileNetworkUtils.showEuiccSettings(mContext) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+ return (!MobileNetworkUtils.isMobileNetworkUserRestricted(mContext)) &&
+ MobileNetworkUtils.showEuiccSettings(mContext) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
private boolean getGlobalState() {
diff --git a/src/com/android/settings/security/MemtagPreferenceController.java b/src/com/android/settings/security/MemtagPreferenceController.java
index b5a4be7..5e224a1 100644
--- a/src/com/android/settings/security/MemtagPreferenceController.java
+++ b/src/com/android/settings/security/MemtagPreferenceController.java
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2022 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.
@@ -58,7 +59,11 @@
refreshSummary(mPreference);
}
if (isChecked != MemtagHelper.isOn()) {
- MemtagRebootDialog.show(mContext, mFragment, isChecked);
+ int msg =
+ isChecked
+ ? R.string.memtag_reboot_message_on
+ : R.string.memtag_reboot_message_off;
+ MemtagRebootDialog.show(mContext, mFragment, msg);
}
return true;
}
diff --git a/src/com/android/settings/security/MemtagRebootDialog.java b/src/com/android/settings/security/MemtagRebootDialog.java
index 735de8f..adedff8 100644
--- a/src/com/android/settings/security/MemtagRebootDialog.java
+++ b/src/com/android/settings/security/MemtagRebootDialog.java
@@ -34,16 +34,16 @@
implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener {
public static final String TAG = "MemtagRebootDialog";
- private boolean mIsChecked;
+ private int mMessage;
- public MemtagRebootDialog(Context context, boolean isChecked) {
- mIsChecked = isChecked;
+ public MemtagRebootDialog(Context context, int msg) {
+ mMessage = msg;
}
- public static void show(Context context, Fragment host, boolean isChecked) {
+ public static void show(Context context, Fragment host, int msg) {
final FragmentManager manager = host.getActivity().getSupportFragmentManager();
if (manager.findFragmentByTag(TAG) == null) {
- final MemtagRebootDialog dialog = new MemtagRebootDialog(context, isChecked);
+ final MemtagRebootDialog dialog = new MemtagRebootDialog(context, msg);
dialog.show(manager, TAG);
}
}
@@ -55,11 +55,9 @@
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
- int msg =
- mIsChecked ? R.string.memtag_reboot_message_on : R.string.memtag_reboot_message_off;
return new AlertDialog.Builder(getActivity())
.setTitle(R.string.memtag_reboot_title)
- .setMessage(msg)
+ .setMessage(mMessage)
.setPositiveButton(R.string.memtag_reboot_yes, this /* onClickListener */)
.setNegativeButton(R.string.memtag_reboot_no, null /* onClickListener */)
.create();
diff --git a/src/com/android/settings/sim/SimDialogActivity.java b/src/com/android/settings/sim/SimDialogActivity.java
index a1258be..dcfa983 100644
--- a/src/com/android/settings/sim/SimDialogActivity.java
+++ b/src/com/android/settings/sim/SimDialogActivity.java
@@ -17,24 +17,35 @@
package com.android.settings.sim;
import android.app.Activity;
+import android.app.settings.SettingsEnums;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
+import android.os.PersistableBundle;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
+import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
+import android.telephony.ims.ImsException;
+import android.telephony.ims.ImsManager;
+import android.telephony.ims.ImsMmTelManager;
import android.util.Log;
import android.view.WindowManager;
import android.widget.Toast;
+import androidx.annotation.NonNull;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
import com.android.settings.R;
+import com.android.settings.network.CarrierConfigCache;
import com.android.settings.network.SubscriptionUtil;
+import com.android.settings.network.ims.WifiCallingQueryImsState;
import com.android.settings.network.telephony.SubscriptionActionDialogActivity;
+import com.android.settings.overlay.FeatureFactory;
+import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
import java.util.List;
@@ -62,6 +73,7 @@
// Show auto data switch dialog(when user enables multi-SIM)
public static final int ENABLE_AUTO_DATA_SWITCH = 6;
+ private MetricsFeatureProvider mMetricsFeatureProvider;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -73,6 +85,7 @@
}
SimDialogProhibitService.supportDismiss(this);
+ mMetricsFeatureProvider = FeatureFactory.getFactory(this).getMetricsFeatureProvider();
getWindow().addSystemFlags(
WindowManager.LayoutParams.SYSTEM_FLAG_HIDE_NON_SYSTEM_OVERLAY_WINDOWS);
showOrUpdateDialog();
@@ -192,6 +205,61 @@
}
}
+ private PersistableBundle getCarrierConfigForSubId(int subId) {
+ if (!SubscriptionManager.isValidSubscriptionId(subId)) {
+ return null;
+ }
+ return CarrierConfigCache.getInstance(this).getConfigForSubId(subId);
+ }
+
+ private boolean isCrossSimCallingAllowedByPlatform(int subId) {
+ if ((new WifiCallingQueryImsState(this, subId)).isWifiCallingSupported()) {
+ PersistableBundle bundle = getCarrierConfigForSubId(subId);
+ return (bundle != null) && bundle.getBoolean(
+ CarrierConfigManager.KEY_CARRIER_CROSS_SIM_IMS_AVAILABLE_BOOL,
+ false /*default*/);
+ }
+ return false;
+ }
+
+ private ImsMmTelManager getImsMmTelManager(int subId) {
+ ImsManager imsMgr = getSystemService(ImsManager.class);
+ return (imsMgr == null) ? null : imsMgr.getImsMmTelManager(subId);
+ }
+
+ private void trySetCrossSimCallingPerSub(int subId, boolean enabled) {
+ try {
+ getImsMmTelManager(subId).setCrossSimCallingEnabled(enabled);
+ } catch (ImsException | IllegalArgumentException | NullPointerException exception) {
+ Log.w(TAG, "failed to change cross SIM calling configuration to " + enabled
+ + " for subID " + subId + "with exception: ", exception);
+ }
+ }
+
+ private boolean autoDataSwitchEnabledOnNonDataSub(@NonNull int[] subIds, int defaultDataSub) {
+ for (int subId : subIds) {
+ if (subId != defaultDataSub) {
+ final TelephonyManager telephonyManager = getSystemService(
+ TelephonyManager.class).createForSubscriptionId(subId);
+ if (telephonyManager.isMobileDataPolicyEnabled(
+ TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH)) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private void trySetCrossSimCalling(int[] subIds, boolean enabled) {
+ mMetricsFeatureProvider.action(this,
+ SettingsEnums.ACTION_UPDATE_CROSS_SIM_CALLING_ON_2ND_SIM_ENABLE, enabled);
+ for (int subId : subIds) {
+ if (isCrossSimCallingAllowedByPlatform(subId)) {
+ trySetCrossSimCallingPerSub(subId, enabled);
+ }
+ }
+ }
+
/**
* Show dialog prompting the user to enable auto data switch
*/
@@ -199,6 +267,26 @@
final FragmentManager fragmentManager = getSupportFragmentManager();
SimDialogFragment fragment = createFragment(ENABLE_AUTO_DATA_SWITCH);
fragment.show(fragmentManager, Integer.toString(ENABLE_AUTO_DATA_SWITCH));
+
+ if (getResources().getBoolean(
+ R.bool.config_auto_data_switch_enables_cross_sim_calling)) {
+ // If auto data switch is already enabled on the non-DDS, the dialog for enabling it
+ // is suppressed (no onEnableAutoDataSwitch()). so we ensure cross-SIM calling is
+ // enabled.
+
+ // OTOH, if auto data switch is disabled on the new non-DDS, the user may still not
+ // enable it in the dialog. So we ensure cross-SIM calling is disabled before the
+ // dialog. If the user does enable auto data switch, we will re-enable cross-SIM calling
+ // through onEnableAutoDataSwitch()- a minor redundancy to ensure correctness.
+ final SubscriptionManager subscriptionManager =
+ getSystemService(SubscriptionManager.class);
+ int[] subIds = subscriptionManager.getActiveSubscriptionIdList();
+ int defaultDataSub = subscriptionManager.getDefaultDataSubscriptionId();
+ if (subIds.length > 1) {
+ trySetCrossSimCalling(subIds,
+ autoDataSwitchEnabledOnNonDataSub(subIds, defaultDataSub));
+ }
+ }
}
/**
@@ -210,6 +298,14 @@
TelephonyManager.class).createForSubscriptionId(subId);
telephonyManager.setMobileDataPolicyEnabled(
TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH, true);
+
+ if (getResources().getBoolean(
+ R.bool.config_auto_data_switch_enables_cross_sim_calling)) {
+ final SubscriptionManager subscriptionManager =
+ getSystemService(SubscriptionManager.class);
+ trySetCrossSimCalling(subscriptionManager.getActiveSubscriptionIdList(),
+ true /* enabled */);
+ }
}
public void onFragmentDismissed(SimDialogFragment simDialogFragment) {
diff --git a/src/com/android/settings/wifi/AddNetworkFragment.java b/src/com/android/settings/wifi/AddNetworkFragment.java
index 47a027d..9fd8626 100644
--- a/src/com/android/settings/wifi/AddNetworkFragment.java
+++ b/src/com/android/settings/wifi/AddNetworkFragment.java
@@ -20,6 +20,7 @@
import android.app.settings.SettingsEnums;
import android.content.Intent;
import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
@@ -28,6 +29,7 @@
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.TextView;
+import android.widget.Toast;
import androidx.annotation.VisibleForTesting;
@@ -51,6 +53,8 @@
private static final int REQUEST_CODE_WIFI_DPP_ENROLLEE_QR_CODE_SCANNER = 0;
+ private static final String EXTRA_SAVE_WHEN_SUBMIT = ":settings:save_when_submit";
+
private WifiConfigController2 mUIController;
private Button mSubmitBtn;
private Button mCancelBtn;
@@ -196,11 +200,35 @@
}
private void successfullyFinish(WifiConfiguration config) {
- final Intent intent = new Intent();
- final Activity activity = getActivity();
- intent.putExtra(WIFI_CONFIG_KEY, config);
- activity.setResult(Activity.RESULT_OK, intent);
- activity.finish();
+ Activity activity = getActivity();
+ boolean autoSave = activity.getIntent().getBooleanExtra(EXTRA_SAVE_WHEN_SUBMIT, false);
+ if (autoSave && config != null) {
+ WifiManager.ActionListener saveListener = new WifiManager.ActionListener() {
+ @Override
+ public void onSuccess() {
+ if (activity != null && !activity.isFinishing()) {
+ activity.setResult(Activity.RESULT_OK);
+ activity.finish();
+ }
+ }
+
+ @Override
+ public void onFailure(int reason) {
+ if (activity != null && !activity.isFinishing()) {
+ Toast.makeText(activity, R.string.wifi_failed_save_message,
+ Toast.LENGTH_SHORT).show();
+ activity.finish();
+ }
+ }
+ };
+
+ activity.getSystemService(WifiManager.class).save(config, saveListener);
+ } else {
+ Intent intent = new Intent();
+ intent.putExtra(WIFI_CONFIG_KEY, config);
+ activity.setResult(Activity.RESULT_OK, intent);
+ activity.finish();
+ }
}
@VisibleForTesting
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizardTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizardTest.java
index 508b229..e14e271 100644
--- a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizardTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsForSetupWizardTest.java
@@ -23,6 +23,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
@@ -45,6 +46,7 @@
import com.android.settings.R;
import com.android.settingslib.RestrictedPreference;
+import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupdesign.GlifPreferenceLayout;
import org.junit.Before;
@@ -79,6 +81,8 @@
private FragmentActivity mActivity;
@Mock
private GlifPreferenceLayout mGlifLayoutView;
+ @Mock
+ private FooterBarMixin mFooterBarMixin;
private AccessibilitySettingsForSetupWizard mFragment;
@Before
@@ -89,6 +93,7 @@
when(mAccessibilityManager.getInstalledAccessibilityServiceList()).thenReturn(
mAccessibilityServices);
doReturn(mActivity).when(mFragment).getActivity();
+ doReturn(mFooterBarMixin).when(mGlifLayoutView).getMixin(FooterBarMixin.class);
}
@Test
@@ -99,6 +104,7 @@
mContext.getString(R.string.vision_settings_title));
verify(mGlifLayoutView).setDescriptionText(
mContext.getString(R.string.vision_settings_description));
+ verify(mFooterBarMixin).setPrimaryButton(any());
}
@Test
diff --git a/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizardTest.java b/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizardTest.java
index 7df24f1..1cd301f 100644
--- a/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizardTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/TextReadingPreferenceFragmentForSetupWizardTest.java
@@ -100,19 +100,10 @@
}
@Test
- public void onViewCreated_verifySetSecondaryButton() {
- mFragment.onViewCreated(mGlifLayoutView, null);
-
- verify(mFooterBarMixin).setSecondaryButton(any());
- }
-
- @Test
- public void onViewCreated_verifySetPrimaryButton() {
- doReturn(mActivity).when(mFragment).getActivity();
- doReturn("setupwizard").when(mActivity).getCallingPackage();
-
+ public void onViewCreated_verifyAction() {
mFragment.onViewCreated(mGlifLayoutView, null);
verify(mFooterBarMixin).setPrimaryButton(any());
+ verify(mFooterBarMixin).setSecondaryButton(any());
}
}
diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizardTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizardTest.java
index c5978f6..84783b21 100644
--- a/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizardTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenMagnificationPreferenceFragmentForSetupWizardTest.java
@@ -18,6 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -38,6 +39,7 @@
import com.android.settings.widget.SettingsMainSwitchBar;
import com.android.settingslib.widget.TopIntroPreference;
+import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupdesign.GlifPreferenceLayout;
import org.junit.Before;
@@ -64,6 +66,8 @@
private GlifPreferenceLayout mGlifLayoutView;
@Mock
private SettingsMainSwitchBar mSwitchBar;
+ @Mock
+ private FooterBarMixin mFooterBarMixin;
private ToggleScreenMagnificationPreferenceFragmentForSetupWizard mFragment;
@Before
@@ -72,6 +76,7 @@
spy(new TestToggleScreenMagnificationPreferenceFragmentForSetupWizard(mContext));
doReturn(mActivity).when(mFragment).getActivity();
when(mActivity.getSwitchBar()).thenReturn(mSwitchBar);
+ doReturn(mFooterBarMixin).when(mGlifLayoutView).getMixin(FooterBarMixin.class);
}
@Test
@@ -83,6 +88,7 @@
verify(mGlifLayoutView).setDescriptionText(
mContext.getString(R.string.accessibility_screen_magnification_intro_text));
verify(mGlifLayoutView).setDividerInsets(Integer.MAX_VALUE, 0);
+ verify(mFooterBarMixin).setPrimaryButton(any());
assertThat(mFragment.mTopIntroPreference.isVisible()).isFalse();
assertThat(mFragment.mSettingsPreference.isVisible()).isFalse();
assertThat(mFragment.mFollowingTypingSwitchPreference.isVisible()).isFalse();
diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizardTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizardTest.java
index 2cbe1ad..c604652 100644
--- a/tests/robotests/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizardTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/ToggleScreenReaderPreferenceFragmentForSetupWizardTest.java
@@ -18,6 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -37,6 +38,7 @@
import com.android.settings.widget.SettingsMainSwitchPreference;
import com.android.settingslib.widget.TopIntroPreference;
+import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupdesign.GlifPreferenceLayout;
import org.junit.Before;
@@ -62,6 +64,8 @@
private GlifPreferenceLayout mGlifLayoutView;
@Mock
private SettingsMainSwitchBar mSwitchBar;
+ @Mock
+ private FooterBarMixin mFooterBarMixin;
private ToggleScreenReaderPreferenceFragmentForSetupWizard mFragment;
@Before
@@ -69,6 +73,7 @@
mFragment = spy(new TestToggleScreenReaderPreferenceFragmentForSetupWizard(mContext));
doReturn(mActivity).when(mFragment).getActivity();
when(mActivity.getSwitchBar()).thenReturn(mSwitchBar);
+ doReturn(mFooterBarMixin).when(mGlifLayoutView).getMixin(FooterBarMixin.class);
}
@Test
@@ -79,6 +84,7 @@
verify(mGlifLayoutView).setDescriptionText(
mContext.getString(R.string.talkback_summary));
verify(mGlifLayoutView).setDividerInsets(Integer.MAX_VALUE, 0);
+ verify(mFooterBarMixin).setPrimaryButton(any());
assertThat(mFragment.mTopIntroPreference.isVisible()).isFalse();
}
diff --git a/tests/robotests/src/com/android/settings/accessibility/ToggleSelectToSpeakPreferenceFragmentForSetupWizardTest.java b/tests/robotests/src/com/android/settings/accessibility/ToggleSelectToSpeakPreferenceFragmentForSetupWizardTest.java
index 43440ff..7893831 100644
--- a/tests/robotests/src/com/android/settings/accessibility/ToggleSelectToSpeakPreferenceFragmentForSetupWizardTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/ToggleSelectToSpeakPreferenceFragmentForSetupWizardTest.java
@@ -18,6 +18,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
@@ -37,6 +38,7 @@
import com.android.settings.widget.SettingsMainSwitchPreference;
import com.android.settingslib.widget.TopIntroPreference;
+import com.google.android.setupcompat.template.FooterBarMixin;
import com.google.android.setupdesign.GlifPreferenceLayout;
import org.junit.Before;
@@ -62,6 +64,8 @@
private GlifPreferenceLayout mGlifLayoutView;
@Mock
private SettingsMainSwitchBar mSwitchBar;
+ @Mock
+ private FooterBarMixin mFooterBarMixin;
private ToggleSelectToSpeakPreferenceFragmentForSetupWizard mFragment;
@Before
@@ -69,6 +73,7 @@
mFragment = spy(new TestToggleSelectToSpeakPreferenceFragmentForSetupWizard(mContext));
doReturn(mActivity).when(mFragment).getActivity();
when(mActivity.getSwitchBar()).thenReturn(mSwitchBar);
+ doReturn(mFooterBarMixin).when(mGlifLayoutView).getMixin(FooterBarMixin.class);
}
@Test
@@ -79,6 +84,7 @@
verify(mGlifLayoutView).setDescriptionText(
mContext.getString(R.string.select_to_speak_summary));
verify(mGlifLayoutView).setDividerInsets(Integer.MAX_VALUE, 0);
+ verify(mFooterBarMixin).setPrimaryButton(any());
assertThat(mFragment.mTopIntroPreference.isVisible()).isFalse();
}
diff --git a/tests/robotests/src/com/android/settings/bluetooth/HearingDeviceAudioRoutingBasePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/bluetooth/HearingDeviceAudioRoutingBasePreferenceControllerTest.java
new file mode 100644
index 0000000..5be36c8
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/bluetooth/HearingDeviceAudioRoutingBasePreferenceControllerTest.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.bluetooth;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.media.AudioAttributes;
+import android.media.AudioDeviceAttributes;
+import android.media.AudioDeviceInfo;
+import android.media.AudioManager;
+import android.media.audiopolicy.AudioProductStrategy;
+
+import androidx.preference.ListPreference;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Spy;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.RobolectricTestRunner;
+
+import java.util.List;
+
+/** Tests for {@link HearingDeviceAudioRoutingBasePreferenceController}. */
+@RunWith(RobolectricTestRunner.class)
+public class HearingDeviceAudioRoutingBasePreferenceControllerTest {
+
+ @Rule
+ public MockitoRule mMockitoRule = MockitoJUnit.rule();
+
+ @Spy
+ private final Context mContext = ApplicationProvider.getApplicationContext();
+ private static final String TEST_DEVICE_ADDRESS = "00:A1:A1:A1:A1:A1";
+ private static final String FAKE_KEY = "fake_key";
+ private static final String TEST_SHARED_PREFERENCE = "test_bluetooth_settings";
+
+ @Mock
+ private CachedBluetoothDevice mCachedBluetoothDevice;
+ @Mock
+ private AudioProductStrategy mAudioProductStrategyMedia;
+ private AudioDeviceAttributes mHearingDeviceAttribute;
+ private ListPreference mListPreference;
+ private TestHearingDeviceAudioRoutingBasePreferenceController mController;
+
+ @Before
+ public void setUp() {
+ mListPreference = new ListPreference(mContext);
+ when(mCachedBluetoothDevice.getAddress()).thenReturn(TEST_DEVICE_ADDRESS);
+ mHearingDeviceAttribute = new AudioDeviceAttributes(
+ AudioDeviceAttributes.ROLE_OUTPUT,
+ AudioDeviceInfo.TYPE_HEARING_AID,
+ TEST_DEVICE_ADDRESS);
+ when(mAudioProductStrategyMedia.getAudioAttributesForLegacyStreamType(
+ AudioManager.STREAM_MUSIC))
+ .thenReturn((new AudioAttributes.Builder()).build());
+ doReturn(getSharedPreferences()).when(mContext).getSharedPreferences(anyString(), anyInt());
+
+ mController = spy(
+ new TestHearingDeviceAudioRoutingBasePreferenceController(mContext, FAKE_KEY));
+ mController.setupForTesting(mCachedBluetoothDevice);
+ doReturn(List.of(mAudioProductStrategyMedia)).when(mController).getAudioProductStrategies();
+ }
+
+ @Test
+ public void onPreferenceChange_routingValueAuto_expectedListValue() {
+ mController.onPreferenceChange(mListPreference, String.valueOf(
+ HearingDeviceAudioRoutingBasePreferenceController.RoutingValue.AUTO));
+
+ verify(mController).removePreferredDeviceForStrategies(any());
+ assertThat(mListPreference.getValue()).isEqualTo(String.valueOf(
+ HearingDeviceAudioRoutingBasePreferenceController.RoutingValue.AUTO));
+ }
+
+ @Test
+ public void onPreferenceChange_routingValueHearingDevice_expectedListValue() {
+ mController.onPreferenceChange(mListPreference, String.valueOf(
+ HearingDeviceAudioRoutingBasePreferenceController.RoutingValue.HEARING_DEVICE));
+
+ verify(mController).setPreferredDeviceForStrategies(any(), eq(mHearingDeviceAttribute));
+ assertThat(mListPreference.getValue()).isEqualTo(String.valueOf(
+ HearingDeviceAudioRoutingBasePreferenceController.RoutingValue.HEARING_DEVICE));
+ }
+
+ @Test
+ public void onPreferenceChange_routingValueDeviceSpeaker_expectedListValue() {
+ final AudioDeviceAttributes deviceSpeakerOut = new AudioDeviceAttributes(
+ AudioDeviceAttributes.ROLE_OUTPUT, AudioDeviceInfo.TYPE_BUILTIN_SPEAKER, "");
+
+ mController.onPreferenceChange(mListPreference, String.valueOf(
+ HearingDeviceAudioRoutingBasePreferenceController.RoutingValue.DEVICE_SPEAKER));
+
+ verify(mController).setPreferredDeviceForStrategies(any(), eq(deviceSpeakerOut));
+ assertThat(mListPreference.getValue()).isEqualTo(String.valueOf(
+ HearingDeviceAudioRoutingBasePreferenceController.RoutingValue.DEVICE_SPEAKER));
+
+ }
+
+ private SharedPreferences getSharedPreferences() {
+ return mContext.getSharedPreferences(TEST_SHARED_PREFERENCE, Context.MODE_PRIVATE);
+ }
+
+ private static class TestHearingDeviceAudioRoutingBasePreferenceController extends
+ HearingDeviceAudioRoutingBasePreferenceController {
+
+ private static CachedBluetoothDevice sCachedBluetoothDevice;
+ private static int sSavedRoutingValue;
+
+ TestHearingDeviceAudioRoutingBasePreferenceController(Context context,
+ String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ @Override
+ protected int[] getSupportedAttributeList() {
+ return new int[]{AudioAttributes.USAGE_MEDIA};
+ }
+
+ @Override
+ protected CachedBluetoothDevice getHearingDevice() {
+ return sCachedBluetoothDevice;
+ }
+
+ @Override
+ protected void saveRoutingValue(Context context, int routingValue) {
+ sSavedRoutingValue = routingValue;
+ }
+
+ @Override
+ protected int restoreRoutingValue(Context context) {
+ return sSavedRoutingValue;
+ }
+
+ public static void setupForTesting(CachedBluetoothDevice cachedBluetoothDevice) {
+ sCachedBluetoothDevice = cachedBluetoothDevice;
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/development/BluetoothSnoopLogFilterProfileMapPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/BluetoothSnoopLogFilterProfileMapPreferenceControllerTest.java
new file mode 100644
index 0000000..411cca0
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/BluetoothSnoopLogFilterProfileMapPreferenceControllerTest.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2022 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.development;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.sysprop.BluetoothProperties;
+
+import androidx.preference.ListPreference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.Locale;
+
+@RunWith(RobolectricTestRunner.class)
+public class BluetoothSnoopLogFilterProfileMapPreferenceControllerTest {
+
+ @Spy private Context mSpyContext = RuntimeEnvironment.application;
+ @Spy private Resources mSpyResources = RuntimeEnvironment.application.getResources();
+ private ListPreference mPreference;
+ @Mock private PreferenceScreen mPreferenceScreen;
+ private BluetoothSnoopLogFilterProfileMapPreferenceController mController;
+
+ private CharSequence[] mListValues;
+ private CharSequence[] mListEntries;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ doReturn(mSpyResources).when(mSpyContext).getResources();
+ // Get XML values without mock
+ // Setup test list preference using XML values
+ mPreference = new ListPreference(mSpyContext);
+ mPreference.setEntries(R.array.bt_hci_snoop_log_profile_filter_entries);
+ mPreference.setEntryValues(R.array.bt_hci_snoop_log_profile_filter_values);
+ // Init the actual controller
+ mController = new BluetoothSnoopLogFilterProfileMapPreferenceController(mSpyContext);
+ // Construct preference in the controller via a mocked preference screen object
+ when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
+ .thenReturn(mPreference);
+ mController.displayPreference(mPreferenceScreen);
+ mListValues = mPreference.getEntryValues();
+ mListEntries = mPreference.getEntries();
+ BluetoothProperties.snoop_log_mode(BluetoothProperties.snoop_log_mode_values.FILTERED);
+ }
+
+ @Test
+ public void verifyResourceSizeAndRange() {
+ Assert.assertTrue(
+ BluetoothSnoopLogFilterProfileMapPreferenceController
+ .isSnoopLogModeFilteredEnabled());
+ // Verify normal list entries and default preference entries have the same size
+ Assert.assertEquals(mListEntries.length, mListValues.length);
+ // Update the preference
+ mController.updateState(mPreference);
+ // Verify default preference value, entry and summary
+ final int defaultIndex = mController.getDefaultModeIndex();
+ Assert.assertEquals(mPreference.getValue(), mListValues[defaultIndex]);
+ Assert.assertEquals(mPreference.getEntry(), mListEntries[defaultIndex]);
+ Assert.assertEquals(mPreference.getSummary(), mListEntries[defaultIndex]);
+ }
+
+ @Test
+ public void onPreferenceChanged_turnOnBluetoothSnoopLogFullFilterMap() {
+ Assert.assertTrue(
+ BluetoothSnoopLogFilterProfileMapPreferenceController
+ .isSnoopLogModeFilteredEnabled());
+ mController.onPreferenceChange(
+ null,
+ mListValues[
+ BluetoothSnoopLogFilterProfileMapPreferenceController
+ .BTSNOOP_LOG_PROFILE_FILTER_MODE_FULL_FILTER_INDEX]);
+ var mode =
+ BluetoothProperties.snoop_log_filter_profile_map()
+ .orElse(BluetoothProperties.snoop_log_filter_profile_map_values.DISABLED);
+ // "fullfilter" is hard-coded between Settings and system/bt
+ Assert.assertEquals(
+ mode, BluetoothProperties.snoop_log_filter_profile_map_values.FULLFILTER);
+ }
+
+ @Test
+ public void onPreferenceChanged_turnOnBluetoothSnoopLogHeaderFilterMap() {
+ Assert.assertTrue(
+ BluetoothSnoopLogFilterProfileMapPreferenceController
+ .isSnoopLogModeFilteredEnabled());
+ mController.onPreferenceChange(
+ null,
+ mListValues[
+ BluetoothSnoopLogFilterProfileMapPreferenceController
+ .BTSNOOP_LOG_PROFILE_FILTER_MODE_HEADER_INDEX]);
+ var mode =
+ BluetoothProperties.snoop_log_filter_profile_map()
+ .orElse(BluetoothProperties.snoop_log_filter_profile_map_values.DISABLED);
+ // "header" is hard-coded between Settings and system/bt
+ Assert.assertEquals(mode, BluetoothProperties.snoop_log_filter_profile_map_values.HEADER);
+ }
+
+ @Test
+ public void onPreferenceChanged_turnOnBluetoothSnoopLogMagicFilterMap() {
+ Assert.assertTrue(
+ BluetoothSnoopLogFilterProfileMapPreferenceController
+ .isSnoopLogModeFilteredEnabled());
+ mController.onPreferenceChange(
+ null,
+ mListValues[
+ BluetoothSnoopLogFilterProfileMapPreferenceController
+ .BTSNOOP_LOG_PROFILE_FILTER_MODE_MAGIC_INDEX]);
+ var mode =
+ BluetoothProperties.snoop_log_filter_profile_map()
+ .orElse(BluetoothProperties.snoop_log_filter_profile_map_values.DISABLED);
+ // "magic" is hard-coded between Settings and system/bt
+ Assert.assertEquals(mode, BluetoothProperties.snoop_log_filter_profile_map_values.MAGIC);
+ }
+
+ @Test
+ public void onPreferenceChanged_turnOffBluetoothSnoopLogFilterMap() {
+ Assert.assertTrue(
+ BluetoothSnoopLogFilterProfileMapPreferenceController
+ .isSnoopLogModeFilteredEnabled());
+ mController.onPreferenceChange(
+ null,
+ mListValues[
+ BluetoothSnoopLogFilterProfileMapPreferenceController
+ .BTSNOOP_LOG_PROFILE_FILTER_MODE_DISABLED_INDEX]);
+ var mode =
+ BluetoothProperties.snoop_log_filter_profile_map()
+ .orElse(BluetoothProperties.snoop_log_filter_profile_map_values.DISABLED);
+ // "disabled" is hard-coded between Settings and system/bt
+ Assert.assertEquals(mode, BluetoothProperties.snoop_log_filter_profile_map_values.DISABLED);
+ }
+
+ @Test
+ public void updateState_preferenceShouldBeSetToRightValue() {
+ Assert.assertTrue(
+ BluetoothSnoopLogFilterProfileMapPreferenceController
+ .isSnoopLogModeFilteredEnabled());
+ for (int i = 0; i < mListValues.length; ++i) {
+ BluetoothProperties.snoop_log_filter_profile_map(
+ BluetoothProperties.snoop_log_filter_profile_map_values.valueOf(
+ mListValues[i].toString().toUpperCase(Locale.US)));
+ mController.updateState(mPreference);
+ Assert.assertEquals(mPreference.getValue(), mListValues[i].toString());
+ Assert.assertEquals(mPreference.getSummary(), mListEntries[i].toString());
+ }
+ }
+
+ @Test
+ public void onDeveloperOptionsDisabled_shouldDisablePreference() {
+ mController.onDeveloperOptionsDisabled();
+ Assert.assertFalse(mPreference.isEnabled());
+ Assert.assertEquals(
+ mPreference.getValue(), mListValues[mController.getDefaultModeIndex()].toString());
+ Assert.assertEquals(
+ mPreference.getSummary(),
+ mListEntries[mController.getDefaultModeIndex()].toString());
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/development/BluetoothSnoopLogFilterProfilePbapPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/BluetoothSnoopLogFilterProfilePbapPreferenceControllerTest.java
new file mode 100644
index 0000000..add84c3
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/BluetoothSnoopLogFilterProfilePbapPreferenceControllerTest.java
@@ -0,0 +1,186 @@
+/*
+ * Copyright (C) 2022 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.development;
+
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.sysprop.BluetoothProperties;
+
+import androidx.preference.ListPreference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.mockito.Spy;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import java.util.Locale;
+
+@RunWith(RobolectricTestRunner.class)
+public class BluetoothSnoopLogFilterProfilePbapPreferenceControllerTest {
+
+ @Spy private Context mSpyContext = RuntimeEnvironment.application;
+ @Spy private Resources mSpyResources = RuntimeEnvironment.application.getResources();
+ private ListPreference mPreference;
+ @Mock private PreferenceScreen mPreferenceScreen;
+ private BluetoothSnoopLogFilterProfilePbapPreferenceController mController;
+
+ private CharSequence[] mListValues;
+ private CharSequence[] mListEntries;
+
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ doReturn(mSpyResources).when(mSpyContext).getResources();
+ // Get XML values without mock
+ // Setup test list preference using XML values
+ mPreference = new ListPreference(mSpyContext);
+ mPreference.setEntries(R.array.bt_hci_snoop_log_profile_filter_entries);
+ mPreference.setEntryValues(R.array.bt_hci_snoop_log_profile_filter_values);
+ // Init the actual controller
+ mController = new BluetoothSnoopLogFilterProfilePbapPreferenceController(mSpyContext);
+ // Construct preference in the controller via a mocked preference screen object
+ when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
+ .thenReturn(mPreference);
+ mController.displayPreference(mPreferenceScreen);
+ mListValues = mPreference.getEntryValues();
+ mListEntries = mPreference.getEntries();
+ BluetoothProperties.snoop_log_mode(BluetoothProperties.snoop_log_mode_values.FILTERED);
+ }
+
+ @Test
+ public void verifyResourceSizeAndRange() {
+ Assert.assertTrue(
+ BluetoothSnoopLogFilterProfilePbapPreferenceController
+ .isSnoopLogModeFilteredEnabled());
+ // Verify normal list entries and default preference entries have the same size
+ Assert.assertEquals(mListEntries.length, mListValues.length);
+ // Update the preference
+ mController.updateState(mPreference);
+ // Verify default preference value, entry and summary
+ final int defaultIndex = mController.getDefaultModeIndex();
+ Assert.assertEquals(mPreference.getValue(), mListValues[defaultIndex]);
+ Assert.assertEquals(mPreference.getEntry(), mListEntries[defaultIndex]);
+ Assert.assertEquals(mPreference.getSummary(), mListEntries[defaultIndex]);
+ }
+
+ @Test
+ public void onPreferenceChanged_turnOnBluetoothSnoopLogFullFilterPbap() {
+ Assert.assertTrue(
+ BluetoothSnoopLogFilterProfilePbapPreferenceController
+ .isSnoopLogModeFilteredEnabled());
+ mController.onPreferenceChange(
+ null,
+ mListValues[
+ BluetoothSnoopLogFilterProfilePbapPreferenceController
+ .BTSNOOP_LOG_PROFILE_FILTER_MODE_FULL_FILTER_INDEX]);
+ var mode =
+ BluetoothProperties.snoop_log_filter_profile_pbap()
+ .orElse(BluetoothProperties.snoop_log_filter_profile_pbap_values.DISABLED);
+ // "fullfilter" is hard-coded between Settings and system/bt
+ Assert.assertEquals(
+ mode, BluetoothProperties.snoop_log_filter_profile_pbap_values.FULLFILTER);
+ }
+
+ @Test
+ public void onPreferenceChanged_turnOnBluetoothSnoopLogHeaderFilterPbap() {
+ Assert.assertTrue(
+ BluetoothSnoopLogFilterProfilePbapPreferenceController
+ .isSnoopLogModeFilteredEnabled());
+ mController.onPreferenceChange(
+ null,
+ mListValues[
+ BluetoothSnoopLogFilterProfilePbapPreferenceController
+ .BTSNOOP_LOG_PROFILE_FILTER_MODE_HEADER_INDEX]);
+ var mode =
+ BluetoothProperties.snoop_log_filter_profile_pbap()
+ .orElse(BluetoothProperties.snoop_log_filter_profile_pbap_values.DISABLED);
+ // "header" is hard-coded between Settings and system/bt
+ Assert.assertEquals(mode, BluetoothProperties.snoop_log_filter_profile_pbap_values.HEADER);
+ }
+
+ @Test
+ public void onPreferenceChanged_turnOnBluetoothSnoopLogMagicFilterPbap() {
+ Assert.assertTrue(
+ BluetoothSnoopLogFilterProfilePbapPreferenceController
+ .isSnoopLogModeFilteredEnabled());
+ mController.onPreferenceChange(
+ null,
+ mListValues[
+ BluetoothSnoopLogFilterProfilePbapPreferenceController
+ .BTSNOOP_LOG_PROFILE_FILTER_MODE_MAGIC_INDEX]);
+ var mode =
+ BluetoothProperties.snoop_log_filter_profile_pbap()
+ .orElse(BluetoothProperties.snoop_log_filter_profile_pbap_values.DISABLED);
+ // "magic" is hard-coded between Settings and system/bt
+ Assert.assertEquals(mode, BluetoothProperties.snoop_log_filter_profile_pbap_values.MAGIC);
+ }
+
+ @Test
+ public void onPreferenceChanged_turnOffBluetoothSnoopLogFilterPbap() {
+ Assert.assertTrue(
+ BluetoothSnoopLogFilterProfilePbapPreferenceController
+ .isSnoopLogModeFilteredEnabled());
+ mController.onPreferenceChange(
+ null,
+ mListValues[
+ BluetoothSnoopLogFilterProfilePbapPreferenceController
+ .BTSNOOP_LOG_PROFILE_FILTER_MODE_DISABLED_INDEX]);
+ var mode =
+ BluetoothProperties.snoop_log_filter_profile_pbap()
+ .orElse(BluetoothProperties.snoop_log_filter_profile_pbap_values.DISABLED);
+ // "disabled" is hard-coded between Settings and system/bt
+ Assert.assertEquals(
+ mode, BluetoothProperties.snoop_log_filter_profile_pbap_values.DISABLED);
+ }
+
+ @Test
+ public void updateState_preferenceShouldBeSetToRightValue() {
+ Assert.assertTrue(
+ BluetoothSnoopLogFilterProfilePbapPreferenceController
+ .isSnoopLogModeFilteredEnabled());
+ for (int i = 0; i < mListValues.length; ++i) {
+ BluetoothProperties.snoop_log_filter_profile_pbap(
+ BluetoothProperties.snoop_log_filter_profile_pbap_values.valueOf(
+ mListValues[i].toString().toUpperCase(Locale.US)));
+ mController.updateState(mPreference);
+ Assert.assertEquals(mPreference.getValue(), mListValues[i].toString());
+ Assert.assertEquals(mPreference.getSummary(), mListEntries[i].toString());
+ }
+ }
+
+ @Test
+ public void onDeveloperOptionsDisabled_shouldDisablePreference() {
+ mController.onDeveloperOptionsDisabled();
+ Assert.assertFalse(mPreference.isEnabled());
+ Assert.assertEquals(
+ mPreference.getValue(), mListValues[mController.getDefaultModeIndex()].toString());
+ Assert.assertEquals(
+ mPreference.getSummary(),
+ mListEntries[mController.getDefaultModeIndex()].toString());
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/development/BluetoothSnoopLogPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/BluetoothSnoopLogPreferenceControllerTest.java
index 630fd5f..6668a53 100644
--- a/tests/robotests/src/com/android/settings/development/BluetoothSnoopLogPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/BluetoothSnoopLogPreferenceControllerTest.java
@@ -17,9 +17,8 @@
package com.android.settings.development;
import static com.android.settings.development.BluetoothSnoopLogPreferenceController.BLUETOOTH_BTSNOOP_LOG_MODE_PROPERTY;
-import static com.google.common.truth.Truth.assertThat;
+
import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.content.Context;
@@ -31,6 +30,7 @@
import com.android.settings.R;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -43,13 +43,10 @@
@RunWith(RobolectricTestRunner.class)
public class BluetoothSnoopLogPreferenceControllerTest {
- @Spy
- private Context mSpyContext = RuntimeEnvironment.application;
- @Spy
- private Resources mSpyResources = RuntimeEnvironment.application.getResources();
+ @Spy private Context mSpyContext = RuntimeEnvironment.application;
+ @Spy private Resources mSpyResources = RuntimeEnvironment.application.getResources();
private ListPreference mPreference;
- @Mock
- private PreferenceScreen mPreferenceScreen;
+ @Mock private PreferenceScreen mPreferenceScreen;
private BluetoothSnoopLogPreferenceController mController;
private CharSequence[] mListValues;
@@ -65,10 +62,10 @@
mPreference.setEntries(R.array.bt_hci_snoop_log_entries);
mPreference.setEntryValues(R.array.bt_hci_snoop_log_values);
// Init the actual controller
- mController = new BluetoothSnoopLogPreferenceController(mSpyContext);
+ mController = new BluetoothSnoopLogPreferenceController(mSpyContext, null);
// Construct preference in the controller via a mocked preference screen object
when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
- .thenReturn(mPreference);
+ .thenReturn(mPreference);
mController.displayPreference(mPreferenceScreen);
mListValues = mPreference.getEntryValues();
mListEntries = mPreference.getEntries();
@@ -77,41 +74,44 @@
@Test
public void verifyResourceSizeAndRange() {
// Verify normal list entries and default preference entries have the same size
- assertThat(mListEntries.length).isEqualTo(mListValues.length);
+ Assert.assertEquals(mListEntries.length, mListValues.length);
// Update the preference
mController.updateState(mPreference);
// Verify default preference value, entry and summary
final int defaultIndex = mController.getDefaultModeIndex();
- assertThat(mPreference.getValue()).isEqualTo(mListValues[defaultIndex]);
- assertThat(mPreference.getEntry()).isEqualTo(mListEntries[defaultIndex]);
- assertThat(mPreference.getSummary()).isEqualTo(mListEntries[defaultIndex]);
+ Assert.assertEquals(mPreference.getValue(), mListValues[defaultIndex]);
+ Assert.assertEquals(mPreference.getEntry(), mListEntries[defaultIndex]);
+ Assert.assertEquals(mPreference.getSummary(), mListEntries[defaultIndex]);
}
@Test
public void onPreferenceChanged_turnOnFullBluetoothSnoopLog() {
- mController.onPreferenceChange(null,
+ mController.onPreferenceChange(
+ null,
mListValues[BluetoothSnoopLogPreferenceController.BTSNOOP_LOG_MODE_FULL_INDEX]);
final String mode = SystemProperties.get(BLUETOOTH_BTSNOOP_LOG_MODE_PROPERTY);
// "full" is hard-coded between Settings and system/bt
- assertThat(mode).isEqualTo("full");
+ Assert.assertEquals(mode, "full");
}
@Test
public void onPreferenceChanged_turnOnFilteredBluetoothSnoopLog() {
- mController.onPreferenceChange(null,
+ mController.onPreferenceChange(
+ null,
mListValues[BluetoothSnoopLogPreferenceController.BTSNOOP_LOG_MODE_FILTERED_INDEX]);
final String mode = SystemProperties.get(BLUETOOTH_BTSNOOP_LOG_MODE_PROPERTY);
// "filtered" is hard-coded between Settings and system/bt
- assertThat(mode).isEqualTo("filtered");
+ Assert.assertEquals(mode, "filtered");
}
@Test
public void onPreferenceChanged_turnOffBluetoothSnoopLog() {
- mController.onPreferenceChange(null,
+ mController.onPreferenceChange(
+ null,
mListValues[BluetoothSnoopLogPreferenceController.BTSNOOP_LOG_MODE_DISABLED_INDEX]);
final String mode = SystemProperties.get(BLUETOOTH_BTSNOOP_LOG_MODE_PROPERTY);
// "disabled" is hard-coded between Settings and system/bt
- assertThat(mode).isEqualTo("disabled");
+ Assert.assertEquals(mode, "disabled");
}
@Test
@@ -119,20 +119,19 @@
for (int i = 0; i < mListValues.length; ++i) {
SystemProperties.set(BLUETOOTH_BTSNOOP_LOG_MODE_PROPERTY, mListValues[i].toString());
mController.updateState(mPreference);
- assertThat(mPreference.getValue()).isEqualTo(mListValues[i].toString());
- assertThat(mPreference.getSummary()).isEqualTo(mListEntries[i].toString());
+ Assert.assertEquals(mPreference.getValue(), mListValues[i].toString());
+ Assert.assertEquals(mPreference.getSummary(), mListEntries[i].toString());
}
}
@Test
public void onDeveloperOptionsDisabled_shouldDisablePreference() {
mController.onDeveloperOptionsDisabled();
- assertThat(mPreference.isEnabled()).isFalse();
- assertThat(mPreference.getValue()).isEqualTo(
- mListValues[mController.getDefaultModeIndex()]
- .toString());
- assertThat(mPreference.getSummary()).isEqualTo(
- mListEntries[mController.getDefaultModeIndex()]
- .toString());
+ Assert.assertFalse(mPreference.isEnabled());
+ Assert.assertEquals(
+ mPreference.getValue(), mListValues[mController.getDefaultModeIndex()].toString());
+ Assert.assertEquals(
+ mPreference.getSummary(),
+ mListEntries[mController.getDefaultModeIndex()].toString());
}
}
diff --git a/tests/robotests/src/com/android/settings/development/DevelopmentMemtagPagePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/DevelopmentMemtagPagePreferenceControllerTest.java
new file mode 100644
index 0000000..7989682
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/DevelopmentMemtagPagePreferenceControllerTest.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+
+import android.content.Context;
+import android.os.SystemProperties;
+
+import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowSystemProperties;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowRestrictedLockUtilsInternal.class})
+public class DevelopmentMemtagPagePreferenceControllerTest {
+ private final String mMemtagSupportedProperty = "ro.arm64.memtag.bootctl_supported";
+
+ private DevelopmentMemtagPagePreferenceController mController;
+ private Context mContext;
+
+ @Mock private DevelopmentSettingsDashboardFragment mFragment;
+ private static final String FRAGMENT_TAG = "memtag_page";
+
+ @Before
+ public void setUp() {
+ ShadowSystemProperties.override(mMemtagSupportedProperty, "true");
+
+ mContext = RuntimeEnvironment.application;
+ mController = new DevelopmentMemtagPagePreferenceController(mContext, mFragment);
+ }
+
+ @Test
+ public void onAvailable_sysPropEnabled() {
+ SystemProperties.set("ro.arm64.memtag.bootctl_supported", "1");
+ assertTrue(mController.isAvailable());
+ }
+
+ @Test
+ public void onAvailable_sysPropDisabled() {
+ SystemProperties.set("ro.arm64.memtag.bootctl_supported", "0");
+ assertFalse(mController.isAvailable());
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/development/DevelopmentMemtagPageTest.java b/tests/robotests/src/com/android/settings/development/DevelopmentMemtagPageTest.java
new file mode 100644
index 0000000..39dc48e
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/DevelopmentMemtagPageTest.java
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+
+import com.android.settings.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class DevelopmentMemtagPageTest {
+ private DevelopmentMemtagPage mMemtagPage;
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ mMemtagPage = new DevelopmentMemtagPage();
+ mContext = RuntimeEnvironment.application;
+ }
+
+ @Test
+ public void getMetricsCategory_isSETTINGS_MEMTAG_CATEGORY() {
+ assertThat(mMemtagPage.getMetricsCategory())
+ .isEqualTo(SettingsEnums.SETTINGS_MEMTAG_CATEGORY);
+ }
+
+ @Test
+ public void getPreferenceScreenResId_isMemtag_page() {
+ assertThat(mMemtagPage.getPreferenceScreenResId()).isEqualTo(R.xml.development_memtag_page);
+ }
+
+ @Test
+ public void SEARCH_INDEX_DATA_PROVIDERgetPreferenceControllers_isNotEmpty() {
+ assertThat(
+ DevelopmentMemtagPage.SEARCH_INDEX_DATA_PROVIDER.getPreferenceControllers(
+ mContext))
+ .isNotEmpty();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/development/DevelopmentMemtagPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/DevelopmentMemtagPreferenceControllerTest.java
new file mode 100644
index 0000000..d4af470
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/DevelopmentMemtagPreferenceControllerTest.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.development;
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.assertion.ViewAssertions.doesNotExist;
+import static androidx.test.espresso.matcher.RootMatchers.isDialog;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.os.Bundle;
+
+import androidx.fragment.app.FragmentActivity;
+import androidx.fragment.app.FragmentContainerView;
+import androidx.test.rule.ActivityTestRule;
+
+import com.android.settings.R;
+import com.android.settings.security.ZygoteShadow;
+import com.android.settings.testutils.shadow.ShadowDeviceConfig;
+import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
+import com.android.settingslib.RestrictedSwitchPreference;
+import com.android.settingslib.testutils.shadow.ShadowInteractionJankMonitor;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowSystemProperties;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(
+ shadows = {
+ ZygoteShadow.class,
+ ShadowDeviceConfig.class,
+ ShadowInteractionJankMonitor.class,
+ ShadowRestrictedLockUtilsInternal.class
+ })
+public class DevelopmentMemtagPreferenceControllerTest {
+ private final String mMemtagSupportedProperty = "ro.arm64.memtag.bootctl_supported";
+
+ @Rule
+ public ActivityTestRule<TestActivity> mActivityTestRule =
+ new ActivityTestRule<>(TestActivity.class);
+
+ private DevelopmentMemtagPage mMemtagPage;
+ private DevelopmentMemtagPreferenceController mController;
+ private Context mContext;
+ private TestActivity mActivity;
+
+ private static final String FRAGMENT_TAG = "development_memtag_page";
+
+ @Before
+ public void setUp() {
+ ShadowSystemProperties.override(mMemtagSupportedProperty, "true");
+
+ mContext = RuntimeEnvironment.application;
+ mMemtagPage = new DevelopmentMemtagPage();
+ mActivity = mActivityTestRule.getActivity();
+ mActivity
+ .getSupportFragmentManager()
+ .beginTransaction()
+ .add(TestActivity.CONTAINER_VIEW_ID, mMemtagPage)
+ .commit();
+ mController = new DevelopmentMemtagPreferenceController(mContext, FRAGMENT_TAG);
+ mController.setFragment(mMemtagPage);
+ }
+
+ @Test
+ public void getSliceHighlightMenuRes_isMenu_key_security() {
+ assertThat(mController.getSliceHighlightMenuRes()).isEqualTo(R.string.menu_key_security);
+ }
+
+ @Test
+ public void setChecked_isChecked_updatesSummary() {
+ ZygoteShadow.setSupportsMemoryTagging(true);
+ mController.setChecked(true);
+ assertThat(mController.getSummary())
+ .isEqualTo(mContext.getResources().getString(R.string.memtag_on));
+ }
+
+ @Test
+ public void setChecked_isUnchecked_updatesSummary() {
+ ZygoteShadow.setSupportsMemoryTagging(false);
+ mController.setChecked(false);
+ assertThat(mController.getSummary())
+ .isEqualTo(mContext.getResources().getString(R.string.memtag_off));
+ }
+
+ @Test
+ public void setChecked_isCheckedPending_updatesSummary() {
+ ZygoteShadow.setSupportsMemoryTagging(false);
+ mController.setChecked(true);
+ assertThat(mController.getSummary())
+ .isEqualTo(mContext.getResources().getString(R.string.memtag_on_pending));
+ }
+
+ @Test
+ public void setChecked_isUncheckedPending_updatesSummary() {
+ ZygoteShadow.setSupportsMemoryTagging(true);
+ mController.setChecked(false);
+ assertThat(mController.getSummary())
+ .isEqualTo(mContext.getResources().getString(R.string.memtag_off_pending));
+ }
+
+ @Test
+ public void setChecked_isCheckedPending_showsDialog() {
+ ZygoteShadow.setSupportsMemoryTagging(false);
+ mController.setChecked(true);
+ onView(withText(R.string.memtag_reboot_title)).inRoot(isDialog());
+ }
+
+ @Test
+ public void setChecked_isUncheckedPending_showsDialog() {
+ ZygoteShadow.setSupportsMemoryTagging(true);
+ mController.setChecked(false);
+ onView(withText(R.string.memtag_reboot_title)).inRoot(isDialog());
+ }
+
+ @Test
+ public void setChecked_isChecked_doesNotShowDialog() {
+ ZygoteShadow.setSupportsMemoryTagging(false);
+ mController.setChecked(false);
+ onView(withText(R.string.memtag_reboot_title)).inRoot(isDialog()).check(doesNotExist());
+ }
+
+ @Test
+ public void setChecked_isUnchecked_doesNotShowDialog() {
+ ZygoteShadow.setSupportsMemoryTagging(true);
+ mController.setChecked(true);
+ onView(withText(R.string.memtag_reboot_title)).inRoot(isDialog()).check(doesNotExist());
+ }
+
+ @Test
+ public void updateState_disabledByAdmin_disablesPreference() {
+ ShadowRestrictedLockUtilsInternal.setMteIsDisabled(true);
+ RestrictedSwitchPreference preference = new RestrictedSwitchPreference(mContext);
+ mController.updateState(preference);
+ assertThat(preference.isDisabledByAdmin()).isTrue();
+ }
+
+ private static final class TestActivity extends FragmentActivity {
+ private static final int CONTAINER_VIEW_ID = 1234;
+
+ @Override
+ protected void onCreate(Bundle bundle) {
+ super.onCreate(bundle);
+
+ FragmentContainerView contentView = new FragmentContainerView(this);
+ contentView.setId(CONTAINER_VIEW_ID);
+ setContentView(contentView);
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/development/RebootWithMtePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/RebootWithMtePreferenceControllerTest.java
index d6b1031..f1e7d3f 100644
--- a/tests/robotests/src/com/android/settings/development/RebootWithMtePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/development/RebootWithMtePreferenceControllerTest.java
@@ -22,6 +22,7 @@
import android.content.Context;
import android.os.SystemProperties;
+import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
import androidx.test.core.app.ApplicationProvider;
@@ -42,14 +43,15 @@
public class RebootWithMtePreferenceControllerTest {
private Context mContext;
private RebootWithMtePreferenceController mController;
- @Mock private DevelopmentSettingsDashboardFragment mSettings;
+ @Mock private Fragment mFragment;
@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
mContext = ApplicationProvider.getApplicationContext();
- mController = new RebootWithMtePreferenceController(mContext, mSettings);
+ mController = new RebootWithMtePreferenceController(mContext);
+ mController.setFragment(mFragment);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/development/snooplogger/SnoopLoggerFiltersDashboardTest.java b/tests/robotests/src/com/android/settings/development/snooplogger/SnoopLoggerFiltersDashboardTest.java
new file mode 100644
index 0000000..40c34bf
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/snooplogger/SnoopLoggerFiltersDashboardTest.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2022 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.development.snooplogger;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.app.settings.SettingsEnums;
+
+import com.android.settings.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+
+@RunWith(RobolectricTestRunner.class)
+public class SnoopLoggerFiltersDashboardTest {
+
+ private SnoopLoggerFiltersDashboard mDashboard;
+
+ @Before
+ public void setUp() {
+ mDashboard = new SnoopLoggerFiltersDashboard();
+ }
+
+ @Test
+ public void shouldNotHaveHelpResource() {
+ assertThat(mDashboard.getHelpResource()).isEqualTo(0);
+ }
+
+ @Test
+ public void shouldLogAsSnoopLoggerFiltersPage() {
+ assertThat(mDashboard.getMetricsCategory())
+ .isEqualTo(SettingsEnums.SETTINGS_SNOOP_LOGGER_DASHBOARD);
+ }
+
+ @Test
+ public void shouldUseSnoopLoggerFiltersPreferenceLayout() {
+ assertThat(mDashboard.getPreferenceScreenResId())
+ .isEqualTo(R.xml.snoop_logger_filters_settings);
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/development/snooplogger/SnoopLoggerFiltersPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/snooplogger/SnoopLoggerFiltersPreferenceControllerTest.java
new file mode 100644
index 0000000..f96ada0
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/snooplogger/SnoopLoggerFiltersPreferenceControllerTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.development.snooplogger;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.core.BasePreferenceController.DISABLED_DEPENDENT_SETTING;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.atLeastOnce;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.sysprop.BluetoothProperties;
+
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceScreen;
+
+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;
+
+@RunWith(RobolectricTestRunner.class)
+public class SnoopLoggerFiltersPreferenceControllerTest {
+
+ @Mock
+ private PreferenceScreen mScreen;
+ @Mock
+ private PreferenceCategory mCategory;
+ private Context mContext;
+ private SnoopLoggerFiltersPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mController = new SnoopLoggerFiltersPreferenceController(mContext, "test_key");
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(mCategory);
+ when(mCategory.getContext()).thenReturn(mContext);
+ mController.displayPreference(mScreen);
+ }
+
+ @Test
+ public void getAvailability_debug_available() {
+ BluetoothProperties.snoop_log_mode(BluetoothProperties.snoop_log_mode_values.FILTERED);
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(AVAILABLE);
+ }
+
+ @Test
+ public void getAvailability_user_unavailable() {
+ BluetoothProperties.snoop_log_mode(BluetoothProperties.snoop_log_mode_values.DISABLED);
+ assertThat(mController.getAvailabilityStatus()).isEqualTo(DISABLED_DEPENDENT_SETTING);
+ }
+
+ @Test
+ public void onStart_shouldRefreshFilters() {
+ mController.displayPreference(mScreen);
+
+ verify(mCategory, atLeastOnce()).addPreference(any(SnoopLoggerFiltersPreference.class));
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/development/snooplogger/SnoopLoggerFiltersPreferenceTest.java b/tests/robotests/src/com/android/settings/development/snooplogger/SnoopLoggerFiltersPreferenceTest.java
new file mode 100644
index 0000000..56f29ba
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/development/snooplogger/SnoopLoggerFiltersPreferenceTest.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2022 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.development.snooplogger;
+
+import android.content.Context;
+
+import com.android.settings.R;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class SnoopLoggerFiltersPreferenceTest {
+
+ private static String sKEY;
+ private static String sENTRY;
+
+ private Context mContext;
+ private SnoopLoggerFiltersPreference mPreference;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ sKEY = mContext.getResources().getStringArray(R.array.bt_hci_snoop_log_filters_values)[0];
+ sENTRY =
+ mContext.getResources().getStringArray(R.array.bt_hci_snoop_log_filters_entries)[0];
+ mPreference = new SnoopLoggerFiltersPreference(mContext, sKEY, sENTRY);
+ }
+
+ @Test
+ public void constructor_shouldSetTitle() {
+ Assert.assertEquals(mPreference.getTitle(), sENTRY);
+ Assert.assertFalse(mPreference.isChecked());
+ }
+
+ @Test
+ public void setChecked_shouldSetChecked() {
+ mPreference.setChecked(true);
+ Assert.assertTrue(mPreference.isChecked());
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/security/ZygoteShadow.java b/tests/robotests/src/com/android/settings/security/ZygoteShadow.java
index 23b30fa..c7b11c3 100644
--- a/tests/robotests/src/com/android/settings/security/ZygoteShadow.java
+++ b/tests/robotests/src/com/android/settings/security/ZygoteShadow.java
@@ -25,7 +25,7 @@
public class ZygoteShadow {
private static boolean sSupportsMemoryTagging;
- static void setSupportsMemoryTagging(boolean value) {
+ public static void setSupportsMemoryTagging(boolean value) {
sSupportsMemoryTagging = value;
}
diff --git a/tests/unit/src/com/android/settings/TestingSettingsTest.java b/tests/unit/src/com/android/settings/TestingSettingsTest.java
new file mode 100644
index 0000000..1f4e385
--- /dev/null
+++ b/tests/unit/src/com/android/settings/TestingSettingsTest.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings;
+
+import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.os.UserManager;
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(AndroidJUnit4.class)
+public class TestingSettingsTest {
+
+ @Mock
+ private UserManager mUserManager;
+ @Mock
+ private TestingSettings mTestingSettings;
+
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = spy(ApplicationProvider.getApplicationContext());
+ }
+
+ @Test
+ public void isRadioInfoVisible_returnFalse_whenUserRestricted() {
+ mockService(mContext, Context.USER_SERVICE, UserManager.class, mUserManager);
+
+ doReturn(true).when(mUserManager).isAdminUser();
+ doReturn(false).when(mUserManager).isGuestUser();
+ doReturn(true).when(mUserManager)
+ .hasUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS);
+
+ assertThat(mTestingSettings.isRadioInfoVisible(mContext)).isFalse();
+ }
+
+ private <T> void mockService(Context context, String serviceName,
+ Class<T> serviceClass, T service) {
+ when(context.getSystemServiceName(serviceClass)).thenReturn(serviceName);
+ when(context.getSystemService(serviceName)).thenReturn(service);
+ }
+}
diff --git a/tests/unit/src/com/android/settings/dashboard/CategoryManagerTest.java b/tests/unit/src/com/android/settings/dashboard/CategoryManagerTest.java
index 98540f9..26ba856 100644
--- a/tests/unit/src/com/android/settings/dashboard/CategoryManagerTest.java
+++ b/tests/unit/src/com/android/settings/dashboard/CategoryManagerTest.java
@@ -22,6 +22,8 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.when;
+
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.ApplicationInfo;
@@ -32,6 +34,7 @@
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import com.android.settings.safetycenter.SafetyCenterManagerWrapper;
import com.android.settingslib.drawer.ActivityTile;
import com.android.settingslib.drawer.CategoryKey;
import com.android.settingslib.drawer.DashboardCategory;
@@ -41,6 +44,8 @@
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import java.util.HashMap;
import java.util.Map;
@@ -54,8 +59,11 @@
private Map<Pair<String, String>, Tile> mTileByComponentCache;
private Map<String, DashboardCategory> mCategoryByKeyMap;
+ @Mock private SafetyCenterManagerWrapper mSafetyCenterManagerWrapper;
+
@Before
public void setUp() {
+ MockitoAnnotations.initMocks(this);
mContext = ApplicationProvider.getApplicationContext();
mActivityInfo = new ActivityInfo();
mActivityInfo.packageName = "pkg";
@@ -64,6 +72,7 @@
mTileByComponentCache = new HashMap<>();
mCategoryByKeyMap = new HashMap<>();
mCategoryManager = CategoryManager.get(mContext);
+ SafetyCenterManagerWrapper.sInstance = mSafetyCenterManagerWrapper;
}
@Test
@@ -132,6 +141,90 @@
}
@Test
+ public void mergeSecurityPrivacyKeys_safetyCenterEnabled_shouldNotChangeOtherKeys() {
+ when(mSafetyCenterManagerWrapper.isEnabled(mContext)).thenReturn(true);
+
+ final Tile tile1 = new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_ACCOUNT);
+ final String oldCategory = "com.android.settings.category.wireless";
+ final Tile tile2 = new ActivityTile(mActivityInfo, oldCategory);
+ final DashboardCategory category1 = new DashboardCategory(CategoryKey.CATEGORY_ACCOUNT);
+ category1.addTile(tile1);
+ final DashboardCategory category2 = new DashboardCategory(oldCategory);
+ category2.addTile(tile2);
+ mCategoryByKeyMap.put(CategoryKey.CATEGORY_ACCOUNT, category1);
+ mCategoryByKeyMap.put(oldCategory, category2);
+ mTileByComponentCache.put(new Pair<>("PACKAGE", "CLASS1"), tile1);
+ mTileByComponentCache.put(new Pair<>("PACKAGE", "CLASS2"), tile2);
+
+ mCategoryManager.mergeSecurityPrivacyKeys(
+ mContext, mTileByComponentCache, mCategoryByKeyMap);
+
+ assertThat(mCategoryByKeyMap.size()).isEqualTo(2);
+ assertThat(mCategoryByKeyMap.get(CategoryKey.CATEGORY_ACCOUNT).getTilesCount())
+ .isEqualTo(1);
+ assertThat(mCategoryByKeyMap.get(oldCategory).getTilesCount()).isEqualTo(1);
+ assertThat(mCategoryByKeyMap.get(CategoryKey.CATEGORY_MORE_SECURITY_PRIVACY_SETTINGS))
+ .isNull();
+ }
+
+ @Test
+ public void mergeSecurityPrivacyKeys_safetyCenterEnabled_shouldChangeSecurityPrivacyKeys() {
+ when(mSafetyCenterManagerWrapper.isEnabled(mContext)).thenReturn(true);
+
+ final Tile tileWithSecurityCategory =
+ new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_SECURITY_ADVANCED_SETTINGS);
+ final Tile tileWithPrivacyCategory =
+ new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_PRIVACY);
+ final DashboardCategory categoryAdvancedSecurity =
+ new DashboardCategory(CategoryKey.CATEGORY_SECURITY_ADVANCED_SETTINGS);
+ categoryAdvancedSecurity.addTile(tileWithSecurityCategory);
+ final DashboardCategory categoryPrivacy =
+ new DashboardCategory(CategoryKey.CATEGORY_PRIVACY);
+ categoryPrivacy.addTile(tileWithPrivacyCategory);
+ mCategoryByKeyMap.put(
+ CategoryKey.CATEGORY_SECURITY_ADVANCED_SETTINGS, categoryAdvancedSecurity);
+ mCategoryByKeyMap.put(CategoryKey.CATEGORY_PRIVACY, categoryPrivacy);
+ mTileByComponentCache.put(new Pair<>("PACKAGE", "CLASS1"), tileWithSecurityCategory);
+ mTileByComponentCache.put(new Pair<>("PACKAGE", "CLASS2"), tileWithPrivacyCategory);
+
+ mCategoryManager.mergeSecurityPrivacyKeys(
+ mContext, mTileByComponentCache, mCategoryByKeyMap);
+
+ assertThat(
+ mCategoryByKeyMap
+ .get(CategoryKey.CATEGORY_MORE_SECURITY_PRIVACY_SETTINGS)
+ .getTilesCount())
+ .isEqualTo(2);
+ }
+
+ @Test
+ public void mergeSecurityPrivacyKeys_safetyCenterDisabled_shouldNotChangeSecurityPrivacyKeys() {
+ when(mSafetyCenterManagerWrapper.isEnabled(mContext)).thenReturn(false);
+
+ final Tile tileWithSecurityCategory =
+ new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_SECURITY_ADVANCED_SETTINGS);
+ final Tile tileWithPrivacyCategory =
+ new ActivityTile(mActivityInfo, CategoryKey.CATEGORY_PRIVACY);
+ final DashboardCategory categoryAdvancedSecurity =
+ new DashboardCategory(CategoryKey.CATEGORY_SECURITY_ADVANCED_SETTINGS);
+ categoryAdvancedSecurity.addTile(tileWithSecurityCategory);
+ final DashboardCategory categoryPrivacy =
+ new DashboardCategory(CategoryKey.CATEGORY_PRIVACY);
+ categoryPrivacy.addTile(tileWithPrivacyCategory);
+ mCategoryByKeyMap.put(
+ CategoryKey.CATEGORY_SECURITY_ADVANCED_SETTINGS, categoryAdvancedSecurity);
+ mCategoryByKeyMap.put(CategoryKey.CATEGORY_PRIVACY, categoryPrivacy);
+ mTileByComponentCache.put(new Pair<>("PACKAGE", "CLASS1"), tileWithSecurityCategory);
+ mTileByComponentCache.put(new Pair<>("PACKAGE", "CLASS2"), tileWithPrivacyCategory);
+
+ mCategoryManager.mergeSecurityPrivacyKeys(
+ mContext, mTileByComponentCache, mCategoryByKeyMap);
+
+ assertThat(mCategoryByKeyMap.get(CategoryKey.CATEGORY_MORE_SECURITY_PRIVACY_SETTINGS))
+ .isNull();
+ }
+
+ @Test
public void sortCategories_singlePackage_shouldReorderBasedOnPriority() {
// Create some fake tiles that are not sorted.
final String testPackage = "com.android.test";
diff --git a/tests/unit/src/com/android/settings/nearby/FastPairPreferenceControllerTest.java b/tests/unit/src/com/android/settings/nearby/FastPairPreferenceControllerTest.java
deleted file mode 100644
index f06be4b..0000000
--- a/tests/unit/src/com/android/settings/nearby/FastPairPreferenceControllerTest.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright (C) 2022 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.nearby;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.spy;
-
-import android.content.Context;
-import android.os.Looper;
-
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class FastPairPreferenceControllerTest {
-
- private Context mContext;
- private FastPairPreferenceController mController;
-
- @Before
- public void setUp() {
- mContext = spy(ApplicationProvider.getApplicationContext());
- mController = new FastPairPreferenceController(mContext);
- if (Looper.myLooper() == null) {
- Looper.prepare();
- }
- }
-
- @Test
- public void isAvailable_shouldBeTrue() {
- assertThat(mController.isAvailable()).isTrue();
- }
-}
diff --git a/tests/unit/src/com/android/settings/nearby/FastPairSettingsFragmentTest.java b/tests/unit/src/com/android/settings/nearby/FastPairSettingsFragmentTest.java
deleted file mode 100644
index faabe8f..0000000
--- a/tests/unit/src/com/android/settings/nearby/FastPairSettingsFragmentTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (C) 2022 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.nearby;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import android.app.Instrumentation;
-import android.app.settings.SettingsEnums;
-
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.platform.app.InstrumentationRegistry;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-@RunWith(AndroidJUnit4.class)
-public class FastPairSettingsFragmentTest {
-
- private FastPairSettingsFragment mFragment;
-
- @Before
- public void setUp() {
- final Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
- instrumentation.runOnMainSync(() -> mFragment = new FastPairSettingsFragment());
- }
-
- @Test
- public void getCategoryKey_isNetwork() {
- assertThat(mFragment.getMetricsCategory())
- .isEqualTo(SettingsEnums.CONNECTION_DEVICE_ADVANCED_FAST_PAIR);
- }
-}