Merge "Fix errorprone warnings that should be errors" am: 5744d7c560 am: 7094507528
Original change: https://android-review.googlesource.com/c/platform/packages/apps/Settings/+/2255054
Change-Id: I369fd8dc4e2cec46ffd4e61a32e7e55cb11b41a8
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index f51719b..8334466 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -146,6 +146,7 @@
android:configChanges="orientation|keyboard|keyboardHidden|screenSize|screenLayout|smallestScreenSize">
<intent-filter android:priority="1">
<action android:name="android.settings.SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
@@ -231,6 +232,7 @@
<action android:name="android.settings.WIRELESS_SETTINGS" />
<action android:name="android.settings.AIRPLANE_MODE_SETTINGS" />
<action android:name="com.android.settings.sim.SIM_SUB_INFO_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
@@ -262,6 +264,7 @@
<action android:name="android.settings.NETWORK_OPERATOR_SETTINGS" />
<action android:name="android.settings.DATA_ROAMING_SETTINGS" />
<action android:name="android.settings.MMS_MESSAGE_SETTING" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
@@ -289,6 +292,7 @@
android:icon="@drawable/ic_homepage_connected_device">
<intent-filter android:priority="1">
<action android:name="android.settings.BLUETOOTH_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
@@ -338,6 +342,7 @@
android:configChanges="orientation|keyboardHidden|screenSize">
<intent-filter android:priority="1">
<action android:name="android.settings.WIFI_SETTINGS"/>
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
@@ -449,6 +454,7 @@
android:configChanges="orientation|keyboardHidden|screenSize">
<intent-filter android:priority="1">
<action android:name="android.settings.WIFI_IP_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
@@ -785,6 +791,7 @@
android:icon="@drawable/ic_homepage_vpn">
<intent-filter android:priority="1">
<action android:name="android.settings.VPN_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<action android:name="android.net.vpn.SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
@@ -821,6 +828,7 @@
android:icon="@drawable/ic_settings_date_time">
<intent-filter android:priority="1">
<action android:name="android.settings.DATE_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
@@ -844,6 +852,7 @@
android:icon="@drawable/ic_settings_language">
<intent-filter android:priority="1">
<action android:name="android.settings.LOCALE_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
@@ -901,6 +910,7 @@
android:label="@string/available_virtual_keyboard_category">
<intent-filter android:priority="1">
<action android:name="android.settings.INPUT_METHOD_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
@@ -915,6 +925,7 @@
android:label="@string/assist_and_voice_input_title">
<intent-filter android:priority="1">
<action android:name="android.settings.VOICE_INPUT_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
@@ -1033,6 +1044,7 @@
</intent-filter>
<intent-filter android:priority="1">
<action android:name="android.settings.ZEN_MODE_PRIORITY_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter android:priority="41">
@@ -1092,6 +1104,7 @@
</intent-filter>
<intent-filter android:priority="1">
<action android:name="android.settings.ACTION_CONDITION_PROVIDER_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
@@ -1194,6 +1207,7 @@
<intent-filter android:priority="1">
<action android:name="com.android.settings.DISPLAY_SETTINGS" />
<action android:name="android.settings.DISPLAY_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter android:priority="30">
@@ -1239,6 +1253,7 @@
</intent-filter>
<intent-filter android:priority="1">
<action android:name="android.settings.NIGHT_DISPLAY_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
@@ -1299,6 +1314,7 @@
android:icon="@drawable/ic_homepage_about">
<intent-filter android:priority="1">
<action android:name="android.settings.DEVICE_INFO_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<action android:name="android.settings.DEVICE_NAME" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
@@ -1383,6 +1399,7 @@
<action android:name="android.settings.APPLICATION_SETTINGS" />
<action android:name="android.settings.MANAGE_APPLICATIONS_SETTINGS" />
<action android:name="android.settings.MANAGE_ALL_APPLICATIONS_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter android:priority="20">
@@ -1442,6 +1459,7 @@
android:label="@string/high_power_apps">
<intent-filter android:priority="1">
<action android:name="android.settings.IGNORE_BATTERY_OPTIMIZATION_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
@@ -1639,6 +1657,7 @@
android:configChanges="orientation|keyboardHidden|screenSize">
<intent-filter android:priority="1">
<action android:name="android.settings.LOCATION_SOURCE_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter android:priority="52">
@@ -1697,6 +1716,7 @@
android:configChanges="orientation|keyboardHidden|screenSize">
<intent-filter android:priority="1">
<action android:name="android.settings.SECURITY_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<action android:name="android.credentials.UNLOCK" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
@@ -1724,6 +1744,8 @@
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.security.SecurityAdvancedSettings" />
+ <meta-data android:name="com.android.settings.HIGHLIGHT_MENU_KEY"
+ android:value="@string/menu_key_security"/>
</activity>
<activity android:name="MonitoringCertInfoActivity"
@@ -1779,6 +1801,7 @@
android:icon="@drawable/ic_settings_privacy">
<intent-filter>
<action android:name="android.settings.PRIVACY_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
@@ -1900,6 +1923,7 @@
android:label="@string/usage_access_title">
<intent-filter android:priority="1">
<action android:name="android.settings.USAGE_ACCESS_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
@@ -1948,6 +1972,7 @@
android:configChanges="orientation|keyboardHidden|screenSize">
<intent-filter android:priority="1">
<action android:name="android.settings.ACCESSIBILITY_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter android:priority="60">
@@ -2097,6 +2122,7 @@
android:label="@string/accessibility_captioning_title">
<intent-filter android:priority="1">
<action android:name="android.settings.CAPTIONING_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
@@ -2250,6 +2276,7 @@
android:theme="@style/GlifTheme.Light">
<intent-filter>
<action android:name="android.settings.BIOMETRIC_ENROLL" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
@@ -2266,6 +2293,7 @@
android:theme="@style/GlifTheme.Light">
<intent-filter>
<action android:name="android.settings.FINGERPRINT_ENROLL" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
@@ -2431,6 +2459,7 @@
<intent-filter android:priority="1">
<action android:name="android.settings.INTERNAL_STORAGE_SETTINGS" />
<action android:name="android.settings.MEMORY_CARD_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter android:priority="50">
@@ -2585,6 +2614,7 @@
android:icon="@drawable/ic_settings_print">
<intent-filter android:priority="1">
<action android:name="android.settings.ACTION_PRINT_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
@@ -2782,6 +2812,7 @@
android:icon="@drawable/ic_cast_24dp">
<intent-filter android:priority="1">
<action android:name="android.settings.CAST_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
@@ -2861,6 +2892,7 @@
android:icon="@drawable/ic_homepage_battery">
<intent-filter android:priority="1">
<action android:name="android.settings.BATTERY_SAVER_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
@@ -2920,6 +2952,7 @@
android:label="@string/header_add_an_account">
<intent-filter android:priority="1">
<action android:name="android.settings.ADD_ACCOUNT_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
@@ -2958,6 +2991,7 @@
android:icon="@drawable/ic_homepage_data_usage">
<intent-filter android:priority="1">
<action android:name="android.settings.DATA_USAGE_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter android:priority="3">
@@ -2990,6 +3024,7 @@
android:icon="@drawable/ic_settings_display">
<intent-filter android:priority="1">
<action android:name="android.settings.DREAM_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
@@ -3041,6 +3076,7 @@
android:icon="@drawable/ic_settings_nfc_payment">
<intent-filter android:priority="1">
<action android:name="android.settings.NFC_PAYMENT_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter>
@@ -3093,6 +3129,7 @@
android:label="@string/manage_notification_access_title" >
<intent-filter android:priority="1">
<action android:name="android.settings.NOTIFICATION_LISTENER_DETAIL_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
@@ -3107,6 +3144,7 @@
android:label="@string/notification_assistant_title">
<intent-filter android:priority="1">
<action android:name="android.settings.NOTIFICATION_ASSISTANT_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
@@ -3311,6 +3349,7 @@
<intent-filter android:priority="1">
<action android:name="com.android.settings.SOUND_SETTINGS" />
<action android:name="android.settings.SOUND_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<action android:name="android.settings.ACTION_OTHER_SOUND_SETTINGS" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
@@ -3409,6 +3448,7 @@
android:enabled="@bool/config_show_regulatory_info">
<intent-filter>
<action android:name="android.settings.SHOW_REGULATORY_INFO" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.PRIMARY_PROFILE_CONTROLLED"
@@ -3637,6 +3677,7 @@
android:label="@string/write_settings_title">
<intent-filter android:priority="1">
<action android:name="android.settings.action.MANAGE_WRITE_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
@@ -3899,6 +3940,7 @@
android:icon="@drawable/ic_homepage_accounts">
<intent-filter android:priority="1">
<action android:name="android.settings.SYNC_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter android:priority="53">
@@ -4103,6 +4145,7 @@
android:label="@string/connected_device_connections_title">
<intent-filter android:priority="1">
<action android:name="android.settings.NFC_SETTINGS" />
+ <category android:name="android.intent.category.BROWSABLE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
<intent-filter android:priority="1">
diff --git a/res/drawable/ic_ring_volume.xml b/res/drawable/ic_ring_volume.xml
new file mode 100644
index 0000000..343fe5d
--- /dev/null
+++ b/res/drawable/ic_ring_volume.xml
@@ -0,0 +1,26 @@
+<!--
+ 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:pathData="M11,7V2H13V7ZM17.6,9.85 L16.2,8.4 19.75,4.85 21.15,6.3ZM6.4,9.85 L2.85,6.3 4.25,4.85 7.8,8.4ZM12,12Q14.95,12 17.812,13.188Q20.675,14.375 22.9,16.75Q23.2,17.05 23.2,17.45Q23.2,17.85 22.9,18.15L20.6,20.4Q20.325,20.675 19.963,20.7Q19.6,20.725 19.3,20.5L16.4,18.3Q16.2,18.15 16.1,17.95Q16,17.75 16,17.5V14.65Q15.05,14.35 14.05,14.175Q13.05,14 12,14Q10.95,14 9.95,14.175Q8.95,14.35 8,14.65V17.5Q8,17.75 7.9,17.95Q7.8,18.15 7.6,18.3L4.7,20.5Q4.4,20.725 4.038,20.7Q3.675,20.675 3.4,20.4L1.1,18.15Q0.8,17.85 0.8,17.45Q0.8,17.05 1.1,16.75Q3.3,14.375 6.175,13.188Q9.05,12 12,12ZM6,15.35Q5.275,15.725 4.6,16.212Q3.925,16.7 3.2,17.3L4.2,18.3L6,16.9ZM18,15.4V16.9L19.8,18.3L20.8,17.35Q20.075,16.7 19.4,16.225Q18.725,15.75 18,15.4ZM6,15.35Q6,15.35 6,15.35Q6,15.35 6,15.35ZM18,15.4Q18,15.4 18,15.4Q18,15.4 18,15.4Z"
+ android:fillColor="?android:attr/colorPrimary"/>
+
+</vector>
\ No newline at end of file
diff --git a/res/drawable/ic_ring_volume_off.xml b/res/drawable/ic_ring_volume_off.xml
new file mode 100644
index 0000000..74f30d1
--- /dev/null
+++ b/res/drawable/ic_ring_volume_off.xml
@@ -0,0 +1,34 @@
+<!--
+ 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:pathData="M0.8,4.2l8.1,8.1c-2.2,0.5 -5.2,1.6 -7.8,4.4c-0.4,0.4 -0.4,1 0,1.4l2.3,2.3c0.3,0.3 0.9,0.4 1.3,0.1l2.9,-2.2C7.8,18.1 8,17.8 8,17.5v-2.9c0.9,-0.3 1.7,-0.5 2.7,-0.6l8.5,8.5l1.4,-1.4L2.2,2.8L0.8,4.2z"
+ android:fillColor="?android:attr/colorPrimary"/>
+ <path
+ android:pathData="M11,2h2v5h-2z"
+ android:fillColor="?android:attr/colorPrimary"/>
+ <path
+ android:pathData="M21.2,6.3l-1.4,-1.4l-3.6,3.6l1.4,1.4C17.6,9.8 21,6.3 21.2,6.3z"
+ android:fillColor="?android:attr/colorPrimary"/>
+ <path
+ android:pathData="M22.9,16.7c-2.8,-3 -6.2,-4.1 -8.4,-4.5l7.2,7.2l1.3,-1.3C23.3,17.7 23.3,17.1 22.9,16.7z"
+ android:fillColor="?android:attr/colorPrimary"/>
+</vector>
diff --git a/res/values/arrays.xml b/res/values/arrays.xml
index 0632f72..f8b7f00 100644
--- a/res/values/arrays.xml
+++ b/res/values/arrays.xml
@@ -1216,6 +1216,20 @@
<item>90</item>
</string-array>
+ <!-- Options for screensaver "When to start" for devices that do not support screensavers
+ while on battery -->
+ <string-array name="when_to_start_screensaver_entries_no_battery" translatable="false">
+ <item>@string/screensaver_settings_summary_sleep</item>
+ <item>@string/screensaver_settings_summary_dock_and_charging</item>
+ </string-array>
+
+ <!-- Values for screensaver "When to start" for devices that do not support screensavers
+ while on battery -->
+ <string-array name="when_to_start_screensaver_values_no_battery" translatable="false">
+ <item>while_charging_only</item>
+ <item>while_docked_only</item>
+ </string-array>
+
<string-array name="when_to_start_screensaver_entries" translatable="false">
<item>@string/screensaver_settings_summary_sleep</item>
<item>@string/screensaver_settings_summary_dock</item>
@@ -1650,4 +1664,9 @@
[CHAR LIMIT=NONE] -->
<string-array name="allowlist_hide_summary_in_battery_usage" translatable="false">
</string-array>
+
+ <!-- Array containing help message codes that should not be displayed
+ during fingerprint enrollment. -->
+ <integer-array name="fingerprint_acquired_ignore_list">
+ </integer-array>
</resources>
diff --git a/res/values/config.xml b/res/values/config.xml
index f5ad38b..50e06ba 100755
--- a/res/values/config.xml
+++ b/res/values/config.xml
@@ -331,6 +331,9 @@
surface in search results or not.-->
<bool name="config_show_wifi_settings">true</bool>
+ <!-- Whether Wi-Fi hotspot settings should be shown or not. -->
+ <bool name="config_show_wifi_hotspot_settings">true</bool>
+
<!-- Whether toggle_airplane is available or not. -->
<bool name="config_show_toggle_airplane">true</bool>
@@ -628,9 +631,6 @@
<!-- The extra value for battery tip -->
<integer name="config_battery_extra_tip_value">12</integer>
- <!-- Whether to enable the advanced vpn feature. The default is not to. -->
- <bool name="config_advanced_vpn_enabled">false</bool>
-
<!-- An array of uid name for which packages exempt from Wi-Fi permission check. -->
<string-array name="config_exempt_wifi_permission_uid_name" translatable="false">
<item>@string/config_settingsintelligence_package_name</item>
@@ -639,4 +639,8 @@
<!-- Whether to enable the app battery usage list page feature. -->
<bool name="config_app_battery_usage_list_enabled">false</bool>
+
+ <!-- Whether sim related information is visible to the end user. -->
+ <bool name="config_show_sim_info">true</bool>
+
</resources>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 694fa6d..a847571 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -3365,10 +3365,14 @@
<string name="screensaver_settings_title">Screen saver</string>
<!-- List of synonyms used in the settings search bar to find the “Screen saver”. [CHAR LIMIT=NONE] -->
<string name="keywords_screensaver">screensaver</string>
+ <!-- Summary for screensaver unavailable when Bedtime mode is on [CHAR LIMIT=50] -->
+ <string name="screensaver_settings_when_to_dream_bedtime">Unavailable because bedtime mode is on</string>
<!-- The title for the toggle which disables/enables screen savers [CHAR_LIMIT=30] -->
<string name="screensaver_settings_toggle_title">Use screen saver</string>
<!-- Display settings screen, summary fragment for screen saver options, activated when docked or asleep and charging [CHAR LIMIT=35] -->
<string name="screensaver_settings_summary_either_long">While charging or docked</string>
+ <!-- Display settings screen, summary fragment for screen saver options, actived while docked and charging [CHAR LIMIT=35] -->
+ <string name="screensaver_settings_summary_dock_and_charging">While docked and charging</string>
<!-- Display settings screen, summary fragment for screen saver options, activated when asleep and charging [CHAR LIMIT=35] -->
<string name="screensaver_settings_summary_sleep">While charging</string>
<!-- Display settings screen, summary fragment for screen saver options, activated when docked [CHAR LIMIT=35] -->
@@ -4300,6 +4304,8 @@
<string name="ethernet_tether_checkbox_text">Ethernet tethering</string>
<!-- Ethernet Tethering subtext [CHAR LIMIT=NONE]-->
<string name="ethernet_tethering_subtext" product="default">Share phone\u2019s internet connection via Ethernet</string>
+ <!-- Ethernet Tethering subtext for tablet [CHAR LIMIT=NONE]-->
+ <string name="ethernet_tethering_subtext" product="tablet">Share tablet\u2019s internet connection via Ethernet</string>
<!-- Tethering footer info [CHAR LIMIT=NONE]-->
<string name="tethering_footer_info">Use hotspot and tethering to provide internet to other devices through your mobile data connection. Apps can also create a hotspot to share content with nearby devices.</string>
@@ -8733,9 +8739,12 @@
<!-- Sound: Title for the option managing alarm volume. [CHAR LIMIT=30] -->
<string name="alarm_volume_option_title">Alarm volume</string>
- <!-- Sound: Title for the option managing ring volume. [CHAR LIMIT=30] -->
+ <!-- Sound: Title for the option managing ring & notification volume. [CHAR LIMIT=30] -->
<string name="ring_volume_option_title">Ring & notification volume</string>
+ <!-- Sound: Title for the option managing ring volume. [CHAR LIMIT=30] -->
+ <string name="separate_ring_volume_option_title">Ring volume</string>
+
<!-- Sound: Title for the option managing notification volume. [CHAR LIMIT=30] -->
<string name="notification_volume_option_title">Notification volume</string>
@@ -9894,6 +9903,9 @@
<!-- [CHAR LIMIT=NONE] Text appearing when channel group notifications are off -->
<string name="channel_group_notifications_off_desc">At your request, Android is blocking this group of notifications from appearing on this device</string>
+ <!-- [CHAR LIMIT=NONE] Text appearing when app does not send notifications -->
+ <string name="app_notifications_not_send_desc">This app does not send notifications</string>
+
<!-- [CHAR LIMIT=NONE] App notification settings: channels title -->
<string name="notification_channels">Categories</string>
diff --git a/res/xml/my_device_info.xml b/res/xml/my_device_info.xml
index 9165745..08d3e6c 100644
--- a/res/xml/my_device_info.xml
+++ b/res/xml/my_device_info.xml
@@ -57,6 +57,7 @@
android:order="3"
android:title="@string/status_number"
android:summary="@string/summary_placeholder"
+ settings:isPreferenceVisible="@bool/config_show_sim_info"
settings:controller="com.android.settings.deviceinfo.PhoneNumberPreferenceController"
settings:enableCopying="true"/>
</PreferenceCategory>
@@ -98,6 +99,7 @@
android:title="@string/sim_status_title"
settings:keywords="@string/keywords_sim_status"
android:summary="@string/summary_placeholder"
+ settings:isPreferenceVisible="@bool/config_show_sim_info"
settings:enableCopying="true"/>
<!-- Model & hardware -->
@@ -119,6 +121,7 @@
android:summary="@string/summary_placeholder"
settings:keywords="@string/keywords_imei_info"
settings:enableCopying="true"
+ settings:isPreferenceVisible="@bool/config_show_sim_info"
settings:controller="com.android.settings.deviceinfo.imei.ImeiInfoPreferenceController"/>
<!-- Android version -->
diff --git a/res/xml/network_provider_internet.xml b/res/xml/network_provider_internet.xml
index 07e797a..c9c576e 100644
--- a/res/xml/network_provider_internet.xml
+++ b/res/xml/network_provider_internet.xml
@@ -37,6 +37,7 @@
android:icon="@drawable/ic_calls_sms"
android:order="-20"
android:summary="@string/summary_placeholder"
+ settings:isPreferenceVisible="@bool/config_show_sim_info"
settings:allowDividerBelow="true"
settings:keywords="@string/calls_and_sms"
settings:useAdminDisabledSummary="true" />
@@ -49,6 +50,7 @@
android:order="-15"
settings:keywords="@string/keywords_more_mobile_networks"
settings:userRestriction="no_config_mobile_networks"
+ settings:isPreferenceVisible="@bool/config_show_sim_info"
settings:allowDividerAbove="true"
settings:useAdminDisabledSummary="true" />
@@ -66,6 +68,7 @@
android:persistent="false"
android:order="19"
settings:userRestriction="no_config_mobile_networks"
+ settings:isPreferenceVisible="@bool/config_show_sim_info"
settings:useAdminDisabledSummary="true" />
<com.android.settingslib.RestrictedPreference
diff --git a/res/xml/network_provider_settings.xml b/res/xml/network_provider_settings.xml
index 92eca76..1921ece 100644
--- a/res/xml/network_provider_settings.xml
+++ b/res/xml/network_provider_settings.xml
@@ -46,6 +46,7 @@
android:key="provider_model_mobile_network"
android:title="@string/summary_placeholder"
android:layout="@layout/preference_category_no_label"
+ settings:isPreferenceVisible="@bool/config_show_sim_info"
settings:controller="com.android.settings.network.NetworkMobileProviderController"/>
<com.android.settingslib.RestrictedSwitchPreference
diff --git a/res/xml/reset_dashboard_fragment.xml b/res/xml/reset_dashboard_fragment.xml
index 9497c8f..25161a5 100644
--- a/res/xml/reset_dashboard_fragment.xml
+++ b/res/xml/reset_dashboard_fragment.xml
@@ -37,6 +37,7 @@
<Preference
android:key="erase_euicc_data"
android:title="@string/reset_esim_title"
+ settings:isPreferenceVisible="@bool/config_show_sim_info"
settings:controller="com.android.settings.network.EraseEuiccDataController" />
<!-- Factory reset -->
diff --git a/res/xml/security_advanced_settings.xml b/res/xml/security_advanced_settings.xml
index 6d43fe7..b36fc73 100644
--- a/res/xml/security_advanced_settings.xml
+++ b/res/xml/security_advanced_settings.xml
@@ -64,6 +64,7 @@
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
@@ -103,6 +104,7 @@
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" />
<!-- work profile security section -->
diff --git a/res/xml/sound_settings.xml b/res/xml/sound_settings.xml
index f25b6ec..914ce72 100644
--- a/res/xml/sound_settings.xml
+++ b/res/xml/sound_settings.xml
@@ -72,23 +72,23 @@
android:order="-160"
settings:controller="com.android.settings.notification.RingVolumePreferenceController"/>
+ <!-- Notification volume -->
+ <com.android.settings.notification.VolumeSeekBarPreference
+ android:key="notification_volume"
+ android:icon="@drawable/ic_notifications"
+ android:title="@string/notification_volume_option_title"
+ android:order="-150"
+ settings:controller=
+ "com.android.settings.notification.NotificationVolumePreferenceController"/>
<!-- Alarm volume -->
<com.android.settings.notification.VolumeSeekBarPreference
android:key="alarm_volume"
android:icon="@*android:drawable/ic_audio_alarm"
android:title="@string/alarm_volume_option_title"
- android:order="-150"
- settings:controller="com.android.settings.notification.AlarmVolumePreferenceController"/>
-
- <!-- Notification volume -->
- <com.android.settings.notification.VolumeSeekBarPreference
- android:key="notification_volume"
- android:icon="@drawable/ic_notifications"
- android:title="@string/notification_volume_option_title"
android:order="-140"
- settings:controller="com.android.settings.notification.NotificationVolumePreferenceController"/>
-
+ settings:controller="com.android.settings.notification.AlarmVolumePreferenceController"/>
+x
<!-- TODO(b/174964721): make this a PrimarySwitchPreference -->
<!-- Interruptions -->
<com.android.settingslib.RestrictedPreference
diff --git a/res/xml/vpn_settings2.xml b/res/xml/vpn_settings2.xml
index 0d374c7..08075a6 100644
--- a/res/xml/vpn_settings2.xml
+++ b/res/xml/vpn_settings2.xml
@@ -16,9 +16,4 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
android:title="@string/vpn_title">
- <PreferenceCategory
- android:key="advanced_vpn_group"/>
-
- <PreferenceCategory
- android:key="vpn_group"/>
</PreferenceScreen>
diff --git a/src/com/android/settings/IccLockSettings.java b/src/com/android/settings/IccLockSettings.java
index 71eb0f2..8e54e31 100644
--- a/src/com/android/settings/IccLockSettings.java
+++ b/src/com/android/settings/IccLockSettings.java
@@ -174,8 +174,9 @@
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- if (Utils.isMonkeyRunning()) {
- finish();
+ if (Utils.isMonkeyRunning() ||
+ !SubscriptionUtil.isSimHardwareVisible(getContext())) {
+ finishFragment();
return;
}
diff --git a/src/com/android/settings/MainClear.java b/src/com/android/settings/MainClear.java
index 2b0f010..1434d72 100644
--- a/src/com/android/settings/MainClear.java
+++ b/src/com/android/settings/MainClear.java
@@ -64,6 +64,7 @@
import com.android.settings.core.InstrumentedFragment;
import com.android.settings.enterprise.ActionDisabledByAdminDialogHelper;
+import com.android.settings.network.SubscriptionUtil;
import com.android.settings.password.ChooseLockSettingsHelper;
import com.android.settings.password.ConfirmLockPattern;
import com.android.settingslib.RestrictedLockUtilsInternal;
@@ -382,6 +383,14 @@
}
/**
+ * Whether to show any UI which is SIM related.
+ */
+ @VisibleForTesting
+ boolean showAnySubscriptionInfo(Context context) {
+ return (context != null) && SubscriptionUtil.isSimHardwareVisible(context);
+ }
+
+ /**
* Whether to show strings indicating that the eUICC will be wiped.
*
* <p>We show the strings on any device which supports eUICC as long as the eUICC was ever
@@ -390,7 +399,7 @@
@VisibleForTesting
boolean showWipeEuicc() {
Context context = getContext();
- if (!isEuiccEnabled(context)) {
+ if (!showAnySubscriptionInfo(context) || !isEuiccEnabled(context)) {
return false;
}
ContentResolver cr = context.getContentResolver();
diff --git a/src/com/android/settings/ResetNetwork.java b/src/com/android/settings/ResetNetwork.java
index 7e58c0b..1529a23 100644
--- a/src/com/android/settings/ResetNetwork.java
+++ b/src/com/android/settings/ResetNetwork.java
@@ -239,6 +239,9 @@
}
private List<SubscriptionInfo> getActiveSubscriptionInfoList() {
+ if (!SubscriptionUtil.isSimHardwareVisible(getActivity())) {
+ return Collections.emptyList();
+ }
SubscriptionManager mgr = getActivity().getSystemService(SubscriptionManager.class);
if (mgr == null) {
Log.w(TAG, "No SubscriptionManager");
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index f1c1191..50ffdc7 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -152,6 +152,11 @@
/** Redirects to SafetyCenter if enabled. */
@VisibleForTesting
public void handleSafetyCenterRedirection() {
+ if (isFinishing()) {
+ // Don't trampoline if already exiting this activity.
+ return;
+ }
+
if (SafetyCenterManagerWrapper.get().isEnabled(this)) {
try {
startActivity(new Intent(Intent.ACTION_SAFETY_CENTER));
@@ -213,6 +218,11 @@
/** Redirects to SafetyCenter if enabled. */
@VisibleForTesting
public void handleSafetyCenterRedirection() {
+ if (isFinishing()) {
+ // Don't trampoline if already exiting this activity.
+ return;
+ }
+
if (ACTION_PRIVACY_SETTINGS.equals(getIntent().getAction())
&& SafetyCenterManagerWrapper.get().isEnabled(this)) {
try {
diff --git a/src/com/android/settings/TetherSettings.java b/src/com/android/settings/TetherSettings.java
index f4c9eb2..ffe4593 100644
--- a/src/com/android/settings/TetherSettings.java
+++ b/src/com/android/settings/TetherSettings.java
@@ -20,6 +20,7 @@
import static android.net.ConnectivityManager.TETHERING_USB;
import static android.net.TetheringManager.TETHERING_ETHERNET;
+import static com.android.settings.wifi.WifiUtils.canShowWifiHotspot;
import static com.android.settingslib.RestrictedLockUtilsInternal.checkIfUsbDataSignalingIsDisabled;
import android.app.Activity;
@@ -628,6 +629,9 @@
if (!TetherUtil.isTetherAvailable(context)) {
keys.add(KEY_TETHER_PREFS_SCREEN);
+ }
+
+ if (!canShowWifiHotspot(context) || !TetherUtil.isTetherAvailable(context)) {
keys.add(KEY_WIFI_TETHER);
}
diff --git a/src/com/android/settings/applications/AppStateLocaleBridge.java b/src/com/android/settings/applications/AppStateLocaleBridge.java
index 5600766..8262ce7 100644
--- a/src/com/android/settings/applications/AppStateLocaleBridge.java
+++ b/src/com/android/settings/applications/AppStateLocaleBridge.java
@@ -18,13 +18,19 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
+import android.os.UserHandle;
+import android.os.UserManager;
+import android.util.ArrayMap;
import android.util.Log;
+import com.android.settings.Utils;
import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.applications.ApplicationsState.AppEntry;
import com.android.settingslib.applications.ApplicationsState.AppFilter;
+import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
/**
* Creates a application filter to restrict UI display of applications.
@@ -35,20 +41,22 @@
private static final String TAG = AppStateLocaleBridge.class.getSimpleName();
private final Context mContext;
- private final List<ResolveInfo> mListInfos;
+ private final Map<Integer, AppInfoByProfiles> mUserIdToAppInfoByProfiles = new ArrayMap<>();
public AppStateLocaleBridge(Context context, ApplicationsState appState,
- Callback callback) {
+ Callback callback, UserManager userManager) {
super(appState, callback);
mContext = context;
- mListInfos = context.getPackageManager().queryIntentActivities(
- AppLocaleUtil.LAUNCHER_ENTRY_INTENT, PackageManager.GET_META_DATA);
+ collectLocaleBridgeInfo(userManager);
}
@Override
protected void updateExtraInfo(AppEntry app, String packageName, int uid) {
- app.extraInfo = AppLocaleUtil.canDisplayLocaleUi(mContext, app.info.packageName, mListInfos)
- ? Boolean.TRUE : Boolean.FALSE;
+ AppInfoByProfiles appInfoByProfiles = getAppInfo(UserHandle.getUserId(uid));
+
+ app.extraInfo = AppLocaleUtil.canDisplayLocaleUi(appInfoByProfiles.mContextAsUser,
+ app.info.packageName,
+ appInfoByProfiles.mListInfos) ? Boolean.TRUE : Boolean.FALSE;
}
@Override
@@ -56,9 +64,11 @@
final List<AppEntry> allApps = mAppSession.getAllApps();
for (int i = 0; i < allApps.size(); i++) {
AppEntry app = allApps.get(i);
- app.extraInfo =
- AppLocaleUtil.canDisplayLocaleUi(mContext, app.info.packageName, mListInfos)
- ? Boolean.TRUE : Boolean.FALSE;
+ AppInfoByProfiles appInfoByProfiles = getAppInfo(UserHandle.getUserId(app.info.uid));
+
+ app.extraInfo = AppLocaleUtil.canDisplayLocaleUi(appInfoByProfiles.mContextAsUser,
+ app.info.packageName,
+ appInfoByProfiles.mListInfos) ? Boolean.TRUE : Boolean.FALSE;
}
}
@@ -78,4 +88,47 @@
return (Boolean) entry.extraInfo;
}
};
+
+ private void collectLocaleBridgeInfo(UserManager userManager) {
+ List<Integer> userIds = new ArrayList<>();
+
+ userIds.add(mContext.getUserId());
+ int workUserId = Utils.getManagedProfileId(userManager, mContext.getUserId());
+ if (workUserId != UserHandle.USER_NULL) {
+ userIds.add(workUserId);
+ }
+
+ // Separate the app information by profiles.
+ for (int userId : userIds) {
+ if (!mUserIdToAppInfoByProfiles.containsKey(userId)) {
+ mUserIdToAppInfoByProfiles.put(userId, new AppInfoByProfiles(mContext, userId));
+ }
+ }
+ }
+
+ private AppInfoByProfiles getAppInfo(int userId) {
+ AppInfoByProfiles info;
+ if (mUserIdToAppInfoByProfiles.containsKey(userId)) {
+ info = mUserIdToAppInfoByProfiles.get(userId);
+ } else {
+ info = new AppInfoByProfiles(mContext, userId);
+ mUserIdToAppInfoByProfiles.put(userId, info);
+ }
+
+ return info;
+ }
+
+ /**
+ * The app information by profiles.
+ */
+ private static class AppInfoByProfiles {
+ public final Context mContextAsUser;
+ public final List<ResolveInfo> mListInfos;
+
+ private AppInfoByProfiles(Context context, int userId) {
+ mContextAsUser = context.createContextAsUser(UserHandle.of(userId), 0);
+ mListInfos = mContextAsUser.getPackageManager().queryIntentActivities(
+ AppLocaleUtil.LAUNCHER_ENTRY_INTENT, PackageManager.GET_META_DATA);
+ }
+ }
}
diff --git a/src/com/android/settings/applications/manageapplications/ManageApplications.java b/src/com/android/settings/applications/manageapplications/ManageApplications.java
index 9a4d13c..5ee059e 100644
--- a/src/com/android/settings/applications/manageapplications/ManageApplications.java
+++ b/src/com/android/settings/applications/manageapplications/ManageApplications.java
@@ -1148,7 +1148,8 @@
} else if (mManageApplications.mListType == LIST_TYPE_MEDIA_MANAGEMENT_APPS) {
mExtraInfoBridge = new AppStateMediaManagementAppsBridge(mContext, mState, this);
} else if (mManageApplications.mListType == LIST_TYPE_APPS_LOCALE) {
- mExtraInfoBridge = new AppStateLocaleBridge(mContext, mState, this);
+ mExtraInfoBridge = new AppStateLocaleBridge(mContext, mState, this,
+ mManageApplications.mUserManager);
} else if (mManageApplications.mListType == LIST_TYPE_BATTERY_OPTIMIZATION) {
mExtraInfoBridge = new AppStateAppBatteryUsageBridge(mContext, mState, this);
} else {
diff --git a/src/com/android/settings/biometrics/combination/BiometricsSettingsBase.java b/src/com/android/settings/biometrics/combination/BiometricsSettingsBase.java
index 404fe6d..4da42d4 100644
--- a/src/com/android/settings/biometrics/combination/BiometricsSettingsBase.java
+++ b/src/com/android/settings/biometrics/combination/BiometricsSettingsBase.java
@@ -28,11 +28,13 @@
import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
import android.os.Bundle;
import android.os.UserHandle;
+import android.text.TextUtils;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
+import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import com.android.settings.R;
@@ -50,11 +52,16 @@
*/
public abstract class BiometricsSettingsBase extends DashboardFragment {
- private static final int CONFIRM_REQUEST = 2001;
+ @VisibleForTesting
+ static final int CONFIRM_REQUEST = 2001;
private static final int CHOOSE_LOCK_REQUEST = 2002;
private static final String SAVE_STATE_CONFIRM_CREDETIAL = "confirm_credential";
private static final String DO_NOT_FINISH_ACTIVITY = "do_not_finish_activity";
+ @VisibleForTesting
+ static final String RETRY_PREFERENCE_KEY = "retry_preference_key";
+ @VisibleForTesting
+ static final String RETRY_PREFERENCE_BUNDLE = "retry_preference_bundle";
protected int mUserId;
protected long mGkPwHandle;
@@ -63,6 +70,8 @@
@Nullable private FingerprintManager mFingerprintManager;
// Do not finish() if choosing/confirming credential, or showing fp/face settings
private boolean mDoNotFinishActivity;
+ @Nullable private String mRetryPreferenceKey = null;
+ @Nullable private Bundle mRetryPreferenceExtra = null;
@Override
public void onAttach(Context context) {
@@ -84,6 +93,8 @@
if (savedInstanceState != null) {
mConfirmCredential = savedInstanceState.getBoolean(SAVE_STATE_CONFIRM_CREDETIAL);
mDoNotFinishActivity = savedInstanceState.getBoolean(DO_NOT_FINISH_ACTIVITY);
+ mRetryPreferenceKey = savedInstanceState.getString(RETRY_PREFERENCE_KEY);
+ mRetryPreferenceExtra = savedInstanceState.getBundle(RETRY_PREFERENCE_BUNDLE);
if (savedInstanceState.containsKey(
ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE)) {
mGkPwHandle = savedInstanceState.getLong(
@@ -124,8 +135,7 @@
}
}
- @Override
- public boolean onPreferenceTreeClick(Preference preference) {
+ private boolean onRetryPreferenceTreeClick(Preference preference, final boolean retry) {
final String key = preference.getKey();
final Context context = requireActivity().getApplicationContext();
@@ -134,31 +144,77 @@
if (getFacePreferenceKey().equals(key)) {
mDoNotFinishActivity = true;
mFaceManager.generateChallenge(mUserId, (sensorId, userId, challenge) -> {
- final byte[] token = BiometricUtils.requestGatekeeperHat(context, mGkPwHandle,
- mUserId, challenge);
- final Bundle extras = preference.getExtras();
- extras.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
- extras.putInt(BiometricEnrollBase.EXTRA_KEY_SENSOR_ID, sensorId);
- extras.putLong(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, challenge);
- super.onPreferenceTreeClick(preference);
+ try {
+ final byte[] token = requestGatekeeperHat(context, mGkPwHandle, mUserId,
+ challenge);
+ final Bundle extras = preference.getExtras();
+ extras.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
+ extras.putInt(BiometricEnrollBase.EXTRA_KEY_SENSOR_ID, sensorId);
+ extras.putLong(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, challenge);
+ super.onPreferenceTreeClick(preference);
+ } catch (IllegalStateException e) {
+ if (retry) {
+ mRetryPreferenceKey = preference.getKey();
+ mRetryPreferenceExtra = preference.getExtras();
+ mConfirmCredential = true;
+ launchChooseOrConfirmLock();
+ } else {
+ Log.e(getLogTag(), "face generateChallenge fail", e);
+ mDoNotFinishActivity = false;
+ }
+ }
});
-
return true;
} else if (getFingerprintPreferenceKey().equals(key)) {
mDoNotFinishActivity = true;
mFingerprintManager.generateChallenge(mUserId, (sensorId, userId, challenge) -> {
- final byte[] token = BiometricUtils.requestGatekeeperHat(context, mGkPwHandle,
- mUserId, challenge);
- final Bundle extras = preference.getExtras();
- extras.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
- extras.putLong(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, challenge);
- super.onPreferenceTreeClick(preference);
+ try {
+ final byte[] token = requestGatekeeperHat(context, mGkPwHandle, mUserId,
+ challenge);
+ final Bundle extras = preference.getExtras();
+ extras.putByteArray(ChooseLockSettingsHelper.EXTRA_KEY_CHALLENGE_TOKEN, token);
+ extras.putLong(BiometricEnrollBase.EXTRA_KEY_CHALLENGE, challenge);
+ super.onPreferenceTreeClick(preference);
+ } catch (IllegalStateException e) {
+ if (retry) {
+ mRetryPreferenceKey = preference.getKey();
+ mRetryPreferenceExtra = preference.getExtras();
+ mConfirmCredential = true;
+ launchChooseOrConfirmLock();
+ } else {
+ Log.e(getLogTag(), "fingerprint generateChallenge fail", e);
+ mDoNotFinishActivity = false;
+ }
+ }
});
-
return true;
}
+ return false;
+ }
- return super.onPreferenceTreeClick(preference);
+ @VisibleForTesting
+ protected byte[] requestGatekeeperHat(@NonNull Context context, long gkPwHandle, int userId,
+ long challenge) {
+ return BiometricUtils.requestGatekeeperHat(context, gkPwHandle, userId, challenge);
+ }
+
+ @Override
+ public boolean onPreferenceTreeClick(Preference preference) {
+ return onRetryPreferenceTreeClick(preference, true)
+ || super.onPreferenceTreeClick(preference);
+ }
+
+ private void retryPreferenceKey(@NonNull String key, @Nullable Bundle extras) {
+ final Preference preference = findPreference(key);
+ if (preference == null) {
+ Log.w(getLogTag(), ".retryPreferenceKey, fail to find " + key);
+ return;
+ }
+
+ if (extras != null) {
+ preference.getExtras().putAll(extras);
+ }
+ onRetryPreferenceTreeClick(preference, false);
}
@Override
@@ -169,6 +225,10 @@
if (mGkPwHandle != 0L) {
outState.putLong(ChooseLockSettingsHelper.EXTRA_KEY_REQUEST_GK_PW_HANDLE, mGkPwHandle);
}
+ if (!TextUtils.isEmpty(mRetryPreferenceKey)) {
+ outState.putString(RETRY_PREFERENCE_KEY, mRetryPreferenceKey);
+ outState.putBundle(RETRY_PREFERENCE_BUNDLE, mRetryPreferenceExtra);
+ }
}
@Override
@@ -180,6 +240,11 @@
if (resultCode == RESULT_FINISHED || resultCode == RESULT_OK) {
if (BiometricUtils.containsGatekeeperPasswordHandle(data)) {
mGkPwHandle = BiometricUtils.getGatekeeperPasswordHandle(data);
+ if (!TextUtils.isEmpty(mRetryPreferenceKey)) {
+ getActivity().overridePendingTransition(R.anim.sud_slide_next_in,
+ R.anim.sud_slide_next_out);
+ retryPreferenceKey(mRetryPreferenceKey, mRetryPreferenceExtra);
+ }
} else {
Log.d(getLogTag(), "Data null or GK PW missing.");
finish();
@@ -188,6 +253,8 @@
Log.d(getLogTag(), "Password not confirmed.");
finish();
}
+ mRetryPreferenceKey = null;
+ mRetryPreferenceExtra = null;
}
}
@@ -211,7 +278,8 @@
*/
public abstract String getUseInAppsPreferenceKey();
- private void launchChooseOrConfirmLock() {
+ @VisibleForTesting
+ protected void launchChooseOrConfirmLock() {
final ChooseLockSettingsHelper.Builder builder =
new ChooseLockSettingsHelper.Builder(getActivity(), this)
.setRequestCode(CONFIRM_REQUEST)
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
index c107998..9b5f549 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrolling.java
@@ -168,7 +168,8 @@
private Vibrator mVibrator;
private boolean mIsSetupWizard;
private boolean mIsOrientationChanged;
- private boolean mIsCanceled;
+ @VisibleForTesting
+ boolean mIsCanceled;
private AccessibilityManager mAccessibilityManager;
private boolean mIsAccessibilityEnabled;
private LottieAnimationView mIllustrationLottie;
@@ -196,7 +197,7 @@
@Override
public void onWindowFocusChanged(boolean hasFocus) {
- if (hasFocus) {
+ if (hasFocus || mIsCanceled) {
return;
}
@@ -411,8 +412,10 @@
@VisibleForTesting
void onCancelEnrollment(@IdRes int errorMsgId) {
- FingerprintErrorDialog.showErrorDialog(this, errorMsgId);
+ // showErrorDialog() will cause onWindowFocusChanged(false), set mIsCanceled to false
+ // before showErrorDialog() to prevent that another error dialog is triggered again.
mIsCanceled = true;
+ FingerprintErrorDialog.showErrorDialog(this, errorMsgId);
mIsOrientationChanged = false;
cancelEnrollment();
stopIconAnimation();
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java
index d8ecd20..d1e512e 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollSidecar.java
@@ -21,9 +21,14 @@
import android.hardware.fingerprint.FingerprintManager;
import android.util.Log;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.biometrics.BiometricEnrollSidecar;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
/**
* Sidecar fragment to handle the state around fingerprint enrollment.
*/
@@ -32,11 +37,19 @@
private FingerprintUpdater mFingerprintUpdater;
private @FingerprintManager.EnrollReason int mEnrollReason;
+ private Set<Integer> mHelpIgnore;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mFingerprintUpdater = new FingerprintUpdater(activity);
+ final int[] ignoreAcquiredInfo = getResources().getIntArray(
+ R.array.fingerprint_acquired_ignore_list);
+ mHelpIgnore = new HashSet<>();
+ for (int acquiredInfo: ignoreAcquiredInfo) {
+ mHelpIgnore.add(acquiredInfo);
+ }
+ mHelpIgnore = Collections.unmodifiableSet(mHelpIgnore);
}
@Override
@@ -49,7 +62,6 @@
getString(R.string.fingerprint_intro_error_unknown));
return;
}
-
mFingerprintUpdater.enroll(mToken, mEnrollmentCancel, mUserId, mEnrollmentCallback,
mEnrollReason);
}
@@ -58,7 +70,7 @@
mEnrollReason = enrollReason;
}
- private FingerprintManager.EnrollmentCallback mEnrollmentCallback
+ @VisibleForTesting FingerprintManager.EnrollmentCallback mEnrollmentCallback
= new FingerprintManager.EnrollmentCallback() {
@Override
@@ -68,6 +80,9 @@
@Override
public void onEnrollmentHelp(int helpMsgId, CharSequence helpString) {
+ if (mHelpIgnore.contains(helpMsgId)) {
+ return;
+ }
FingerprintEnrollSidecar.super.onEnrollmentHelp(helpMsgId, helpString);
}
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintErrorDialog.java b/src/com/android/settings/biometrics/fingerprint/FingerprintErrorDialog.java
index 9f9efdc..39d35dc 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintErrorDialog.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintErrorDialog.java
@@ -72,6 +72,7 @@
dialog.dismiss();
Activity activity = getActivity();
Intent intent = activity.getIntent();
+ intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
intent.putExtra(KEY_STATE_CANCELED, false);
activity.startActivity(intent);
activity.finish();
diff --git a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
index 44b3a40..c031fe6 100644
--- a/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
+++ b/src/com/android/settings/biometrics/fingerprint/FingerprintSettings.java
@@ -669,6 +669,14 @@
mLaunchedConfirm = false;
if (resultCode == RESULT_FINISHED || resultCode == RESULT_OK) {
if (data != null && BiometricUtils.containsGatekeeperPasswordHandle(data)) {
+ if (!mHasFirstEnrolled && !mIsEnrolling) {
+ final Activity activity = getActivity();
+ if (activity != null) {
+ // Apply pending transition for auto adding first fingerprint case
+ activity.overridePendingTransition(R.anim.sud_slide_next_in,
+ R.anim.sud_slide_next_out);
+ }
+ }
mFingerprintManager.generateChallenge(mUserId,
(sensorId, userId, challenge) -> {
mToken = BiometricUtils.requestGatekeeperHat(getActivity(),
diff --git a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
index c643842..a86b758 100644
--- a/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
+++ b/src/com/android/settings/bluetooth/BluetoothDetailsProfilesController.java
@@ -341,7 +341,7 @@
/**
* When user disable the Le Audio profile, the system needs to do two things.
- * 1) Disable the Le Audio profile for each of the Le Audio devices.
+ * 1) Disable the Le Audio profile, VCP and CSIP for each of the Le Audio devices.
* 2) Enable the A2dp profile and Headset profile for the associated device. The system
* can't enable the A2dp profile and Headset profile if the Le Audio profile is enabled.
*
@@ -352,14 +352,23 @@
Log.e(TAG, "There is no the LE profile or no device in mProfileDeviceMap. Do nothing.");
return;
}
+ LocalBluetoothProfile vcp = mProfileManager.getVolumeControlProfile();
+ LocalBluetoothProfile csip = mProfileManager.getCsipSetCoordinatorProfile();
+ LocalBluetoothProfile a2dp = mProfileManager.getA2dpProfile();
+ LocalBluetoothProfile headset = mProfileManager.getHeadsetProfile();
+
for (CachedBluetoothDevice leAudioDevice : mProfileDeviceMap.get(profile.toString())) {
Log.d(TAG,
"User disable LE device: " + leAudioDevice.getDevice().getAnonymizedAddress());
profile.setEnabled(leAudioDevice.getDevice(), false);
+ if (vcp != null) {
+ vcp.setEnabled(leAudioDevice.getDevice(), false);
+ }
+ if (csip != null) {
+ csip.setEnabled(leAudioDevice.getDevice(), false);
+ }
}
- LocalBluetoothProfile a2dp = mProfileManager.getA2dpProfile();
- LocalBluetoothProfile headset = mProfileManager.getHeadsetProfile();
enableProfileAfterUserDisablesLeAudio(a2dp);
enableProfileAfterUserDisablesLeAudio(headset);
}
@@ -368,7 +377,7 @@
* When user enable the Le Audio profile, the system needs to do two things.
* 1) Disable the A2dp profile and Headset profile for the associated device. The system
* can't enable the Le Audio if the A2dp profile and Headset profile are enabled.
- * 2) Enable the Le Audio profile for each of the Le Audio devices.
+ * 2) Enable the Le Audio profile, VCP and CSIP for each of the Le Audio devices.
*
* @param profile the LeAudio profile
*/
@@ -379,6 +388,9 @@
}
LocalBluetoothProfile a2dp = mProfileManager.getA2dpProfile();
LocalBluetoothProfile headset = mProfileManager.getHeadsetProfile();
+ LocalBluetoothProfile vcp = mProfileManager.getVolumeControlProfile();
+ LocalBluetoothProfile csip = mProfileManager.getCsipSetCoordinatorProfile();
+
disableProfileBeforeUserEnablesLeAudio(a2dp);
disableProfileBeforeUserEnablesLeAudio(headset);
@@ -386,6 +398,12 @@
Log.d(TAG,
"User enable LE device: " + leAudioDevice.getDevice().getAnonymizedAddress());
profile.setEnabled(leAudioDevice.getDevice(), true);
+ if (vcp != null) {
+ vcp.setEnabled(leAudioDevice.getDevice(), true);
+ }
+ if (csip != null) {
+ csip.setEnabled(leAudioDevice.getDevice(), true);
+ }
}
}
diff --git a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
index 999e34d..fa15b5c 100644
--- a/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
+++ b/src/com/android/settings/bluetooth/BluetoothDeviceDetailsFragment.java
@@ -153,8 +153,11 @@
controlUri = null;
}
}
- use(SlicePreferenceController.class).setSliceUri(sliceEnabled ? controlUri : null);
- use(SlicePreferenceController.class).onStart();
+ final SlicePreferenceController slicePreferenceController = use(
+ SlicePreferenceController.class);
+ slicePreferenceController.setSliceUri(sliceEnabled ? controlUri : null);
+ slicePreferenceController.onStart();
+ slicePreferenceController.displayPreference(getPreferenceScreen());
}
private final ViewTreeObserver.OnGlobalLayoutListener mOnGlobalLayoutListener =
diff --git a/src/com/android/settings/bluetooth/BluetoothPairingRequest.java b/src/com/android/settings/bluetooth/BluetoothPairingRequest.java
index d5de41a..ed7a1fc 100644
--- a/src/com/android/settings/bluetooth/BluetoothPairingRequest.java
+++ b/src/com/android/settings/bluetooth/BluetoothPairingRequest.java
@@ -87,9 +87,7 @@
return;
}
- if (mBluetoothManager.getCachedDeviceManager().shouldPairByCsip(device, groupId)) {
- device.createBond(BluetoothDevice.TRANSPORT_LE);
- }
+ mBluetoothManager.getCachedDeviceManager().pairDeviceByCsip(device, groupId);
}
}
}
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index d92fb7f..70fbefc 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -60,6 +60,7 @@
import com.android.settings.development.bluetooth.BluetoothSampleRateDialogPreferenceController;
import com.android.settings.development.qstile.DevelopmentTiles;
import com.android.settings.development.storage.SharedDataPreferenceController;
+import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.actionbar.SearchMenuController;
import com.android.settings.widget.SettingsMainSwitchBar;
@@ -308,6 +309,8 @@
DisableDevSettingsDialogFragment.show(this /* host */);
}
}
+ FeatureFactory.getFactory(
+ getContext()).getSearchFeatureProvider().sendPreIndexIntent(getContext());
}
}
@@ -369,12 +372,12 @@
final BluetoothLeAudioHwOffloadPreferenceController leAudioController =
getDevelopmentOptionsController(
- BluetoothLeAudioHwOffloadPreferenceController.class);
+ BluetoothLeAudioHwOffloadPreferenceController.class);
leAudioController.onRebootDialogConfirmed();
final BluetoothLeAudioPreferenceController leAudioFeatureController =
getDevelopmentOptionsController(
- BluetoothLeAudioPreferenceController.class);
+ BluetoothLeAudioPreferenceController.class);
leAudioFeatureController.onRebootDialogConfirmed();
}
@@ -386,12 +389,12 @@
final BluetoothLeAudioHwOffloadPreferenceController leAudioController =
getDevelopmentOptionsController(
- BluetoothLeAudioHwOffloadPreferenceController.class);
+ BluetoothLeAudioHwOffloadPreferenceController.class);
leAudioController.onRebootDialogCanceled();
final BluetoothLeAudioPreferenceController leAudioFeatureController =
getDevelopmentOptionsController(
- BluetoothLeAudioPreferenceController.class);
+ BluetoothLeAudioPreferenceController.class);
leAudioFeatureController.onRebootDialogCanceled();
}
diff --git a/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java b/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java
index 7ddca79..6af58b5 100644
--- a/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/BuildNumberPreferenceController.java
@@ -240,6 +240,8 @@
mDevHitToast = Toast.makeText(mContext, R.string.show_dev_on,
Toast.LENGTH_LONG);
mDevHitToast.show();
+
+ FeatureFactory.getFactory(mContext).getSearchFeatureProvider().sendPreIndexIntent(mContext);
}
@VisibleForTesting
diff --git a/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java b/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
index eb8add5..f91b98f 100644
--- a/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/PhoneNumberPreferenceController.java
@@ -29,6 +29,7 @@
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;
@@ -51,7 +52,8 @@
@Override
public int getAvailabilityStatus() {
- return mTelephonyManager.isVoiceCapable() ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
+ return SubscriptionUtil.isSimHardwareVisible(mContext) ?
+ AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
@Override
@@ -79,6 +81,9 @@
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
+ if (!SubscriptionUtil.isSimHardwareVisible(mContext)) {
+ return;
+ }
final Preference preference = screen.findPreference(getPreferenceKey());
final PreferenceCategory category = screen.findPreference(KEY_PREFERENCE_CATEGORY);
mPreferenceList.add(preference);
diff --git a/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceController.java b/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceController.java
index e904772..9b7359b 100644
--- a/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceController.java
@@ -33,6 +33,7 @@
import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import com.android.settings.deviceinfo.PhoneNumberSummaryPreference;
+import com.android.settings.network.SubscriptionUtil;
import com.android.settingslib.Utils;
import java.util.ArrayList;
@@ -63,6 +64,9 @@
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
+ if (!SubscriptionUtil.isSimHardwareVisible(mContext)) {
+ return;
+ }
final Preference preference = screen.findPreference(getPreferenceKey());
final PreferenceCategory category = screen.findPreference(KEY_PREFERENCE_CATEGORY);
@@ -119,7 +123,8 @@
@Override
public int getAvailabilityStatus() {
- return mContext.getSystemService(UserManager.class).isAdminUser()
+ return SubscriptionUtil.isSimHardwareVisible(mContext) &&
+ mContext.getSystemService(UserManager.class).isAdminUser()
&& !Utils.isWifiOnly(mContext) ? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
diff --git a/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceController.java b/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceController.java
index e392bd6..f811d2a 100644
--- a/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceController.java
@@ -29,6 +29,7 @@
import com.android.settings.R;
import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.network.SubscriptionUtil;
import com.android.settingslib.deviceinfo.AbstractSimStatusImeiInfoPreferenceController;
import java.util.ArrayList;
@@ -60,8 +61,17 @@
}
@Override
+ public boolean isAvailable() {
+ return SubscriptionUtil.isSimHardwareVisible(mContext) &&
+ super.isAvailable();
+ }
+
+ @Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
+ if (!SubscriptionUtil.isSimHardwareVisible(mContext)) {
+ return;
+ }
final Preference preference = screen.findPreference(getPreferenceKey());
if (!isAvailable() || preference == null || !preference.isVisible()) {
return;
diff --git a/src/com/android/settings/display/ScreenSaverPreferenceController.java b/src/com/android/settings/display/ScreenSaverPreferenceController.java
index 676a567..de1aaea 100644
--- a/src/com/android/settings/display/ScreenSaverPreferenceController.java
+++ b/src/com/android/settings/display/ScreenSaverPreferenceController.java
@@ -18,6 +18,7 @@
import androidx.preference.Preference;
+import com.android.settings.R;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.dream.DreamSettings;
import com.android.settingslib.core.AbstractPreferenceController;
@@ -26,9 +27,12 @@
PreferenceControllerMixin {
private static final String KEY_SCREEN_SAVER = "screensaver";
+ private final boolean mDreamsDisabledByAmbientModeSuppression;
public ScreenSaverPreferenceController(Context context) {
super(context);
+ mDreamsDisabledByAmbientModeSuppression = context.getResources().getBoolean(
+ com.android.internal.R.bool.config_dreamsDisabledByAmbientModeSuppressionConfig);
}
@Override
@@ -47,7 +51,12 @@
@Override
public void updateState(Preference preference) {
- preference.setSummary(DreamSettings.getSummaryTextWithDreamName(mContext));
+ if (mDreamsDisabledByAmbientModeSuppression
+ && AmbientDisplayAlwaysOnPreferenceController.isAodSuppressedByBedtime(mContext)) {
+ preference.setSummary(R.string.screensaver_settings_when_to_dream_bedtime);
+ } else {
+ preference.setSummary(DreamSettings.getSummaryTextWithDreamName(mContext));
+ }
}
private boolean isSystemUser() {
diff --git a/src/com/android/settings/dream/DreamSettings.java b/src/com/android/settings/dream/DreamSettings.java
index 1d12c1a..580211a 100644
--- a/src/com/android/settings/dream/DreamSettings.java
+++ b/src/com/android/settings/dream/DreamSettings.java
@@ -90,12 +90,14 @@
}
}
- static int getDreamSettingDescriptionResId(@WhenToDream int dreamSetting) {
+ static int getDreamSettingDescriptionResId(@WhenToDream int dreamSetting,
+ boolean enabledOnBattery) {
switch (dreamSetting) {
case WHILE_CHARGING:
return R.string.screensaver_settings_summary_sleep;
case WHILE_DOCKED:
- return R.string.screensaver_settings_summary_dock;
+ return enabledOnBattery ? R.string.screensaver_settings_summary_dock
+ : R.string.screensaver_settings_summary_dock_and_charging;
case EITHER:
return R.string.screensaver_settings_summary_either_long;
case NEVER:
diff --git a/src/com/android/settings/dream/WhenToDreamPicker.java b/src/com/android/settings/dream/WhenToDreamPicker.java
index 1c5e25e..13cdadf 100644
--- a/src/com/android/settings/dream/WhenToDreamPicker.java
+++ b/src/com/android/settings/dream/WhenToDreamPicker.java
@@ -32,12 +32,15 @@
private static final String TAG = "WhenToDreamPicker";
private DreamBackend mBackend;
+ private boolean mDreamsSupportedOnBattery;
@Override
public void onAttach(Context context) {
super.onAttach(context);
mBackend = DreamBackend.getInstance(context);
+ mDreamsSupportedOnBattery = getResources().getBoolean(
+ com.android.internal.R.bool.config_dreamsEnabledOnBattery);
}
@Override
@@ -69,11 +72,17 @@
}
private String[] entries() {
- return getResources().getStringArray(R.array.when_to_start_screensaver_entries);
+ if (mDreamsSupportedOnBattery) {
+ return getResources().getStringArray(R.array.when_to_start_screensaver_entries);
+ }
+ return getResources().getStringArray(R.array.when_to_start_screensaver_entries_no_battery);
}
private String[] keys() {
- return getResources().getStringArray(R.array.when_to_start_screensaver_values);
+ if (mDreamsSupportedOnBattery) {
+ return getResources().getStringArray(R.array.when_to_start_screensaver_values);
+ }
+ return getResources().getStringArray(R.array.when_to_start_screensaver_values_no_battery);
}
@Override
diff --git a/src/com/android/settings/dream/WhenToDreamPreferenceController.java b/src/com/android/settings/dream/WhenToDreamPreferenceController.java
index 4108e85..c3bae00 100644
--- a/src/com/android/settings/dream/WhenToDreamPreferenceController.java
+++ b/src/com/android/settings/dream/WhenToDreamPreferenceController.java
@@ -20,7 +20,10 @@
import androidx.preference.Preference;
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.settings.R;
import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.display.AmbientDisplayAlwaysOnPreferenceController;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.dream.DreamBackend;
@@ -29,19 +32,39 @@
private static final String WHEN_TO_START = "when_to_start";
private final DreamBackend mBackend;
+ private final boolean mDreamsDisabledByAmbientModeSuppression;
+ private final boolean mDreamsEnabledOnBattery;
WhenToDreamPreferenceController(Context context) {
+ this(context, context.getResources().getBoolean(
+ com.android.internal.R.bool.config_dreamsDisabledByAmbientModeSuppressionConfig),
+ context.getResources().getBoolean(
+ com.android.internal.R.bool.config_dreamsEnabledOnBattery));
+ }
+
+ @VisibleForTesting
+ WhenToDreamPreferenceController(Context context,
+ boolean dreamsDisabledByAmbientModeSuppression,
+ boolean dreamsEnabledOnBattery) {
super(context);
mBackend = DreamBackend.getInstance(context);
+ mDreamsDisabledByAmbientModeSuppression = dreamsDisabledByAmbientModeSuppression;
+ mDreamsEnabledOnBattery = dreamsEnabledOnBattery;
}
@Override
public void updateState(Preference preference) {
super.updateState(preference);
- int resId = DreamSettings.getDreamSettingDescriptionResId(mBackend.getWhenToDreamSetting());
- preference.setSummary(preference.getContext().getString(resId));
+ if (mDreamsDisabledByAmbientModeSuppression
+ && AmbientDisplayAlwaysOnPreferenceController.isAodSuppressedByBedtime(mContext)) {
+ preference.setSummary(R.string.screensaver_settings_when_to_dream_bedtime);
+ } else {
+ final int resId = DreamSettings.getDreamSettingDescriptionResId(
+ mBackend.getWhenToDreamSetting(), mDreamsEnabledOnBattery);
+ preference.setSummary(resId);
+ }
}
@Override
diff --git a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
index 2c92488..56da0f4 100644
--- a/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
+++ b/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceController.java
@@ -108,6 +108,7 @@
private boolean mIs24HourFormat;
private boolean mIsFooterPrefAdded = false;
+ private boolean mHourlyChartVisible = true;
private View mBatteryChartViewGroup;
private View mCategoryTitleView;
private PreferenceScreen mPreferenceScreen;
@@ -690,9 +691,10 @@
}
private void animateBatteryHourlyChartView(final boolean visible) {
- if (mHourlyChartView == null) {
+ if (mHourlyChartView == null || mHourlyChartVisible == visible) {
return;
}
+ mHourlyChartVisible = visible;
if (visible) {
mHourlyChartView.setVisibility(View.VISIBLE);
diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java
index 8e14c5a..5c89fb3 100644
--- a/src/com/android/settings/homepage/SettingsHomepageActivity.java
+++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java
@@ -65,6 +65,7 @@
import com.android.settings.core.FeatureFlags;
import com.android.settings.homepage.contextualcards.ContextualCardsFragment;
import com.android.settings.overlay.FeatureFactory;
+import com.android.settings.safetycenter.SafetyCenterManagerWrapper;
import com.android.settingslib.Utils;
import com.android.settingslib.core.lifecycle.HideNonSystemOverlayMixin;
@@ -479,12 +480,28 @@
final String menuKey = intent.getStringExtra(
EXTRA_SETTINGS_EMBEDDED_DEEP_LINK_HIGHLIGHT_MENU_KEY);
if (!TextUtils.isEmpty(menuKey)) {
- return menuKey;
+ return maybeRemapMenuKey(menuKey);
}
}
return getString(DEFAULT_HIGHLIGHT_MENU_KEY);
}
+ private String maybeRemapMenuKey(String menuKey) {
+ boolean isPrivacyOrSecurityMenuKey =
+ getString(R.string.menu_key_privacy).equals(menuKey)
+ || getString(R.string.menu_key_security).equals(menuKey);
+ boolean isSafetyCenterMenuKey = getString(R.string.menu_key_safety_center).equals(menuKey);
+
+ if (isPrivacyOrSecurityMenuKey && SafetyCenterManagerWrapper.get().isEnabled(this)) {
+ return getString(R.string.menu_key_safety_center);
+ }
+ if (isSafetyCenterMenuKey && !SafetyCenterManagerWrapper.get().isEnabled(this)) {
+ // We don't know if security or privacy, default to security as it is above.
+ return getString(R.string.menu_key_security);
+ }
+ return menuKey;
+ }
+
private void reloadHighlightMenuKey() {
mMainFragment.getArguments().putString(SettingsActivity.EXTRA_FRAGMENT_ARG_KEY,
getHighlightMenuKey());
diff --git a/src/com/android/settings/homepage/TopLevelSettings.java b/src/com/android/settings/homepage/TopLevelSettings.java
index 70530fc..8c122ef 100644
--- a/src/com/android/settings/homepage/TopLevelSettings.java
+++ b/src/com/android/settings/homepage/TopLevelSettings.java
@@ -43,6 +43,7 @@
import com.android.settings.activityembedding.ActivityEmbeddingUtils;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.support.SupportPreferenceController;
import com.android.settings.widget.HomepagePreference;
@@ -157,6 +158,8 @@
public void onStart() {
if (mFirstStarted) {
mFirstStarted = false;
+ FeatureFactory.getFactory(getContext()).getSearchFeatureProvider().sendPreIndexIntent(
+ getContext());
} else if (mIsEmbeddingActivityEnabled && isOnlyOneActivityInTask()
&& !SplitController.getInstance().isActivityEmbedded(getActivity())) {
// Set default highlight menu key for 1-pane homepage since it will show the placeholder
@@ -346,7 +349,9 @@
}
private interface PreferenceJob {
- default void init() {}
+ default void init() {
+ }
+
void doForEach(Preference preference);
}
diff --git a/src/com/android/settings/media/MediaOutputIndicatorWorker.java b/src/com/android/settings/media/MediaOutputIndicatorWorker.java
index 09e0672..bf1e06e 100644
--- a/src/com/android/settings/media/MediaOutputIndicatorWorker.java
+++ b/src/com/android/settings/media/MediaOutputIndicatorWorker.java
@@ -165,6 +165,13 @@
return mPackageName;
}
+ /** Check if this device supports LE Audio Broadcast feature */
+ public boolean isBroadcastSupported() {
+ LocalBluetoothLeBroadcast broadcast =
+ mLocalBluetoothManager.getProfileManager().getLeAudioBroadcastProfile();
+ return broadcast != null ? true : false;
+ }
+
public boolean isDeviceBroadcasting() {
LocalBluetoothLeBroadcast broadcast =
mLocalBluetoothManager.getProfileManager().getLeAudioBroadcastProfile();
diff --git a/src/com/android/settings/media/MediaOutputUtils.java b/src/com/android/settings/media/MediaOutputUtils.java
index 977c517..fcb2fb2 100644
--- a/src/com/android/settings/media/MediaOutputUtils.java
+++ b/src/com/android/settings/media/MediaOutputUtils.java
@@ -64,7 +64,9 @@
+ ", play back type : " + pi.getPlaybackType() + ", play back state : "
+ playbackState.getState());
}
- if (playbackState.getState() != PlaybackState.STATE_PLAYING) {
+ if (playbackState.getState() == PlaybackState.STATE_STOPPED
+ || playbackState.getState() == PlaybackState.STATE_NONE
+ || playbackState.getState() == PlaybackState.STATE_ERROR) {
// do nothing
continue;
}
diff --git a/src/com/android/settings/network/CarrierConfigChangedReceiver.java b/src/com/android/settings/network/CarrierConfigChangedReceiver.java
index 8a6d47d..d9ff03e 100644
--- a/src/com/android/settings/network/CarrierConfigChangedReceiver.java
+++ b/src/com/android/settings/network/CarrierConfigChangedReceiver.java
@@ -32,9 +32,20 @@
CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED;
private final CountDownLatch mLatch;
+ private final boolean mIsWaitingForValidSubId;
- public CarrierConfigChangedReceiver(CountDownLatch latch) {
+ /**
+ * This is the CarrierConfigChanged receiver. If it receives the carrier config changed, then it
+ * call the CountDownLatch.countDown().
+ * If the "isWaitingForValidSubId" is true, then the receiver skip the carrier config changed
+ * with the subId = -1. The receiver executes the countDown when the CarrierConfigChanged
+ * with valid subId.
+ * If the "isWaitingForValidSubId" is false, then the receiver executes the countDown when
+ * receiving any CarrierConfigChanged.
+ */
+ public CarrierConfigChangedReceiver(CountDownLatch latch, boolean isWaitingForValidSubId) {
mLatch = latch;
+ mIsWaitingForValidSubId = isWaitingForValidSubId;
}
public void registerOn(Context context) {
@@ -53,7 +64,8 @@
}
private void checkSubscriptionIndex(Intent intent) {
- if (intent.hasExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX)) {
+ if (intent.hasExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX)
+ || !mIsWaitingForValidSubId) {
int subId = intent.getIntExtra(CarrierConfigManager.EXTRA_SUBSCRIPTION_INDEX, -1);
Log.i(TAG, "subId from config changed: " + subId);
mLatch.countDown();
diff --git a/src/com/android/settings/network/EraseEuiccDataController.java b/src/com/android/settings/network/EraseEuiccDataController.java
index b1f964b..091b6d7 100644
--- a/src/com/android/settings/network/EraseEuiccDataController.java
+++ b/src/com/android/settings/network/EraseEuiccDataController.java
@@ -51,7 +51,8 @@
@Override
public int getAvailabilityStatus() {
- return mContext.getPackageManager().hasSystemFeature(
+ return SubscriptionUtil.isSimHardwareVisible(mContext) &&
+ mContext.getPackageManager().hasSystemFeature(
PackageManager.FEATURE_TELEPHONY_EUICC) ? AVAILABLE_UNSEARCHABLE
: UNSUPPORTED_ON_DEVICE;
}
diff --git a/src/com/android/settings/network/MobileNetworkListFragment.java b/src/com/android/settings/network/MobileNetworkListFragment.java
index 7881690..ea7031a 100644
--- a/src/com/android/settings/network/MobileNetworkListFragment.java
+++ b/src/com/android/settings/network/MobileNetworkListFragment.java
@@ -60,6 +60,10 @@
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
final List<AbstractPreferenceController> controllers = new ArrayList<>();
+ if (!SubscriptionUtil.isSimHardwareVisible(getContext())) {
+ finish();
+ return controllers;
+ }
NetworkProviderSimsCategoryController simCategoryPrefCtrl =
new NetworkProviderSimsCategoryController(context, KEY_PREFERENCE_CATEGORY_SIM,
@@ -88,7 +92,8 @@
@Override
protected boolean isPageSearchEnabled(Context context) {
- return context.getSystemService(UserManager.class).isAdminUser();
+ return SubscriptionUtil.isSimHardwareVisible(context) &&
+ context.getSystemService(UserManager.class).isAdminUser();
}
};
}
diff --git a/src/com/android/settings/network/MobileNetworkSummaryController.java b/src/com/android/settings/network/MobileNetworkSummaryController.java
index 1a85a7f..61dd079 100644
--- a/src/com/android/settings/network/MobileNetworkSummaryController.java
+++ b/src/com/android/settings/network/MobileNetworkSummaryController.java
@@ -206,7 +206,8 @@
@Override
public boolean isAvailable() {
- return !Utils.isWifiOnly(mContext) && mUserManager.isAdminUser();
+ return SubscriptionUtil.isSimHardwareVisible(mContext) &&
+ !Utils.isWifiOnly(mContext) && mUserManager.isAdminUser();
}
@Override
diff --git a/src/com/android/settings/network/NetworkProviderCallsSmsController.java b/src/com/android/settings/network/NetworkProviderCallsSmsController.java
index c8b1c49..585c99e 100644
--- a/src/com/android/settings/network/NetworkProviderCallsSmsController.java
+++ b/src/com/android/settings/network/NetworkProviderCallsSmsController.java
@@ -190,7 +190,8 @@
@Override
public boolean isAvailable() {
- return mUserManager.isAdminUser();
+ return SubscriptionUtil.isSimHardwareVisible(mContext) &&
+ mUserManager.isAdminUser();
}
@Override
diff --git a/src/com/android/settings/network/NetworkProviderCallsSmsFragment.java b/src/com/android/settings/network/NetworkProviderCallsSmsFragment.java
index aad9b10..b2cf74e 100644
--- a/src/com/android/settings/network/NetworkProviderCallsSmsFragment.java
+++ b/src/com/android/settings/network/NetworkProviderCallsSmsFragment.java
@@ -100,7 +100,8 @@
@Override
protected boolean isPageSearchEnabled(Context context) {
- return context.getSystemService(UserManager.class).isAdminUser();
+ return SubscriptionUtil.isSimHardwareVisible(context) &&
+ context.getSystemService(UserManager.class).isAdminUser();
}
};
}
diff --git a/src/com/android/settings/network/NetworkProviderSettings.java b/src/com/android/settings/network/NetworkProviderSettings.java
index 1c480e0..19ebd36 100644
--- a/src/com/android/settings/network/NetworkProviderSettings.java
+++ b/src/com/android/settings/network/NetworkProviderSettings.java
@@ -34,6 +34,7 @@
import android.os.Bundle;
import android.os.Handler;
import android.os.PowerManager;
+import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.telephony.TelephonyManager;
@@ -341,7 +342,18 @@
}
}
+ /**
+ * Whether to show any UI which is SIM related.
+ */
+ @VisibleForTesting
+ boolean showAnySubscriptionInfo(Context context) {
+ return (context != null) && SubscriptionUtil.isSimHardwareVisible(context);
+ }
+
private void addNetworkMobileProviderController() {
+ if (!showAnySubscriptionInfo(getContext())) {
+ return;
+ }
if (mNetworkMobileProviderController == null) {
mNetworkMobileProviderController = new NetworkMobileProviderController(
getContext(), PREF_KEY_PROVIDER_MOBILE_NETWORK);
@@ -598,10 +610,7 @@
return;
}
- if (mSelectedWifiEntry.isSaved() && mSelectedWifiEntry.getConnectedState()
- != WifiEntry.CONNECTED_STATE_CONNECTED) {
- menu.add(Menu.NONE, MENU_ID_MODIFY, 0 /* order */, R.string.wifi_modify);
- }
+ addModifyMenuIfSuitable(menu, mSelectedWifiEntry);
}
@VisibleForTesting
@@ -621,6 +630,14 @@
}
}
+ @VisibleForTesting
+ void addModifyMenuIfSuitable(ContextMenu menu, WifiEntry wifiEntry) {
+ if (mIsAdmin && wifiEntry.isSaved()
+ && wifiEntry.getConnectedState() != WifiEntry.CONNECTED_STATE_CONNECTED) {
+ menu.add(Menu.NONE, MENU_ID_MODIFY, 0 /* order */, R.string.wifi_modify);
+ }
+ }
+
private boolean canForgetNetwork() {
return mSelectedWifiEntry.canForget() && !WifiUtils.isNetworkLockedDown(getActivity(),
mSelectedWifiEntry.getWifiConfiguration());
@@ -643,6 +660,12 @@
() -> launchWifiDppConfiguratorActivity(mSelectedWifiEntry));
return true;
case MENU_ID_MODIFY:
+ if (!mIsAdmin) {
+ Log.e(TAG, "Can't modify Wi-Fi because the user isn't admin.");
+ EventLog.writeEvent(0x534e4554, "237672190", UserHandle.myUserId(),
+ "User isn't admin");
+ return true;
+ }
showDialog(mSelectedWifiEntry, WifiConfigUiBase2.MODE_MODIFY);
return true;
default:
diff --git a/src/com/android/settings/network/SubscriptionUtil.java b/src/com/android/settings/network/SubscriptionUtil.java
index 0bba86f..ccfcfb0 100644
--- a/src/com/android/settings/network/SubscriptionUtil.java
+++ b/src/com/android/settings/network/SubscriptionUtil.java
@@ -86,6 +86,14 @@
return subscriptions;
}
+ /**
+ * Check if SIM hardware is visible to the end user.
+ */
+ public static boolean isSimHardwareVisible(Context context) {
+ return context.getResources()
+ .getBoolean(R.bool.config_show_sim_info);
+ }
+
@VisibleForTesting
static boolean isInactiveInsertedPSim(UiccSlotInfo slotInfo) {
if (slotInfo == null) {
diff --git a/src/com/android/settings/network/UiccSlotUtil.java b/src/com/android/settings/network/UiccSlotUtil.java
index e5323d1..4c26995 100644
--- a/src/com/android/settings/network/UiccSlotUtil.java
+++ b/src/com/android/settings/network/UiccSlotUtil.java
@@ -28,7 +28,6 @@
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.uicc.UiccController;
import com.android.settingslib.utils.ThreadUtils;
import com.google.common.collect.ImmutableList;
@@ -141,7 +140,8 @@
inactiveRemovableSlot,
/*removable sim's port Id*/ TelephonyManager.DEFAULT_PORT_INDEX,
excludedLogicalSlotIndex),
- context);
+ context,
+ /*isWaitingForValidSubId=*/ true);
}
/**
@@ -179,7 +179,8 @@
performSwitchToSlot(telMgr,
prepareUiccSlotMappings(uiccSlotMappings, /*slot is not psim*/ false,
physicalSlotId, port, excludedLogicalSlotIndex),
- context);
+ context,
+ /*isWaitingForValidSubId=*/ false);
}
/**
@@ -231,7 +232,8 @@
}
private static void performSwitchToSlot(TelephonyManager telMgr,
- Collection<UiccSlotMapping> uiccSlotMappings, Context context)
+ Collection<UiccSlotMapping> uiccSlotMappings, Context context,
+ boolean isWaitingForValidSubId)
throws UiccSlotsException {
CarrierConfigChangedReceiver receiver = null;
long waitingTimeMillis =
@@ -241,7 +243,7 @@
DEFAULT_WAIT_AFTER_SWITCH_TIMEOUT_MILLIS);
try {
CountDownLatch latch = new CountDownLatch(1);
- receiver = new CarrierConfigChangedReceiver(latch);
+ receiver = new CarrierConfigChangedReceiver(latch, isWaitingForValidSubId);
receiver.registerOn(context);
telMgr.setSimSlotMapping(uiccSlotMappings);
latch.await(waitingTimeMillis, TimeUnit.MILLISECONDS);
@@ -270,6 +272,7 @@
if (slotId == INVALID_PHYSICAL_SLOT_ID) {
for (int i = 0; i < slots.length; i++) {
if (slots[i].isRemovable()
+ && !slots[i].getIsEuicc()
&& !slots[i].getPorts().stream().findFirst().get().isActive()
&& slots[i].getCardStateInfo() != UiccSlotInfo.CARD_STATE_INFO_ERROR
&& slots[i].getCardStateInfo() != UiccSlotInfo.CARD_STATE_INFO_RESTRICTED) {
@@ -410,4 +413,29 @@
.findFirst()
.orElse(INVALID_LOGICAL_SLOT_ID);
}
+
+ /**
+ * Return whether the removable psim is enabled.
+ *
+ * @param telMgr is a TelephonyManager.
+ * @return whether the removable psim is enabled.
+ */
+ public static boolean isRemovableSimEnabled(TelephonyManager telMgr) {
+ if (telMgr == null) {
+ return false;
+ }
+ ImmutableList<UiccSlotInfo> slotInfos = UiccSlotUtil.getSlotInfos(telMgr);
+ boolean isRemovableSimEnabled =
+ slotInfos.stream()
+ .anyMatch(
+ slot -> slot != null
+ && slot.isRemovable()
+ && !slot.getIsEuicc()
+ && slot.getPorts().stream().anyMatch(
+ port -> port.isActive())
+ && slot.getCardStateInfo()
+ == UiccSlotInfo.CARD_STATE_INFO_PRESENT);
+ Log.i(TAG, "isRemovableSimEnabled: " + isRemovableSimEnabled);
+ return isRemovableSimEnabled;
+ }
}
diff --git a/src/com/android/settings/network/telephony/MobileNetworkSettings.java b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
index 94b6aaf..05e58e9 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkSettings.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkSettings.java
@@ -120,6 +120,10 @@
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
+ if (!SubscriptionUtil.isSimHardwareVisible(context)) {
+ finish();
+ return Arrays.asList();
+ }
if (getArguments() == null) {
Intent intent = getIntent();
if (intent != null) {
@@ -398,7 +402,8 @@
/** suppress full page if user is not admin */
@Override
protected boolean isPageSearchEnabled(Context context) {
- return context.getSystemService(UserManager.class).isAdminUser();
+ return SubscriptionUtil.isSimHardwareVisible(context) &&
+ context.getSystemService(UserManager.class).isAdminUser();
}
};
diff --git a/src/com/android/settings/network/telephony/MobileNetworkUtils.java b/src/com/android/settings/network/telephony/MobileNetworkUtils.java
index e769a4e..8305c4a 100644
--- a/src/com/android/settings/network/telephony/MobileNetworkUtils.java
+++ b/src/com/android/settings/network/telephony/MobileNetworkUtils.java
@@ -263,6 +263,9 @@
* the user has enabled development mode.
*/
public static boolean showEuiccSettings(Context context) {
+ if (!SubscriptionUtil.isSimHardwareVisible(context)) {
+ return false;
+ }
long timeForAccess = SystemClock.elapsedRealtime();
try {
Boolean isShow = ((Future<Boolean>) ThreadUtils.postOnBackgroundThread(() -> {
diff --git a/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java b/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java
index a878cb3..6fa803d 100644
--- a/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java
+++ b/src/com/android/settings/network/telephony/ToggleSubscriptionDialogActivity.java
@@ -24,7 +24,6 @@
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.UiccCardInfo;
-import android.telephony.UiccSlotInfo;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
@@ -39,8 +38,6 @@
import com.android.settings.network.UiccSlotUtil;
import com.android.settings.sim.SimActivationNotifier;
-import com.google.common.collect.ImmutableList;
-
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@@ -586,18 +583,7 @@
}
private boolean isRemovableSimEnabled() {
- ImmutableList<UiccSlotInfo> slotInfos = UiccSlotUtil.getSlotInfos(mTelMgr);
- boolean isRemovableSimEnabled =
- slotInfos.stream()
- .anyMatch(
- slot -> slot != null
- && slot.isRemovable()
- && slot.getPorts().stream().anyMatch(
- port -> port.isActive())
- && slot.getCardStateInfo()
- == UiccSlotInfo.CARD_STATE_INFO_PRESENT);
- Log.i(TAG, "isRemovableSimEnabled: " + isRemovableSimEnabled);
- return isRemovableSimEnabled;
+ return UiccSlotUtil.isRemovableSimEnabled(mTelMgr);
}
private boolean isMultipleEnabledProfilesSupported() {
diff --git a/src/com/android/settings/notification/MediaVolumePreferenceController.java b/src/com/android/settings/notification/MediaVolumePreferenceController.java
index 2466b77..0ddba08 100644
--- a/src/com/android/settings/notification/MediaVolumePreferenceController.java
+++ b/src/com/android/settings/notification/MediaVolumePreferenceController.java
@@ -93,7 +93,7 @@
@VisibleForTesting
boolean isSupportEndItem() {
- return isConnectedBLEDevice();
+ return getWorker() != null && getWorker().isBroadcastSupported() && isConnectedBLEDevice();
}
private boolean isConnectedBLEDevice() {
diff --git a/src/com/android/settings/notification/NotificationAssistantPreferenceController.java b/src/com/android/settings/notification/NotificationAssistantPreferenceController.java
index 2c02db9..ee36273 100644
--- a/src/com/android/settings/notification/NotificationAssistantPreferenceController.java
+++ b/src/com/android/settings/notification/NotificationAssistantPreferenceController.java
@@ -141,7 +141,10 @@
@Override
public void updateState(Preference preference) {
super.updateState(preference);
- if (isNASSettingActivityAvailable()) {
+ if (mDefaultNASComponent == null) {
+ preference.setEnabled(false);
+ ((PrimarySwitchPreference) preference).setSwitchEnabled(false);
+ } else if (isNASSettingActivityAvailable()) {
preference.setIntent(mNASSettingIntent);
} else {
// Cannot find settings activity from the default NAS app
diff --git a/src/com/android/settings/notification/NotificationBackend.java b/src/com/android/settings/notification/NotificationBackend.java
index 150dbe0..68f5d08 100644
--- a/src/com/android/settings/notification/NotificationBackend.java
+++ b/src/com/android/settings/notification/NotificationBackend.java
@@ -126,6 +126,7 @@
if (app.requestedPermissions == null || Arrays.stream(app.requestedPermissions)
.noneMatch(p -> p.equals(android.Manifest.permission.POST_NOTIFICATIONS))) {
row.lockedImportance = true;
+ row.permissionStateLocked = true;
}
}
}
@@ -684,6 +685,9 @@
public boolean systemApp;
public boolean lockedImportance;
public boolean showBadge;
+ // For apps target T but have not but has not requested the permission
+ // we cannot change the permission state
+ public boolean permissionStateLocked;
public int bubblePreference = NotificationManager.BUBBLE_PREFERENCE_NONE;
public int userId;
public int blockedChannelCount;
diff --git a/src/com/android/settings/notification/NotificationVolumePreferenceController.java b/src/com/android/settings/notification/NotificationVolumePreferenceController.java
index 0fe0d62..322bb6c 100644
--- a/src/com/android/settings/notification/NotificationVolumePreferenceController.java
+++ b/src/com/android/settings/notification/NotificationVolumePreferenceController.java
@@ -16,26 +16,96 @@
package com.android.settings.notification;
+import android.app.INotificationManager;
+import android.app.NotificationManager;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
import android.media.AudioManager;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.ServiceManager;
+import android.os.Vibrator;
+import android.service.notification.NotificationListenerService;
import android.text.TextUtils;
+import android.util.Log;
+import androidx.lifecycle.OnLifecycleEvent;
+
+import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.Utils;
+import com.android.settingslib.core.lifecycle.Lifecycle;
-public class NotificationVolumePreferenceController extends
- RingVolumePreferenceController {
+import java.util.Objects;
+/**
+ * Update notification volume icon in Settings in response to user adjusting volume
+ */
+public class NotificationVolumePreferenceController extends VolumeSeekBarPreferenceController {
+
+ private static final String TAG = "NotificationVolumePreferenceController";
private static final String KEY_NOTIFICATION_VOLUME = "notification_volume";
+ private Vibrator mVibrator;
+ private int mRingerMode = AudioManager.RINGER_MODE_NORMAL;
+ private ComponentName mSuppressor;
+ private final RingReceiver mReceiver = new RingReceiver();
+ private final H mHandler = new H();
+ private INotificationManager mNoMan;
+
+
+ private int mMuteIcon;
+ private final int mNormalIconId = R.drawable.ic_notifications;
+ private final int mVibrateIconId = R.drawable.ic_volume_ringer_vibrate;
+ private final int mSilentIconId = R.drawable.ic_notifications_off_24dp;
+
+ private final boolean mRingNotificationAliased;
+
+
public NotificationVolumePreferenceController(Context context) {
- super(context, KEY_NOTIFICATION_VOLUME);
+ this(context, KEY_NOTIFICATION_VOLUME);
+ }
+
+ public NotificationVolumePreferenceController(Context context, String key) {
+ super(context, key);
+ mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
+ if (mVibrator != null && !mVibrator.hasVibrator()) {
+ mVibrator = null;
+ }
+
+ mRingNotificationAliased = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_alias_ring_notif_stream_types);
+ updateRingerMode();
+ }
+
+ @OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
+ @Override
+ public void onResume() {
+ super.onResume();
+ mReceiver.register(true);
+ updateEffectsSuppressor();
+ updatePreferenceIconAndSliderState();
+ }
+
+ @OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
+ @Override
+ public void onPause() {
+ super.onPause();
+ mReceiver.register(false);
}
@Override
public int getAvailabilityStatus() {
+
+ // Show separate notification slider if ring/notification are not aliased by AudioManager --
+ // if they are, notification volume is controlled by RingVolumePreferenceController.
return mContext.getResources().getBoolean(R.bool.config_show_notification_volume)
- && !Utils.isVoiceCapable(mContext) && !mHelper.isSingleVolume()
+ && (!mRingNotificationAliased || !Utils.isVoiceCapable(mContext))
+ && !mHelper.isSingleVolume()
? AVAILABLE : UNSUPPORTED_ON_DEVICE;
}
@@ -55,13 +125,152 @@
}
@Override
+ public boolean useDynamicSliceSummary() {
+ return true;
+ }
+
+ @Override
public int getAudioStream() {
return AudioManager.STREAM_NOTIFICATION;
}
@Override
public int getMuteIcon() {
- return R.drawable.ic_notifications_off_24dp;
+ return mMuteIcon;
+ }
+
+ private void updateRingerMode() {
+ final int ringerMode = mHelper.getRingerModeInternal();
+ if (mRingerMode == ringerMode) return;
+ mRingerMode = ringerMode;
+ updatePreferenceIconAndSliderState();
+ }
+
+ private void updateEffectsSuppressor() {
+ final ComponentName suppressor = NotificationManager.from(mContext).getEffectsSuppressor();
+ if (Objects.equals(suppressor, mSuppressor)) return;
+
+ if (mNoMan == null) {
+ mNoMan = INotificationManager.Stub.asInterface(
+ ServiceManager.getService(Context.NOTIFICATION_SERVICE));
+ }
+
+ final int hints;
+ try {
+ hints = mNoMan.getHintsFromListenerNoToken();
+ } catch (android.os.RemoteException exception) {
+ Log.w(TAG, "updateEffectsSuppressor: " + exception.getLocalizedMessage());
+ return;
+ }
+
+ if (hintsMatch(hints)) {
+
+ mSuppressor = suppressor;
+ if (mPreference != null) {
+ final String text = SuppressorHelper.getSuppressionText(mContext, suppressor);
+ mPreference.setSuppressionText(text);
+ }
+ }
+ }
+
+ @VisibleForTesting
+ boolean hintsMatch(int hints) {
+ boolean allEffectsDisabled =
+ (hints & NotificationListenerService.HINT_HOST_DISABLE_EFFECTS) != 0;
+ boolean notificationEffectsDisabled =
+ (hints & NotificationListenerService.HINT_HOST_DISABLE_NOTIFICATION_EFFECTS) != 0;
+
+ return allEffectsDisabled || notificationEffectsDisabled;
+ }
+
+ private void updatePreferenceIconAndSliderState() {
+ if (mPreference != null) {
+ if (mVibrator != null && mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
+ mMuteIcon = mVibrateIconId;
+ mPreference.showIcon(mVibrateIconId);
+ mPreference.setEnabled(false);
+
+ } else if (mRingerMode == AudioManager.RINGER_MODE_SILENT
+ || mVibrator == null && mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
+ mMuteIcon = mSilentIconId;
+ mPreference.showIcon(mSilentIconId);
+ mPreference.setEnabled(false);
+ } else { // ringmode normal: could be that we are still silent
+ mPreference.setEnabled(true);
+ if (mHelper.getStreamVolume(AudioManager.STREAM_NOTIFICATION) == 0) {
+ // ring is in normal, but notification is in silent
+ mMuteIcon = mSilentIconId;
+ mPreference.showIcon(mSilentIconId);
+ } else {
+ mPreference.showIcon(mNormalIconId);
+ }
+ }
+ }
+ }
+
+ private final class H extends Handler {
+ private static final int UPDATE_EFFECTS_SUPPRESSOR = 1;
+ private static final int UPDATE_RINGER_MODE = 2;
+ private static final int NOTIFICATION_VOLUME_CHANGED = 3;
+
+ private H() {
+ super(Looper.getMainLooper());
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case UPDATE_EFFECTS_SUPPRESSOR:
+ updateEffectsSuppressor();
+ break;
+ case UPDATE_RINGER_MODE:
+ updateRingerMode();
+ break;
+ case NOTIFICATION_VOLUME_CHANGED:
+ updatePreferenceIconAndSliderState();
+ break;
+ }
+ }
+ }
+
+ /**
+ * For notification volume icon to be accurate, we need to listen to volume change as well.
+ * That is because the icon can change from mute/vibrate to normal without ringer mode changing.
+ */
+ private class RingReceiver extends BroadcastReceiver {
+ private boolean mRegistered;
+
+ public void register(boolean register) {
+ if (mRegistered == register) return;
+ if (register) {
+ final IntentFilter filter = new IntentFilter();
+ filter.addAction(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED);
+ filter.addAction(AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION);
+ filter.addAction(AudioManager.VOLUME_CHANGED_ACTION);
+ mContext.registerReceiver(this, filter);
+ } else {
+ mContext.unregisterReceiver(this);
+ }
+ mRegistered = register;
+ }
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ final String action = intent.getAction();
+ if (NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED.equals(action)) {
+ mHandler.sendEmptyMessage(H.UPDATE_EFFECTS_SUPPRESSOR);
+ } else if (AudioManager.INTERNAL_RINGER_MODE_CHANGED_ACTION.equals(action)) {
+ mHandler.sendEmptyMessage(H.UPDATE_RINGER_MODE);
+ } else if (AudioManager.VOLUME_CHANGED_ACTION.equals(action)) {
+ int streamType = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_TYPE, -1);
+ if (streamType == AudioManager.STREAM_NOTIFICATION) {
+ int streamValue = intent.getIntExtra(AudioManager.EXTRA_VOLUME_STREAM_VALUE,
+ -1);
+ mHandler.obtainMessage(H.NOTIFICATION_VOLUME_CHANGED, streamValue, 0)
+ .sendToTarget();
+ }
+ }
+ }
}
}
diff --git a/src/com/android/settings/notification/RingVolumePreferenceController.java b/src/com/android/settings/notification/RingVolumePreferenceController.java
index 5e7d067..a78689f 100644
--- a/src/com/android/settings/notification/RingVolumePreferenceController.java
+++ b/src/com/android/settings/notification/RingVolumePreferenceController.java
@@ -16,6 +16,7 @@
package com.android.settings.notification;
+import android.app.INotificationManager;
import android.app.NotificationManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
@@ -26,30 +27,56 @@
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
+import android.os.ServiceManager;
import android.os.Vibrator;
+import android.service.notification.NotificationListenerService;
import android.text.TextUtils;
+import android.util.Log;
import androidx.lifecycle.OnLifecycleEvent;
+import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
import com.android.settings.Utils;
import com.android.settingslib.core.lifecycle.Lifecycle;
import java.util.Objects;
+/**
+ * This slider can represent both ring and notification, if the corresponding streams are aliased,
+ * and only ring if the streams are not aliased.
+ */
public class RingVolumePreferenceController extends VolumeSeekBarPreferenceController {
- private static final String TAG = "RingVolumeController";
+ private static final String TAG = "RingVolumePreferenceController";
private static final String KEY_RING_VOLUME = "ring_volume";
private Vibrator mVibrator;
- private int mRingerMode = -1;
+ private int mRingerMode = AudioManager.RINGER_MODE_NORMAL;
private ComponentName mSuppressor;
private final RingReceiver mReceiver = new RingReceiver();
private final H mHandler = new H();
private int mMuteIcon;
+ /*
+ * Whether ring and notification streams are aliased together by AudioManager.
+ * If they are, we'll present one volume control for both.
+ * If not, we'll present separate volume controls.
+ */
+ private final boolean mRingAliasNotif;
+
+ private final int mNormalIconId;
+ @VisibleForTesting
+ final int mVibrateIconId;
+ @VisibleForTesting
+ final int mSilentIconId;
+
+ @VisibleForTesting
+ final int mTitleId;
+
+ private INotificationManager mNoMan;
+
public RingVolumePreferenceController(Context context) {
this(context, KEY_RING_VOLUME);
}
@@ -60,9 +87,31 @@
if (mVibrator != null && !mVibrator.hasVibrator()) {
mVibrator = null;
}
+
+ mRingAliasNotif = isRingAliasNotification();
+ if (mRingAliasNotif) {
+ mTitleId = R.string.ring_volume_option_title;
+
+ mNormalIconId = R.drawable.ic_notifications;
+ mSilentIconId = R.drawable.ic_notifications_off_24dp;
+ } else {
+ mTitleId = R.string.separate_ring_volume_option_title;
+
+ mNormalIconId = R.drawable.ic_ring_volume;
+ mSilentIconId = R.drawable.ic_ring_volume_off;
+ }
+ // todo: set a distinct vibrate icon for ring vs notification
+ mVibrateIconId = R.drawable.ic_volume_ringer_vibrate;
+
updateRingerMode();
}
+ @VisibleForTesting
+ boolean isRingAliasNotification() {
+ return mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_alias_ring_notif_stream_types);
+ }
+
@OnLifecycleEvent(Lifecycle.Event.ON_RESUME)
@Override
public void onResume() {
@@ -70,6 +119,7 @@
mReceiver.register(true);
updateEffectsSuppressor();
updatePreferenceIcon();
+ setPreferenceTitle();
}
@OnLifecycleEvent(Lifecycle.Event.ON_PAUSE)
@@ -115,7 +165,8 @@
return mMuteIcon;
}
- private void updateRingerMode() {
+ @VisibleForTesting
+ void updateRingerMode() {
final int ringerMode = mHelper.getRingerModeInternal();
if (mRingerMode == ringerMode) return;
mRingerMode = ringerMode;
@@ -125,28 +176,73 @@
private void updateEffectsSuppressor() {
final ComponentName suppressor = NotificationManager.from(mContext).getEffectsSuppressor();
if (Objects.equals(suppressor, mSuppressor)) return;
- mSuppressor = suppressor;
- if (mPreference != null) {
- final String text = SuppressorHelper.getSuppressionText(mContext, suppressor);
- mPreference.setSuppressionText(text);
+
+ if (mNoMan == null) {
+ mNoMan = INotificationManager.Stub.asInterface(
+ ServiceManager.getService(Context.NOTIFICATION_SERVICE));
}
- updatePreferenceIcon();
+
+ final int hints;
+ try {
+ hints = mNoMan.getHintsFromListenerNoToken();
+ } catch (android.os.RemoteException ex) {
+ Log.w(TAG, "updateEffectsSuppressor: " + ex.getMessage());
+ return;
+ }
+
+ if (hintsMatch(hints, mRingAliasNotif)) {
+ mSuppressor = suppressor;
+ if (mPreference != null) {
+ final String text = SuppressorHelper.getSuppressionText(mContext, suppressor);
+ mPreference.setSuppressionText(text);
+ }
+ }
+ }
+
+ @VisibleForTesting
+ boolean hintsMatch(int hints, boolean ringNotificationAliased) {
+ return (hints & NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS) != 0
+ || (hints & NotificationListenerService.HINT_HOST_DISABLE_EFFECTS) != 0
+ || ((hints & NotificationListenerService.HINT_HOST_DISABLE_NOTIFICATION_EFFECTS)
+ != 0 && ringNotificationAliased);
+ }
+
+ @VisibleForTesting
+ void setPreference(VolumeSeekBarPreference volumeSeekBarPreference) {
+ mPreference = volumeSeekBarPreference;
+ }
+
+ @VisibleForTesting
+ void setVibrator(Vibrator vibrator) {
+ mVibrator = vibrator;
}
private void updatePreferenceIcon() {
if (mPreference != null) {
- if (mRingerMode == AudioManager.RINGER_MODE_VIBRATE) {
- mMuteIcon = R.drawable.ic_volume_ringer_vibrate;
- mPreference.showIcon(R.drawable.ic_volume_ringer_vibrate);
- } else if (mRingerMode == AudioManager.RINGER_MODE_SILENT) {
- mMuteIcon = R.drawable.ic_notifications_off_24dp;
- mPreference.showIcon(R.drawable.ic_notifications_off_24dp);
+ if (mRingerMode == AudioManager.RINGER_MODE_NORMAL) {
+ mPreference.showIcon(mNormalIconId);
} else {
- mPreference.showIcon(R.drawable.ic_notifications);
+ if (mRingerMode == AudioManager.RINGER_MODE_VIBRATE && mVibrator != null) {
+ mMuteIcon = mVibrateIconId;
+ } else {
+ mMuteIcon = mSilentIconId;
+ }
+ mPreference.showIcon(mMuteIcon);
}
}
}
+ /**
+ * This slider can represent both ring and notification, or only ring.
+ * Note: This cannot be used in the constructor, as the reference to preference object would
+ * still be null.
+ */
+ private void setPreferenceTitle() {
+ if (mPreference != null) {
+ mPreference.setTitle(mTitleId);
+ }
+ }
+
private final class H extends Handler {
private static final int UPDATE_EFFECTS_SUPPRESSOR = 1;
private static final int UPDATE_RINGER_MODE = 2;
diff --git a/src/com/android/settings/notification/ShowOnLockScreenNotificationPreferenceController.java b/src/com/android/settings/notification/ShowOnLockScreenNotificationPreferenceController.java
index f7dc391..1addd82 100644
--- a/src/com/android/settings/notification/ShowOnLockScreenNotificationPreferenceController.java
+++ b/src/com/android/settings/notification/ShowOnLockScreenNotificationPreferenceController.java
@@ -23,6 +23,9 @@
import android.os.UserHandle;
import android.provider.Settings;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
import com.android.settings.R;
import com.android.settings.RestrictedListPreference;
import com.android.settings.core.PreferenceControllerMixin;
@@ -34,9 +37,6 @@
import java.util.ArrayList;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
public class ShowOnLockScreenNotificationPreferenceController extends AbstractPreferenceController
implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
@@ -157,6 +157,6 @@
private boolean getLockscreenSilentNotificationsEnabled() {
return Settings.Secure.getInt(mContext.getContentResolver(),
- Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 1) != 0;
+ Settings.Secure.LOCK_SCREEN_SHOW_SILENT_NOTIFICATIONS, 0) != 0;
}
}
diff --git a/src/com/android/settings/notification/VibrateIconPreferenceController.java b/src/com/android/settings/notification/VibrateIconPreferenceController.java
index 25d2326..d772b47 100644
--- a/src/com/android/settings/notification/VibrateIconPreferenceController.java
+++ b/src/com/android/settings/notification/VibrateIconPreferenceController.java
@@ -19,6 +19,7 @@
import static com.android.settings.notification.SettingPref.TYPE_SECURE;
import android.content.Context;
+import android.os.Vibrator;
import android.provider.Settings.Secure;
import com.android.settings.SettingsPreferenceFragment;
@@ -27,16 +28,18 @@
public class VibrateIconPreferenceController extends SettingPrefController {
private static final String KEY_VIBRATE_ICON = "vibrate_icon";
+ private final boolean mHasVibrator;
public VibrateIconPreferenceController(Context context, SettingsPreferenceFragment parent,
Lifecycle lifecycle) {
super(context, parent, lifecycle);
+ mHasVibrator = context.getSystemService(Vibrator.class).hasVibrator();
mPreference = new SettingPref(
TYPE_SECURE, KEY_VIBRATE_ICON, Secure.STATUS_BAR_SHOW_VIBRATE_ICON, 0 /*default off*/);
}
@Override
public boolean isAvailable() {
- return true;
+ return mHasVibrator;
}
}
diff --git a/src/com/android/settings/notification/app/NotificationsOffPreferenceController.java b/src/com/android/settings/notification/app/NotificationsOffPreferenceController.java
index 0c7cd23..04e3f0e 100644
--- a/src/com/android/settings/notification/app/NotificationsOffPreferenceController.java
+++ b/src/com/android/settings/notification/app/NotificationsOffPreferenceController.java
@@ -62,6 +62,8 @@
preference.setTitle(R.string.channel_notifications_off_desc);
} else if (mChannelGroup != null) {
preference.setTitle(R.string.channel_group_notifications_off_desc);
+ } else if (mAppRow.permissionStateLocked) {
+ preference.setTitle(R.string.app_notifications_not_send_desc);
} else {
preference.setTitle(R.string.app_notifications_off_desc);
}
diff --git a/src/com/android/settings/overlay/FeatureFactory.java b/src/com/android/settings/overlay/FeatureFactory.java
index c59b385..aff7197 100644
--- a/src/com/android/settings/overlay/FeatureFactory.java
+++ b/src/com/android/settings/overlay/FeatureFactory.java
@@ -45,7 +45,6 @@
import com.android.settings.security.SecuritySettingsFeatureProvider;
import com.android.settings.slices.SlicesFeatureProvider;
import com.android.settings.users.UserFeatureProvider;
-import com.android.settings.vpn2.AdvancedVpnFeatureProvider;
import com.android.settings.wifi.WifiTrackerLibProvider;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
@@ -178,11 +177,6 @@
*/
public abstract AccessibilityMetricsFeatureProvider getAccessibilityMetricsFeatureProvider();
- /**
- * Retrieves implementation for advanced vpn feature.
- */
- public abstract AdvancedVpnFeatureProvider getAdvancedVpnFeatureProvider();
-
public static final class FactoryNotFoundException extends RuntimeException {
public FactoryNotFoundException(Throwable throwable) {
super("Unable to create factory. Did you misconfigure Proguard?", throwable);
diff --git a/src/com/android/settings/overlay/FeatureFactoryImpl.java b/src/com/android/settings/overlay/FeatureFactoryImpl.java
index 593b866..89f74de 100644
--- a/src/com/android/settings/overlay/FeatureFactoryImpl.java
+++ b/src/com/android/settings/overlay/FeatureFactoryImpl.java
@@ -71,8 +71,6 @@
import com.android.settings.slices.SlicesFeatureProviderImpl;
import com.android.settings.users.UserFeatureProvider;
import com.android.settings.users.UserFeatureProviderImpl;
-import com.android.settings.vpn2.AdvancedVpnFeatureProvider;
-import com.android.settings.vpn2.AdvancedVpnFeatureProviderImpl;
import com.android.settings.wifi.WifiTrackerLibProvider;
import com.android.settings.wifi.WifiTrackerLibProviderImpl;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
@@ -108,7 +106,6 @@
private SecuritySettingsFeatureProvider mSecuritySettingsFeatureProvider;
private AccessibilitySearchFeatureProvider mAccessibilitySearchFeatureProvider;
private AccessibilityMetricsFeatureProvider mAccessibilityMetricsFeatureProvider;
- private AdvancedVpnFeatureProvider mAdvancedVpnFeatureProvider;
@Override
public SupportFeatureProvider getSupportFeatureProvider(Context context) {
@@ -337,12 +334,4 @@
}
return mAccessibilityMetricsFeatureProvider;
}
-
- @Override
- public AdvancedVpnFeatureProvider getAdvancedVpnFeatureProvider() {
- if (mAdvancedVpnFeatureProvider == null) {
- mAdvancedVpnFeatureProvider = new AdvancedVpnFeatureProviderImpl();
- }
- return mAdvancedVpnFeatureProvider;
- }
}
diff --git a/src/com/android/settings/panel/PanelFragment.java b/src/com/android/settings/panel/PanelFragment.java
index 04ae311..1ce4492 100644
--- a/src/com/android/settings/panel/PanelFragment.java
+++ b/src/com/android/settings/panel/PanelFragment.java
@@ -60,6 +60,7 @@
import com.google.android.setupdesign.DividerItemDecoration;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashMap;
import java.util.List;
@@ -339,8 +340,13 @@
mSliceLiveData.put(uri, sliceLiveData);
sliceLiveData.observe(getViewLifecycleOwner(), slice -> {
- // If the Slice has already loaded, do nothing.
+
+ // If the Slice has already loaded, refresh list with slice data.
if (mPanelSlicesLoaderCountdownLatch.isSliceLoaded(uri)) {
+ if (mAdapter != null) {
+ int itemIndex = (new ArrayList<>(mSliceLiveData.keySet())).indexOf(uri);
+ mAdapter.notifyItemChanged(itemIndex);
+ }
return;
}
diff --git a/src/com/android/settings/panel/PanelSlicesAdapter.java b/src/com/android/settings/panel/PanelSlicesAdapter.java
index 9f5ffe9..d728366 100644
--- a/src/com/android/settings/panel/PanelSlicesAdapter.java
+++ b/src/com/android/settings/panel/PanelSlicesAdapter.java
@@ -54,7 +54,7 @@
* Maximum number of slices allowed on the panel view.
*/
@VisibleForTesting
- static final int MAX_NUM_OF_SLICES = 6;
+ static final int MAX_NUM_OF_SLICES = 7;
private final List<LiveData<Slice>> mSliceLiveData;
private final int mMetricsCategory;
@@ -84,7 +84,7 @@
@Override
public void onBindViewHolder(@NonNull SliceRowViewHolder sliceRowViewHolder, int position) {
- sliceRowViewHolder.onBind(mSliceLiveData.get(position), position);
+ sliceRowViewHolder.onBind(mSliceLiveData.get(position).getValue());
}
/**
@@ -132,15 +132,14 @@
/**
* Called when the view is displayed.
*/
- public void onBind(LiveData<Slice> sliceLiveData, int position) {
- sliceLiveData.observe(mPanelFragment.getViewLifecycleOwner(), sliceView);
-
- // Do not show the divider above media devices switcher slice per request
- final Slice slice = sliceLiveData.getValue();
-
+ public void onBind(Slice slice) {
// Hides slice which reports with error hint or not contain any slice sub-item.
if (slice == null || !isValidSlice(slice)) {
sliceView.setVisibility(View.GONE);
+ return;
+ } else {
+ sliceView.setSlice(slice);
+ sliceView.setVisibility(View.VISIBLE);
}
// Add divider for the end icon
@@ -154,7 +153,7 @@
.action(0 /* attribution */,
SettingsEnums.ACTION_PANEL_INTERACTION,
mMetricsCategory,
- sliceLiveData.getValue().getUri().getLastPathSegment()
+ slice.getUri().getLastPathSegment()
/* log key */,
eventInfo.actionType /* value */);
})
diff --git a/src/com/android/settings/search/SearchFeatureProvider.java b/src/com/android/settings/search/SearchFeatureProvider.java
index 1785361..b14a4d7 100644
--- a/src/com/android/settings/search/SearchFeatureProvider.java
+++ b/src/com/android/settings/search/SearchFeatureProvider.java
@@ -72,6 +72,12 @@
}
/**
+ * Send the pre-index intent.
+ */
+ default void sendPreIndexIntent(Context context){
+ }
+
+ /**
* Initializes the search toolbar.
*/
default void initSearchToolbar(FragmentActivity activity, Toolbar toolbar, int pageId) {
diff --git a/src/com/android/settings/security/SimLockPreferenceController.java b/src/com/android/settings/security/SimLockPreferenceController.java
index 7cd0173..8429a9f 100644
--- a/src/com/android/settings/security/SimLockPreferenceController.java
+++ b/src/com/android/settings/security/SimLockPreferenceController.java
@@ -28,6 +28,7 @@
import androidx.preference.PreferenceScreen;
import com.android.settings.core.BasePreferenceController;
+import com.android.settings.network.SubscriptionUtil;
import java.util.List;
@@ -50,6 +51,10 @@
@Override
public int getAvailabilityStatus() {
+ if (!SubscriptionUtil.isSimHardwareVisible(mContext)) {
+ return UNSUPPORTED_ON_DEVICE;
+ }
+
final List<SubscriptionInfo> subInfoList =
mSubscriptionManager.getActiveSubscriptionInfoList();
diff --git a/src/com/android/settings/sim/SimDialogActivity.java b/src/com/android/settings/sim/SimDialogActivity.java
index 9c4f8f1..464ba9b 100644
--- a/src/com/android/settings/sim/SimDialogActivity.java
+++ b/src/com/android/settings/sim/SimDialogActivity.java
@@ -35,6 +35,7 @@
import androidx.fragment.app.FragmentManager;
import com.android.settings.R;
+import com.android.settings.network.SubscriptionUtil;
import com.android.settings.network.telephony.SubscriptionActionDialogActivity;
import java.util.List;
@@ -65,6 +66,11 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ if (!SubscriptionUtil.isSimHardwareVisible(this)) {
+ Log.d(TAG, "Not support on device without SIM.");
+ finish();
+ return;
+ }
SimDialogProhibitService.supportDismiss(this);
getWindow().addSystemFlags(
diff --git a/src/com/android/settings/sim/SimSelectNotification.java b/src/com/android/settings/sim/SimSelectNotification.java
index 9d3f860..9b235ce 100644
--- a/src/com/android/settings/sim/SimSelectNotification.java
+++ b/src/com/android/settings/sim/SimSelectNotification.java
@@ -77,6 +77,10 @@
@Override
public void onReceive(Context context, Intent intent) {
+ if (!SubscriptionUtil.isSimHardwareVisible(context)) {
+ Log.w(TAG, "Received unexpected intent with null action.");
+ return;
+ }
String action = intent.getAction();
if (action == null) {
diff --git a/src/com/android/settings/sim/smartForwarding/SmartForwardingActivity.java b/src/com/android/settings/sim/smartForwarding/SmartForwardingActivity.java
index 217801e..070e65a 100644
--- a/src/com/android/settings/sim/smartForwarding/SmartForwardingActivity.java
+++ b/src/com/android/settings/sim/smartForwarding/SmartForwardingActivity.java
@@ -38,6 +38,7 @@
import com.android.settings.R;
import com.android.settings.core.SettingsBaseActivity;
+import com.android.settings.network.SubscriptionUtil;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.Futures;
@@ -48,6 +49,7 @@
import java.util.concurrent.Executors;
public class SmartForwardingActivity extends SettingsBaseActivity {
+ static final String LOG_TAG = SmartForwardingActivity.class.toString();
final ListeningExecutorService service =
MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor());
@@ -55,6 +57,12 @@
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
+ if (!SubscriptionUtil.isSimHardwareVisible(this)) {
+ Log.d(LOG_TAG, "Not support on device without SIM.");
+ finish();
+ return;
+ }
+
final Toolbar toolbar = findViewById(R.id.action_bar);
toolbar.setVisibility(View.VISIBLE);
setActionBar(toolbar);
@@ -166,4 +174,4 @@
.create();
mDialog.show();
}
-}
\ No newline at end of file
+}
diff --git a/src/com/android/settings/slices/CustomSliceRegistry.java b/src/com/android/settings/slices/CustomSliceRegistry.java
index d1b169c..569a0ea 100644
--- a/src/com/android/settings/slices/CustomSliceRegistry.java
+++ b/src/com/android/settings/slices/CustomSliceRegistry.java
@@ -218,6 +218,16 @@
.build();
/**
+ * Full {@link Uri} for the Notification volume Slice.
+ */
+ public static final Uri VOLUME_NOTIFICATION_URI = new Uri.Builder()
+ .scheme(ContentResolver.SCHEME_CONTENT)
+ .authority(SettingsSliceProvider.SLICE_AUTHORITY)
+ .appendPath(SettingsSlicesContract.PATH_SETTING_ACTION)
+ .appendPath("notification_volume")
+ .build();
+
+ /**
* Full {@link Uri} for the all volume Slices.
*/
public static final Uri VOLUME_SLICES_URI = new Uri.Builder()
diff --git a/src/com/android/settings/sound/AudioSwitchPreferenceController.java b/src/com/android/settings/sound/AudioSwitchPreferenceController.java
index 5b70d16..6475257 100644
--- a/src/com/android/settings/sound/AudioSwitchPreferenceController.java
+++ b/src/com/android/settings/sound/AudioSwitchPreferenceController.java
@@ -45,6 +45,7 @@
import com.android.settingslib.bluetooth.CachedBluetoothDevice;
import com.android.settingslib.bluetooth.HeadsetProfile;
import com.android.settingslib.bluetooth.HearingAidProfile;
+import com.android.settingslib.bluetooth.LeAudioProfile;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import com.android.settingslib.core.lifecycle.LifecycleObserver;
@@ -52,6 +53,7 @@
import com.android.settingslib.core.lifecycle.events.OnStop;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
@@ -215,6 +217,41 @@
}
/**
+ * Get LE Audio profile connected devices
+ */
+ protected List<BluetoothDevice> getConnectedLeAudioDevices() {
+ final List<BluetoothDevice> connectedDevices = new ArrayList<>();
+ final LeAudioProfile leAudioProfile = mProfileManager.getLeAudioProfile();
+ if (leAudioProfile == null) {
+ Log.d(TAG, "LeAudioProfile is null");
+ return connectedDevices;
+ }
+ final List<BluetoothDevice> devices = leAudioProfile.getConnectedDevices();
+ for (BluetoothDevice device : devices) {
+ if (device.isConnected() && isDeviceInCachedList(device)) {
+ connectedDevices.add(device);
+ }
+ }
+ return connectedDevices;
+ }
+
+ /**
+ * Confirm if the device exists in the cached devices list. If return true, it means
+ * the device is main device in the LE Audio device group. Otherwise, the device is the member
+ * device in the group.
+ */
+ protected boolean isDeviceInCachedList(BluetoothDevice device) {
+ Collection<CachedBluetoothDevice> cachedDevices =
+ mLocalBluetoothManager.getCachedDeviceManager().getCachedDevicesCopy();
+ for (CachedBluetoothDevice cachedDevice : cachedDevices) {
+ if (cachedDevice.getDevice().equals(device)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* get hearing aid profile connected device, exclude other devices with same hiSyncId.
*/
protected List<BluetoothDevice> getConnectedHearingAidDevices() {
@@ -260,6 +297,24 @@
}
/**
+ * Find active LE Audio device
+ */
+ protected BluetoothDevice findActiveLeAudioDevice() {
+ final LeAudioProfile leAudioProfile = mProfileManager.getLeAudioProfile();
+
+ if (leAudioProfile != null) {
+ List<BluetoothDevice> activeDevices = leAudioProfile.getActiveDevices();
+ for (BluetoothDevice leAudioDevice : activeDevices) {
+ if (leAudioDevice != null) {
+ return leAudioDevice;
+ }
+ }
+ }
+ Log.d(TAG, "There is no LE audio profile or no active LE audio device");
+ return null;
+ }
+
+ /**
* Find the active device from the corresponding profile.
*
* @return the active device. Return null if the
diff --git a/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java b/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java
index 15f47cf..35cc65f 100644
--- a/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java
+++ b/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceController.java
@@ -103,6 +103,7 @@
mConnectedDevices.clear();
mConnectedDevices.addAll(getConnectedHfpDevices());
mConnectedDevices.addAll(getConnectedHearingAidDevices());
+ mConnectedDevices.addAll(getConnectedLeAudioDevices());
final int numDevices = mConnectedDevices.size();
if (numDevices == 0) {
@@ -181,12 +182,22 @@
@Override
public BluetoothDevice findActiveDevice() {
- BluetoothDevice activeDevice = findActiveHearingAidDevice();
+ BluetoothDevice haActiveDevice = findActiveHearingAidDevice();
+ BluetoothDevice leAudioActiveDevice = findActiveLeAudioDevice();
final HeadsetProfile headsetProfile = mProfileManager.getHeadsetProfile();
- if (activeDevice == null && headsetProfile != null) {
- activeDevice = headsetProfile.getActiveDevice();
+ if (haActiveDevice != null) {
+ return haActiveDevice;
}
- return activeDevice;
+
+ if (leAudioActiveDevice != null) {
+ return leAudioActiveDevice;
+ }
+
+ if (headsetProfile != null && headsetProfile.getActiveDevice() != null) {
+ return headsetProfile.getActiveDevice();
+ }
+
+ return null;
}
}
diff --git a/src/com/android/settings/sound/MediaOutputPreferenceController.java b/src/com/android/settings/sound/MediaOutputPreferenceController.java
index 4ec00e3..758f7e3 100644
--- a/src/com/android/settings/sound/MediaOutputPreferenceController.java
+++ b/src/com/android/settings/sound/MediaOutputPreferenceController.java
@@ -88,9 +88,11 @@
// Find active device and set its name as the preference's summary
List<BluetoothDevice> connectedA2dpDevices = getConnectedA2dpDevices();
List<BluetoothDevice> connectedHADevices = getConnectedHearingAidDevices();
+ List<BluetoothDevice> connectedLeAudioDevices = getConnectedLeAudioDevices();
if (mAudioManager.getMode() == AudioManager.MODE_NORMAL
&& ((connectedA2dpDevices != null && !connectedA2dpDevices.isEmpty())
- || (connectedHADevices != null && !connectedHADevices.isEmpty()))) {
+ || (connectedHADevices != null && !connectedHADevices.isEmpty())
+ || (connectedLeAudioDevices != null && !connectedLeAudioDevices.isEmpty()))) {
activeDevice = findActiveDevice();
}
mPreference.setTitle(mContext.getString(R.string.media_output_label_title,
@@ -103,13 +105,23 @@
@Override
public BluetoothDevice findActiveDevice() {
- BluetoothDevice activeDevice = findActiveHearingAidDevice();
+ BluetoothDevice haActiveDevice = findActiveHearingAidDevice();
+ BluetoothDevice leAudioActiveDevice = findActiveLeAudioDevice();
final A2dpProfile a2dpProfile = mProfileManager.getA2dpProfile();
- if (activeDevice == null && a2dpProfile != null) {
- activeDevice = a2dpProfile.getActiveDevice();
+ if (haActiveDevice != null) {
+ return haActiveDevice;
}
- return activeDevice;
+
+ if (leAudioActiveDevice != null) {
+ return leAudioActiveDevice;
+ }
+
+ if (a2dpProfile != null && a2dpProfile.getActiveDevice() != null) {
+ return a2dpProfile.getActiveDevice();
+ }
+
+ return null;
}
/**
diff --git a/src/com/android/settings/vpn2/AdvancedVpnFeatureProvider.java b/src/com/android/settings/vpn2/AdvancedVpnFeatureProvider.java
deleted file mode 100644
index 962b6c2..0000000
--- a/src/com/android/settings/vpn2/AdvancedVpnFeatureProvider.java
+++ /dev/null
@@ -1,55 +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.vpn2;
-
-import android.content.Context;
-
-/**
- * Feature Provider used in vpn usage
- */
-public interface AdvancedVpnFeatureProvider {
-
- /**
- * Returns package name of advanced vpn.
- */
- String getAdvancedVpnPackageName();
-
- /**
- * Returns {@code true} advanced vpn is supported.
- */
- boolean isAdvancedVpnSupported(Context context);
-
- /**
- * Returns the title of advanced vpn preference group.
- */
- String getAdvancedVpnPreferenceGroupTitle(Context context);
-
- /**
- * Returns the title of vpn preference group.
- */
- String getVpnPreferenceGroupTitle(Context context);
-
- /**
- * Returns {@code true} advanced vpn is removable.
- */
- boolean isAdvancedVpnRemovable();
-
- /**
- * Returns {@code true} if the disconnect dialog is enabled when advanced vpn is connected.
- */
- boolean isDisconnectDialogEnabled();
-}
diff --git a/src/com/android/settings/vpn2/AdvancedVpnFeatureProviderImpl.java b/src/com/android/settings/vpn2/AdvancedVpnFeatureProviderImpl.java
deleted file mode 100644
index b8f58a9..0000000
--- a/src/com/android/settings/vpn2/AdvancedVpnFeatureProviderImpl.java
+++ /dev/null
@@ -1,54 +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.vpn2;
-
-import android.content.Context;
-
-/**
- * Feature provider implementation for advanced vpn.
- */
-public class AdvancedVpnFeatureProviderImpl implements AdvancedVpnFeatureProvider {
- @Override
- public String getAdvancedVpnPackageName() {
- return null;
- }
-
- @Override
- public boolean isAdvancedVpnSupported(Context context) {
- return false;
- }
-
- @Override
- public String getAdvancedVpnPreferenceGroupTitle(Context context) {
- return null;
- }
-
- @Override
- public String getVpnPreferenceGroupTitle(Context context) {
- return null;
- }
-
- @Override
- public boolean isAdvancedVpnRemovable() {
- return true;
- }
-
- @Override
- public boolean isDisconnectDialogEnabled() {
- return true;
- }
-}
diff --git a/src/com/android/settings/vpn2/AppManagementFragment.java b/src/com/android/settings/vpn2/AppManagementFragment.java
index d2fa5fc..d4ee5b9 100644
--- a/src/com/android/settings/vpn2/AppManagementFragment.java
+++ b/src/com/android/settings/vpn2/AppManagementFragment.java
@@ -48,7 +48,6 @@
import com.android.settings.SettingsPreferenceFragment;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.core.instrumentation.InstrumentedDialogFragment;
-import com.android.settings.overlay.FeatureFactory;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import com.android.settingslib.RestrictedPreference;
@@ -72,7 +71,6 @@
private PackageManager mPackageManager;
private DevicePolicyManager mDevicePolicyManager;
private VpnManager mVpnManager;
- private AdvancedVpnFeatureProvider mFeatureProvider;
// VPN app info
private final int mUserId = UserHandle.myUserId();
@@ -124,7 +122,6 @@
mPackageManager = getContext().getPackageManager();
mDevicePolicyManager = getContext().getSystemService(DevicePolicyManager.class);
mVpnManager = getContext().getSystemService(VpnManager.class);
- mFeatureProvider = FeatureFactory.getFactory(getContext()).getAdvancedVpnFeatureProvider();
mPreferenceAlwaysOn = (RestrictedSwitchPreference) findPreference(KEY_ALWAYS_ON_VPN);
mPreferenceLockdown = (RestrictedSwitchPreference) findPreference(KEY_LOCKDOWN_VPN);
@@ -286,16 +283,7 @@
}
}
- @VisibleForTesting
- void updateRestrictedViews() {
- if (mFeatureProvider.isAdvancedVpnSupported(getContext())
- && !mFeatureProvider.isAdvancedVpnRemovable()
- && TextUtils.equals(mPackageName, mFeatureProvider.getAdvancedVpnPackageName())) {
- mPreferenceForget.setVisible(false);
- } else {
- mPreferenceForget.setVisible(true);
- }
-
+ private void updateRestrictedViews() {
if (isAdded()) {
mPreferenceAlwaysOn.checkRestrictionAndSetDisabled(UserManager.DISALLOW_CONFIG_VPN,
mUserId);
@@ -326,14 +314,6 @@
}
}
- @VisibleForTesting
- void init(String packageName, AdvancedVpnFeatureProvider featureProvider,
- RestrictedPreference preference) {
- mPackageName = packageName;
- mFeatureProvider = featureProvider;
- mPreferenceForget = preference;
- }
-
private String getAlwaysOnVpnPackage() {
return mVpnManager.getAlwaysOnVpnPackageForUser(mUserId);
}
diff --git a/src/com/android/settings/vpn2/VpnSettings.java b/src/com/android/settings/vpn2/VpnSettings.java
index a91bb6c..e89785f 100644
--- a/src/com/android/settings/vpn2/VpnSettings.java
+++ b/src/com/android/settings/vpn2/VpnSettings.java
@@ -26,7 +26,6 @@
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.Intent;
-import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.ConnectivityManager;
@@ -43,7 +42,6 @@
import android.os.UserManager;
import android.security.Credentials;
import android.security.LegacyVpnProfileStore;
-import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.Log;
@@ -54,7 +52,6 @@
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceGroup;
-import androidx.preference.PreferenceScreen;
import com.android.internal.annotations.GuardedBy;
import com.android.internal.net.LegacyVpnInfo;
@@ -62,7 +59,6 @@
import com.android.internal.net.VpnProfile;
import com.android.settings.R;
import com.android.settings.RestrictedSettingsFragment;
-import com.android.settings.overlay.FeatureFactory;
import com.android.settings.widget.GearPreference;
import com.android.settings.widget.GearPreference.OnGearClickListener;
import com.android.settingslib.RestrictedLockUtilsInternal;
@@ -83,12 +79,9 @@
public class VpnSettings extends RestrictedSettingsFragment implements
Handler.Callback, Preference.OnPreferenceClickListener {
private static final String LOG_TAG = "VpnSettings";
- private static final boolean DEBUG = Log.isLoggable(LOG_TAG, Log.DEBUG);
private static final int RESCAN_MESSAGE = 0;
private static final int RESCAN_INTERVAL_MS = 1000;
- private static final String ADVANCED_VPN_GROUP_KEY = "advanced_vpn_group";
- private static final String VPN_GROUP_KEY = "vpn_group";
private static final NetworkRequest VPN_REQUEST = new NetworkRequest.Builder()
.removeCapability(NetworkCapabilities.NET_CAPABILITY_NOT_VPN)
@@ -109,9 +102,6 @@
private LegacyVpnInfo mConnectedLegacyVpn;
private boolean mUnavailable;
- private AdvancedVpnFeatureProvider mFeatureProvider;
- private PreferenceScreen mPreferenceScreen;
- private boolean mIsAdvancedVpnSupported;
public VpnSettings() {
super(UserManager.DISALLOW_CONFIG_VPN);
@@ -129,14 +119,11 @@
mUserManager = (UserManager) getSystemService(Context.USER_SERVICE);
mConnectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
mVpnManager = (VpnManager) getSystemService(Context.VPN_MANAGEMENT_SERVICE);
- mFeatureProvider = FeatureFactory.getFactory(getContext()).getAdvancedVpnFeatureProvider();
- mIsAdvancedVpnSupported = mFeatureProvider.isAdvancedVpnSupported(getContext());
mUnavailable = isUiRestricted();
setHasOptionsMenu(!mUnavailable);
addPreferencesFromResource(R.xml.vpn_settings2);
- mPreferenceScreen = getPreferenceScreen();
}
@Override
@@ -242,8 +229,7 @@
// Run heavy RPCs before switching to UI thread
final List<VpnProfile> vpnProfiles = loadVpnProfiles();
- final List<AppVpnInfo> vpnApps = getVpnApps(context, /* includeProfiles */ true,
- mFeatureProvider);
+ final List<AppVpnInfo> vpnApps = getVpnApps(context, /* includeProfiles */ true);
final Map<String, LegacyVpnInfo> connectedLegacyVpns = getConnectedLegacyVpns();
final Set<AppVpnInfo> connectedAppVpns = getConnectedAppVpns();
@@ -279,7 +265,7 @@
private final VpnSettings mSettings;
- UpdatePreferences(VpnSettings settings) {
+ public UpdatePreferences(VpnSettings settings) {
mSettings = settings;
}
@@ -346,14 +332,7 @@
}
// Trim out deleted VPN preferences
- if (DEBUG) {
- Log.d(LOG_TAG, "isAdvancedVpnSupported() : " + mSettings.mIsAdvancedVpnSupported);
- }
- if (mSettings.mIsAdvancedVpnSupported) {
- mSettings.setShownAdvancedPreferences(updates);
- } else {
- mSettings.setShownPreferences(updates);
- }
+ mSettings.setShownPreferences(updates);
}
}
@@ -364,61 +343,12 @@
@VisibleForTesting @UiThread
public void setShownPreferences(final Collection<Preference> updates) {
- retainAllPreference(updates);
-
- final PreferenceGroup vpnGroup = mPreferenceScreen;
- updatePreferenceGroup(vpnGroup, updates);
-
- // Show all new preferences on the screen
- for (Preference pref : updates) {
- vpnGroup.addPreference(pref);
- }
- }
-
- @VisibleForTesting @UiThread
- void setShownAdvancedPreferences(final Collection<Preference> updates) {
- retainAllPreference(updates);
-
- PreferenceGroup advancedVpnGroup = mPreferenceScreen.findPreference(ADVANCED_VPN_GROUP_KEY);
- PreferenceGroup vpnGroup = mPreferenceScreen.findPreference(VPN_GROUP_KEY);
- advancedVpnGroup.setTitle(
- mFeatureProvider.getAdvancedVpnPreferenceGroupTitle(getContext()));
- vpnGroup.setTitle(mFeatureProvider.getVpnPreferenceGroupTitle(getContext()));
- updatePreferenceGroup(advancedVpnGroup, updates);
- updatePreferenceGroup(vpnGroup, updates);
-
- // Show all new preferences on the screen
- for (Preference pref : updates) {
- String packageName = "";
- if (pref instanceof LegacyVpnPreference) {
- LegacyVpnPreference legacyPref = (LegacyVpnPreference) pref;
- packageName = legacyPref.getPackageName();
- } else if (pref instanceof AppPreference) {
- AppPreference appPref = (AppPreference) pref;
- packageName = appPref.getPackageName();
- }
- if (DEBUG) {
- Log.d(LOG_TAG, "setShownAdvancedPreferences() package name : " + packageName);
- }
- if (TextUtils.equals(packageName, mFeatureProvider.getAdvancedVpnPackageName())) {
- advancedVpnGroup.addPreference(pref);
- } else {
- vpnGroup.addPreference(pref);
- }
- }
-
- advancedVpnGroup.setVisible(advancedVpnGroup.getPreferenceCount() > 0);
- vpnGroup.setVisible(vpnGroup.getPreferenceCount() > 0);
- }
-
- private void retainAllPreference(Collection<Preference> updates) {
mLegacyVpnPreferences.values().retainAll(updates);
mAppPreferences.values().retainAll(updates);
- }
- private void updatePreferenceGroup(PreferenceGroup vpnGroup, Collection<Preference> updates) {
// Change {@param updates} in-place to only contain new preferences that were not already
// added to the preference screen.
+ final PreferenceGroup vpnGroup = getPreferenceScreen();
for (int i = vpnGroup.getPreferenceCount() - 1; i >= 0; i--) {
Preference p = vpnGroup.getPreference(i);
if (updates.contains(p)) {
@@ -427,6 +357,11 @@
vpnGroup.removePreference(p);
}
}
+
+ // Show any new preferences on the screen
+ for (Preference pref : updates) {
+ vpnGroup.addPreference(pref);
+ }
}
@Override
@@ -448,16 +383,14 @@
} else if (preference instanceof AppPreference) {
AppPreference pref = (AppPreference) preference;
boolean connected = (pref.getState() == AppPreference.STATE_CONNECTED);
- String vpnPackageName = pref.getPackageName();
- if ((!connected) || (isAdvancedVpn(mFeatureProvider, vpnPackageName, getContext())
- && !mFeatureProvider.isDisconnectDialogEnabled())) {
+ if (!connected) {
try {
UserHandle user = UserHandle.of(pref.getUserId());
- Context userContext = getContext().createPackageContextAsUser(
- getContext().getPackageName(), 0 /* flags */, user);
+ Context userContext = getActivity().createPackageContextAsUser(
+ getActivity().getPackageName(), 0 /* flags */, user);
PackageManager pm = userContext.getPackageManager();
- Intent appIntent = pm.getLaunchIntentForPackage(vpnPackageName);
+ Intent appIntent = pm.getLaunchIntentForPackage(pref.getPackageName());
if (appIntent != null) {
userContext.startActivityAsUser(appIntent, user);
return true;
@@ -537,32 +470,9 @@
pref.setOnPreferenceClickListener(this);
mAppPreferences.put(app, pref);
}
- enableAdvancedVpnGearIconIfNecessary(pref);
return pref;
}
- private void enableAdvancedVpnGearIconIfNecessary(AppPreference pref) {
- Context context = getContext();
- if (!isAdvancedVpn(mFeatureProvider, pref.getPackageName(), context)) {
- return;
- }
-
- boolean isEnabled = false;
- AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
- List<AppOpsManager.PackageOps> apps =
- appOpsManager.getPackagesForOps(
- new int[] {OP_ACTIVATE_VPN, OP_ACTIVATE_PLATFORM_VPN});
- if (apps != null) {
- for (AppOpsManager.PackageOps pkg : apps) {
- if (isAdvancedVpn(mFeatureProvider, pkg.getPackageName(), context)) {
- isEnabled = true;
- break;
- }
- }
- }
- pref.setOnGearClickListener(isEnabled ? mGearListener : null);
- }
-
@WorkerThread
private Map<String, LegacyVpnInfo> getConnectedLegacyVpns() {
mConnectedLegacyVpn = mVpnManager.getLegacyVpnInfo(UserHandle.myUserId());
@@ -598,15 +508,7 @@
return result;
}
- static List<AppVpnInfo> getVpnApps(Context context, boolean includeProfiles,
- AdvancedVpnFeatureProvider featureProvider) {
- return getVpnApps(context, includeProfiles, featureProvider,
- context.getSystemService(AppOpsManager.class));
- }
-
- @VisibleForTesting
- static List<AppVpnInfo> getVpnApps(Context context, boolean includeProfiles,
- AdvancedVpnFeatureProvider featureProvider, AppOpsManager aom) {
+ static List<AppVpnInfo> getVpnApps(Context context, boolean includeProfiles) {
List<AppVpnInfo> result = Lists.newArrayList();
final Set<Integer> profileIds;
@@ -619,19 +521,8 @@
profileIds = Collections.singleton(UserHandle.myUserId());
}
- if (featureProvider.isAdvancedVpnSupported(context)) {
- PackageManager pm = context.getPackageManager();
- try {
- ApplicationInfo appInfo =
- pm.getApplicationInfo(
- featureProvider.getAdvancedVpnPackageName(), /* flags= */ 0);
- int userId = UserHandle.getUserId(appInfo.uid);
- result.add(new AppVpnInfo(userId, featureProvider.getAdvancedVpnPackageName()));
- } catch (PackageManager.NameNotFoundException e) {
- Log.e(LOG_TAG, "Advanced VPN package name not found.", e);
- }
- }
-
+ // Fetch VPN-enabled apps from AppOps.
+ AppOpsManager aom = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
List<AppOpsManager.PackageOps> apps =
aom.getPackagesForOps(new int[] {OP_ACTIVATE_VPN, OP_ACTIVATE_PLATFORM_VPN});
if (apps != null) {
@@ -641,9 +532,6 @@
// Skip packages for users outside of our profile group.
continue;
}
- if (isAdvancedVpn(featureProvider, pkg.getPackageName(), context)) {
- continue;
- }
// Look for a MODE_ALLOWED permission to activate VPN.
boolean allowed = false;
for (AppOpsManager.OpEntry op : pkg.getOps()) {
@@ -662,12 +550,6 @@
return result;
}
- private static boolean isAdvancedVpn(AdvancedVpnFeatureProvider featureProvider,
- String packageName, Context context) {
- return featureProvider.isAdvancedVpnSupported(context)
- && TextUtils.equals(packageName, featureProvider.getAdvancedVpnPackageName());
- }
-
private static List<VpnProfile> loadVpnProfiles() {
final ArrayList<VpnProfile> result = Lists.newArrayList();
@@ -680,10 +562,4 @@
}
return result;
}
-
- @VisibleForTesting
- void init(PreferenceScreen preferenceScreen, AdvancedVpnFeatureProvider featureProvider) {
- mPreferenceScreen = preferenceScreen;
- mFeatureProvider = featureProvider;
- }
}
diff --git a/src/com/android/settings/wifi/WifiUtils.java b/src/com/android/settings/wifi/WifiUtils.java
index 4b94c81..a9010ac 100644
--- a/src/com/android/settings/wifi/WifiUtils.java
+++ b/src/com/android/settings/wifi/WifiUtils.java
@@ -22,14 +22,20 @@
import android.content.Context;
import android.content.pm.PackageManager;
import android.net.NetworkCapabilities;
+import android.net.TetheringManager;
import android.net.wifi.ScanResult;
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.provider.Settings;
import android.text.TextUtils;
+import android.util.Log;
+import androidx.annotation.VisibleForTesting;
+
+import com.android.settings.R;
import com.android.settings.Utils;
import com.android.wifitrackerlib.WifiEntry;
@@ -38,12 +44,16 @@
/** A utility class for Wi-Fi functions. */
public class WifiUtils extends com.android.settingslib.wifi.WifiUtils {
+ static final String TAG = "WifiUtils";
+
private static final int SSID_ASCII_MIN_LENGTH = 1;
private static final int SSID_ASCII_MAX_LENGTH = 32;
private static final int PSK_PASSPHRASE_ASCII_MIN_LENGTH = 8;
private static final int PSK_PASSPHRASE_ASCII_MAX_LENGTH = 63;
+ private static Boolean sCanShowWifiHotspotCached;
+
public static boolean isSSIDTooLong(String ssid) {
if (TextUtils.isEmpty(ssid)) {
return false;
@@ -240,4 +250,62 @@
return WifiEntry.SECURITY_NONE;
}
+
+ /**
+ * Check if Wi-Fi hotspot settings can be displayed.
+ *
+ * @param context Context of caller
+ * @return true if Wi-Fi hotspot settings can be displayed
+ */
+ public static boolean checkShowWifiHotspot(Context context) {
+ if (context == null) return false;
+
+ boolean showWifiHotspotSettings =
+ context.getResources().getBoolean(R.bool.config_show_wifi_hotspot_settings);
+ if (!showWifiHotspotSettings) {
+ Log.w(TAG, "config_show_wifi_hotspot_settings:false");
+ return false;
+ }
+
+ WifiManager wifiManager = context.getSystemService(WifiManager.class);
+ if (wifiManager == null) {
+ Log.e(TAG, "WifiManager is null");
+ return false;
+ }
+
+ TetheringManager tetheringManager = context.getSystemService(TetheringManager.class);
+ if (tetheringManager == null) {
+ Log.e(TAG, "TetheringManager is null");
+ return false;
+ }
+ String[] wifiRegexs = tetheringManager.getTetherableWifiRegexs();
+ if (wifiRegexs == null || wifiRegexs.length == 0) {
+ Log.w(TAG, "TetherableWifiRegexs is empty");
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Return the cached result to see if Wi-Fi hotspot settings can be displayed.
+ *
+ * @param context Context of caller
+ * @return true if Wi-Fi hotspot settings can be displayed
+ */
+ public static boolean canShowWifiHotspot(Context context) {
+ if (sCanShowWifiHotspotCached == null) {
+ sCanShowWifiHotspotCached = checkShowWifiHotspot(context);
+ }
+ return sCanShowWifiHotspotCached;
+ }
+
+ /**
+ * Sets the sCanShowWifiHotspotCached for testing purposes.
+ *
+ * @param cached Cached value for #canShowWifiHotspot()
+ */
+ @VisibleForTesting
+ public static void setCanShowWifiHotspotCached(Boolean cached) {
+ sCanShowWifiHotspotCached = cached;
+ }
}
diff --git a/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java b/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java
index 73ff31d..a9c3559 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherPreferenceController.java
@@ -16,9 +16,10 @@
package com.android.settings.wifi.tether;
+import static com.android.settings.wifi.WifiUtils.canShowWifiHotspot;
+
import android.annotation.NonNull;
import android.content.Context;
-import android.net.TetheringManager;
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.WifiClient;
import android.net.wifi.WifiManager;
@@ -46,7 +47,6 @@
private static final String WIFI_TETHER_SETTINGS = "wifi_tether";
- private boolean mIsWifiTetherable;
private WifiManager mWifiManager;
private boolean mIsWifiTetheringAllow;
private int mSoftApState;
@@ -57,8 +57,7 @@
public WifiTetherPreferenceController(Context context, Lifecycle lifecycle) {
this(context, lifecycle,
- context.getSystemService(WifiManager.class),
- context.getSystemService(TetheringManager.class),
+ context.getApplicationContext().getSystemService(WifiManager.class),
true /* initSoftApManager */,
WifiEnterpriseRestrictionUtils.isWifiTetheringAllowed(context));
}
@@ -68,15 +67,9 @@
Context context,
Lifecycle lifecycle,
WifiManager wifiManager,
- TetheringManager tetheringManager,
boolean initSoftApManager,
boolean isWifiTetheringAllow) {
super(context);
- final String[] wifiRegexs = tetheringManager.getTetherableWifiRegexs();
- if (wifiRegexs != null && wifiRegexs.length != 0) {
- mIsWifiTetherable = true;
- }
-
mIsWifiTetheringAllow = isWifiTetheringAllow;
if (!isWifiTetheringAllow) return;
@@ -92,7 +85,7 @@
@Override
public boolean isAvailable() {
- return mIsWifiTetherable && !Utils.isMonkeyRunning();
+ return canShowWifiHotspot(mContext) && !Utils.isMonkeyRunning();
}
@Override
diff --git a/src/com/android/settings/wifi/tether/WifiTetherSettings.java b/src/com/android/settings/wifi/tether/WifiTetherSettings.java
index 5b9ce42..47dba76 100644
--- a/src/com/android/settings/wifi/tether/WifiTetherSettings.java
+++ b/src/com/android/settings/wifi/tether/WifiTetherSettings.java
@@ -18,6 +18,8 @@
import static android.net.wifi.WifiManager.WIFI_AP_STATE_CHANGED_ACTION;
+import static com.android.settings.wifi.WifiUtils.canShowWifiHotspot;
+
import android.app.settings.SettingsEnums;
import android.content.BroadcastReceiver;
import android.content.Context;
@@ -39,6 +41,7 @@
import com.android.settings.dashboard.RestrictedDashboardFragment;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.widget.SettingsMainSwitchBar;
+import com.android.settings.wifi.WifiUtils;
import com.android.settingslib.TetherUtil;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.search.SearchIndexable;
@@ -108,6 +111,13 @@
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ if (!canShowWifiHotspot(getContext())) {
+ Log.e(TAG, "can not launch Wi-Fi hotspot settings"
+ + " because the config is not set to show.");
+ finish();
+ return;
+ }
+
setIfOnlyAvailableForAdmins(true);
mUnavailable = isUiRestricted() || !mWifiRestriction.isHotspotAvailable(getContext());
}
@@ -287,12 +297,12 @@
@Override
protected boolean isPageSearchEnabled(Context context) {
+ if (context == null || !WifiUtils.canShowWifiHotspot(context)) return false;
return !FeatureFlagUtils.isEnabled(context, FeatureFlags.TETHER_ALL_IN_ONE);
}
@Override
- public List<AbstractPreferenceController> createPreferenceControllers(
- Context context) {
+ public List<AbstractPreferenceController> createPreferenceControllers(Context context) {
return buildPreferenceControllers(context, null /* listener */);
}
}
diff --git a/tests/robotests/src/com/android/settings/MainClearTest.java b/tests/robotests/src/com/android/settings/MainClearTest.java
index ec33fad..9795092 100644
--- a/tests/robotests/src/com/android/settings/MainClearTest.java
+++ b/tests/robotests/src/com/android/settings/MainClearTest.java
@@ -102,7 +102,10 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
- mMainClear = spy(new MainClear());
+ mMainClear = spy(new MainClear() {
+ @Override
+ boolean showAnySubscriptionInfo(Context context) { return true; }
+ });
mActivity = Robolectric.setupActivity(FragmentActivity.class);
mShadowActivity = Shadows.shadowOf(mActivity);
UserManager userManager = mActivity.getSystemService(UserManager.class);
diff --git a/tests/robotests/src/com/android/settings/TetherSettingsTest.java b/tests/robotests/src/com/android/settings/TetherSettingsTest.java
index 71cb9d2..79814b3 100644
--- a/tests/robotests/src/com/android/settings/TetherSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/TetherSettingsTest.java
@@ -20,6 +20,8 @@
import static android.content.Intent.ACTION_MEDIA_UNSHARED;
import static android.hardware.usb.UsbManager.ACTION_USB_STATE;
+import static com.android.settings.wifi.WifiUtils.setCanShowWifiHotspotCached;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
@@ -93,6 +95,7 @@
any(String.class), anyInt(), any(UserHandle.class));
setupIsTetherAvailable(true);
+ setCanShowWifiHotspotCached(true);
when(mTetheringManager.getTetherableUsbRegexs()).thenReturn(new String[0]);
when(mTetheringManager.getTetherableBluetoothRegexs()).thenReturn(new String[0]);
@@ -124,6 +127,16 @@
}
@Test
+ public void getNonIndexableKeys_canNotShowWifiHotspot_containsWifiTether() {
+ setCanShowWifiHotspotCached(false);
+ setupIsTetherAvailable(true);
+
+ List<String> keys = TetherSettings.SEARCH_INDEX_DATA_PROVIDER.getNonIndexableKeys(mContext);
+
+ assertThat(keys).contains(TetherSettings.KEY_WIFI_TETHER);
+ }
+
+ @Test
public void testTetherNonIndexableKeys_usbNotAvailable_usbKeyReturned() {
when(mTetheringManager.getTetherableUsbRegexs()).thenReturn(new String[0]);
diff --git a/tests/robotests/src/com/android/settings/biometrics/combination/CombinedBiometricProfileSettingsTest.java b/tests/robotests/src/com/android/settings/biometrics/combination/CombinedBiometricProfileSettingsTest.java
new file mode 100644
index 0000000..ac8008d
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/biometrics/combination/CombinedBiometricProfileSettingsTest.java
@@ -0,0 +1,358 @@
+/*
+ * 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.biometrics.combination;
+
+import static com.android.settings.biometrics.combination.BiometricsSettingsBase.CONFIRM_REQUEST;
+import static com.android.settings.password.ChooseLockPattern.RESULT_FINISHED;
+
+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.anyLong;
+import static org.mockito.Mockito.doAnswer;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.content.Context;
+import android.content.Intent;
+import android.hardware.face.FaceManager;
+import android.hardware.fingerprint.FingerprintManager;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.XmlRes;
+import androidx.fragment.app.FragmentActivity;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceManager;
+import androidx.preference.PreferenceScreen;
+import androidx.test.core.app.ApplicationProvider;
+
+import com.android.settings.R;
+import com.android.settings.password.ChooseLockSettingsHelper;
+import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.shadow.ShadowFragment;
+import com.android.settings.testutils.shadow.ShadowSettingsPreferenceFragment;
+import com.android.settings.testutils.shadow.ShadowUtils;
+import com.android.settingslib.core.AbstractPreferenceController;
+
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
+import org.robolectric.util.ReflectionHelpers;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(shadows = {ShadowSettingsPreferenceFragment.class, ShadowUtils.class, ShadowFragment.class})
+public class CombinedBiometricProfileSettingsTest {
+
+ private TestCombinedBiometricProfileSettings mFragment;
+ private Context mContext;
+
+ @Rule
+ public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ @Captor
+ private ArgumentCaptor<Preference> mPreferenceCaptor;
+ @Mock
+ private FingerprintManager mFingerprintManager;
+ @Mock
+ private BiometricSettingsAppPreferenceController mBiometricSettingsAppPreferenceController;
+ @Mock
+ private FaceManager mFaceManager;
+
+ @Before
+ public void setUp() {
+ ShadowUtils.setFingerprintManager(mFingerprintManager);
+ ShadowUtils.setFaceManager(mFaceManager);
+ FakeFeatureFactory.setupForTest();
+
+ FragmentActivity activity = Robolectric.buildActivity(FragmentActivity.class,
+ new Intent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, 1L)).get();
+ mContext = spy(ApplicationProvider.getApplicationContext());
+ mFragment = spy(new TestCombinedBiometricProfileSettings(mContext));
+ doReturn(activity).when(mFragment).getActivity();
+
+ ReflectionHelpers.setField(mFragment, "mDashboardFeatureProvider",
+ FakeFeatureFactory.setupForTest().dashboardFeatureProvider);
+
+ final Map<Class<?>, List<AbstractPreferenceController>> preferenceControllers =
+ ReflectionHelpers.getField(mFragment, "mPreferenceControllers");
+ List<AbstractPreferenceController> controllerList = new ArrayList<>();
+ controllerList.add(mBiometricSettingsAppPreferenceController);
+ preferenceControllers.put(BiometricSettingsAppPreferenceController.class, controllerList);
+
+ doAnswer(invocation -> {
+ final CharSequence key = invocation.getArgument(0);
+ final Preference preference = new Preference(mContext);
+ preference.setKey(key.toString());
+ return preference;
+ }).when(mFragment).findPreference(any());
+ }
+
+ @Test
+ public void testClickFingerprintUnlockWithValidGkPwHandle() {
+ doAnswer(invocation -> {
+ final FingerprintManager.GenerateChallengeCallback callback =
+ invocation.getArgument(1);
+ callback.onChallengeGenerated(0, 0, 1L);
+ return null;
+ }).when(mFingerprintManager).generateChallenge(anyInt(), any());
+ doReturn(new byte[] { 1 }).when(mFragment).requestGatekeeperHat(any(), anyLong(), anyInt(),
+ anyLong());
+
+ // Start fragment
+ mFragment.onAttach(mContext);
+ mFragment.onCreate(null);
+ mFragment.onCreateView(LayoutInflater.from(mContext), mock(ViewGroup.class), Bundle.EMPTY);
+ mFragment.onResume();
+
+ // User clicks on "Fingerprint Unlock"
+ final Preference preference = new Preference(mContext);
+ preference.setKey(mFragment.getFingerprintPreferenceKey());
+ mFragment.onPreferenceTreeClick(preference);
+
+ verify(mBiometricSettingsAppPreferenceController).handlePreferenceTreeClick(
+ mPreferenceCaptor.capture());
+ List<Preference> capturedPreferences = mPreferenceCaptor.getAllValues();
+
+ assertThat(capturedPreferences.size()).isEqualTo(1);
+ assertThat(capturedPreferences.get(0).getKey())
+ .isEqualTo(mFragment.getFingerprintPreferenceKey());
+ }
+
+ @Test
+ public void testClickFingerprintUnlockIfGkPwHandleTimeout() {
+ doAnswer(invocation -> {
+ final FingerprintManager.GenerateChallengeCallback callback =
+ invocation.getArgument(1);
+ callback.onChallengeGenerated(0, 0, 1L);
+ return null;
+ }).when(mFingerprintManager).generateChallenge(anyInt(), any());
+ doThrow(new IllegalStateException("Test")).when(mFragment).requestGatekeeperHat(any(),
+ anyLong(), anyInt(), anyLong());
+
+ // Start fragment
+ mFragment.onAttach(mContext);
+ mFragment.onCreate(null);
+ mFragment.onCreateView(LayoutInflater.from(mContext), mock(ViewGroup.class), Bundle.EMPTY);
+ mFragment.onResume();
+
+ // User clicks on "Fingerprint Unlock"
+ final Preference preference = new Preference(mContext);
+ preference.setKey(mFragment.getFingerprintPreferenceKey());
+ mFragment.onPreferenceTreeClick(preference);
+
+ verify(mFragment).launchChooseOrConfirmLock();
+ }
+
+ @Test
+ public void testActivityResultLaunchFingerprintUnlock() {
+ doAnswer(invocation -> {
+ final FingerprintManager.GenerateChallengeCallback callback =
+ invocation.getArgument(1);
+ callback.onChallengeGenerated(0, 0, 1L);
+ return null;
+ }).when(mFingerprintManager).generateChallenge(anyInt(), any());
+ doReturn(new byte[] { 1 }).when(mFragment).requestGatekeeperHat(any(), anyLong(), anyInt(),
+ anyLong());
+
+ // Start fragment
+ mFragment.onAttach(mContext);
+ final Bundle bundle = new Bundle();
+ bundle.putString(BiometricsSettingsBase.RETRY_PREFERENCE_KEY,
+ mFragment.getFingerprintPreferenceKey());
+ final Bundle retryBundle = new Bundle();
+ bundle.putBundle(BiometricsSettingsBase.RETRY_PREFERENCE_BUNDLE, retryBundle);
+ mFragment.onCreate(bundle);
+ mFragment.onCreateView(LayoutInflater.from(mContext), mock(ViewGroup.class), Bundle.EMPTY);
+ mFragment.onResume();
+
+ // onActivityResult
+ mFragment.onActivityResult(CONFIRM_REQUEST, RESULT_FINISHED,
+ new Intent().putExtra(ChooseLockSettingsHelper.EXTRA_KEY_GK_PW_HANDLE, 1L));
+
+ verify(mBiometricSettingsAppPreferenceController).handlePreferenceTreeClick(
+ mPreferenceCaptor.capture());
+ List<Preference> capturedPreferences = mPreferenceCaptor.getAllValues();
+ assertThat(capturedPreferences.size()).isEqualTo(1);
+ assertThat(capturedPreferences.get(0).getKey())
+ .isEqualTo(mFragment.getFingerprintPreferenceKey());
+ }
+
+ @Test
+ public void testClickFaceUnlock() {
+ doAnswer(invocation -> {
+ final FaceManager.GenerateChallengeCallback callback =
+ invocation.getArgument(1);
+ callback.onGenerateChallengeResult(0, 0, 1L);
+ return null;
+ }).when(mFaceManager).generateChallenge(anyInt(), any());
+ doReturn(new byte[] { 1 }).when(mFragment).requestGatekeeperHat(any(), anyLong(), anyInt(),
+ anyLong());
+
+ // Start fragment
+ mFragment.onAttach(mContext);
+ mFragment.onCreate(null);
+ mFragment.onCreateView(LayoutInflater.from(mContext), mock(ViewGroup.class), Bundle.EMPTY);
+ mFragment.onResume();
+
+ // User clicks on "Face Unlock"
+ final Preference preference = new Preference(mContext);
+ preference.setKey(mFragment.getFacePreferenceKey());
+ mFragment.onPreferenceTreeClick(preference);
+
+ verify(mBiometricSettingsAppPreferenceController).handlePreferenceTreeClick(
+ mPreferenceCaptor.capture());
+ List<Preference> capturedPreferences = mPreferenceCaptor.getAllValues();
+ assertThat(capturedPreferences.size()).isEqualTo(1);
+ assertThat(capturedPreferences.get(0).getKey()).isEqualTo(mFragment.getFacePreferenceKey());
+ }
+
+ @Test
+ public void testClickFaceUnlockIfGkPwHandleTimeout() {
+ doAnswer(invocation -> {
+ final FaceManager.GenerateChallengeCallback callback =
+ invocation.getArgument(1);
+ callback.onGenerateChallengeResult(0, 0, 1L);
+ return null;
+ }).when(mFaceManager).generateChallenge(anyInt(), any());
+ doThrow(new IllegalStateException("Test")).when(mFragment).requestGatekeeperHat(any(),
+ anyLong(), anyInt(), anyLong());
+
+ // Start fragment
+ mFragment.onAttach(mContext);
+ mFragment.onCreate(null);
+ mFragment.onCreateView(LayoutInflater.from(mContext), mock(ViewGroup.class), Bundle.EMPTY);
+ mFragment.onResume();
+
+ // User clicks on "Face Unlock"
+ final Preference preference = new Preference(mContext);
+ preference.setKey(mFragment.getFacePreferenceKey());
+ mFragment.onPreferenceTreeClick(preference);
+
+ verify(mFragment).launchChooseOrConfirmLock();
+ }
+
+ @Test
+ public void testActivityResultLaunchFaceUnlock() {
+ doAnswer(invocation -> {
+ final FaceManager.GenerateChallengeCallback callback =
+ invocation.getArgument(1);
+ callback.onGenerateChallengeResult(0, 0, 1L);
+ return null;
+ }).when(mFaceManager).generateChallenge(anyInt(), any());
+ doReturn(new byte[] { 1 }).when(mFragment).requestGatekeeperHat(any(), anyLong(), anyInt(),
+ anyLong());
+
+ // Start fragment
+ mFragment.onAttach(mContext);
+ final Bundle bundle = new Bundle();
+ bundle.putString(BiometricsSettingsBase.RETRY_PREFERENCE_KEY,
+ mFragment.getFingerprintPreferenceKey());
+ final Bundle retryBundle = new Bundle();
+ bundle.putBundle(BiometricsSettingsBase.RETRY_PREFERENCE_BUNDLE, retryBundle);
+ mFragment.onCreate(bundle);
+ mFragment.onCreateView(LayoutInflater.from(mContext), mock(ViewGroup.class), Bundle.EMPTY);
+ mFragment.onResume();
+
+ // User clicks on "Face Unlock"
+ final Preference preference = new Preference(mContext);
+ preference.setKey(mFragment.getFacePreferenceKey());
+ mFragment.onPreferenceTreeClick(preference);
+
+ verify(mBiometricSettingsAppPreferenceController).handlePreferenceTreeClick(
+ mPreferenceCaptor.capture());
+ List<Preference> capturedPreferences = mPreferenceCaptor.getAllValues();
+ assertThat(capturedPreferences.size()).isEqualTo(1);
+ assertThat(capturedPreferences.get(0).getKey()).isEqualTo(mFragment.getFacePreferenceKey());
+ }
+
+ /**
+ * a test fragment that initializes PreferenceScreen for testing.
+ */
+ static class TestCombinedBiometricProfileSettings extends CombinedBiometricProfileSettings {
+
+ private final Context mContext;
+ private final PreferenceManager mPreferenceManager;
+
+ TestCombinedBiometricProfileSettings(Context context) {
+ super();
+ mContext = context;
+ mPreferenceManager = new PreferenceManager(context);
+ mPreferenceManager.setPreferences(mPreferenceManager.createPreferenceScreen(context));
+ setArguments(new Bundle());
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return 0;
+ }
+
+ @Override
+ public int getPreferenceScreenResId() {
+ return R.xml.placeholder_prefs;
+ }
+
+ @Override
+ public PreferenceScreen getPreferenceScreen() {
+ return mPreferenceManager.getPreferenceScreen();
+ }
+
+ @Override
+ public PreferenceManager getPreferenceManager() {
+ return mPreferenceManager;
+ }
+
+ @Override
+ public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
+ // do nothing
+ }
+
+ @Override
+ public void addPreferencesFromResource(@XmlRes int preferencesResId) {
+ // do nothing
+ }
+
+ @Override
+ public Context getContext() {
+ return mContext;
+ }
+
+ @Override
+ protected void launchChooseOrConfirmLock() {
+ // do nothing
+ }
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/biometrics/face/FaceSettingsLockscreenBypassPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/biometrics/face/FaceSettingsLockscreenBypassPreferenceControllerTest.java
index b9692cf..77a6b02 100644
--- a/tests/robotests/src/com/android/settings/biometrics/face/FaceSettingsLockscreenBypassPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/face/FaceSettingsLockscreenBypassPreferenceControllerTest.java
@@ -31,6 +31,7 @@
import android.os.UserManager;
import android.provider.Settings;
+import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowUtils;
import com.android.settingslib.RestrictedLockUtils.EnforcedAdmin;
import com.android.settingslib.RestrictedSwitchPreference;
@@ -65,6 +66,9 @@
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
+ ShadowUtils.setFaceManager(mFaceManager);
+ FakeFeatureFactory.setupForTest();
+
mContext = spy(RuntimeEnvironment.application);
when(mContext.getSystemService(eq(Context.FACE_SERVICE))).thenReturn(mFaceManager);
when(mContext.getPackageManager()).thenReturn(mPackageManager);
diff --git a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java
index b808319..289bfab 100644
--- a/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java
+++ b/tests/robotests/src/com/android/settings/biometrics/fingerprint/FingerprintEnrollEnrollingTest.java
@@ -18,6 +18,7 @@
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_POWER_BUTTON;
import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UDFPS_OPTICAL;
+import static android.hardware.fingerprint.FingerprintSensorProperties.TYPE_UNKNOWN;
import static com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling.KEY_STATE_PREVIOUS_ROTATION;
import static com.android.settings.biometrics.fingerprint.FingerprintEnrollEnrolling.SFPS_STAGE_NO_ANIMATION;
@@ -35,6 +36,8 @@
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import static org.mockito.Mockito.mock;
+
import android.content.Context;
import android.content.res.ColorStateList;
@@ -52,6 +55,8 @@
import android.view.Surface;
import android.widget.TextView;
+import androidx.annotation.Nullable;
+
import com.android.settings.R;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.widget.RingProgressBar;
@@ -59,7 +64,6 @@
import com.airbnb.lottie.LottieAnimationView;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -100,16 +104,39 @@
}
@Test
- @Ignore
public void fingerprintEnrollHelp_shouldShowHelpText() {
- EnrollmentCallback enrollmentCallback = verifyAndCaptureEnrollmentCallback();
+ initializeActivityFor(TYPE_UNKNOWN);
+ TestFingerprintEnrollSidecar sidecar = new TestFingerprintEnrollSidecar();
+ Resources resources = mock(Resources.class);
+ doReturn(resources).when(mContext).getResources();
+ when(resources.getIntArray(R.array.fingerprint_acquired_ignore_list))
+ .thenReturn(new int[]{3});
- enrollmentCallback.onEnrollmentProgress(123);
- enrollmentCallback.onEnrollmentHelp(
- FingerprintManager.FINGERPRINT_ERROR_UNABLE_TO_PROCESS, "test enrollment help");
+ sidecar.setListener(mActivity);
+ sidecar.onAttach(mActivity);
+ sidecar.mEnrollmentCallback.onEnrollmentHelp(5,
+ "Help message should be displayed.");
TextView errorText = mActivity.findViewById(R.id.error_text);
- assertThat(errorText.getText()).isEqualTo("test enrollment help");
+ assertThat(errorText.getText()).isEqualTo("Help message should be displayed.");
+ }
+
+ @Test
+ public void fingerprintEnrollHelp_shouldNotShowHelpText() {
+ initializeActivityFor(TYPE_UNKNOWN);
+ TestFingerprintEnrollSidecar sidecar = new TestFingerprintEnrollSidecar();
+ Resources resources = mock(Resources.class);
+ doReturn(resources).when(mContext).getResources();
+ when(resources.getIntArray(R.array.fingerprint_acquired_ignore_list))
+ .thenReturn(new int[]{3});
+
+ sidecar.setListener(mActivity);
+ sidecar.onAttach(mActivity);
+ sidecar.mEnrollmentCallback.onEnrollmentHelp(3,
+ "Help message should not be displayed.");
+
+ TextView errorText = mActivity.findViewById(R.id.error_text);
+ assertThat(errorText.getText()).isEqualTo("");
}
@Test
@@ -151,6 +178,16 @@
}
@Test
+ public void fingerprintUdfpsOverlayEnrollment_loseFocusWithCancelFlag_shouldNotCancelAgain() {
+ initializeActivityFor(TYPE_UDFPS_OPTICAL);
+
+ mActivity.mIsCanceled = true;
+ mActivity.onWindowFocusChanged(true);
+
+ verify(mActivity, never()).onCancelEnrollment(anyInt());
+ }
+
+ @Test
public void fingerprintSfpsEnroll_PlaysAllAnimationsAssetsCorrectly() {
initializeActivityFor(TYPE_POWER_BUTTON);
@@ -309,4 +346,12 @@
return callbackCaptor.getValue();
}
+
+ private class TestFingerprintEnrollSidecar extends FingerprintEnrollSidecar {
+ @Nullable
+ @Override
+ public Context getContext() {
+ return mContext;
+ }
+ }
}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceControllerTest.java
index 55194ad..bae629c 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/imei/ImeiInfoPreferenceControllerTest.java
@@ -29,6 +29,7 @@
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.content.res.Resources;
import android.os.UserManager;
import android.telephony.TelephonyManager;
@@ -69,12 +70,18 @@
private PreferenceCategory mCategory;
private Context mContext;
+ private Resources mResources;
private ImeiInfoPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
+
+ mResources = spy(mContext.getResources());
+ when(mContext.getResources()).thenReturn(mResources);
+ when(mResources.getBoolean(R.bool.config_show_sim_info)).thenReturn(true);
+
doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
mController = spy(new ImeiInfoPreferenceController(mContext, "imei_info"));
mController.setHost(mFragment);
diff --git a/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceControllerTest.java
index 85a6fac..4ffaf7a 100644
--- a/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/deviceinfo/simstatus/SimStatusPreferenceControllerTest.java
@@ -25,6 +25,7 @@
import android.content.Context;
import android.os.UserManager;
+import android.content.res.Resources;
import android.telephony.TelephonyManager;
import androidx.fragment.app.Fragment;
@@ -64,12 +65,18 @@
private PreferenceCategory mCategory;
private Context mContext;
+ private Resources mResources;
private SimStatusPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
+
+ mResources = spy(mContext.getResources());
+ when(mContext.getResources()).thenReturn(mResources);
+ when(mResources.getBoolean(R.bool.config_show_sim_info)).thenReturn(true);
+
doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
mController = spy(new SimStatusPreferenceController(mContext, mFragment));
doReturn(true).when(mController).isAvailable();
diff --git a/tests/robotests/src/com/android/settings/dream/DreamSettingsTest.java b/tests/robotests/src/com/android/settings/dream/DreamSettingsTest.java
index a554564..c1cc6ae 100644
--- a/tests/robotests/src/com/android/settings/dream/DreamSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/dream/DreamSettingsTest.java
@@ -29,33 +29,40 @@
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
import java.util.Arrays;
import java.util.List;
-import org.robolectric.RobolectricTestRunner;
@RunWith(RobolectricTestRunner.class)
public class DreamSettingsTest {
private static final List<String> KEYS = Arrays.asList(
- DreamSettings.WHILE_CHARGING_ONLY,
- DreamSettings.WHILE_DOCKED_ONLY,
- DreamSettings.EITHER_CHARGING_OR_DOCKED,
- DreamSettings.NEVER_DREAM
+ DreamSettings.WHILE_CHARGING_ONLY,
+ DreamSettings.WHILE_DOCKED_ONLY,
+ DreamSettings.EITHER_CHARGING_OR_DOCKED,
+ DreamSettings.NEVER_DREAM
);
private static final @WhenToDream int[] SETTINGS = {
- DreamBackend.WHILE_CHARGING,
- DreamBackend.WHILE_DOCKED,
- DreamBackend.EITHER,
- DreamBackend.NEVER,
+ DreamBackend.WHILE_CHARGING,
+ DreamBackend.WHILE_DOCKED,
+ DreamBackend.EITHER,
+ DreamBackend.NEVER,
};
private static final int[] RES_IDS = {
- R.string.screensaver_settings_summary_sleep,
- R.string.screensaver_settings_summary_dock,
- R.string.screensaver_settings_summary_either_long,
- R.string.screensaver_settings_summary_never
+ R.string.screensaver_settings_summary_sleep,
+ R.string.screensaver_settings_summary_dock,
+ R.string.screensaver_settings_summary_either_long,
+ R.string.screensaver_settings_summary_never
+ };
+
+ private static final int[] RES_IDS_NO_BATTERY = {
+ R.string.screensaver_settings_summary_sleep,
+ R.string.screensaver_settings_summary_dock_and_charging,
+ R.string.screensaver_settings_summary_either_long,
+ R.string.screensaver_settings_summary_never
};
@Test
@@ -81,11 +88,17 @@
@Test
public void getDreamSettingDescriptionResId() {
for (int i = 0; i < SETTINGS.length; i++) {
- assertThat(DreamSettings.getDreamSettingDescriptionResId(SETTINGS[i]))
+ assertThat(DreamSettings.getDreamSettingDescriptionResId(
+ SETTINGS[i], /* enabledOnBattery= */ false))
+ .isEqualTo(RES_IDS_NO_BATTERY[i]);
+ assertThat(DreamSettings.getDreamSettingDescriptionResId(
+ SETTINGS[i], /* enabledOnBattery= */ true))
.isEqualTo(RES_IDS[i]);
}
// Default
- assertThat(DreamSettings.getDreamSettingDescriptionResId(-1))
+ assertThat(DreamSettings.getDreamSettingDescriptionResId(-1, /* enabledOnBattery= */ false))
+ .isEqualTo(R.string.screensaver_settings_summary_never);
+ assertThat(DreamSettings.getDreamSettingDescriptionResId(-1, /* enabledOnBattery= */ true))
.isEqualTo(R.string.screensaver_settings_summary_never);
}
diff --git a/tests/robotests/src/com/android/settings/dream/WhenToDreamPickerTest.java b/tests/robotests/src/com/android/settings/dream/WhenToDreamPickerTest.java
index 16f8599..91ec299 100644
--- a/tests/robotests/src/com/android/settings/dream/WhenToDreamPickerTest.java
+++ b/tests/robotests/src/com/android/settings/dream/WhenToDreamPickerTest.java
@@ -28,6 +28,7 @@
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.testutils.FakeFeatureFactory;
+import com.android.settings.testutils.shadow.SettingsShadowResources;
import com.android.settingslib.dream.DreamBackend;
import org.junit.Before;
@@ -37,9 +38,11 @@
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
+import org.robolectric.annotation.Config;
import org.robolectric.util.ReflectionHelpers;
@RunWith(RobolectricTestRunner.class)
+@Config(shadows = SettingsShadowResources.class)
public class WhenToDreamPickerTest {
private WhenToDreamPicker mPicker;
@@ -53,10 +56,15 @@
MockitoAnnotations.initMocks(this);
final Context context = spy(ApplicationProvider.getApplicationContext());
+ SettingsShadowResources.overrideResource(
+ com.android.internal.R.bool.config_dreamsEnabledOnBattery,
+ true);
+
when(context.getSystemService(Context.USER_SERVICE)).thenReturn(mUserManager);
FakeFeatureFactory.setupForTest();
- mPicker = new WhenToDreamPicker();
+ mPicker = spy(new WhenToDreamPicker());
+ when(mPicker.getContext()).thenReturn(context);
mPicker.onAttach(context);
ReflectionHelpers.setField(mPicker, "mBackend", mBackend);
diff --git a/tests/robotests/src/com/android/settings/dream/WhenToDreamPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/dream/WhenToDreamPreferenceControllerTest.java
index 3305cde..6e687bb 100644
--- a/tests/robotests/src/com/android/settings/dream/WhenToDreamPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/dream/WhenToDreamPreferenceControllerTest.java
@@ -16,15 +16,24 @@
package com.android.settings.dream;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.anyInt;
+import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.mock;
+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.pm.ApplicationInfo;
+import android.content.pm.PackageManager;
+import android.os.PowerManager;
import androidx.preference.Preference;
import androidx.test.core.app.ApplicationProvider;
+import com.android.settings.R;
+import com.android.settings.display.AmbientDisplayAlwaysOnPreferenceController;
import com.android.settingslib.dream.DreamBackend;
import com.android.settingslib.dream.DreamBackend.WhenToDream;
@@ -38,32 +47,64 @@
@RunWith(RobolectricTestRunner.class)
public class WhenToDreamPreferenceControllerTest {
+ private static final String TEST_PACKAGE = "com.android.test";
private WhenToDreamPreferenceController mController;
private Context mContext;
@Mock
private DreamBackend mBackend;
+ @Mock
+ private PowerManager mPowerManager;
+ @Mock
+ private PackageManager mPackageManager;
+ @Mock
+ private ApplicationInfo mApplicationInfo;
@Before
- public void setup() {
+ public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
- mContext = ApplicationProvider.getApplicationContext();
- mController = new WhenToDreamPreferenceController(mContext);
+ mContext = spy(ApplicationProvider.getApplicationContext());
+ mController = new WhenToDreamPreferenceController(mContext, true, true);
ReflectionHelpers.setField(mController, "mBackend", mBackend);
+ when(mContext.getSystemService(PowerManager.class)).thenReturn(mPowerManager);
+ when(mPowerManager.isAmbientDisplaySuppressedForTokenByApp(anyString(), anyInt()))
+ .thenReturn(false);
+
+ mApplicationInfo.uid = 1;
+ when(mContext.getString(
+ com.android.internal.R.string.config_defaultWellbeingPackage)).thenReturn(
+ TEST_PACKAGE);
+
+ when(mContext.getPackageManager()).thenReturn(mPackageManager);
+ when(mPackageManager.getApplicationInfo(TEST_PACKAGE, /* flag= */ 0)).thenReturn(
+ mApplicationInfo);
}
@Test
- public void updateSummary() {
+ public void testUpdateSummary() {
// Don't have to test the other settings because DreamSettings tests that all
// @WhenToDream values map to the correct ResId
final @WhenToDream int testSetting = DreamBackend.WHILE_CHARGING;
final Preference mockPref = mock(Preference.class);
when(mockPref.getContext()).thenReturn(mContext);
when(mBackend.getWhenToDreamSetting()).thenReturn(testSetting);
- final String expectedString =
- mContext.getString(DreamSettings.getDreamSettingDescriptionResId(testSetting));
+ final int expectedResId = DreamSettings.getDreamSettingDescriptionResId(testSetting, true);
mController.updateState(mockPref);
- verify(mockPref).setSummary(expectedString);
+ verify(mockPref).setSummary(expectedResId);
+ }
+
+ @Test
+ public void testBedtimeModeSuppression() {
+ final Preference mockPref = mock(Preference.class);
+ when(mockPref.getContext()).thenReturn(mContext);
+ when(mBackend.getWhenToDreamSetting()).thenReturn(DreamBackend.WHILE_CHARGING);
+ when(mPowerManager.isAmbientDisplaySuppressedForTokenByApp(anyString(), anyInt()))
+ .thenReturn(true);
+
+ assertTrue(AmbientDisplayAlwaysOnPreferenceController.isAodSuppressedByBedtime(mContext));
+
+ mController.updateState(mockPref);
+ verify(mockPref).setSummary(R.string.screensaver_settings_when_to_dream_bedtime);
}
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java
index 26e0f50..9fbcb16 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/BatteryChartPreferenceControllerTest.java
@@ -18,6 +18,8 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.ArgumentMatchers.anyFloat;
+import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.atLeast;
import static org.mockito.Mockito.atLeastOnce;
@@ -36,6 +38,7 @@
import android.os.LocaleList;
import android.text.format.DateUtils;
import android.view.View;
+import android.view.ViewPropertyAnimator;
import android.widget.LinearLayout;
import androidx.preference.Preference;
@@ -85,6 +88,8 @@
@Mock
private BatteryChartView mHourlyChartView;
@Mock
+ private ViewPropertyAnimator mViewPropertyAnimator;
+ @Mock
private PowerGaugePreference mPowerGaugePreference;
@Mock
private BatteryUtils mBatteryUtils;
@@ -116,6 +121,7 @@
.when(mFeatureFactory.powerUsageFeatureProvider)
.getHideApplicationEntries(mContext);
doReturn(mLayoutParams).when(mDailyChartView).getLayoutParams();
+ setupHourlyChartViewAnimationMock();
mBatteryChartPreferenceController = createController();
mBatteryChartPreferenceController.mPrefContext = mContext;
mBatteryChartPreferenceController.mAppListPrefGroup = mAppListGroup;
@@ -174,11 +180,13 @@
@Test
public void setBatteryChartViewModel_6Hours() {
+ reset(mDailyChartView);
reset(mHourlyChartView);
+ setupHourlyChartViewAnimationMock();
+
mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(6));
verify(mDailyChartView, atLeastOnce()).setVisibility(View.GONE);
- verify(mHourlyChartView, atLeastOnce()).setVisibility(View.VISIBLE);
// Ignore fast refresh ui from the data processor callback.
verify(mHourlyChartView, atLeast(0)).setViewModel(null);
verify(mHourlyChartView, atLeastOnce()).setViewModel(new BatteryChartViewModel(
@@ -192,6 +200,10 @@
@Test
public void setBatteryChartViewModel_60Hours() {
+ reset(mDailyChartView);
+ reset(mHourlyChartView);
+ setupHourlyChartViewAnimationMock();
+
BatteryChartViewModel expectedDailyViewModel = new BatteryChartViewModel(
List.of(100, 83, 59, 41),
// "Sat", "Sun", "Mon", "Mon"
@@ -205,16 +217,18 @@
mBatteryChartPreferenceController.setBatteryHistoryMap(createBatteryHistoryMap(60));
verify(mDailyChartView, atLeastOnce()).setVisibility(View.VISIBLE);
- verify(mHourlyChartView, atLeastOnce()).setVisibility(View.GONE);
+ verify(mViewPropertyAnimator, atLeastOnce()).alpha(0f);
verify(mDailyChartView).setViewModel(expectedDailyViewModel);
reset(mDailyChartView);
reset(mHourlyChartView);
+ setupHourlyChartViewAnimationMock();
doReturn(mLayoutParams).when(mDailyChartView).getLayoutParams();
mBatteryChartPreferenceController.mDailyChartIndex = 0;
mBatteryChartPreferenceController.refreshUi();
verify(mDailyChartView).setVisibility(View.VISIBLE);
verify(mHourlyChartView).setVisibility(View.VISIBLE);
+ verify(mViewPropertyAnimator, atLeastOnce()).alpha(1f);
expectedDailyViewModel.setSelectedIndex(0);
verify(mDailyChartView).setViewModel(expectedDailyViewModel);
@@ -234,12 +248,13 @@
reset(mDailyChartView);
reset(mHourlyChartView);
+ setupHourlyChartViewAnimationMock();
doReturn(mLayoutParams).when(mDailyChartView).getLayoutParams();
mBatteryChartPreferenceController.mDailyChartIndex = 1;
mBatteryChartPreferenceController.mHourlyChartIndex = 6;
mBatteryChartPreferenceController.refreshUi();
verify(mDailyChartView).setVisibility(View.VISIBLE);
- verify(mHourlyChartView).setVisibility(View.VISIBLE);
+ verify(mViewPropertyAnimator, atLeastOnce()).alpha(1f);
expectedDailyViewModel.setSelectedIndex(1);
verify(mDailyChartView).setViewModel(expectedDailyViewModel);
BatteryChartViewModel expectedHourlyViewModel = new BatteryChartViewModel(
@@ -264,13 +279,14 @@
reset(mDailyChartView);
reset(mHourlyChartView);
+ setupHourlyChartViewAnimationMock();
doReturn(mLayoutParams).when(mDailyChartView).getLayoutParams();
mBatteryChartPreferenceController.mDailyChartIndex = 2;
mBatteryChartPreferenceController.mHourlyChartIndex =
BatteryChartViewModel.SELECTED_INDEX_ALL;
mBatteryChartPreferenceController.refreshUi();
verify(mDailyChartView).setVisibility(View.VISIBLE);
- verify(mHourlyChartView).setVisibility(View.VISIBLE);
+ verify(mViewPropertyAnimator, atLeastOnce()).alpha(1f);
expectedDailyViewModel.setSelectedIndex(2);
verify(mDailyChartView).setViewModel(expectedDailyViewModel);
verify(mHourlyChartView).setViewModel(new BatteryChartViewModel(
@@ -734,4 +750,11 @@
controller.mPrefContext = mContext;
return controller;
}
+
+ private void setupHourlyChartViewAnimationMock() {
+ doReturn(mViewPropertyAnimator).when(mHourlyChartView).animate();
+ doReturn(mViewPropertyAnimator).when(mViewPropertyAnimator).alpha(anyFloat());
+ doReturn(mViewPropertyAnimator).when(mViewPropertyAnimator).setDuration(anyLong());
+ doReturn(mViewPropertyAnimator).when(mViewPropertyAnimator).setListener(any());
+ }
}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
index c483204..df9d865 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batteryusage/DataProcessorTest.java
@@ -579,9 +579,13 @@
ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY, /*consumePercentage=*/ 25.0,
/*foregroundUsageTimeInMs=*/ 50, /*backgroundUsageTimeInMs=*/ 60);
verify(mMetricsFeatureProvider)
- .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT, 3);
+ .action(mContext.getApplicationContext(),
+ SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT,
+ 3);
verify(mMetricsFeatureProvider)
- .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT, 0);
+ .action(mContext.getApplicationContext(),
+ SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT,
+ 0);
}
@Test
@@ -674,9 +678,13 @@
assertThat(resultMap.get(0).get(0)).isNotNull();
assertThat(resultMap.get(0).get(DataProcessor.SELECTED_INDEX_ALL)).isNotNull();
verify(mMetricsFeatureProvider)
- .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT, 2);
+ .action(mContext.getApplicationContext(),
+ SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT,
+ 2);
verify(mMetricsFeatureProvider)
- .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT, 0);
+ .action(mContext.getApplicationContext(),
+ SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT,
+ 0);
}
@Test
@@ -739,9 +747,13 @@
assertThat(resultMap.get(0).get(0)).isNotNull();
assertThat(resultMap.get(0).get(DataProcessor.SELECTED_INDEX_ALL)).isNotNull();
verify(mMetricsFeatureProvider)
- .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT, 1);
+ .action(mContext.getApplicationContext(),
+ SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT,
+ 1);
verify(mMetricsFeatureProvider)
- .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT, 0);
+ .action(mContext.getApplicationContext(),
+ SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT,
+ 0);
}
@Test
@@ -814,9 +826,13 @@
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 50.0,
/*foregroundUsageTimeInMs=*/ 10, /*backgroundUsageTimeInMs=*/ 20);
verify(mMetricsFeatureProvider)
- .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT, 1);
+ .action(mContext.getApplicationContext(),
+ SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT,
+ 1);
verify(mMetricsFeatureProvider)
- .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT, 1);
+ .action(mContext.getApplicationContext(),
+ SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT,
+ 1);
}
@Test
@@ -889,9 +905,13 @@
resultEntry = resultDiffData.getAppDiffEntryList().get(1);
assertThat(resultEntry.mBackgroundUsageTimeInMs).isEqualTo(0);
verify(mMetricsFeatureProvider)
- .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT, 2);
+ .action(mContext.getApplicationContext(),
+ SettingsEnums.ACTION_BATTERY_USAGE_SHOWN_APP_COUNT,
+ 2);
verify(mMetricsFeatureProvider)
- .action(mContext, SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT, 0);
+ .action(mContext.getApplicationContext(),
+ SettingsEnums.ACTION_BATTERY_USAGE_HIDDEN_APP_COUNT,
+ 0);
}
@Test
diff --git a/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorWorkerTest.java b/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorWorkerTest.java
index 2339f4c..cd06bae 100644
--- a/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorWorkerTest.java
+++ b/tests/robotests/src/com/android/settings/media/MediaOutputIndicatorWorkerTest.java
@@ -38,11 +38,14 @@
import android.media.session.PlaybackState;
import android.net.Uri;
+import com.android.settings.bluetooth.Utils;
import com.android.settings.slices.ShadowSliceBackgroundWorker;
import com.android.settings.testutils.shadow.ShadowBluetoothAdapter;
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
import com.android.settingslib.bluetooth.BluetoothEventManager;
+import com.android.settingslib.bluetooth.LocalBluetoothLeBroadcast;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
+import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import com.android.settingslib.media.LocalMediaManager;
import org.junit.Before;
@@ -69,13 +72,17 @@
@Mock
private BluetoothEventManager mBluetoothEventManager;
@Mock
- private LocalBluetoothManager mLocalBluetoothManager;
+ private LocalBluetoothManager mLocalBtManager;
+ @Mock
+ private LocalBluetoothProfileManager mLocalBluetoothProfileManager;
@Mock
private MediaSessionManager mMediaSessionManager;
@Mock
private MediaController mMediaController;
@Mock
private LocalMediaManager mLocalMediaManager;
+ @Mock
+ private LocalBluetoothLeBroadcast mLeAudioBroadcastProfile;
private Context mContext;
private MediaOutputIndicatorWorker mMediaOutputIndicatorWorker;
@@ -84,14 +91,18 @@
private List<MediaController> mMediaControllers = new ArrayList<>();
private PlaybackState mPlaybackState;
private MediaController.PlaybackInfo mPlaybackInfo;
+ private LocalBluetoothManager mLocalBluetoothManager;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mShadowApplication = ShadowApplication.getInstance();
mContext = spy(RuntimeEnvironment.application);
- ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBluetoothManager;
+ ShadowBluetoothUtils.sLocalBluetoothManager = mLocalBtManager;
+ mLocalBluetoothManager = Utils.getLocalBtManager(mContext);
when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager);
+ when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager);
+ when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile()).thenReturn(null);
mMediaOutputIndicatorWorker = new MediaOutputIndicatorWorker(mContext, URI);
doReturn(mMediaSessionManager).when(mContext).getSystemService(MediaSessionManager.class);
mMediaControllers.add(mMediaController);
@@ -284,4 +295,22 @@
assertThat(mMediaOutputIndicatorWorker.getActiveLocalMediaController()).isNull();
}
+
+ @Test
+ public void isBroadcastSupported_leAudioBroadcastProfileIsNull_returnFalse() {
+ mMediaOutputIndicatorWorker.mLocalMediaManager = mLocalMediaManager;
+ mMediaOutputIndicatorWorker.onSlicePinned();
+
+ assertThat(mMediaOutputIndicatorWorker.isBroadcastSupported()).isFalse();
+ }
+
+ @Test
+ public void isBroadcastSupported_leAudioBroadcastProfileNotNull_returnTrue() {
+ mMediaOutputIndicatorWorker.mLocalMediaManager = mLocalMediaManager;
+ mMediaOutputIndicatorWorker.onSlicePinned();
+ when(mLocalBluetoothProfileManager.getLeAudioBroadcastProfile())
+ .thenReturn(mLeAudioBroadcastProfile);
+
+ assertThat(mMediaOutputIndicatorWorker.isBroadcastSupported()).isTrue();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/media/MediaOutputUtilsTest.java b/tests/robotests/src/com/android/settings/media/MediaOutputUtilsTest.java
index dea6a2c..5fa7fdd 100644
--- a/tests/robotests/src/com/android/settings/media/MediaOutputUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/media/MediaOutputUtilsTest.java
@@ -66,7 +66,18 @@
@Test
public void getActiveLocalMediaController_localMediaPlaying_returnController() {
- initPlayback();
+ initPlayback(PlaybackState.STATE_PLAYING);
+
+ when(mMediaController.getPlaybackInfo()).thenReturn(mPlaybackInfo);
+ when(mMediaController.getPlaybackState()).thenReturn(mPlaybackState);
+
+ assertThat(MediaOutputUtils.getActiveLocalMediaController(mMediaSessionManager)).isEqualTo(
+ mMediaController);
+ }
+
+ @Test
+ public void getActiveLocalMediaController_localMediaPause_returnController() {
+ initPlayback(PlaybackState.STATE_PAUSED);
when(mMediaController.getPlaybackInfo()).thenReturn(mPlaybackInfo);
when(mMediaController.getPlaybackState()).thenReturn(mPlaybackState);
@@ -114,6 +125,44 @@
}
@Test
+ public void getActiveLocalMediaController_localMediaNone_returnNull() {
+ mPlaybackInfo = new MediaController.PlaybackInfo(
+ MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL,
+ VolumeProvider.VOLUME_CONTROL_ABSOLUTE,
+ 100,
+ 10,
+ new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build(),
+ null);
+ mPlaybackState = new PlaybackState.Builder()
+ .setState(PlaybackState.STATE_NONE, 0, 1)
+ .build();
+
+ when(mMediaController.getPlaybackInfo()).thenReturn(mPlaybackInfo);
+ when(mMediaController.getPlaybackState()).thenReturn(mPlaybackState);
+
+ assertThat(MediaOutputUtils.getActiveLocalMediaController(mMediaSessionManager)).isNull();
+ }
+
+ @Test
+ public void getActiveLocalMediaController_localMediaError_returnNull() {
+ mPlaybackInfo = new MediaController.PlaybackInfo(
+ MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL,
+ VolumeProvider.VOLUME_CONTROL_ABSOLUTE,
+ 100,
+ 10,
+ new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build(),
+ null);
+ mPlaybackState = new PlaybackState.Builder()
+ .setState(PlaybackState.STATE_ERROR, 0, 1)
+ .build();
+
+ when(mMediaController.getPlaybackInfo()).thenReturn(mPlaybackInfo);
+ when(mMediaController.getPlaybackState()).thenReturn(mPlaybackState);
+
+ assertThat(MediaOutputUtils.getActiveLocalMediaController(mMediaSessionManager)).isNull();
+ }
+
+ @Test
public void getActiveLocalMediaController_bothHaveRemoteMediaAndLocalMedia_returnNull() {
mMediaControllers.clear();
final MediaController.PlaybackInfo playbackInfo = new MediaController.PlaybackInfo(
@@ -130,7 +179,7 @@
mMediaControllers.add(remoteMediaController);
mMediaControllers.add(mMediaController);
- initPlayback();
+ initPlayback(PlaybackState.STATE_PLAYING);
when(mMediaController.getPlaybackInfo()).thenReturn(mPlaybackInfo);
when(mMediaController.getPlaybackState()).thenReturn(mPlaybackState);
@@ -155,7 +204,7 @@
final MediaController remoteMediaController = mock(MediaController.class);
mMediaControllers.add(remoteMediaController);
- initPlayback();
+ initPlayback(PlaybackState.STATE_PLAYING);
when(mMediaController.getPlaybackInfo()).thenReturn(mPlaybackInfo);
when(mMediaController.getPlaybackState()).thenReturn(mPlaybackState);
@@ -165,7 +214,7 @@
assertThat(MediaOutputUtils.getActiveLocalMediaController(mMediaSessionManager)).isNull();
}
- private void initPlayback() {
+ private void initPlayback(int playbackState) {
mPlaybackInfo = new MediaController.PlaybackInfo(
MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL,
VolumeProvider.VOLUME_CONTROL_ABSOLUTE,
@@ -174,7 +223,7 @@
new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build(),
null);
mPlaybackState = new PlaybackState.Builder()
- .setState(PlaybackState.STATE_PLAYING, 0, 1)
+ .setState(playbackState, 0, 1)
.build();
}
}
diff --git a/tests/robotests/src/com/android/settings/network/MobileNetworkListFragmentTest.java b/tests/robotests/src/com/android/settings/network/MobileNetworkListFragmentTest.java
index fd2b520..2e04ea7 100644
--- a/tests/robotests/src/com/android/settings/network/MobileNetworkListFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/network/MobileNetworkListFragmentTest.java
@@ -21,8 +21,10 @@
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.content.res.Resources;
import android.os.UserManager;
+import com.android.settings.R;
import com.android.settings.search.BaseSearchIndexProvider;
import org.junit.Before;
@@ -38,6 +40,8 @@
@Mock
private Context mContext;
@Mock
+ private Resources mResources;
+ @Mock
private UserManager mUserManager;
private MobileNetworkListFragment mFragment;
@@ -55,6 +59,9 @@
final BaseSearchIndexProvider provider =
(BaseSearchIndexProvider) mFragment.SEARCH_INDEX_DATA_PROVIDER;
+ when(mContext.getResources()).thenReturn(mResources);
+ when(mResources.getBoolean(R.bool.config_show_sim_info)).thenReturn(true);
+
final Object obj = ReflectionHelpers.callInstanceMethod(provider, "isPageSearchEnabled",
ReflectionHelpers.ClassParameter.from(Context.class, mContext));
final boolean isEnabled = (Boolean) obj;
@@ -69,6 +76,9 @@
final BaseSearchIndexProvider provider =
(BaseSearchIndexProvider) mFragment.SEARCH_INDEX_DATA_PROVIDER;
+ when(mContext.getResources()).thenReturn(mResources);
+ when(mResources.getBoolean(R.bool.config_show_sim_info)).thenReturn(true);
+
final Object obj = ReflectionHelpers.callInstanceMethod(provider, "isPageSearchEnabled",
ReflectionHelpers.ClassParameter.from(Context.class, mContext));
final boolean isEnabled = (Boolean) obj;
diff --git a/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java b/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java
index 5122def..b347ac0 100644
--- a/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/network/NetworkProviderSettingsTest.java
@@ -17,9 +17,11 @@
import static com.android.settings.network.NetworkProviderSettings.MENU_ID_DISCONNECT;
import static com.android.settings.network.NetworkProviderSettings.MENU_ID_FORGET;
+import static com.android.settings.network.NetworkProviderSettings.MENU_ID_MODIFY;
import static com.android.settings.network.NetworkProviderSettings.MENU_ID_SHARE;
import static com.android.settings.wifi.WifiConfigUiBase2.MODE_CONNECT;
import static com.android.settings.wifi.WifiConfigUiBase2.MODE_MODIFY;
+import static com.android.wifitrackerlib.WifiEntry.CONNECTED_STATE_DISCONNECTED;
import static com.google.common.truth.Truth.assertThat;
@@ -145,7 +147,10 @@
@Before
public void setUp() {
- mNetworkProviderSettings = spy(new NetworkProviderSettings());
+ mNetworkProviderSettings = spy(new NetworkProviderSettings() {
+ @Override
+ boolean showAnySubscriptionInfo(Context context) { return true; }
+ });
doReturn(mContext).when(mNetworkProviderSettings).getContext();
doReturn(mPreferenceManager).when(mNetworkProviderSettings).getPreferenceManager();
doReturn(mPowerManager).when(mContext).getSystemService(PowerManager.class);
@@ -730,6 +735,28 @@
}
@Test
+ public void addModifyMenuIfSuitable_isAdmin_addMenu() {
+ mNetworkProviderSettings.mIsAdmin = true;
+ when(mWifiEntry.isSaved()).thenReturn(true);
+ when(mWifiEntry.getConnectedState()).thenReturn(CONNECTED_STATE_DISCONNECTED);
+
+ mNetworkProviderSettings.addModifyMenuIfSuitable(mContextMenu, mWifiEntry);
+
+ verify(mContextMenu).add(anyInt(), eq(MENU_ID_MODIFY), anyInt(), anyInt());
+ }
+
+ @Test
+ public void addModifyMenuIfSuitable_isNotAdmin_notAddMenu() {
+ mNetworkProviderSettings.mIsAdmin = false;
+ when(mWifiEntry.isSaved()).thenReturn(true);
+ when(mWifiEntry.getConnectedState()).thenReturn(CONNECTED_STATE_DISCONNECTED);
+
+ mNetworkProviderSettings.addModifyMenuIfSuitable(mContextMenu, mWifiEntry);
+
+ verify(mContextMenu, never()).add(anyInt(), eq(MENU_ID_MODIFY), anyInt(), anyInt());
+ }
+
+ @Test
public void getNonIndexableKeys_allowedChangeWifiState_keyNotReturned() {
when(mWifiRestriction.isChangeWifiStateAllowed(mContext)).thenReturn(true);
NetworkProviderSettings.SearchIndexProvider searchIndexProvider =
diff --git a/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSettingsTest.java b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSettingsTest.java
index 44611ce..3e219a4 100644
--- a/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/network/telephony/MobileNetworkSettingsTest.java
@@ -29,6 +29,7 @@
import android.app.Activity;
import android.app.usage.NetworkStatsManager;
import android.content.Context;
+import android.content.res.Resources;
import android.net.NetworkPolicyManager;
import android.os.Bundle;
import android.os.UserManager;
@@ -37,6 +38,7 @@
import androidx.fragment.app.FragmentActivity;
+import com.android.settings.R;
import com.android.settings.datausage.DataUsageSummaryPreferenceController;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.testutils.shadow.ShadowEntityHeaderController;
@@ -68,12 +70,18 @@
private FragmentActivity mActivity;
private Context mContext;
+ private Resources mResources;
private MobileNetworkSettings mFragment;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
mContext = spy(RuntimeEnvironment.application);
+
+ mResources = spy(mContext.getResources());
+ when(mContext.getResources()).thenReturn(mResources);
+ when(mResources.getBoolean(R.bool.config_show_sim_info)).thenReturn(true);
+
when(mActivity.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
when(mTelephonyManager.createForSubscriptionId(anyInt())).thenReturn(mTelephonyManager);
when(mContext.getSystemService(NetworkStatsManager.class)).thenReturn(mNetworkStatsManager);
diff --git a/tests/robotests/src/com/android/settings/notification/MediaVolumePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/MediaVolumePreferenceControllerTest.java
index 56e83bb..2d023d7 100644
--- a/tests/robotests/src/com/android/settings/notification/MediaVolumePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/MediaVolumePreferenceControllerTest.java
@@ -113,13 +113,23 @@
@Test
public void isSupportEndItem_withBleDevice_returnsTrue() {
+ doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
doReturn(mDevice1).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice();
assertThat(mController.isSupportEndItem()).isTrue();
}
@Test
+ public void isSupportEndItem_notSupportedBroadcast_returnsFalse() {
+ doReturn(false).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
+ doReturn(mDevice1).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice();
+
+ assertThat(mController.isSupportEndItem()).isFalse();
+ }
+
+ @Test
public void isSupportEndItem_withNonBleDevice_returnsFalse() {
+ doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
doReturn(mDevice2).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice();
assertThat(mController.isSupportEndItem()).isFalse();
@@ -127,6 +137,7 @@
@Test
public void getSliceEndItem_NotSupportEndItem_getsNullSliceAction() {
+ doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
doReturn(mDevice2).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice();
final SliceAction sliceAction = mController.getSliceEndItem(mContext);
@@ -136,6 +147,7 @@
@Test
public void getSliceEndItem_deviceIsBroadcasting_getsBroadcastIntent() {
+ doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
doReturn(mDevice1).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice();
doReturn(true).when(sMediaOutputIndicatorWorker).isDeviceBroadcasting();
doReturn(mMediaController).when(sMediaOutputIndicatorWorker)
@@ -155,6 +167,7 @@
final CachedBluetoothDevice cachedDevice = mock(CachedBluetoothDevice.class);
when(((BluetoothMediaDevice) device).getCachedDevice()).thenReturn(cachedDevice);
when(device.isBLEDevice()).thenReturn(true);
+ doReturn(true).when(sMediaOutputIndicatorWorker).isBroadcastSupported();
doReturn(device).when(sMediaOutputIndicatorWorker).getCurrentConnectedMediaDevice();
doReturn(false).when(sMediaOutputIndicatorWorker).isDeviceBroadcasting();
doReturn(mMediaController).when(sMediaOutputIndicatorWorker)
diff --git a/tests/robotests/src/com/android/settings/notification/NotificationAssistantPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/NotificationAssistantPreferenceControllerTest.java
index b594667..1dac399 100644
--- a/tests/robotests/src/com/android/settings/notification/NotificationAssistantPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/NotificationAssistantPreferenceControllerTest.java
@@ -226,4 +226,14 @@
.setNASMigrationDoneAndResetDefault(eq(10), anyBoolean());
}
+ @Test
+ public void testNASUnavailable_settingDisabled() throws Exception {
+ when(mBackend.getDefaultNotificationAssistant()).thenReturn(null);
+ mPreferenceController.getDefaultNASIntent();
+ mPreferenceController.updateState(mPreference);
+
+ verify(mPreference, times(1)).setSwitchEnabled(eq(false));
+ assertFalse(mPreference.isEnabled());
+ }
+
}
diff --git a/tests/robotests/src/com/android/settings/notification/NotificationVolumePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/NotificationVolumePreferenceControllerTest.java
index fe4744f..96b9e62 100644
--- a/tests/robotests/src/com/android/settings/notification/NotificationVolumePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/NotificationVolumePreferenceControllerTest.java
@@ -22,10 +22,14 @@
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.content.res.Resources;
import android.media.AudioManager;
import android.os.Vibrator;
+import android.service.notification.NotificationListenerService;
import android.telephony.TelephonyManager;
+import com.android.internal.R;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -46,6 +50,8 @@
private AudioManager mAudioManager;
@Mock
private Vibrator mVibrator;
+ @Mock
+ private Resources mResources;
private Context mContext;
private NotificationVolumePreferenceController mController;
@@ -57,6 +63,8 @@
when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager);
when(mContext.getSystemService(Context.AUDIO_SERVICE)).thenReturn(mAudioManager);
when(mContext.getSystemService(Context.VIBRATOR_SERVICE)).thenReturn(mVibrator);
+ when(mContext.getResources()).thenReturn(mResources);
+
mController = new NotificationVolumePreferenceController(mContext);
mController.setAudioHelper(mHelper);
}
@@ -76,15 +84,50 @@
}
@Test
- public void isAvailable_voiceCapable_shouldReturnFalse() {
+ public void isAvailable_voiceCapable_aliasedWithRing_shouldReturnFalse() {
+ when(mResources.getBoolean(
+ com.android.settings.R.bool.config_show_notification_volume)).thenReturn(true);
+ when(mResources.getBoolean(R.bool.config_alias_ring_notif_stream_types)).thenReturn(true);
+
+ NotificationVolumePreferenceController controller =
+ new NotificationVolumePreferenceController(mContext);
when(mHelper.isSingleVolume()).thenReturn(false);
when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
+ assertThat(controller.isAvailable()).isFalse();
+ }
+
+ /**
+ * With the introduction of ring-notification volume separation, voice-capable devices could now
+ * display the notification volume slider.
+ */
+ @Test
+ public void isAvailable_voiceCapable_separatedFromRing_shouldReturnTrue() {
+ when(mResources.getBoolean(
+ com.android.settings.R.bool.config_show_notification_volume)).thenReturn(true);
+ when(mResources.getBoolean(R.bool.config_alias_ring_notif_stream_types)).thenReturn(false);
+
+ NotificationVolumePreferenceController controller =
+ new NotificationVolumePreferenceController(mContext);
+
+ when(mHelper.isSingleVolume()).thenReturn(false);
+ when(mTelephonyManager.isVoiceCapable()).thenReturn(true);
+
+ assertThat(controller.isAvailable()).isTrue();
+ }
+
+ @Test
+ public void isAvailable_notShowNotificationVolume_shouldReturnFalse() {
+ when(mResources.getBoolean(
+ com.android.settings.R.bool.config_show_notification_volume)).thenReturn(false);
+
assertThat(mController.isAvailable()).isFalse();
}
@Test
public void isAvailable_notSingleVolume_notVoiceCapable_shouldReturnTrue() {
+ when(mResources.getBoolean(
+ com.android.settings.R.bool.config_show_notification_volume)).thenReturn(true);
when(mHelper.isSingleVolume()).thenReturn(false);
when(mTelephonyManager.isVoiceCapable()).thenReturn(false);
@@ -107,4 +150,24 @@
public void isPublicSlice_returnTrue() {
assertThat(mController.isPublicSlice()).isTrue();
}
+
+ @Test
+ public void setHintsRing_DoesNotMatch() {
+ assertThat(mController.hintsMatch(
+ NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS)).isFalse();
+ }
+
+ @Test
+ public void setHintsAll_Matches() {
+ assertThat(mController.hintsMatch(NotificationListenerService.HINT_HOST_DISABLE_EFFECTS))
+ .isTrue();
+ }
+
+ @Test
+ public void setHintNotification_Matches() {
+ assertThat(mController
+ .hintsMatch(NotificationListenerService.HINT_HOST_DISABLE_NOTIFICATION_EFFECTS))
+ .isTrue();
+ }
+
}
diff --git a/tests/robotests/src/com/android/settings/notification/RingVolumePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/RingVolumePreferenceControllerTest.java
index 5e484a3..02757d5 100644
--- a/tests/robotests/src/com/android/settings/notification/RingVolumePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/RingVolumePreferenceControllerTest.java
@@ -18,15 +18,20 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.app.NotificationManager;
import android.content.ComponentName;
import android.content.Context;
+import android.content.res.Resources;
import android.media.AudioManager;
import android.os.Vibrator;
+import android.service.notification.NotificationListenerService;
import android.telephony.TelephonyManager;
+import com.android.settings.R;
+
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -51,8 +56,13 @@
private NotificationManager mNotificationManager;
@Mock
private ComponentName mSuppressor;
+ @Mock
+ private Resources mResources;
+ @Mock
+ private VolumeSeekBarPreference mPreference;
private Context mContext;
+
private RingVolumePreferenceController mController;
@Before
@@ -63,8 +73,9 @@
shadowContext.setSystemService(Context.AUDIO_SERVICE, mAudioManager);
shadowContext.setSystemService(Context.VIBRATOR_SERVICE, mVibrator);
shadowContext.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
- mContext = RuntimeEnvironment.application;
+ mContext = spy(RuntimeEnvironment.application);
when(mNotificationManager.getEffectsSuppressor()).thenReturn(mSuppressor);
+ when(mContext.getResources()).thenReturn(mResources);
mController = new RingVolumePreferenceController(mContext);
mController.setAudioHelper(mHelper);
}
@@ -109,4 +120,92 @@
public void isPublicSlice_returnTrue() {
assertThat(mController.isPublicSlice()).isTrue();
}
+
+ // todo: verify that the title change is displayed, by examining the underlying preference
+ @Test
+ public void ringNotificationStreamsNotAliased_sliderTitleSetToRingOnly() {
+ when(mResources.getBoolean(
+ com.android.internal.R.bool.config_alias_ring_notif_stream_types))
+ .thenReturn(false);
+ final RingVolumePreferenceController controller =
+ new RingVolumePreferenceController(mContext);
+
+ int expectedTitleId = R.string.separate_ring_volume_option_title;
+
+ assertThat(controller.mTitleId).isEqualTo(expectedTitleId);
+ }
+
+ @Test
+ public void ringNotificationStreamsAliased_sliderTitleIncludesBothRingNotification() {
+
+ when(mResources.getBoolean(
+ com.android.internal.R.bool.config_alias_ring_notif_stream_types)).thenReturn(true);
+ final RingVolumePreferenceController control = new RingVolumePreferenceController(mContext);
+
+ int expectedTitleId = R.string.ring_volume_option_title;
+
+ assertThat(control.mTitleId).isEqualTo(expectedTitleId);
+ }
+
+ @Test
+ public void setHintsRing_aliased_Matches() {
+ assertThat(mController.hintsMatch(
+ NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS, true)).isTrue();
+ }
+
+ @Test
+ public void setHintsRingNotification_aliased_Matches() {
+ assertThat(mController.hintsMatch(NotificationListenerService.HINT_HOST_DISABLE_EFFECTS,
+ true)).isTrue();
+ }
+
+ @Test
+ public void setHintNotification_aliased_Matches() {
+ assertThat(mController
+ .hintsMatch(NotificationListenerService.HINT_HOST_DISABLE_NOTIFICATION_EFFECTS,
+ true)).isTrue();
+ }
+
+ @Test
+ public void setHintsRing_unaliased_Matches() {
+ assertThat(mController.hintsMatch(
+ NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS, false)).isTrue();
+ }
+
+ @Test
+ public void setHintsRingNotification_unaliased_Matches() {
+ assertThat(mController.hintsMatch(NotificationListenerService.HINT_HOST_DISABLE_EFFECTS,
+ false)).isTrue();
+ }
+
+ @Test
+ public void setHintNotification_unaliased_doesNotMatch() {
+ assertThat(mController
+ .hintsMatch(NotificationListenerService.HINT_HOST_DISABLE_NOTIFICATION_EFFECTS,
+ false)).isFalse();
+ }
+
+ @Test
+ public void setRingerModeToVibrate_butNoVibratorAvailable_iconIsSilent() {
+ when(mHelper.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
+
+ mController.setPreference(mPreference);
+ mController.setVibrator(null);
+ mController.updateRingerMode();
+
+ assertThat(mController.getMuteIcon()).isEqualTo(mController.mSilentIconId);
+ }
+
+ @Test
+ public void setRingerModeToVibrate_VibratorAvailable_iconIsVibrate() {
+ when(mHelper.getRingerModeInternal()).thenReturn(AudioManager.RINGER_MODE_VIBRATE);
+ when(mVibrator.hasVibrator()).thenReturn(true);
+
+ mController.setPreference(mPreference);
+ mController.setVibrator(mVibrator);
+ mController.updateRingerMode();
+
+ assertThat(mController.getMuteIcon()).isEqualTo(mController.mVibrateIconId);
+ }
+
}
diff --git a/tests/robotests/src/com/android/settings/notification/ShowOnLockscreenNotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/ShowOnLockscreenNotificationPreferenceControllerTest.java
index 496897f..567c7ff 100644
--- a/tests/robotests/src/com/android/settings/notification/ShowOnLockscreenNotificationPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/ShowOnLockscreenNotificationPreferenceControllerTest.java
@@ -28,6 +28,8 @@
import android.content.Context;
import android.provider.Settings;
+import androidx.preference.PreferenceScreen;
+
import com.android.settings.R;
import com.android.settings.RestrictedListPreference;
import com.android.settings.testutils.shadow.ShadowRestrictedLockUtilsInternal;
@@ -42,11 +44,8 @@
import org.robolectric.Robolectric;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-import org.robolectric.Shadows;
import org.robolectric.annotation.Config;
-import androidx.preference.PreferenceScreen;
-
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowUserManager.class, ShadowRestrictedLockUtilsInternal.class})
public class ShowOnLockscreenNotificationPreferenceControllerTest {
@@ -94,7 +93,7 @@
assertThat(mPreference.getValue()).isEqualTo(
String.valueOf(R.string.lock_screen_notifs_show_none));
- assertThat(mPreference.getSummary())
+ assertThat(mPreference.getSummary().toString())
.isEqualTo(mContext.getString(R.string.lock_screen_notifs_show_none));
}
@@ -111,7 +110,7 @@
assertThat(mPreference.getValue()).isEqualTo(
String.valueOf(R.string.lock_screen_notifs_show_alerting));
- assertThat(mPreference.getSummary())
+ assertThat(mPreference.getSummary().toString())
.isEqualTo(mContext.getString(R.string.lock_screen_notifs_show_alerting));
}
@@ -128,20 +127,20 @@
assertThat(mPreference.getValue()).isEqualTo(
String.valueOf(R.string.lock_screen_notifs_show_all));
- assertThat(mPreference.getSummary())
+ assertThat(mPreference.getSummary().toString())
.isEqualTo(mContext.getString(R.string.lock_screen_notifs_show_all));
}
@Test
- public void updateState_allNotifsOnLockscreen_isDefault() {
+ public void updateState_alertingNotifsOnLockscreen_isDefault() {
// settings don't exist
mController.displayPreference(mScreen);
assertThat(mPreference.getValue()).isEqualTo(
- String.valueOf(R.string.lock_screen_notifs_show_all));
- assertThat(mPreference.getSummary())
- .isEqualTo(mContext.getString(R.string.lock_screen_notifs_show_all));
+ String.valueOf(R.string.lock_screen_notifs_show_alerting));
+ assertThat(mPreference.getSummary().toString())
+ .isEqualTo(mContext.getString(R.string.lock_screen_notifs_show_alerting));
}
@Test
diff --git a/tests/robotests/src/com/android/settings/notification/SoundSettingsTest.java b/tests/robotests/src/com/android/settings/notification/SoundSettingsTest.java
index c2ea6e7..9e84883 100644
--- a/tests/robotests/src/com/android/settings/notification/SoundSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/notification/SoundSettingsTest.java
@@ -35,6 +35,7 @@
import com.android.settings.testutils.shadow.ShadowDeviceConfig;
import com.android.settings.testutils.shadow.ShadowUserManager;
+import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricTestRunner;
@@ -44,8 +45,6 @@
import java.util.List;
-import org.junit.Ignore;
-
@RunWith(RobolectricTestRunner.class)
public class SoundSettingsTest {
@@ -86,4 +85,19 @@
assertThat(settings.mHandler.hasMessages(SoundSettings.STOP_SAMPLE)).isTrue();
}
+
+ @Test
+ public void notificationVolume_isBetweenRingAndAlarm() {
+ final Context context = spy(RuntimeEnvironment.application);
+ final SoundSettings settings = new SoundSettings();
+ final int xmlId = settings.getPreferenceScreenResId();
+ final List<String> keys = XmlTestUtils.getKeysFromPreferenceXml(context, xmlId);
+
+ int ring = keys.indexOf("ring_volume");
+ int notification = keys.indexOf("notification_volume");
+ int alarm = keys.indexOf("alarm_volume");
+
+ assertThat(ring < notification).isTrue();
+ assertThat(notification < alarm).isTrue();
+ }
}
diff --git a/tests/robotests/src/com/android/settings/notification/app/NotificationsOffPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/app/NotificationsOffPreferenceControllerTest.java
index 34e94a0..2eebd3a 100644
--- a/tests/robotests/src/com/android/settings/notification/app/NotificationsOffPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/app/NotificationsOffPreferenceControllerTest.java
@@ -20,6 +20,7 @@
import static com.google.common.truth.Truth.assertThat;
+import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
@@ -32,6 +33,7 @@
import androidx.preference.Preference;
+import com.android.settings.R;
import com.android.settings.notification.NotificationBackend;
import com.google.common.collect.ImmutableList;
@@ -157,4 +159,23 @@
assertThat(pref.getTitle().toString()).contains("app");
assertThat(pref.isSelectable()).isFalse();
}
+
+ @Test
+ public void testUpdateState_whenToggleDisabled() {
+ // Given: the app does not request to post notifications
+ // and it's preference toggle is disabled
+ NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+ appRow.banned = true;
+ appRow.permissionStateLocked = true;
+ mController.onResume(appRow, null, null, null, null, null, null);
+ Preference pref = new Preference(RuntimeEnvironment.application);
+
+ // When: updateState(Preference preference) is called
+ mController.updateState(pref);
+
+ // Then: title of pref should be app_notifications_not_send_desc
+ assertEquals(
+ RuntimeEnvironment.application.getString(R.string.app_notifications_not_send_desc),
+ pref.getTitle().toString());
+ }
}
diff --git a/tests/robotests/src/com/android/settings/security/SimLockPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/security/SimLockPreferenceControllerTest.java
index ef5973c..f38cc49 100644
--- a/tests/robotests/src/com/android/settings/security/SimLockPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/security/SimLockPreferenceControllerTest.java
@@ -22,9 +22,11 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.content.res.Resources;
import android.os.PersistableBundle;
import android.os.UserManager;
import android.telephony.CarrierConfigManager;
@@ -35,6 +37,7 @@
import androidx.preference.Preference;
import androidx.preference.PreferenceScreen;
+import com.android.settings.R;
import com.android.settings.core.BasePreferenceController;
import org.junit.Before;
@@ -66,6 +69,7 @@
private SimLockPreferenceController mController;
private Preference mPreference;
private Context mContext;
+ private Resources mResources;
@Before
public void setUp() {
@@ -76,7 +80,11 @@
shadowApplication.setSystemService(Context.CARRIER_CONFIG_SERVICE, mCarrierManager);
shadowApplication.setSystemService(Context.USER_SERVICE, mUserManager);
shadowApplication.setSystemService(Context.TELEPHONY_SERVICE, mTelephonyManager);
- mContext = RuntimeEnvironment.application;
+ mContext = spy(RuntimeEnvironment.application);
+
+ mResources = spy(mContext.getResources());
+ when(mContext.getResources()).thenReturn(mResources);
+
mController = new SimLockPreferenceController(mContext, "key");
mPreference = new Preference(mContext);
mPreference.setKey(mController.getPreferenceKey());
@@ -84,7 +92,16 @@
}
@Test
+ public void isAvailable_notShowSimUi_false() {
+ when(mResources.getBoolean(R.bool.config_show_sim_info)).thenReturn(false);
+
+ assertThat(mController.getAvailabilityStatus())
+ .isEqualTo(BasePreferenceController.UNSUPPORTED_ON_DEVICE);
+ }
+
+ @Test
public void isAvailable_notAdmin_false() {
+ when(mResources.getBoolean(R.bool.config_show_sim_info)).thenReturn(true);
when(mUserManager.isAdminUser()).thenReturn(false);
assertThat(mController.getAvailabilityStatus())
@@ -93,6 +110,7 @@
@Test
public void isAvailable_simIccNotReady_false() {
+ when(mResources.getBoolean(R.bool.config_show_sim_info)).thenReturn(true);
when(mUserManager.isAdminUser()).thenReturn(true);
assertThat(mController.getAvailabilityStatus())
@@ -124,6 +142,7 @@
@Test
public void displayPreference_simReady_enablePreference() {
+ when(mResources.getBoolean(R.bool.config_show_sim_info)).thenReturn(true);
mController.displayPreference(mScreen);
assertThat(mPreference.isEnabled()).isFalse();
@@ -140,12 +159,14 @@
@Test
public void getPreferenceKey_whenGivenValue_returnsGivenValue() {
+ when(mResources.getBoolean(R.bool.config_show_sim_info)).thenReturn(true);
mController = new SimLockPreferenceController(mContext, "key");
assertThat(mController.getPreferenceKey()).isEqualTo("key");
}
private void setupMockIcc() {
+ when(mResources.getBoolean(R.bool.config_show_sim_info)).thenReturn(true);
final List<SubscriptionInfo> subscriptionInfoList = new ArrayList<>();
SubscriptionInfo info = mock(SubscriptionInfo.class);
subscriptionInfoList.add(info);
@@ -156,6 +177,7 @@
}
private void setupMockSimReady() {
+ when(mResources.getBoolean(R.bool.config_show_sim_info)).thenReturn(true);
final List<SubscriptionInfo> subscriptionInfoList = new ArrayList<>();
SubscriptionInfo info = mock(SubscriptionInfo.class);
subscriptionInfoList.add(info);
diff --git a/tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java b/tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java
index b33e94b..e1b2b4e 100644
--- a/tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java
+++ b/tests/robotests/src/com/android/settings/sim/SimSelectNotificationTest.java
@@ -143,6 +143,7 @@
when(mSubInfo.getDisplayName()).thenReturn(mFakeDisplayName);
when(mContext.getResources()).thenReturn(mResources);
+ when(mResources.getBoolean(R.bool.config_show_sim_info)).thenReturn(true);
when(mResources.getText(R.string.enable_sending_mms_notification_title))
.thenReturn(mFakeNotificationTitle);
when(mResources.getText(R.string.enable_mms_notification_channel_title))
diff --git a/tests/robotests/src/com/android/settings/sound/AudioOutputSwitchPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/sound/AudioOutputSwitchPreferenceControllerTest.java
index b04a2cd..151d1f2 100644
--- a/tests/robotests/src/com/android/settings/sound/AudioOutputSwitchPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/sound/AudioOutputSwitchPreferenceControllerTest.java
@@ -51,14 +51,16 @@
import com.android.settingslib.bluetooth.A2dpProfile;
import com.android.settingslib.bluetooth.BluetoothCallback;
import com.android.settingslib.bluetooth.BluetoothEventManager;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
import com.android.settingslib.bluetooth.HeadsetProfile;
import com.android.settingslib.bluetooth.HearingAidProfile;
+import com.android.settingslib.bluetooth.LeAudioProfile;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -71,10 +73,10 @@
import org.robolectric.shadows.ShadowPackageManager;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
-@Ignore
@Config(shadows = {
ShadowAudioManager.class,
ShadowBluetoothUtils.class,
@@ -102,6 +104,14 @@
private HeadsetProfile mHeadsetProfile;
@Mock
private HearingAidProfile mHearingAidProfile;
+ @Mock
+ private LeAudioProfile mLeAudioProfile;
+ @Mock
+ private CachedBluetoothDeviceManager mCachedDeviceManager;
+ @Mock
+ private CachedBluetoothDevice mCachedBluetoothDeviceL;
+ @Mock
+ private CachedBluetoothDevice mCachedBluetoothDeviceR;
private Context mContext;
private PreferenceScreen mScreen;
@@ -117,8 +127,10 @@
private AudioSwitchPreferenceController mController;
private List<BluetoothDevice> mProfileConnectedDevices;
private List<BluetoothDevice> mHearingAidActiveDevices;
+ private List<BluetoothDevice> mLeAudioActiveDevices;
private List<BluetoothDevice> mEmptyDevices;
private ShadowPackageManager mPackageManager;
+ private Collection<CachedBluetoothDevice> mCachedDevices;
@Before
public void setUp() {
@@ -133,15 +145,22 @@
when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager);
when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager);
+ when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager);
when(mLocalBluetoothProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
when(mLocalBluetoothProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile);
when(mLocalBluetoothProfileManager.getHeadsetProfile()).thenReturn(mHeadsetProfile);
+ when(mLocalBluetoothProfileManager.getLeAudioProfile()).thenReturn(mLeAudioProfile);
mPackageManager = Shadow.extract(mContext.getPackageManager());
mPackageManager.setSystemFeature(PackageManager.FEATURE_BLUETOOTH, true);
mBluetoothManager = mContext.getSystemService(BluetoothManager.class);
mBluetoothAdapter = mBluetoothManager.getAdapter();
+ mCachedDevices = new ArrayList<>();
+ mCachedDevices.add(mCachedBluetoothDeviceL);
+ mCachedDevices.add(mCachedBluetoothDeviceR);
+ when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(mCachedDevices);
+
mBluetoothDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_1));
when(mBluetoothDevice.getName()).thenReturn(TEST_DEVICE_NAME_1);
when(mBluetoothDevice.isConnected()).thenReturn(true);
@@ -156,6 +175,7 @@
mPreference = new ListPreference(mContext);
mProfileConnectedDevices = new ArrayList<>();
mHearingAidActiveDevices = new ArrayList<>(2);
+ mLeAudioActiveDevices = new ArrayList<>();
mEmptyDevices = new ArrayList<>(2);
when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
@@ -391,6 +411,79 @@
assertThat(mEmptyDevices).containsExactly(mBluetoothDevice, mLeftBluetoothHapDevice);
}
+ @Test
+ public void getConnectedLeAudioDevices_connectedLeAudioDevice_shouldAddDeviceToList() {
+ when(mCachedBluetoothDeviceL.getDevice()).thenReturn(mBluetoothDevice);
+ mEmptyDevices.clear();
+ mProfileConnectedDevices.clear();
+ mProfileConnectedDevices.add(mBluetoothDevice);
+ when(mLeAudioProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
+
+ mEmptyDevices.addAll(mController.getConnectedLeAudioDevices());
+
+ assertThat(mEmptyDevices).containsExactly(mBluetoothDevice);
+ }
+
+ @Test
+ public void getConnectedLeAudioDevices_disconnectedLeAudioDevice_shouldNotAddDeviceToList() {
+ BluetoothDevice connectedBtLeAduioDevice =
+ spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_2));
+ when(connectedBtLeAduioDevice.isConnected()).thenReturn(true);
+ BluetoothDevice disconnectedBtLeAduioDevice =
+ spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_3));
+ when(disconnectedBtLeAduioDevice.isConnected()).thenReturn(false);
+ when(mCachedBluetoothDeviceL.getDevice()).thenReturn(mBluetoothDevice);
+ when(mCachedBluetoothDeviceR.getDevice()).thenReturn(connectedBtLeAduioDevice);
+ mEmptyDevices.clear();
+ mProfileConnectedDevices.clear();
+ mProfileConnectedDevices.add(mBluetoothDevice);
+ mProfileConnectedDevices.add(connectedBtLeAduioDevice);
+ mProfileConnectedDevices.add(disconnectedBtLeAduioDevice);
+ when(mLeAudioProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
+
+ mEmptyDevices.addAll(mController.getConnectedLeAudioDevices());
+
+ assertThat(mEmptyDevices).containsExactly(mBluetoothDevice, connectedBtLeAduioDevice);
+ }
+
+ @Test
+ public void getConnectedLeAudioDevices_notInCachedDeviceList_shouldNotAddDeviceToList() {
+ BluetoothDevice connectedBtLeAduioDevice1 =
+ spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_2));
+ when(connectedBtLeAduioDevice1.isConnected()).thenReturn(true);
+ BluetoothDevice connectedBtLeAduioDevice2 =
+ spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_3));
+ when(connectedBtLeAduioDevice2.isConnected()).thenReturn(true);
+ when(mCachedBluetoothDeviceL.getDevice()).thenReturn(mBluetoothDevice);
+ when(mCachedBluetoothDeviceR.getDevice()).thenReturn(connectedBtLeAduioDevice1);
+ mEmptyDevices.clear();
+ mProfileConnectedDevices.clear();
+ mProfileConnectedDevices.add(connectedBtLeAduioDevice1);
+ mProfileConnectedDevices.add(connectedBtLeAduioDevice2);
+ when(mLeAudioProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
+
+ mEmptyDevices.addAll(mController.getConnectedLeAudioDevices());
+
+ assertThat(mEmptyDevices).containsExactly(connectedBtLeAduioDevice1);
+ }
+
+ @Test
+ public void findActiveLeAudioDevice_noActiveDevice_returnNull() {
+ mLeAudioActiveDevices.clear();
+ when(mLeAudioProfile.getActiveDevices()).thenReturn(mLeAudioActiveDevices);
+
+ assertThat(mController.findActiveLeAudioDevice()).isNull();
+ }
+
+ @Test
+ public void findActiveLeAudioDevice_withActiveDevice_returnActiveDevice() {
+ mLeAudioActiveDevices.clear();
+ mLeAudioActiveDevices.add(mBluetoothDevice);
+ when(mLeAudioProfile.getActiveDevices()).thenReturn(mLeAudioActiveDevices);
+
+ assertThat(mController.findActiveLeAudioDevice()).isEqualTo(mBluetoothDevice);
+ }
+
private class AudioSwitchPreferenceControllerTestable extends
AudioSwitchPreferenceController {
AudioSwitchPreferenceControllerTestable(Context context, String key) {
diff --git a/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java
index 2580bfd..cc2606b 100644
--- a/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/sound/HandsFreeProfileOutputPreferenceControllerTest.java
@@ -16,6 +16,7 @@
package com.android.settings.sound;
+import static android.media.AudioSystem.DEVICE_OUT_BLE_HEADSET;
import static android.media.AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
import static android.media.AudioSystem.DEVICE_OUT_HEARING_AID;
@@ -44,29 +45,30 @@
import com.android.settings.testutils.shadow.ShadowAudioManager;
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
import com.android.settingslib.bluetooth.BluetoothEventManager;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
import com.android.settingslib.bluetooth.HeadsetProfile;
import com.android.settingslib.bluetooth.HearingAidProfile;
+import com.android.settingslib.bluetooth.LeAudioProfile;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-import org.robolectric.Shadows;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowBluetoothDevice;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
-@Ignore
@Config(shadows = {
ShadowAudioManager.class,
ShadowBluetoothUtils.class,
@@ -78,10 +80,12 @@
private static final String TEST_DEVICE_NAME_2 = "Test_HFP_BT_Device_NAME_2";
private static final String TEST_HAP_DEVICE_NAME_1 = "Test_HAP_BT_Device_NAME_1";
private static final String TEST_HAP_DEVICE_NAME_2 = "Test_HAP_BT_Device_NAME_2";
+ private static final String TEST_LE_AUDIO_DEVICE_NAME_1 = "Test_LE_AUDIO_Device_NAME_1";
private static final String TEST_DEVICE_ADDRESS_1 = "00:A1:A1:A1:A1:A1";
private static final String TEST_DEVICE_ADDRESS_2 = "00:B2:B2:B2:B2:B2";
private static final String TEST_DEVICE_ADDRESS_3 = "00:C3:C3:C3:C3:C3";
private static final String TEST_DEVICE_ADDRESS_4 = "00:D4:D4:D4:D4:D4";
+ private static final String TEST_DEVICE_ADDRESS_5 = "00:E5:E5:E5:E5:E5";
private final static long HISYNCID1 = 10;
private final static long HISYNCID2 = 11;
@@ -96,7 +100,15 @@
@Mock
private HearingAidProfile mHearingAidProfile;
@Mock
+ private LeAudioProfile mLeAudioProfile;
+ @Mock
private AudioSwitchPreferenceController.AudioSwitchCallback mAudioSwitchPreferenceCallback;
+ @Mock
+ private CachedBluetoothDeviceManager mCachedDeviceManager;
+ @Mock
+ private CachedBluetoothDevice mCachedBluetoothDeviceL;
+ @Mock
+ private CachedBluetoothDevice mCachedBluetoothDeviceR;
private Context mContext;
private PreferenceScreen mScreen;
@@ -113,6 +125,8 @@
private HandsFreeProfileOutputPreferenceController mController;
private List<BluetoothDevice> mProfileConnectedDevices;
private List<BluetoothDevice> mHearingAidActiveDevices;
+ private List<BluetoothDevice> mLeAudioActiveDevices;
+ private Collection<CachedBluetoothDevice> mCachedDevices;
@Before
public void setUp() {
@@ -127,26 +141,37 @@
when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager);
when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager);
+ when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager);
when(mLocalBluetoothProfileManager.getHeadsetProfile()).thenReturn(mHeadsetProfile);
when(mLocalBluetoothProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile);
+ when(mLocalBluetoothProfileManager.getLeAudioProfile()).thenReturn(mLeAudioProfile);
mBluetoothManager = mContext.getSystemService(BluetoothManager.class);
mBluetoothAdapter = mBluetoothManager.getAdapter();
+ mCachedDevices = new ArrayList<>();
+ mCachedDevices.add(mCachedBluetoothDeviceL);
+ mCachedDevices.add(mCachedBluetoothDeviceR);
+ when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(mCachedDevices);
+
mBluetoothDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_1));
when(mBluetoothDevice.getName()).thenReturn(TEST_DEVICE_NAME_1);
+ when(mBluetoothDevice.getAlias()).thenReturn(TEST_DEVICE_NAME_1);
when(mBluetoothDevice.isConnected()).thenReturn(true);
mSecondBluetoothDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_2));
when(mSecondBluetoothDevice.getName()).thenReturn(TEST_DEVICE_NAME_2);
+ when(mSecondBluetoothDevice.getAlias()).thenReturn(TEST_DEVICE_NAME_2);
when(mSecondBluetoothDevice.isConnected()).thenReturn(true);
mLeftBluetoothHapDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_3));
when(mLeftBluetoothHapDevice.getName()).thenReturn(TEST_HAP_DEVICE_NAME_1);
+ when(mLeftBluetoothHapDevice.getAlias()).thenReturn(TEST_HAP_DEVICE_NAME_1);
when(mLeftBluetoothHapDevice.isConnected()).thenReturn(true);
mRightBluetoothHapDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_4));
when(mRightBluetoothHapDevice.getName()).thenReturn(TEST_HAP_DEVICE_NAME_2);
+ when(mRightBluetoothHapDevice.getAlias()).thenReturn(TEST_HAP_DEVICE_NAME_2);
when(mRightBluetoothHapDevice.isConnected()).thenReturn(true);
mController = new HandsFreeProfileOutputPreferenceController(mContext, TEST_KEY);
@@ -154,6 +179,7 @@
mPreference = new ListPreference(mContext);
mProfileConnectedDevices = new ArrayList<>();
mHearingAidActiveDevices = new ArrayList<>(2);
+ mLeAudioActiveDevices = new ArrayList<>();
when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
when(mScreen.getContext()).thenReturn(mContext);
@@ -245,7 +271,6 @@
* Preference summary should be the activated device name
*/
@Test
- @Ignore
public void updateState_oneHeadsetsAvailableAndActivated_shouldSetDeviceName() {
mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_SCO);
@@ -267,7 +292,6 @@
* Preference summary should be the activated device name
*/
@Test
- @Ignore
public void updateState_moreThanOneHfpBtDevicesAreAvailable_shouldSetActivatedDeviceName() {
mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_SCO);
@@ -328,7 +352,6 @@
* Preference summary should be the activated device name
*/
@Test
- @Ignore
public void updateState_oneHapBtDeviceAreAvailable_shouldSetActivatedDeviceName() {
mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID);
@@ -353,7 +376,6 @@
* Preference summary should be the activated device name
*/
@Test
- @Ignore
public void updateState_moreThanOneHapBtDevicesAreAvailable_shouldSetActivatedDeviceName() {
mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID);
@@ -382,7 +404,6 @@
* ConnectedDevice should not contain second HAP device with same HisyncId
*/
@Test
- @Ignore
public void updateState_hapBtDeviceWithSameId_shouldSetActivatedDeviceName() {
mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID);
@@ -416,7 +437,6 @@
* ConnectedDevice should not contain second HAP device with same HisyncId
*/
@Test
- @Ignore
public void updateState_hapBtDeviceWithSameIdButDifferentOrder_shouldSetActivatedDeviceName() {
mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID);
@@ -449,7 +469,6 @@
* ConnectedDevice should contain both HAP device with different HisyncId
*/
@Test
- @Ignore
public void updateState_hapBtDeviceWithDifferentId_shouldSetActivatedDeviceName() {
mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID);
@@ -474,6 +493,26 @@
}
@Test
+ public void updateState_leAudioDeviceActive_shouldSetActivatedDeviceName() {
+ mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
+ mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLE_HEADSET);
+ when(mCachedBluetoothDeviceL.getDevice()).thenReturn(mBluetoothDevice);
+ when(mBluetoothDevice.getName()).thenReturn(TEST_LE_AUDIO_DEVICE_NAME_1);
+ when(mBluetoothDevice.getAlias()).thenReturn(TEST_LE_AUDIO_DEVICE_NAME_1);
+ mProfileConnectedDevices.clear();
+ mProfileConnectedDevices.add(mBluetoothDevice);
+ mLeAudioActiveDevices.clear();
+ mLeAudioActiveDevices.add(mBluetoothDevice);
+ when(mLeAudioProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
+ when(mLeAudioProfile.getActiveDevices()).thenReturn(mLeAudioActiveDevices);
+
+ mController.updateState(mPreference);
+
+ assertThat(mPreference.isVisible()).isTrue();
+ assertThat(mPreference.getSummary()).isEqualTo(mBluetoothDevice.getName());
+ }
+
+ @Test
public void findActiveDevice_onlyHeadsetDeviceActive_returnHeadsetDevice() {
when(mLocalBluetoothProfileManager.getHearingAidProfile()).thenReturn(null);
when(mHeadsetProfile.getActiveDevice()).thenReturn(mBluetoothDevice);
@@ -489,12 +528,60 @@
assertThat(mController.findActiveDevice()).isNull();
}
+ @Test
+ public void findActiveDevice_allProfilesWithActiveDevice_returnHADevice() {
+ BluetoothDevice btLeDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_5));
+ when(btLeDevice.getName()).thenReturn(TEST_LE_AUDIO_DEVICE_NAME_1);
+ mController.mConnectedDevices.clear();
+ mController.mConnectedDevices.add(mBluetoothDevice);
+ mController.mConnectedDevices.add(mLeftBluetoothHapDevice);
+ mController.mConnectedDevices.add(btLeDevice);
+ mLeAudioActiveDevices.clear();
+ mLeAudioActiveDevices.add(btLeDevice);
+ mHearingAidActiveDevices.clear();
+ mHearingAidActiveDevices.add(mLeftBluetoothHapDevice);
+ when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices);
+ when(mHearingAidProfile.getHiSyncId(mLeftBluetoothHapDevice)).thenReturn(HISYNCID1);
+ when(mHeadsetProfile.getActiveDevice()).thenReturn(mBluetoothDevice);
+ when(mLeAudioProfile.getActiveDevices()).thenReturn(mLeAudioActiveDevices);
+
+ assertThat(mController.findActiveDevice()).isEqualTo(mLeftBluetoothHapDevice);
+ }
+
+ @Test
+ public void findActiveDevice_headsetDeviceAndLeAudioDeviceActive_returnLeAudioDevice() {
+ BluetoothDevice btLeDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_5));
+ when(btLeDevice.getName()).thenReturn(TEST_LE_AUDIO_DEVICE_NAME_1);
+ mLeAudioActiveDevices.clear();
+ mLeAudioActiveDevices.add(btLeDevice);
+ mHearingAidActiveDevices.clear();
+ when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices);
+ when(mHeadsetProfile.getActiveDevice()).thenReturn(mBluetoothDevice);
+ when(mLeAudioProfile.getActiveDevices()).thenReturn(mLeAudioActiveDevices);
+
+ assertThat(mController.findActiveDevice()).isEqualTo(btLeDevice);
+ }
+
+ @Test
+ public void findActiveDevice_onlyLeAudioDeviceActive_returnLeAudioDevice() {
+ BluetoothDevice btLeDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_5));
+ when(btLeDevice.getName()).thenReturn(TEST_LE_AUDIO_DEVICE_NAME_1);
+ mLeAudioActiveDevices.clear();
+ mLeAudioActiveDevices.add(btLeDevice);
+ mHearingAidActiveDevices.clear();
+ when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices);
+ when(mHeadsetProfile.getActiveDevice()).thenReturn(null);
+ when(mLeAudioProfile.getActiveDevices()).thenReturn(mLeAudioActiveDevices);
+
+ assertThat(mController.findActiveDevice()).isEqualTo(btLeDevice);
+ }
+
+
/**
* One Bluetooth devices are available, and select the device.
* Preference summary should be device name.
*/
@Test
- @Ignore
public void onPreferenceChange_toBtDevice_shouldSetBtDeviceName() {
mController.mConnectedDevices.clear();
mController.mConnectedDevices.add(mBluetoothDevice);
@@ -509,16 +596,10 @@
* Preference summary should be second device name.
*/
@Test
- @Ignore
public void onPreferenceChange_toBtDevices_shouldSetSecondBtDeviceName() {
- ShadowBluetoothDevice shadowBluetoothDevice;
- BluetoothDevice secondBluetoothDevice;
- secondBluetoothDevice = mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_2);
- shadowBluetoothDevice = Shadows.shadowOf(secondBluetoothDevice);
- shadowBluetoothDevice.setName(TEST_DEVICE_NAME_2);
mController.mConnectedDevices.clear();
mController.mConnectedDevices.add(mBluetoothDevice);
- mController.mConnectedDevices.add(secondBluetoothDevice);
+ mController.mConnectedDevices.add(mSecondBluetoothDevice);
mController.onPreferenceChange(mPreference, TEST_DEVICE_ADDRESS_2);
diff --git a/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java
index 10471cb..5a92a08 100644
--- a/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/sound/MediaOutputPreferenceControllerTest.java
@@ -16,6 +16,7 @@
package com.android.settings.sound;
+import static android.media.AudioSystem.DEVICE_OUT_BLE_HEADSET;
import static android.media.AudioSystem.DEVICE_OUT_BLUETOOTH_A2DP;
import static android.media.AudioSystem.DEVICE_OUT_EARPIECE;
import static android.media.AudioSystem.DEVICE_OUT_HEARING_AID;
@@ -55,14 +56,16 @@
import com.android.settings.testutils.shadow.ShadowBluetoothUtils;
import com.android.settingslib.bluetooth.A2dpProfile;
import com.android.settingslib.bluetooth.BluetoothEventManager;
+import com.android.settingslib.bluetooth.CachedBluetoothDevice;
+import com.android.settingslib.bluetooth.CachedBluetoothDeviceManager;
import com.android.settingslib.bluetooth.HearingAidProfile;
+import com.android.settingslib.bluetooth.LeAudioProfile;
import com.android.settingslib.bluetooth.LocalBluetoothManager;
import com.android.settingslib.bluetooth.LocalBluetoothProfileManager;
import com.android.settingslib.media.MediaOutputConstants;
import org.junit.After;
import org.junit.Before;
-import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -76,10 +79,10 @@
import org.robolectric.shadows.ShadowPackageManager;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
@RunWith(RobolectricTestRunner.class)
-@Ignore
@Config(shadows = {
ShadowAudioManager.class,
ShadowBluetoothUtils.class,
@@ -91,10 +94,12 @@
private static final String TEST_DEVICE_NAME_2 = "Test_A2DP_BT_Device_NAME_2";
private static final String TEST_HAP_DEVICE_NAME_1 = "Test_HAP_BT_Device_NAME_1";
private static final String TEST_HAP_DEVICE_NAME_2 = "Test_HAP_BT_Device_NAME_2";
+ private static final String TEST_LE_AUDIO_DEVICE_NAME_1 = "Test_LE_AUDIO_Device_NAME_1";
private static final String TEST_DEVICE_ADDRESS_1 = "00:A1:A1:A1:A1:A1";
private static final String TEST_DEVICE_ADDRESS_2 = "00:B2:B2:B2:B2:B2";
private static final String TEST_DEVICE_ADDRESS_3 = "00:C3:C3:C3:C3:C3";
private static final String TEST_DEVICE_ADDRESS_4 = "00:D4:D4:D4:D4:D4";
+ private static final String TEST_DEVICE_ADDRESS_5 = "00:E5:E5:E5:E5:E5";
private static final String TEST_PACKAGE_NAME = "com.test.packagename";
private static final String TEST_APPLICATION_LABEL = "APP Test Label";
@@ -109,11 +114,19 @@
@Mock
private HearingAidProfile mHearingAidProfile;
@Mock
+ private LeAudioProfile mLeAudioProfile;
+ @Mock
private AudioSwitchPreferenceController.AudioSwitchCallback mAudioSwitchPreferenceCallback;
@Mock
private MediaSessionManager mMediaSessionManager;
@Mock
private MediaController mMediaController;
+ @Mock
+ private CachedBluetoothDeviceManager mCachedDeviceManager;
+ @Mock
+ private CachedBluetoothDevice mCachedBluetoothDeviceL;
+ @Mock
+ private CachedBluetoothDevice mCachedBluetoothDeviceR;
private Context mContext;
private PreferenceScreen mScreen;
@@ -130,6 +143,7 @@
private MediaOutputPreferenceController mController;
private List<BluetoothDevice> mProfileConnectedDevices;
private List<BluetoothDevice> mHearingAidActiveDevices;
+ private List<BluetoothDevice> mLeAudioActiveDevices;
private List<MediaController> mMediaControllers = new ArrayList<>();
private MediaController.PlaybackInfo mPlaybackInfo;
private PlaybackState mPlaybackState;
@@ -137,6 +151,7 @@
private ApplicationInfo mAppInfo;
private PackageInfo mPackageInfo;
private PackageStats mPackageStats;
+ private Collection<CachedBluetoothDevice> mCachedDevices;
@Before
public void setUp() {
@@ -168,14 +183,22 @@
when(mLocalBluetoothManager.getEventManager()).thenReturn(mBluetoothEventManager);
when(mLocalBluetoothManager.getProfileManager()).thenReturn(mLocalBluetoothProfileManager);
+ when(mLocalBluetoothManager.getCachedDeviceManager()).thenReturn(mCachedDeviceManager);
when(mLocalBluetoothProfileManager.getA2dpProfile()).thenReturn(mA2dpProfile);
when(mLocalBluetoothProfileManager.getHearingAidProfile()).thenReturn(mHearingAidProfile);
+ when(mLocalBluetoothProfileManager.getLeAudioProfile()).thenReturn(mLeAudioProfile);
mBluetoothManager = mContext.getSystemService(BluetoothManager.class);
mBluetoothAdapter = mBluetoothManager.getAdapter();
+ mCachedDevices = new ArrayList<>();
+ mCachedDevices.add(mCachedBluetoothDeviceL);
+ mCachedDevices.add(mCachedBluetoothDeviceR);
+ when(mCachedDeviceManager.getCachedDevicesCopy()).thenReturn(mCachedDevices);
+
mBluetoothDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_1));
when(mBluetoothDevice.getName()).thenReturn(TEST_DEVICE_NAME_1);
+ when(mBluetoothDevice.getAlias()).thenReturn(TEST_DEVICE_NAME_1);
when(mBluetoothDevice.isConnected()).thenReturn(true);
mSecondBluetoothDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_2));
@@ -184,6 +207,7 @@
mLeftBluetoothHapDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_3));
when(mLeftBluetoothHapDevice.getName()).thenReturn(TEST_HAP_DEVICE_NAME_1);
+ when(mLeftBluetoothHapDevice.getAlias()).thenReturn(TEST_HAP_DEVICE_NAME_1);
when(mLeftBluetoothHapDevice.isConnected()).thenReturn(true);
mRightBluetoothHapDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_4));
@@ -195,6 +219,7 @@
mPreference = new Preference(mContext);
mProfileConnectedDevices = new ArrayList<>();
mHearingAidActiveDevices = new ArrayList<>(2);
+ mLeAudioActiveDevices = new ArrayList<>();
when(mScreen.getPreferenceManager()).thenReturn(mock(PreferenceManager.class));
when(mScreen.getContext()).thenReturn(mContext);
@@ -234,7 +259,6 @@
* Preference summary should be device's name
*/
@Test
- @Ignore
public void updateState_withActiveBtDevice_setActivatedDeviceName() {
mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLUETOOTH_A2DP);
mAudioManager.setMode(AudioManager.MODE_NORMAL);
@@ -254,7 +278,6 @@
* Preference summary should be device's name
*/
@Test
- @Ignore
public void updateState_withActiveHADevice_setActivatedDeviceName() {
mShadowAudioManager.setOutputDevice(DEVICE_OUT_HEARING_AID);
mAudioManager.setMode(AudioManager.MODE_NORMAL);
@@ -270,6 +293,26 @@
}
@Test
+ public void updateState_withActiveLeAudioDevice_setActivatedDeviceName() {
+ mShadowAudioManager.setOutputDevice(DEVICE_OUT_BLE_HEADSET);
+ mAudioManager.setMode(AudioManager.MODE_NORMAL);
+ when(mCachedBluetoothDeviceL.getDevice()).thenReturn(mBluetoothDevice);
+ when(mCachedBluetoothDeviceR.getDevice()).thenReturn(mSecondBluetoothDevice);
+ when(mBluetoothDevice.getAlias()).thenReturn(TEST_LE_AUDIO_DEVICE_NAME_1);
+ mProfileConnectedDevices.clear();
+ mProfileConnectedDevices.add(mBluetoothDevice);
+ mProfileConnectedDevices.add(mSecondBluetoothDevice);
+ mLeAudioActiveDevices.clear();
+ mLeAudioActiveDevices.add(mBluetoothDevice);
+ when(mLeAudioProfile.getConnectedDevices()).thenReturn(mProfileConnectedDevices);
+ when(mLeAudioProfile.getActiveDevices()).thenReturn(mLeAudioActiveDevices);
+
+ assertThat(mPreference.getSummary()).isNull();
+ mController.updateState(mPreference);
+ assertThat(mPreference.getSummary()).isEqualTo(TEST_LE_AUDIO_DEVICE_NAME_1);
+ }
+
+ @Test
public void updateState_noActiveLocalPlayback_noTitle() {
mPlaybackState = new PlaybackState.Builder()
.setState(PlaybackState.STATE_NONE, 0, 1)
@@ -350,6 +393,49 @@
assertThat(mController.findActiveDevice()).isNull();
}
+ @Test
+ public void findActiveDevice_allProfilesWithActiveDevice_returnHADevice() {
+ BluetoothDevice btLeDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_5));
+ when(btLeDevice.getName()).thenReturn(TEST_LE_AUDIO_DEVICE_NAME_1);
+ mLeAudioActiveDevices.clear();
+ mLeAudioActiveDevices.add(btLeDevice);
+ mHearingAidActiveDevices.clear();
+ mHearingAidActiveDevices.add(mLeftBluetoothHapDevice);
+ when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices);
+ when(mA2dpProfile.getActiveDevice()).thenReturn(mBluetoothDevice);
+ when(mLeAudioProfile.getActiveDevices()).thenReturn(mLeAudioActiveDevices);
+
+ assertThat(mController.findActiveDevice()).isEqualTo(mLeftBluetoothHapDevice);
+ }
+
+ @Test
+ public void findActiveDevice_a2dpDeviceAndLeAudioDeviceActive_returnLeAudioDevice() {
+ BluetoothDevice btLeDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_5));
+ when(btLeDevice.getName()).thenReturn(TEST_LE_AUDIO_DEVICE_NAME_1);
+ mLeAudioActiveDevices.clear();
+ mLeAudioActiveDevices.add(btLeDevice);
+ mHearingAidActiveDevices.clear();
+ when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices);
+ when(mA2dpProfile.getActiveDevice()).thenReturn(mBluetoothDevice);
+ when(mLeAudioProfile.getActiveDevices()).thenReturn(mLeAudioActiveDevices);
+
+ assertThat(mController.findActiveDevice()).isEqualTo(btLeDevice);
+ }
+
+ @Test
+ public void findActiveDevice_onlyLeAudioDeviceActive_returnLeAudioDevice() {
+ BluetoothDevice btLeDevice = spy(mBluetoothAdapter.getRemoteDevice(TEST_DEVICE_ADDRESS_5));
+ when(btLeDevice.getName()).thenReturn(TEST_LE_AUDIO_DEVICE_NAME_1);
+ mLeAudioActiveDevices.clear();
+ mLeAudioActiveDevices.add(btLeDevice);
+ mHearingAidActiveDevices.clear();
+ when(mHearingAidProfile.getActiveDevices()).thenReturn(mHearingAidActiveDevices);
+ when(mA2dpProfile.getActiveDevice()).thenReturn(null);
+ when(mLeAudioProfile.getActiveDevices()).thenReturn(mLeAudioActiveDevices);
+
+ assertThat(mController.findActiveDevice()).isEqualTo(btLeDevice);
+ }
+
private void initPackage() {
mShadowPackageManager = Shadows.shadowOf(mContext.getPackageManager());
mAppInfo = new ApplicationInfo();
diff --git a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
index 2f24832..518aee9 100644
--- a/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
+++ b/tests/robotests/src/com/android/settings/testutils/FakeFeatureFactory.java
@@ -47,7 +47,6 @@
import com.android.settings.security.SecuritySettingsFeatureProvider;
import com.android.settings.slices.SlicesFeatureProvider;
import com.android.settings.users.UserFeatureProvider;
-import com.android.settings.vpn2.AdvancedVpnFeatureProvider;
import com.android.settings.wifi.WifiTrackerLibProvider;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
@@ -88,7 +87,6 @@
public SecuritySettingsFeatureProvider securitySettingsFeatureProvider;
public AccessibilitySearchFeatureProvider mAccessibilitySearchFeatureProvider;
public AccessibilityMetricsFeatureProvider mAccessibilityMetricsFeatureProvider;
- public AdvancedVpnFeatureProvider mAdvancedVpnFeatureProvider;
/**
* Call this in {@code @Before} method of the test class to use fake factory.
@@ -138,7 +136,6 @@
securitySettingsFeatureProvider = mock(SecuritySettingsFeatureProvider.class);
mAccessibilitySearchFeatureProvider = mock(AccessibilitySearchFeatureProvider.class);
mAccessibilityMetricsFeatureProvider = mock(AccessibilityMetricsFeatureProvider.class);
- mAdvancedVpnFeatureProvider = mock(AdvancedVpnFeatureProvider.class);
}
@Override
@@ -275,9 +272,4 @@
public AccessibilityMetricsFeatureProvider getAccessibilityMetricsFeatureProvider() {
return mAccessibilityMetricsFeatureProvider;
}
-
- @Override
- public AdvancedVpnFeatureProvider getAdvancedVpnFeatureProvider() {
- return mAdvancedVpnFeatureProvider;
- }
}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java
index 40cb25b..5f8c434 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUtils.java
@@ -22,6 +22,7 @@
import android.content.pm.PackageManager;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
+import android.hardware.face.FaceManager;
import android.hardware.fingerprint.FingerprintManager;
import android.os.UserHandle;
import android.os.UserManager;
@@ -39,6 +40,7 @@
public class ShadowUtils {
private static FingerprintManager sFingerprintManager = null;
+ private static FaceManager sFaceManager = null;
private static boolean sIsUserAMonkey;
private static boolean sIsDemoUser;
private static ComponentName sDeviceOwnerComponentName;
@@ -63,6 +65,15 @@
sFingerprintManager = fingerprintManager;
}
+ @Implementation
+ protected static FaceManager getFaceManagerOrNull(Context context) {
+ return sFaceManager;
+ }
+
+ public static void setFaceManager(FaceManager faceManager) {
+ sFaceManager = faceManager;
+ }
+
public static void reset() {
sFingerprintManager = null;
sIsUserAMonkey = false;
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPreferenceControllerTest.java
index e8ee7c3..bc6053b 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherPreferenceControllerTest.java
@@ -16,13 +16,14 @@
package com.android.settings.wifi.tether;
+import static com.android.settings.wifi.WifiUtils.setCanShowWifiHotspotCached;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;
import android.content.Context;
-import android.net.TetheringManager;
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.WifiManager;
@@ -62,8 +63,6 @@
@Mock
private Lifecycle mLifecycle;
@Mock
- private TetheringManager mTetheringManager;
- @Mock
private WifiManager mWifiManager;
@Mock
private PreferenceScreen mScreen;
@@ -74,38 +73,37 @@
@Before
public void setUp() {
+ setCanShowWifiHotspotCached(true);
FakeFeatureFactory.setupForTest();
mPreference = new PrimarySwitchPreference(mContext);
- when(mContext.getSystemService(Context.TETHERING_SERVICE)).thenReturn(mTetheringManager);
when(mContext.getSystemService(Context.WIFI_SERVICE)).thenReturn(mWifiManager);
when(mScreen.findPreference(anyString())).thenReturn(mPreference);
mSoftApConfiguration = new SoftApConfiguration.Builder().setSsid(SSID).build();
when(mWifiManager.getSoftApConfiguration()).thenReturn(mSoftApConfiguration);
- when(mTetheringManager.getTetherableWifiRegexs()).thenReturn(new String[]{"1", "2"});
mController = new WifiTetherPreferenceController(mContext, mLifecycle, mWifiManager,
- mTetheringManager, false /* initSoftApManager */, true /* isWifiTetheringAllow */);
+ false /* initSoftApManager */, true /* isWifiTetheringAllow */);
mController.displayPreference(mScreen);
}
@Test
- public void isAvailable_noTetherRegex_shouldReturnFalse() {
- when(mTetheringManager.getTetherableWifiRegexs()).thenReturn(new String[]{});
- mController = new WifiTetherPreferenceController(mContext, mLifecycle, mWifiManager,
- mTetheringManager, false /* initSoftApManager */, true /* isWifiTetheringAllow */);
+ public void isAvailable_canNotShowWifiHotspot_shouldReturnFalse() {
+ setCanShowWifiHotspotCached(false);
assertThat(mController.isAvailable()).isFalse();
}
@Test
- public void isAvailable_hasTetherRegex_shouldReturnTrue() {
+ public void isAvailable_canShowWifiHostspot_shouldReturnTrue() {
+ setCanShowWifiHotspotCached(true);
+
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void displayPreference_wifiTetheringNotAllowed_shouldDisable() {
mController = new WifiTetherPreferenceController(mContext, mLifecycle, mWifiManager,
- mTetheringManager, false /* initSoftApManager */, false /* isWifiTetheringAllow */);
+ false /* initSoftApManager */, false /* isWifiTetheringAllow */);
mController.displayPreference(mScreen);
@@ -116,7 +114,7 @@
@Test
public void displayPreference_wifiTetheringAllowed_shouldEnable() {
mController = new WifiTetherPreferenceController(mContext, mLifecycle, mWifiManager,
- mTetheringManager, false /* initSoftApManager */, true /* isWifiTetheringAllow */);
+ false /* initSoftApManager */, true /* isWifiTetheringAllow */);
mController.displayPreference(mScreen);
diff --git a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java
index d19bc90..7f8a06d 100644
--- a/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/tether/WifiTetherSettingsTest.java
@@ -16,6 +16,8 @@
package com.android.settings.wifi.tether;
+import static com.android.settings.wifi.WifiUtils.setCanShowWifiHotspotCached;
+
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
@@ -35,6 +37,7 @@
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.os.UserManager;
+import android.util.FeatureFlagUtils;
import android.widget.TextView;
import androidx.fragment.app.FragmentActivity;
@@ -42,6 +45,8 @@
import androidx.test.core.app.ApplicationProvider;
import com.android.settings.R;
+import com.android.settings.core.FeatureFlags;
+import com.android.settings.dashboard.RestrictedDashboardFragment;
import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.shadow.ShadowFragment;
@@ -55,6 +60,8 @@
import org.mockito.junit.MockitoRule;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
import org.robolectric.util.ReflectionHelpers;
import java.util.List;
@@ -88,6 +95,8 @@
@Before
public void setUp() {
+ FeatureFlagUtils.setEnabled(mContext, FeatureFlags.TETHER_ALL_IN_ONE, false);
+ setCanShowWifiHotspotCached(true);
doReturn(mWifiManager).when(mContext).getSystemService(WifiManager.class);
doReturn(mConnectivityManager)
.when(mContext).getSystemService(Context.CONNECTIVITY_SERVICE);
@@ -101,6 +110,17 @@
}
@Test
+ @Config(shadows = ShadowRestrictedDashboardFragment.class)
+ public void onCreate_canNotShowWifiHotspot_shouldFinish() {
+ setCanShowWifiHotspotCached(false);
+ mWifiTetherSettings = spy(new WifiTetherSettings(mWifiRestriction));
+
+ mWifiTetherSettings.onCreate(null);
+
+ verify(mWifiTetherSettings).finish();
+ }
+
+ @Test
@Config(shadows = ShadowFragment.class)
public void onStart_uiIsRestricted_removeAllPreferences() {
spyWifiTetherSettings();
@@ -201,6 +221,22 @@
assertThat(keys).contains(WifiTetherSettings.KEY_WIFI_TETHER_MAXIMIZE_COMPATIBILITY);
}
+ @Test
+ public void isPageSearchEnabled_canShowWifiHotspot_returnTrue() {
+ setCanShowWifiHotspotCached(true);
+
+ assertThat(WifiTetherSettings.SEARCH_INDEX_DATA_PROVIDER.isPageSearchEnabled(mContext))
+ .isTrue();
+ }
+
+ @Test
+ public void isPageSearchEnabled_canNotShowWifiHotspot_returnFalse() {
+ setCanShowWifiHotspotCached(false);
+
+ assertThat(WifiTetherSettings.SEARCH_INDEX_DATA_PROVIDER.isPageSearchEnabled(mContext))
+ .isFalse();
+ }
+
private void spyWifiTetherSettings() {
mWifiTetherSettings = spy(new WifiTetherSettings(mWifiRestriction));
final FragmentActivity activity = mock(FragmentActivity.class);
@@ -219,4 +255,13 @@
mWifiTetherSettings.onCreate(Bundle.EMPTY);
}
+
+ @Implements(RestrictedDashboardFragment.class)
+ public static final class ShadowRestrictedDashboardFragment {
+
+ @Implementation
+ public void onCreate(Bundle icicle) {
+ // do nothing
+ }
+ }
}
diff --git a/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java b/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java
index 43a32b5..63dca7e 100644
--- a/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java
+++ b/tests/unit/src/com/android/settings/network/SubscriptionUtilTest.java
@@ -25,11 +25,14 @@
import static org.mockito.Mockito.when;
import android.content.Context;
+import android.content.res.Resources;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
+import com.android.settings.R;
+
import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
@@ -58,6 +61,8 @@
private SubscriptionManager mSubMgr;
@Mock
private TelephonyManager mTelMgr;
+ @Mock
+ private Resources mResources;
@Before
@@ -443,4 +448,22 @@
public void isInactiveInsertedPSim_nullSubInfo_doesNotCrash() {
assertThat(SubscriptionUtil.isInactiveInsertedPSim(null)).isFalse();
}
+
+ @Test
+ public void isSimHardwareVisible_configAsInvisible_returnFalse() {
+ when(mContext.getResources()).thenReturn(mResources);
+ when(mResources.getBoolean(R.bool.config_show_sim_info))
+ .thenReturn(false);
+
+ assertThat(SubscriptionUtil.isSimHardwareVisible(mContext)).isFalse();
+ }
+
+ @Test
+ public void isSimHardwareVisible_configAsVisible_returnTrue() {
+ when(mContext.getResources()).thenReturn(mResources);
+ when(mResources.getBoolean(R.bool.config_show_sim_info))
+ .thenReturn(true);
+
+ assertTrue(SubscriptionUtil.isSimHardwareVisible(mContext));
+ }
}
diff --git a/tests/unit/src/com/android/settings/network/UiccSlotUtilTest.java b/tests/unit/src/com/android/settings/network/UiccSlotUtilTest.java
index 4282b3e6..9a2c611 100644
--- a/tests/unit/src/com/android/settings/network/UiccSlotUtilTest.java
+++ b/tests/unit/src/com/android/settings/network/UiccSlotUtilTest.java
@@ -638,6 +638,106 @@
assertThat(testExcludedLogicalSlotIndex).isEqualTo(verifyExcludedLogicalSlotIndex);
}
+ @Test
+ public void isRemovableSimEnabled_noPsim_returnsFalse() {
+ when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
+ oneSimSlotDeviceActiveEsim());
+
+ boolean testSlot = UiccSlotUtil.isRemovableSimEnabled(mTelephonyManager);
+
+ assertThat(testSlot).isFalse();
+ }
+
+ @Test
+ public void isRemovableSimEnabled_activeRemovableEsimAndInactivePsim_returnsFalse() {
+ when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
+ twoSimSlotsDeviceActiveRemovableEsimInactivePsim());
+
+ boolean testSlot = UiccSlotUtil.isRemovableSimEnabled(mTelephonyManager);
+
+ assertThat(testSlot).isFalse();
+ }
+
+ @Test
+ public void isRemovableSimEnabled_activeRemovableEsimAndActivePsim_returnsTrue() {
+ when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
+ twoSimSlotsDeviceActivePsimActiveRemovableEsim());
+
+ boolean testSlot = UiccSlotUtil.isRemovableSimEnabled(mTelephonyManager);
+
+ assertThat(testSlot).isTrue();
+ }
+
+ @Test
+ public void isRemovableSimEnabled_inactiveRemovableEsimAndActivePsim_returnsTrue() {
+ when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
+ twoSimSlotsDeviceInactiveRemovableEsimActivePsim());
+
+ boolean testSlot = UiccSlotUtil.isRemovableSimEnabled(mTelephonyManager);
+
+ assertThat(testSlot).isTrue();
+ }
+
+ @Test
+ public void isRemovableSimEnabled_twoActiveRemovableEsimsAndInactivePsim_returnsFalse() {
+ when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
+ twoSimSlotsDeviceTwoActiveRemovableEsimsInactivePsim());
+
+ boolean testSlot = UiccSlotUtil.isRemovableSimEnabled(mTelephonyManager);
+
+ assertThat(testSlot).isFalse();
+ }
+
+ @Test
+ public void isRemovableSimEnabled_oneActiveOneInactiveRemovableEsimActivePsim_returnsTrue() {
+ when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
+ twoSimSlotsDeviceOneActiveOneInactiveRemovableEsimsActivePsim());
+
+ boolean testSlot = UiccSlotUtil.isRemovableSimEnabled(mTelephonyManager);
+
+ assertThat(testSlot).isTrue();
+ }
+
+ @Test
+ public void isRemovableSimEnabled_activePsim_returnsTrue() {
+ when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
+ oneSimSlotDeviceActivePsim());
+
+ boolean testSlot = UiccSlotUtil.isRemovableSimEnabled(mTelephonyManager);
+
+ assertThat(testSlot).isTrue();
+ }
+
+ @Test
+ public void isRemovableSimEnabled_inactivePsim_returnsFalse() {
+ when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
+ oneSimSlotDeviceinactivePsim());
+
+ boolean testSlot = UiccSlotUtil.isRemovableSimEnabled(mTelephonyManager);
+
+ assertThat(testSlot).isFalse();
+ }
+
+ @Test
+ public void isRemovableSimEnabled_activeEsimAndActivePsim_returnsTrue() {
+ when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
+ twoSimSlotsDeviceActivePsimActiveEsim());
+
+ boolean testSlot = UiccSlotUtil.isRemovableSimEnabled(mTelephonyManager);
+
+ assertThat(testSlot).isTrue();
+ }
+
+ @Test
+ public void isRemovableSimEnabled_activeEsimAndInactivePsim_returnsFalse() {
+ when(mTelephonyManager.getUiccSlotsInfo()).thenReturn(
+ twoSimSlotsDeviceInactivePsimActiveEsim());
+
+ boolean testSlot = UiccSlotUtil.isRemovableSimEnabled(mTelephonyManager);
+
+ assertThat(testSlot).isFalse();
+ }
+
private void compareTwoUiccSlotMappings(Collection<UiccSlotMapping> testUiccSlotMappings,
Collection<UiccSlotMapping> verifyUiccSlotMappings) {
assertThat(testUiccSlotMappings.size()).isEqualTo(verifyUiccSlotMappings.size());
@@ -792,6 +892,10 @@
return new UiccSlotInfo[]{createUiccSlotInfo(true, false, 1, true)};
}
+ private UiccSlotInfo[] oneSimSlotDeviceinactivePsim() {
+ return new UiccSlotInfo[]{createUiccSlotInfo(false, true, -1, false)};
+ }
+
private UiccSlotInfo[] twoSimSlotsDeviceActivePsimActiveEsim() {
return new UiccSlotInfo[]{
createUiccSlotInfo(false, true, 0, true),
@@ -810,6 +914,30 @@
createUiccSlotInfo(true, true, 1, true)};
}
+ private UiccSlotInfo[] twoSimSlotsDeviceActiveRemovableEsimInactivePsim() {
+ return new UiccSlotInfo[]{
+ createUiccSlotInfo(true, true, 0, true),
+ createUiccSlotInfo(false, true, -1, false)};
+ }
+
+ private UiccSlotInfo[] twoSimSlotsDeviceInactiveRemovableEsimActivePsim() {
+ return new UiccSlotInfo[]{
+ createUiccSlotInfo(true, true, -1, false),
+ createUiccSlotInfo(false, true, 0, true)};
+ }
+
+ private UiccSlotInfo[] twoSimSlotsDeviceTwoActiveRemovableEsimsInactivePsim() {
+ return new UiccSlotInfo[]{
+ createUiccSlotInfoForRemovableEsimMep(0, true, 1, true),
+ createUiccSlotInfo(false, true, -1, false)};
+ }
+
+ private UiccSlotInfo[] twoSimSlotsDeviceOneActiveOneInactiveRemovableEsimsActivePsim() {
+ return new UiccSlotInfo[]{
+ createUiccSlotInfoForRemovableEsimMep(1, true, -1, false),
+ createUiccSlotInfo(false, true, 0, true)};
+ }
+
private UiccSlotInfo[] twoSimSlotsDeviceActiveEsimActivePsim() {
return new UiccSlotInfo[]{
createUiccSlotInfo(true, false, 0, true),
@@ -872,4 +1000,20 @@
logicalSlotIdx2 /* logicalSlotIdx */,
isActiveEsim2 /* isActive */)));
}
+
+ private UiccSlotInfo createUiccSlotInfoForRemovableEsimMep(int logicalSlotIdx1,
+ boolean isActiveEsim1, int logicalSlotIdx2, boolean isActiveEsim2) {
+ return new UiccSlotInfo(
+ true, /* isEuicc */
+ "123", /* cardId */
+ CARD_STATE_INFO_PRESENT, /* cardStateInfo */
+ true, /* isExtendApduSupported */
+ true, /* isRemovable */
+ Arrays.asList(
+ new UiccPortInfo("" /* iccId */, 0 /* portIdx */,
+ logicalSlotIdx1 /* logicalSlotIdx */, isActiveEsim1 /* isActive */),
+ new UiccPortInfo("" /* iccId */, 1 /* portIdx */,
+ logicalSlotIdx2 /* logicalSlotIdx */,
+ isActiveEsim2 /* isActive */)));
+ }
}
diff --git a/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java b/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java
index f565075..717de79 100644
--- a/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java
+++ b/tests/unit/src/com/android/settings/testutils/FakeFeatureFactory.java
@@ -45,7 +45,6 @@
import com.android.settings.security.SecuritySettingsFeatureProvider;
import com.android.settings.slices.SlicesFeatureProvider;
import com.android.settings.users.UserFeatureProvider;
-import com.android.settings.vpn2.AdvancedVpnFeatureProvider;
import com.android.settings.wifi.WifiTrackerLibProvider;
import com.android.settingslib.core.instrumentation.MetricsFeatureProvider;
@@ -83,7 +82,6 @@
public SecuritySettingsFeatureProvider securitySettingsFeatureProvider;
public AccessibilitySearchFeatureProvider mAccessibilitySearchFeatureProvider;
public AccessibilityMetricsFeatureProvider mAccessibilityMetricsFeatureProvider;
- public AdvancedVpnFeatureProvider mAdvancedVpnFeatureProvider;
/**
* Call this in {@code @Before} method of the test class to use fake factory.
@@ -124,7 +122,6 @@
securitySettingsFeatureProvider = mock(SecuritySettingsFeatureProvider.class);
mAccessibilitySearchFeatureProvider = mock(AccessibilitySearchFeatureProvider.class);
mAccessibilityMetricsFeatureProvider = mock(AccessibilityMetricsFeatureProvider.class);
- mAdvancedVpnFeatureProvider = mock(AdvancedVpnFeatureProvider.class);
}
@Override
@@ -261,9 +258,4 @@
public AccessibilityMetricsFeatureProvider getAccessibilityMetricsFeatureProvider() {
return mAccessibilityMetricsFeatureProvider;
}
-
- @Override
- public AdvancedVpnFeatureProvider getAdvancedVpnFeatureProvider() {
- return mAdvancedVpnFeatureProvider;
- }
}
diff --git a/tests/unit/src/com/android/settings/vpn2/AppManagementFragmentTest.java b/tests/unit/src/com/android/settings/vpn2/AppManagementFragmentTest.java
deleted file mode 100644
index 80bb393..0000000
--- a/tests/unit/src/com/android/settings/vpn2/AppManagementFragmentTest.java
+++ /dev/null
@@ -1,102 +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.vpn2;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.os.Looper;
-
-import androidx.test.annotation.UiThreadTest;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.settings.testutils.FakeFeatureFactory;
-import com.android.settingslib.RestrictedPreference;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-@RunWith(AndroidJUnit4.class)
-public class AppManagementFragmentTest {
- private static final String FAKE_PACKAGE_NAME = "com.fake.package.name";
- private static final String ADVANCED_VPN_GROUP_PACKAGE_NAME = "com.advanced.package.name";
-
- @Rule
- public final MockitoRule mMockitoRule = MockitoJUnit.rule();
-
- private AppManagementFragment mFragment;
- private Context mContext;
- private FakeFeatureFactory mFakeFeatureFactory;
- private RestrictedPreference mPreferenceForget;
-
- @Before
- @UiThreadTest
- public void setUp() {
- if (Looper.myLooper() == null) {
- Looper.prepare();
- }
-
- mFragment = spy(new AppManagementFragment());
- mContext = spy(ApplicationProvider.getApplicationContext());
- mPreferenceForget = new RestrictedPreference(mContext);
-
- mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
- mFragment.init(ADVANCED_VPN_GROUP_PACKAGE_NAME,
- mFakeFeatureFactory.getAdvancedVpnFeatureProvider(), mPreferenceForget);
- when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.getAdvancedVpnPackageName())
- .thenReturn(ADVANCED_VPN_GROUP_PACKAGE_NAME);
- when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.isAdvancedVpnSupported(any()))
- .thenReturn(true);
- }
-
- @Test
- public void updateRestrictedViews_isAdvancedVpn_hidesForgetPreference() {
- when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.isAdvancedVpnRemovable())
- .thenReturn(false);
- mFragment.updateRestrictedViews();
- assertThat(mPreferenceForget.isVisible()).isFalse();
- }
-
- @Test
- public void updateRestrictedViews_isNotAdvancedVpn_showsForgetPreference() {
- when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.isAdvancedVpnRemovable())
- .thenReturn(false);
- mFragment.init(FAKE_PACKAGE_NAME,
- mFakeFeatureFactory.getAdvancedVpnFeatureProvider(), mPreferenceForget);
- mFragment.updateRestrictedViews();
- assertThat(mPreferenceForget.isVisible()).isTrue();
- }
-
- @Test
- public void updateRestrictedViews_isAdvancedVpnRemovable_showsForgetPreference() {
- when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.isAdvancedVpnRemovable())
- .thenReturn(true);
- mFragment.init(FAKE_PACKAGE_NAME,
- mFakeFeatureFactory.getAdvancedVpnFeatureProvider(), mPreferenceForget);
- mFragment.updateRestrictedViews();
- assertThat(mPreferenceForget.isVisible()).isTrue();
- }
-}
diff --git a/tests/unit/src/com/android/settings/vpn2/VpnSettingsTest.java b/tests/unit/src/com/android/settings/vpn2/VpnSettingsTest.java
deleted file mode 100644
index 953a524..0000000
--- a/tests/unit/src/com/android/settings/vpn2/VpnSettingsTest.java
+++ /dev/null
@@ -1,285 +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.vpn2;
-
-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.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.AppOpsManager;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.ApplicationInfo;
-import android.content.pm.PackageManager;
-import android.os.Looper;
-import android.os.UserHandle;
-import android.text.TextUtils;
-import android.util.ArraySet;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceCategory;
-import androidx.preference.PreferenceGroup;
-import androidx.preference.PreferenceManager;
-import androidx.preference.PreferenceScreen;
-import androidx.test.annotation.UiThreadTest;
-import androidx.test.core.app.ApplicationProvider;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import com.android.settings.testutils.FakeFeatureFactory;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-
-@RunWith(AndroidJUnit4.class)
-public class VpnSettingsTest {
- private static final int USER_ID_1 = UserHandle.USER_NULL;
- private static final String VPN_GROUP_KEY = "vpn_group";
- private static final String VPN_GROUP_TITLE = "vpn_group_title";
- private static final String VPN_PACKAGE_NAME = "vpn.package.name";
- private static final String VPN_LAUNCH_INTENT = "vpn.action";
- private static final String ADVANCED_VPN_GROUP_KEY = "advanced_vpn_group";
- private static final String ADVANCED_VPN_GROUP_TITLE = "advanced_vpn_group_title";
- private static final String ADVANCED_VPN_PACKAGE_NAME = "advanced.vpn.package.name";
- private static final String ADVANCED_VPN_LAUNCH_INTENT = "advanced.vpn.action";
-
- private final Intent mVpnIntent = new Intent().setAction(VPN_LAUNCH_INTENT);
- private final Intent mAdvancedVpnIntent = new Intent().setAction(ADVANCED_VPN_LAUNCH_INTENT);
-
- @Rule
- public final MockitoRule mMockitoRule = MockitoJUnit.rule();
-
- @Mock
- private AppOpsManager mAppOpsManager;
- @Mock
- private PackageManager mPackageManager;
-
- private VpnSettings mVpnSettings;
- private Context mContext;
- private PreferenceManager mPreferenceManager;
- private PreferenceScreen mPreferenceScreen;
- private PreferenceGroup mAdvancedVpnGroup;
- private PreferenceGroup mVpnGroup;
- private FakeFeatureFactory mFakeFeatureFactory;
-
- @Before
- @UiThreadTest
- public void setUp() throws PackageManager.NameNotFoundException {
- if (Looper.myLooper() == null) {
- Looper.prepare();
- }
-
- mVpnSettings = spy(new VpnSettings());
- mContext = spy(ApplicationProvider.getApplicationContext());
- mAdvancedVpnGroup = spy(new PreferenceCategory(mContext));
- mVpnGroup = spy(new PreferenceCategory(mContext));
- mAdvancedVpnGroup.setKey(ADVANCED_VPN_GROUP_KEY);
- mVpnGroup.setKey(VPN_GROUP_KEY);
- mPreferenceManager = new PreferenceManager(mContext);
- mPreferenceScreen = mPreferenceManager.createPreferenceScreen(mContext);
- mPreferenceScreen.addPreference(mAdvancedVpnGroup);
- mPreferenceScreen.addPreference(mVpnGroup);
- mFakeFeatureFactory = FakeFeatureFactory.setupForTest();
- mVpnSettings.init(mPreferenceScreen, mFakeFeatureFactory.getAdvancedVpnFeatureProvider());
-
- when(mVpnSettings.getContext()).thenReturn(mContext);
- when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider
- .getAdvancedVpnPreferenceGroupTitle(mContext)).thenReturn(ADVANCED_VPN_GROUP_TITLE);
- when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.getVpnPreferenceGroupTitle(mContext))
- .thenReturn(VPN_GROUP_TITLE);
- when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.getAdvancedVpnPackageName())
- .thenReturn(ADVANCED_VPN_PACKAGE_NAME);
- when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.isAdvancedVpnSupported(any()))
- .thenReturn(true);
- when(mContext.getPackageManager()).thenReturn(mPackageManager);
- doReturn(mContext).when(mContext).createContextAsUser(any(), anyInt());
- doReturn(mContext).when(mContext).createPackageContextAsUser(any(), anyInt(), any());
- doReturn(mPreferenceManager).when(mVpnGroup).getPreferenceManager();
- doReturn(mPreferenceManager).when(mAdvancedVpnGroup).getPreferenceManager();
- }
-
- @Test
- public void setShownAdvancedPreferences_hasGeneralVpn_returnsVpnCountAs1() {
- Set<Preference> updates = new ArraySet<>();
- AppPreference pref =
- spy(new AppPreference(mContext, USER_ID_1, VPN_PACKAGE_NAME));
- updates.add(pref);
-
- mVpnSettings.setShownAdvancedPreferences(updates);
-
- assertThat(mVpnGroup.getPreferenceCount()).isEqualTo(1);
- assertThat(mVpnGroup.isVisible()).isTrue();
- assertThat(mAdvancedVpnGroup.isVisible()).isFalse();
- }
-
- @Test
- public void setShownAdvancedPreferences_hasAdvancedVpn_returnsAdvancedVpnCountAs1() {
- Set<Preference> updates = new ArraySet<>();
- AppPreference pref =
- spy(new AppPreference(mContext, USER_ID_1, ADVANCED_VPN_PACKAGE_NAME));
- updates.add(pref);
-
- mVpnSettings.setShownAdvancedPreferences(updates);
-
- assertThat(mAdvancedVpnGroup.getPreferenceCount()).isEqualTo(1);
- assertThat(mAdvancedVpnGroup.isVisible()).isTrue();
- assertThat(mVpnGroup.isVisible()).isFalse();
- }
-
- @Test
- public void setShownAdvancedPreferences_noVpn_returnsEmpty() {
- Set<Preference> updates = new ArraySet<>();
-
- mVpnSettings.setShownAdvancedPreferences(updates);
-
- assertThat(mAdvancedVpnGroup.getPreferenceCount()).isEqualTo(0);
- assertThat(mVpnGroup.getPreferenceCount()).isEqualTo(0);
- assertThat(mAdvancedVpnGroup.isVisible()).isFalse();
- assertThat(mVpnGroup.isVisible()).isFalse();
- }
-
- @Test
- public void getVpnApps_isAdvancedVpn_returnsOne() throws Exception {
- ApplicationInfo info = new ApplicationInfo();
- info.uid = 1111;
- when(mPackageManager.getApplicationInfo(anyString(), anyInt())).thenReturn(info);
-
- assertThat(VpnSettings.getVpnApps(mContext, /* includeProfiles= */ false,
- mFakeFeatureFactory.getAdvancedVpnFeatureProvider(),
- mAppOpsManager).size()).isEqualTo(1);
- }
-
- @Test
- public void getVpnApps_isNotAdvancedVpn_returnsEmpty() {
- int uid = 1111;
- List<AppOpsManager.OpEntry> opEntries = new ArrayList<>();
- List<AppOpsManager.PackageOps> apps = new ArrayList<>();
- AppOpsManager.PackageOps packageOps =
- new AppOpsManager.PackageOps(VPN_PACKAGE_NAME, uid, opEntries);
- apps.add(packageOps);
- when(mAppOpsManager.getPackagesForOps((int[]) any())).thenReturn(apps);
- when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.isAdvancedVpnSupported(any()))
- .thenReturn(false);
-
- assertThat(VpnSettings.getVpnApps(mContext, /* includeProfiles= */ false,
- mFakeFeatureFactory.getAdvancedVpnFeatureProvider(),
- mAppOpsManager)).isEmpty();
- }
-
- @Test
- public void clickVpn_VpnConnected_doesNotStartVpnLaunchIntent()
- throws PackageManager.NameNotFoundException {
- Set<Preference> updates = new ArraySet<>();
- AppPreference pref = spy(new AppPreference(mContext, USER_ID_1, VPN_PACKAGE_NAME));
- pref.setState(AppPreference.STATE_CONNECTED);
- updates.add(pref);
- when(mContext.createPackageContextAsUser(any(), anyInt(), any())).thenReturn(mContext);
- when(mContext.getPackageManager()).thenReturn(mPackageManager);
- when(mPackageManager.getLaunchIntentForPackage(any())).thenReturn(mVpnIntent);
- ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
- doNothing().when(mContext).startActivityAsUser(captor.capture(), any());
- mVpnSettings.setShownPreferences(updates);
-
- mVpnSettings.onPreferenceClick(pref);
-
- verify(mContext, never()).startActivityAsUser(any(), any());
- }
-
- @Test
- public void clickVpn_VpnDisconnected_startsVpnLaunchIntent()
- throws PackageManager.NameNotFoundException {
- Set<Preference> updates = new ArraySet<>();
- AppPreference pref = spy(new AppPreference(mContext, USER_ID_1, VPN_PACKAGE_NAME));
- pref.setState(AppPreference.STATE_DISCONNECTED);
- updates.add(pref);
- when(mContext.createPackageContextAsUser(any(), anyInt(), any())).thenReturn(mContext);
- when(mContext.getPackageManager()).thenReturn(mPackageManager);
- when(mPackageManager.getLaunchIntentForPackage(any())).thenReturn(mVpnIntent);
- ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
- doNothing().when(mContext).startActivityAsUser(captor.capture(), any());
- mVpnSettings.setShownPreferences(updates);
-
- mVpnSettings.onPreferenceClick(pref);
-
- verify(mContext).startActivityAsUser(captor.capture(), any());
- assertThat(TextUtils.equals(captor.getValue().getAction(),
- VPN_LAUNCH_INTENT)).isTrue();
- }
-
- @Test
- public void clickAdvancedVpn_VpnConnectedDisconnectDialogDisabled_startsAppLaunchIntent()
- throws PackageManager.NameNotFoundException {
- Set<Preference> updates = new ArraySet<>();
- AppPreference pref =
- spy(new AppPreference(mContext, USER_ID_1, ADVANCED_VPN_PACKAGE_NAME));
- pref.setState(AppPreference.STATE_CONNECTED);
- updates.add(pref);
- when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.isDisconnectDialogEnabled())
- .thenReturn(false);
- when(mContext.createPackageContextAsUser(any(), anyInt(), any())).thenReturn(mContext);
- when(mContext.getPackageManager()).thenReturn(mPackageManager);
- when(mPackageManager.getLaunchIntentForPackage(any())).thenReturn(mAdvancedVpnIntent);
- ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
- doNothing().when(mContext).startActivityAsUser(captor.capture(), any());
- mVpnSettings.setShownAdvancedPreferences(updates);
-
- mVpnSettings.onPreferenceClick(pref);
-
- verify(mContext).startActivityAsUser(captor.capture(), any());
- assertThat(TextUtils.equals(captor.getValue().getAction(),
- ADVANCED_VPN_LAUNCH_INTENT)).isTrue();
- }
-
- @Test
- public void clickAdvancedVpn_VpnConnectedDisconnectDialogEnabled_doesNotStartAppLaunchIntent()
- throws PackageManager.NameNotFoundException {
- Set<Preference> updates = new ArraySet<>();
- AppPreference pref =
- spy(new AppPreference(mContext, USER_ID_1, ADVANCED_VPN_PACKAGE_NAME));
- pref.setState(AppPreference.STATE_CONNECTED);
- updates.add(pref);
- when(mFakeFeatureFactory.mAdvancedVpnFeatureProvider.isDisconnectDialogEnabled())
- .thenReturn(true);
- when(mContext.createPackageContextAsUser(any(), anyInt(), any())).thenReturn(mContext);
- when(mContext.getPackageManager()).thenReturn(mPackageManager);
- when(mPackageManager.getLaunchIntentForPackage(any())).thenReturn(mAdvancedVpnIntent);
- ArgumentCaptor<Intent> captor = ArgumentCaptor.forClass(Intent.class);
- doNothing().when(mContext).startActivityAsUser(captor.capture(), any());
- mVpnSettings.setShownAdvancedPreferences(updates);
-
- mVpnSettings.onPreferenceClick(pref);
-
- verify(mContext, never()).startActivityAsUser(any(), any());
- }
-}
diff --git a/tests/unit/src/com/android/settings/wifi/WifiUtilsTest.java b/tests/unit/src/com/android/settings/wifi/WifiUtilsTest.java
index 1a5e852..2826310 100644
--- a/tests/unit/src/com/android/settings/wifi/WifiUtilsTest.java
+++ b/tests/unit/src/com/android/settings/wifi/WifiUtilsTest.java
@@ -21,19 +21,53 @@
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import android.content.Context;
+import android.content.res.Resources;
+import android.net.TetheringManager;
import android.net.wifi.SoftApConfiguration;
import android.net.wifi.WifiConfiguration;
+import android.net.wifi.WifiManager;
+import androidx.test.core.app.ApplicationProvider;
import androidx.test.ext.junit.runners.AndroidJUnit4;
+import com.android.settings.R;
import com.android.wifitrackerlib.WifiEntry;
+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;
@RunWith(AndroidJUnit4.class)
public class WifiUtilsTest {
+ static final String[] WIFI_REGEXS = {"wifi_regexs"};
+
+ @Rule
+ public final MockitoRule mMockitoRule = MockitoJUnit.rule();
+ @Spy
+ Context mContext = ApplicationProvider.getApplicationContext();
+ @Mock
+ Resources mResources;
+ @Mock
+ WifiManager mWifiManager;
+ @Mock
+ TetheringManager mTetheringManager;
+
+ @Before
+ public void setUp() {
+ when(mContext.getResources()).thenReturn(mResources);
+ when(mResources.getBoolean(R.bool.config_show_wifi_hotspot_settings)).thenReturn(true);
+ when(mContext.getSystemService(WifiManager.class)).thenReturn(mWifiManager);
+ when(mContext.getSystemService(TetheringManager.class)).thenReturn(mTetheringManager);
+ when(mTetheringManager.getTetherableWifiRegexs()).thenReturn(WIFI_REGEXS);
+ }
+
@Test
public void testSSID() {
assertThat(WifiUtils.isSSIDTooLong("123")).isFalse();
@@ -108,4 +142,53 @@
WifiConfiguration config = WifiUtils.getWifiConfig(null /* wifiEntry */,
null /* scanResult */);
}
+
+ @Test
+ public void checkShowWifiHotspot_allReady_returnTrue() {
+ assertThat(WifiUtils.checkShowWifiHotspot(mContext)).isTrue();
+ }
+
+ @Test
+ public void checkShowWifiHotspot_contextIsNull_returnFalse() {
+ assertThat(WifiUtils.checkShowWifiHotspot(null)).isFalse();
+ }
+
+ @Test
+ public void checkShowWifiHotspot_configIsNotShow_returnFalse() {
+ when(mResources.getBoolean(R.bool.config_show_wifi_hotspot_settings)).thenReturn(false);
+
+ assertThat(WifiUtils.checkShowWifiHotspot(mContext)).isFalse();
+ }
+
+ @Test
+ public void checkShowWifiHotspot_wifiManagerIsNull_returnFalse() {
+ when(mContext.getSystemService(WifiManager.class)).thenReturn(null);
+
+ assertThat(WifiUtils.checkShowWifiHotspot(mContext)).isFalse();
+ }
+
+ @Test
+ public void checkShowWifiHotspot_tetheringManagerIsNull_returnFalse() {
+ when(mContext.getSystemService(TetheringManager.class)).thenReturn(null);
+
+ assertThat(WifiUtils.checkShowWifiHotspot(mContext)).isFalse();
+ }
+
+ @Test
+ public void checkShowWifiHotspot_wifiRegexsIsEmpty_returnFalse() {
+ when(mTetheringManager.getTetherableWifiRegexs()).thenReturn(null);
+
+ assertThat(WifiUtils.checkShowWifiHotspot(mContext)).isFalse();
+ }
+
+ @Test
+ public void canShowWifiHotspot_cachedIsReady_returnCached() {
+ WifiUtils.setCanShowWifiHotspotCached(true);
+
+ assertThat(WifiUtils.canShowWifiHotspot(null)).isTrue();
+
+ WifiUtils.setCanShowWifiHotspotCached(false);
+
+ assertThat(WifiUtils.canShowWifiHotspot(null)).isFalse();
+ }
}