Merge "Remove method that used to get rainbow bt icon"
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 9f6cdb5..651ef48 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -620,8 +620,7 @@
<activity
android:name="Settings$ManageAssistActivity"
- android:label="@string/assist_and_voice_input_title"
- android:parentActivityName="Settings">
+ 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.DEFAULT" />
@@ -795,7 +794,8 @@
<activity android:name="Settings$WallpaperSettingsActivity"
android:label="@string/wallpaper_settings_fragment_title"
- android:icon="@drawable/ic_wallpaper">
+ android:icon="@drawable/ic_wallpaper"
+ android:exported="true">
<meta-data android:name="com.android.settings.FRAGMENT_CLASS"
android:value="com.android.settings.wallpaper.WallpaperTypeSettings" />
</activity>
@@ -2455,6 +2455,18 @@
</activity>
<activity
+ android:name="Settings$AppBubbleNotificationSettingsActivity"
+ android:label="@string/bubbles_app_toggle_title"
+ android:parentActivityName="Settings$NotificationAppListActivity">
+ <intent-filter android:priority="1">
+ <action android:name="android.settings.APP_NOTIFICATION_BUBBLE_SETTINGS" />
+ <category android:name="android.intent.category.DEFAULT" />
+ </intent-filter>
+ <meta-data android:name="com.android.settings.FRAGMENT_CLASS"
+ android:value="com.android.settings.notification.AppBubbleNotificationSettings" />
+ </activity>
+
+ <activity
android:name="Settings$SoundSettingsActivity"
android:label="@string/sound_settings"
android:icon="@drawable/ic_homepage_sound"
@@ -2566,7 +2578,7 @@
<receiver android:name=".sim.SimSelectNotification">
<intent-filter>
- <action android:name="android.intent.action.PRIMARY_SUBSCRIPTION_LIST_CHANGED"/>
+ <action android:name="android.telephony.action.PRIMARY_SUBSCRIPTION_LIST_CHANGED"/>
</intent-filter>
</receiver>
diff --git a/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml b/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml
index c408a97..887d0fb 100644
--- a/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml
+++ b/res/layout-land/wifi_dpp_qrcode_scanner_fragment.xml
@@ -43,7 +43,7 @@
android:layout_marginBottom="8dp"
style="?android:attr/progressBarStyleHorizontal"/>
- <com.android.settings.wifi.qrcode.QrPreviewLayout
+ <FrameLayout
android:layout_width="@dimen/qrcode_preview_size"
android:layout_height="@dimen/qrcode_preview_size">
<TextureView
@@ -54,7 +54,7 @@
android:id="@+id/decorate_view"
android:layout_width="wrap_content"
android:layout_height="match_parent"/>
- </com.android.settings.wifi.qrcode.QrPreviewLayout>
+ </FrameLayout>
<TextView
android:id="@+id/error_message"
diff --git a/res/layout/homepage_condition_header.xml b/res/layout/homepage_condition_header.xml
index 5460be9..30b9033 100644
--- a/res/layout/homepage_condition_header.xml
+++ b/res/layout/homepage_condition_header.xml
@@ -19,6 +19,7 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
+ android:contentDescription="@string/condition_expand_show"
style="@style/ContextualCardStyle">
<LinearLayout
diff --git a/res/layout/wifi_dpp_qrcode_scanner_fragment.xml b/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
index 9bd742a..68ba277 100644
--- a/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
+++ b/res/layout/wifi_dpp_qrcode_scanner_fragment.xml
@@ -43,18 +43,21 @@
android:layout_marginBottom="8dp"
style="?android:attr/progressBarStyleHorizontal"/>
- <com.android.settings.wifi.qrcode.QrPreviewLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent">
+ <androidx.constraintlayout.widget.ConstraintLayout
+ xmlns:app="http://schemas.android.com/apk/res-auto"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content">
<TextureView
android:id="@+id/preview_view"
android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
+ android:layout_height="0dp"
+ app:layout_constraintDimensionRatio="1:1"/>
<com.android.settings.wifi.qrcode.QrDecorateView
android:id="@+id/decorate_view"
android:layout_width="match_parent"
- android:layout_height="wrap_content"/>
- </com.android.settings.wifi.qrcode.QrPreviewLayout>
+ android:layout_height="0dp"
+ app:layout_constraintDimensionRatio="1:1"/>
+ </androidx.constraintlayout.widget.ConstraintLayout>
<TextView
android:id="@+id/error_message"
diff --git a/res/values-night/colors.xml b/res/values-night/colors.xml
index 617feb3..8a6b697 100644
--- a/res/values-night/colors.xml
+++ b/res/values-night/colors.xml
@@ -16,7 +16,6 @@
<resources>
<color name="switchbar_text_color">@android:color/black</color>
- <color name="switch_bar_background">#dadce0</color>
<color name="switchbar_switch_track_tint">#82000000</color>
<color name="switchbar_switch_thumb_tint">@android:color/black</color>
<color name="homepage_accessibility_background">#783BE5</color>
diff --git a/res/values-night/themes.xml b/res/values-night/themes.xml
index 8deae1c..2227b88 100644
--- a/res/values-night/themes.xml
+++ b/res/values-night/themes.xml
@@ -29,9 +29,7 @@
<item name="android:colorControlNormal">?android:attr/colorAccent</item>
</style>
- <style name="Theme.SubSettings" parent="Theme.SubSettings.Base">
- <item name="android:colorControlNormal">?android:attr/colorAccent</item>
- </style>
+ <style name="Theme.SubSettings" parent="Theme.SubSettings.Base"/>
<style name="Theme.AlertDialog.Base" parent="@style/Theme.AppCompat.DayNight.Dialog.Alert">
<item name="colorAccent">@*android:color/accent_device_default_dark</item>
diff --git a/res/values/colors.xml b/res/values/colors.xml
index b547b5d..9f99755 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -56,7 +56,6 @@
<color name="material_blue_700">#3367D6</color>
<color name="material_grey_100">#f5f5f5</color>
<color name="material_grey_200">#ffffff</color>
- <color name="switch_bar_background">#757575</color>
<color name="message_text_incoming">#ffffffff</color>
<color name="message_text_outgoing">#ff323232</color>
diff --git a/res/values/dimens.xml b/res/values/dimens.xml
index 886f558..60724c3 100755
--- a/res/values/dimens.xml
+++ b/res/values/dimens.xml
@@ -346,6 +346,7 @@
<dimen name="homepage_card_icon_padding_start">14dp</dimen>
<dimen name="homepage_card_text_padding_start">16dp</dimen>
<dimen name="homepage_card_padding_end">16dp</dimen>
+ <dimen name="homepage_card_corner_radius">@*android:dimen/config_dialogCornerRadius</dimen>
<dimen name="homepage_full_card_padding_end">12dp</dimen>
<dimen name="homepage_half_card_padding_top">12dp</dimen>
<dimen name="homepage_half_card_padding_bottom">16dp</dimen>
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 2e2320d..b27e9d0 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2284,6 +2284,8 @@
</plurals>
<!-- Wi-Fi settings screen, advanced, settings section. This is a header shown above advanced wifi settings. [CHAR LIMIT=30] -->
<string name="wifi_advanced_titlebar">Advanced Wi\u2011Fi</string>
+ <!-- Wi-Fi settings screen, advanced, title of the item to show the Wi-Fi device's SSID. [CHAR LIMIT=20] -->
+ <string name="wifi_advanced_ssid_title">SSID</string>
<!-- Wi-Fi settings screen, advanced, title of the item to show the Wi-Fi device's MAC address. -->
<string name="wifi_advanced_mac_address_title">MAC address</string>
<!-- Title of the screen to adjust IP settings -->
@@ -7789,9 +7791,9 @@
<string name="notification_badging_title">Allow notification dots</string>
<!-- Configure Notifications: Title for the notification bubbles option. [CHAR LIMIT=60] -->
- <string name="notification_bubbles_title">Allow bubbles</string>
+ <string name="notification_bubbles_title">Bubbles</string>
<!-- Configure Notifications: Summary for the notification bubbles option. [CHAR LIMIT=NONE] -->
- <string name="notification_bubbles_summary">Allow apps to show some notifications as bubbles</string>
+ <string name="notification_bubbles_summary">Quickly access app content from anywhere using floating shortcuts</string>
<!-- Feature education for bubbles. [CHAR LIMIT=NONE] -->
<string name="bubbles_feature_education">Some notifications and other content can appear as bubbles on the screen. To open a bubble, tap it. To dismiss it, drag it down the screen.</string>
<!-- Title for the toggle shown on the app-level bubbles page [CHAR LIMIT=60] -->
@@ -11013,11 +11015,11 @@
<!-- Message for forget passpoint dialog [CHAR LIMIT=none] -->
<string name="forget_passpoint_dialog_message">You may lose access to any remaining time or data. Check with your provider before removing.</string>
- <!-- Keywords for Content Capture feature [CHAR_LIMIT=32] -->
- <string name="keywords_content_capture">content capture</string>
+ <!-- Keywords for Content Capture / Smart Suggestions feature [CHAR_LIMIT=none] -->
+ <string name="keywords_content_capture">content capture, smart suggestions</string>
<!-- Title of the 'Content Capture' feature toggle in the Settings -> Privacy screen [CHAR LIMIT=none]-->
- <string name="content_capture">Content Capture</string>
- <!-- Description of the 'Content Capture' feature toggle in the Settings -> Privacy screen [CHAR LIMIT=NONE]-->
+ <string name="content_capture">Smart Suggestions</string>
+ <!-- Description of the 'Content Capture / Smart Suggestions' feature toggle in the Settings -> Privacy screen [CHAR LIMIT=NONE]-->
<string name="content_capture_summary">Allow Android to save information seen on your screen or heard in video or audio content. Android makes helpful suggestions based on your device activity.</string>
<!-- Title for the button to initiate a heap dump for the system server. [CHAR LIMIT=NONE] -->
@@ -11030,4 +11032,7 @@
<string name="automatic_system_heap_dump_title">Automatically capture system heap dumps</string>
<!-- Summary of toggle for whether to enable automatic heap dumps for the system server or not. [CHAR LIMIT=NONE] -->
<string name="automatic_system_heap_dump_summary">Automatically capture a heap dump for Android System when it uses too much memory</string>
+
+ <!-- Button label to disconnect a Wi-Fi network. [CHAR LIMIT=40] -->
+ <string name="wifi_disconnect_button_text">Disconnect</string>
</resources>
diff --git a/res/values/styles.xml b/res/values/styles.xml
index 02db995..8cd22fe 100644
--- a/res/values/styles.xml
+++ b/res/values/styles.xml
@@ -418,7 +418,7 @@
<item name="android:layout_marginStart">@dimen/homepage_card_side_margin</item>
<item name="android:layout_marginEnd">@dimen/homepage_card_side_margin</item>
<item name="cardBackgroundColor">@color/contextual_card_background</item>
- <item name="cardCornerRadius">@*android:dimen/config_dialogCornerRadius</item>
+ <item name="cardCornerRadius">@dimen/homepage_card_corner_radius</item>
<item name="cardElevation">0dp</item>
<item name="strokeColor">@color/homepage_card_stroke_color</item>
<item name="strokeWidth">1dp</item>
diff --git a/res/values/themes.xml b/res/values/themes.xml
index a8ae506..59b2b9e 100644
--- a/res/values/themes.xml
+++ b/res/values/themes.xml
@@ -94,7 +94,7 @@
<style name="ThemeOverlay.SwitchBar.Settings" parent="@android:style/ThemeOverlay.Material.ActionBar">
<item name="switchBarMarginStart">@dimen/switchbar_subsettings_margin_start</item>
<item name="switchBarMarginEnd">@dimen/switchbar_subsettings_margin_end</item>
- <item name="switchBarBackgroundColor">@color/switch_bar_background</item>
+ <item name="switchBarBackgroundColor">?android:attr/textColorSecondary</item>
<item name="switchBarBackgroundActivatedColor">?android:attr/colorAccent</item>
<item name="switchBarRestrictionIcon">@*android:drawable/ic_info</item>
</style>
@@ -103,6 +103,7 @@
<item name="android:trackTint">@color/switchbar_switch_track_tint</item>
<item name="android:thumbTint">@color/switchbar_switch_thumb_tint</item>
<item name="android:minHeight">@dimen/min_tap_target_size</item>
+ <item name="android:minWidth">@dimen/min_tap_target_size</item>
</style>
<style name="Theme.CryptKeeper" parent="@android:style/Theme.Material.NoActionBar">
diff --git a/res/xml/accessibility_settings.xml b/res/xml/accessibility_settings.xml
index 1efe2c2..0e417c9 100644
--- a/res/xml/accessibility_settings.xml
+++ b/res/xml/accessibility_settings.xml
@@ -58,12 +58,10 @@
android:title="@string/screen_zoom_title"
settings:searchable="false"/>
- <ListPreference
+ <Preference
android:key="dark_ui_mode_accessibility"
+ android:fragment="com.android.settings.display.DarkUISettings"
android:title="@string/dark_ui_mode"
- android:dialogTitle="@string/dark_ui_mode_title"
- android:entries="@array/dark_ui_mode_entries"
- android:entryValues="@array/dark_ui_mode_values"
settings:searchable="false" />
<Preference
diff --git a/res/xml/app_and_notification.xml b/res/xml/app_and_notification.xml
index 2996afa..fd3725a 100644
--- a/res/xml/app_and_notification.xml
+++ b/res/xml/app_and_notification.xml
@@ -20,7 +20,7 @@
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="apps_and_notification_screen"
android:title="@string/app_and_notification_dashboard_title"
- settings:initialExpandedChildrenCount="8">
+ settings:initialExpandedChildrenCount="3">
<!-- the initial count should include the dynamic tiles -->
<Preference
diff --git a/res/xml/app_bubble_notification_settings.xml b/res/xml/app_bubble_notification_settings.xml
new file mode 100644
index 0000000..8d97f8f
--- /dev/null
+++ b/res/xml/app_bubble_notification_settings.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:title="@string/bubbles_app_toggle_title"
+ android:key="app_bubble_notification_settings">
+ <com.android.settingslib.widget.LayoutPreference
+ android:key="pref_app_header"
+ android:layout="@layout/settings_entity_header"/>
+
+ <com.android.settingslib.RestrictedSwitchPreference
+ android:key="bubble_pref"
+ android:title="@string/notification_bubbles_title"/>
+
+ <com.android.settingslib.widget.FooterPreference
+ android:key="notification_bubbles_footer"
+ android:title="@string/bubbles_feature_education"
+ android:selectable="false" />
+
+</PreferenceScreen>
diff --git a/res/xml/app_notification_settings.xml b/res/xml/app_notification_settings.xml
index faad649..fedd3cc 100644
--- a/res/xml/app_notification_settings.xml
+++ b/res/xml/app_notification_settings.xml
@@ -60,11 +60,10 @@
settings:useAdditionalSummary="true"
android:order="1001"
settings:restrictedSwitchSummary="@string/enabled_by_admin" />
- <com.android.settingslib.RestrictedSwitchPreference
- android:key="bubble_pref"
+ <Preference
+ android:key="bubble_link_pref"
android:title="@string/notification_bubbles_title"
- android:order="1002"
- settings:restrictedSwitchSummary="@string/enabled_by_admin" />
+ android:order="1002" />
<Preference
android:key="app_link"
android:order="1003"
diff --git a/res/xml/bubble_notification_settings.xml b/res/xml/bubble_notification_settings.xml
new file mode 100644
index 0000000..20783fa
--- /dev/null
+++ b/res/xml/bubble_notification_settings.xml
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2019 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:title="@string/bubbles_app_toggle_title"
+ android:key="bubble_notification_settings">
+ <!-- Notification bubbles -->
+ <SwitchPreference
+ android:key="global_notification_bubbles"
+ android:title="@string/notification_bubbles_title"
+ android:summary="@string/notification_bubbles_summary"
+ settings:controller="com.android.settings.notification.BubbleNotificationPreferenceController"/>
+
+ <com.android.settingslib.widget.FooterPreference
+ android:key="notification_bubbles_footer"
+ android:title="@string/bubbles_feature_education"
+ android:selectable="false" />
+
+</PreferenceScreen>
diff --git a/res/xml/channel_notification_settings.xml b/res/xml/channel_notification_settings.xml
index 3158819..14e0366 100644
--- a/res/xml/channel_notification_settings.xml
+++ b/res/xml/channel_notification_settings.xml
@@ -63,8 +63,7 @@
android:dialogTitle="@string/notification_channel_sound_title"
android:order="11"
android:showSilent="true"
- android:showDefault="true"
- android:ringtoneType="notification" />
+ android:showDefault="true"/>
<!-- Vibration -->
<com.android.settingslib.RestrictedSwitchPreference
diff --git a/res/xml/configure_notification_settings.xml b/res/xml/configure_notification_settings.xml
index e48ddc1..97a4182 100644
--- a/res/xml/configure_notification_settings.xml
+++ b/res/xml/configure_notification_settings.xml
@@ -70,11 +70,11 @@
settings:controller="com.android.settings.notification.BadgingNotificationPreferenceController"/>
<!-- Notification bubbles -->
- <SwitchPreference
+ <Preference
android:key="notification_bubbles"
android:title="@string/notification_bubbles_title"
- android:summary="@string/notification_bubbles_summary"
- settings:controller="com.android.settings.notification.BubbleNotificationPreferenceController"/>
+ settings:controller="com.android.settings.notification.BubbleSummaryNotificationPreferenceController"
+ android:fragment="com.android.settings.notification.BubbleNotificationSettings"/>
<!-- Pulse notification light -->
<SwitchPreference
diff --git a/res/xml/network_and_internet_v2.xml b/res/xml/network_and_internet_v2.xml
index 44c3121..f004d06 100644
--- a/res/xml/network_and_internet_v2.xml
+++ b/res/xml/network_and_internet_v2.xml
@@ -23,6 +23,7 @@
<PreferenceCategory
android:key="multi_network_header"
android:title="@string/summary_placeholder"
+ android:layout="@layout/preference_category_no_label"
settings:allowDividerBelow="true"
android:order="-40"
settings:controller="com.android.settings.network.MultiNetworkHeaderController"/>
diff --git a/res/xml/power_usage_summary.xml b/res/xml/power_usage_summary.xml
index 94ead86..88f88f1 100644
--- a/res/xml/power_usage_summary.xml
+++ b/res/xml/power_usage_summary.xml
@@ -26,13 +26,11 @@
android:title="@string/summary_placeholder"
android:selectable="false"
android:layout="@layout/battery_header"
- settings:allowDividerBelow="true"
settings:controller="com.android.settings.fuelgauge.BatteryHeaderPreferenceController" />
<com.android.settings.widget.CardPreference
android:key="battery_tip"
android:title="@string/summary_placeholder"
- settings:allowDividerAbove="true"
settings:controller="com.android.settings.fuelgauge.batterytip.BatteryTipPreferenceController" />
<Preference
diff --git a/res/xml/privacy_dashboard_settings.xml b/res/xml/privacy_dashboard_settings.xml
index f39880c..45b9d19 100644
--- a/res/xml/privacy_dashboard_settings.xml
+++ b/res/xml/privacy_dashboard_settings.xml
@@ -62,26 +62,6 @@
android:summary="@string/summary_placeholder"
settings:searchable="false"/>
- <!-- Content Capture -->
-
- <!-- NOTE: content capture has a different preference, depending whether or not the
- ContentCaptureService implementations defines a custom settings activitiy on its manifest.
- Hence, we show both here, but the controller itself will decide if it's available or not.
- -->
-
- <SwitchPreference
- android:key="content_capture"
- android:title="@string/content_capture"
- android:summary="@string/content_capture_summary"
- settings:controller="com.android.settings.privacy.EnableContentCapturePreferenceController"/>
-
- <com.android.settings.widget.MasterSwitchPreference
- android:key="content_capture_custom_settings"
- android:title="@string/content_capture"
- android:summary="@string/content_capture_summary"
- settings:controller="com.android.settings.privacy.EnableContentCaptureWithServiceSettingsPreferenceController">
- </com.android.settings.widget.MasterSwitchPreference>
-
<!-- Privacy Service -->
<PreferenceCategory
android:key="privacy_services"/>
@@ -105,4 +85,24 @@
settings:searchable="false"/>
</PreferenceCategory>
+ <!-- Content Capture -->
+
+ <!-- NOTE: content capture has a different preference, depending whether or not the
+ ContentCaptureService implementations defines a custom settings activitiy on its manifest.
+ Hence, we show both here, but the controller itself will decide if it's available or not.
+ -->
+
+ <SwitchPreference
+ android:key="content_capture"
+ android:title="@string/content_capture"
+ android:summary="@string/content_capture_summary"
+ settings:controller="com.android.settings.privacy.EnableContentCapturePreferenceController"/>
+
+ <com.android.settings.widget.MasterSwitchPreference
+ android:key="content_capture_custom_settings"
+ android:title="@string/content_capture"
+ android:summary="@string/content_capture_summary"
+ settings:controller="com.android.settings.privacy.EnableContentCaptureWithServiceSettingsPreferenceController">
+ </com.android.settings.widget.MasterSwitchPreference>
+
</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/wifi_network_details_fragment.xml b/res/xml/wifi_network_details_fragment.xml
index 782a7cf..8fb19cb 100644
--- a/res/xml/wifi_network_details_fragment.xml
+++ b/res/xml/wifi_network_details_fragment.xml
@@ -85,6 +85,11 @@
android:key="ip_details_category"
android:title="@string/wifi_setup_detail">
<Preference
+ android:key="ssid"
+ android:title="@string/wifi_advanced_ssid_title"
+ android:selectable="false"
+ settings:enableCopying="true"/>
+ <Preference
android:key="mac_address"
android:title="@string/wifi_advanced_mac_address_title"
android:selectable="false"
diff --git a/src/com/android/settings/Settings.java b/src/com/android/settings/Settings.java
index bdb5889..e1c9aff 100644
--- a/src/com/android/settings/Settings.java
+++ b/src/com/android/settings/Settings.java
@@ -113,6 +113,7 @@
public static class ZenModeEventRuleSettingsActivity extends SettingsActivity { /* empty */ }
public static class SoundSettingsActivity extends SettingsActivity { /* empty */ }
public static class ConfigureNotificationSettingsActivity extends SettingsActivity { /* empty */ }
+ public static class AppBubbleNotificationSettingsActivity extends SettingsActivity { /* empty */ }
public static class NotificationAssistantSettingsActivity extends SettingsActivity{ /* empty */ }
public static class NotificationAppListActivity extends SettingsActivity { /* empty */ }
public static class AppNotificationSettingsActivity extends SettingsActivity { /* empty */ }
diff --git a/src/com/android/settings/SetupWizardUtils.java b/src/com/android/settings/SetupWizardUtils.java
index 70ee2ca..7a2fe80 100644
--- a/src/com/android/settings/SetupWizardUtils.java
+++ b/src/com/android/settings/SetupWizardUtils.java
@@ -30,46 +30,59 @@
if (theme == null) {
theme = SetupWizardProperties.theme().orElse("");
}
+ // TODO(yukl): Move to ThemeResolver and add any additional required attributes in
+ // onApplyThemeResource using Theme overlays
if (theme != null) {
- switch (theme) {
- case ThemeHelper.THEME_GLIF_V3_LIGHT:
- return R.style.GlifV3Theme_Light;
- case ThemeHelper.THEME_GLIF_V3:
- return R.style.GlifV3Theme;
- case ThemeHelper.THEME_GLIF_V2_LIGHT:
- return R.style.GlifV2Theme_Light;
- case ThemeHelper.THEME_GLIF_V2:
- return R.style.GlifV2Theme;
- case ThemeHelper.THEME_GLIF_LIGHT:
- return R.style.GlifTheme_Light;
- case ThemeHelper.THEME_GLIF:
- return R.style.GlifTheme;
+ if (WizardManagerHelper.isAnySetupWizard(intent)) {
+ switch (theme) {
+ case ThemeHelper.THEME_GLIF_V3_LIGHT:
+ return R.style.GlifV3Theme_Light;
+ case ThemeHelper.THEME_GLIF_V3:
+ return R.style.GlifV3Theme;
+ case ThemeHelper.THEME_GLIF_V2_LIGHT:
+ return R.style.GlifV2Theme_Light;
+ case ThemeHelper.THEME_GLIF_V2:
+ return R.style.GlifV2Theme;
+ case ThemeHelper.THEME_GLIF_LIGHT:
+ return R.style.GlifTheme_Light;
+ case ThemeHelper.THEME_GLIF:
+ return R.style.GlifTheme;
+ }
+ } else {
+ switch (theme) {
+ case ThemeHelper.THEME_GLIF_V3_LIGHT:
+ case ThemeHelper.THEME_GLIF_V3:
+ return R.style.GlifV3Theme;
+ case ThemeHelper.THEME_GLIF_V2_LIGHT:
+ case ThemeHelper.THEME_GLIF_V2:
+ return R.style.GlifV2Theme;
+ case ThemeHelper.THEME_GLIF_LIGHT:
+ case ThemeHelper.THEME_GLIF:
+ return R.style.GlifTheme;
+ }
}
}
- return R.style.GlifTheme_Light;
+ return R.style.GlifTheme;
}
public static int getTransparentTheme(Intent intent) {
final int suwTheme = getTheme(intent);
- int wifiDialogTheme = R.style.GlifV2Theme_Light_Transparent;
+ int transparentTheme = R.style.GlifV2Theme_Light_Transparent;
if (suwTheme == R.style.GlifV3Theme) {
- wifiDialogTheme = R.style.GlifV3Theme_Transparent;
+ transparentTheme = R.style.GlifV3Theme_Transparent;
} else if (suwTheme == R.style.GlifV3Theme_Light) {
- wifiDialogTheme = R.style.GlifV3Theme_Light_Transparent;
+ transparentTheme = R.style.GlifV3Theme_Light_Transparent;
} else if (suwTheme == R.style.GlifV2Theme) {
- wifiDialogTheme = R.style.GlifV2Theme_Transparent;
+ transparentTheme = R.style.GlifV2Theme_Transparent;
} else if (suwTheme == R.style.GlifTheme_Light) {
- wifiDialogTheme = R.style.SetupWizardTheme_Light_Transparent;
+ transparentTheme = R.style.SetupWizardTheme_Light_Transparent;
} else if (suwTheme == R.style.GlifTheme) {
- wifiDialogTheme = R.style.SetupWizardTheme_Transparent;
+ transparentTheme = R.style.SetupWizardTheme_Transparent;
}
- return wifiDialogTheme;
+ return transparentTheme;
}
public static void copySetupExtras(Intent fromIntent, Intent toIntent) {
- toIntent.putExtra(WizardManagerHelper.EXTRA_THEME,
- fromIntent.getStringExtra(WizardManagerHelper.EXTRA_THEME));
- toIntent.putExtra(WizardManagerHelper.EXTRA_USE_IMMERSIVE_MODE,
- fromIntent.getBooleanExtra(WizardManagerHelper.EXTRA_USE_IMMERSIVE_MODE, false));
+ WizardManagerHelper.copyWizardManagerExtras(fromIntent, toIntent);
}
}
diff --git a/src/com/android/settings/accessibility/AccessibilitySettings.java b/src/com/android/settings/accessibility/AccessibilitySettings.java
index 4ba605f..efa14f6 100644
--- a/src/com/android/settings/accessibility/AccessibilitySettings.java
+++ b/src/com/android/settings/accessibility/AccessibilitySettings.java
@@ -244,7 +244,7 @@
private SwitchPreference mToggleInversionPreference;
private ColorInversionPreferenceController mInversionPreferenceController;
private AccessibilityHearingAidPreferenceController mHearingAidPreferenceController;
- private ListPreference mDarkUIModePreference;
+ private Preference mDarkUIModePreference;
private DarkUIPreferenceController mDarkUIPreferenceController;
private LiveCaptionPreferenceController mLiveCaptionPreferenceController;
diff --git a/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java b/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java
index d9ddc2f..56d5335 100644
--- a/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java
+++ b/src/com/android/settings/applications/appinfo/AppButtonsPreferenceController.java
@@ -33,13 +33,10 @@
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
-import android.os.RemoteException;
-import android.os.ServiceManager;
import android.os.UserHandle;
import android.os.UserManager;
import android.util.Log;
import android.view.View;
-import android.webkit.IWebViewUpdateService;
import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.Fragment;
@@ -438,10 +435,6 @@
enabled = false;
}
- if (isFallbackPackage(mAppEntry.info.packageName)) {
- enabled = false;
- }
-
mButtonsPref.setButton2Enabled(enabled);
}
@@ -467,22 +460,6 @@
}
@VisibleForTesting
- boolean isFallbackPackage(String packageName) {
- try {
- IWebViewUpdateService webviewUpdateService =
- IWebViewUpdateService.Stub.asInterface(
- ServiceManager.getService("webviewupdate"));
- if (webviewUpdateService.isFallbackPackage(packageName)) {
- return true;
- }
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
-
- return false;
- }
-
- @VisibleForTesting
void updateForceStopButton() {
if (mDpm.packageHasActiveAdmins(mPackageInfo.packageName)) {
// User can't force stop device admin.
diff --git a/src/com/android/settings/applications/manageapplications/ResetAppsHelper.java b/src/com/android/settings/applications/manageapplications/ResetAppsHelper.java
index 3af3500..92c0958 100644
--- a/src/com/android/settings/applications/manageapplications/ResetAppsHelper.java
+++ b/src/com/android/settings/applications/manageapplications/ResetAppsHelper.java
@@ -32,7 +32,6 @@
import android.os.RemoteException;
import android.os.ServiceManager;
import android.os.UserHandle;
-import android.webkit.IWebViewUpdateService;
import androidx.appcompat.app.AlertDialog;
@@ -48,7 +47,6 @@
private final PackageManager mPm;
private final IPackageManager mIPm;
private final INotificationManager mNm;
- private final IWebViewUpdateService mWvus;
private final NetworkPolicyManager mNpm;
private final AppOpsManager mAom;
private final Context mContext;
@@ -61,7 +59,6 @@
mIPm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
mNm = INotificationManager.Stub.asInterface(
ServiceManager.getService(Context.NOTIFICATION_SERVICE));
- mWvus = IWebViewUpdateService.Stub.asInterface(ServiceManager.getService("webviewupdate"));
mNpm = NetworkPolicyManager.from(context);
mAom = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
}
@@ -122,8 +119,7 @@
}
if (!app.enabled) {
if (mPm.getApplicationEnabledSetting(app.packageName)
- == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER
- && !isNonEnableableFallback(app.packageName)) {
+ == PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {
mPm.setApplicationEnabledSetting(app.packageName,
PackageManager.COMPONENT_ENABLED_STATE_DEFAULT,
PackageManager.DONT_KILL_APP);
@@ -147,12 +143,4 @@
}
});
}
-
- private boolean isNonEnableableFallback(String packageName) {
- try {
- return mWvus.isFallbackPackage(packageName);
- } catch (RemoteException e) {
- throw new RuntimeException(e);
- }
- }
}
diff --git a/src/com/android/settings/aware/AwareFeatureProvider.java b/src/com/android/settings/aware/AwareFeatureProvider.java
index a24233f..bda27c7 100644
--- a/src/com/android/settings/aware/AwareFeatureProvider.java
+++ b/src/com/android/settings/aware/AwareFeatureProvider.java
@@ -18,10 +18,15 @@
import android.content.Context;
+import androidx.fragment.app.Fragment;
+
public interface AwareFeatureProvider {
/** Returns true if the aware sensor is supported. */
boolean isSupported(Context context);
/** Returns true if the aware feature is enabled. */
boolean isEnabled(Context context);
+
+ /** Show information dialog. */
+ void showRestrictionDialog(Fragment parent);
}
diff --git a/src/com/android/settings/aware/AwareFeatureProviderImpl.java b/src/com/android/settings/aware/AwareFeatureProviderImpl.java
index 44ec31b..5d16031 100644
--- a/src/com/android/settings/aware/AwareFeatureProviderImpl.java
+++ b/src/com/android/settings/aware/AwareFeatureProviderImpl.java
@@ -18,6 +18,8 @@
import android.content.Context;
+import androidx.fragment.app.Fragment;
+
public class AwareFeatureProviderImpl implements AwareFeatureProvider {
@Override
public boolean isSupported(Context context) {
@@ -28,4 +30,8 @@
public boolean isEnabled(Context context) {
return false;
}
+
+ @Override
+ public void showRestrictionDialog(Fragment parent) {
+ }
}
diff --git a/src/com/android/settings/core/gateway/SettingsGateway.java b/src/com/android/settings/core/gateway/SettingsGateway.java
index 31d54f9..30f6afc 100644
--- a/src/com/android/settings/core/gateway/SettingsGateway.java
+++ b/src/com/android/settings/core/gateway/SettingsGateway.java
@@ -101,7 +101,9 @@
import com.android.settings.network.NetworkDashboardFragment;
import com.android.settings.nfc.AndroidBeam;
import com.android.settings.nfc.PaymentSettings;
+import com.android.settings.notification.AppBubbleNotificationSettings;
import com.android.settings.notification.AppNotificationSettings;
+import com.android.settings.notification.BubbleNotificationSettings;
import com.android.settings.notification.ChannelGroupNotificationSettings;
import com.android.settings.notification.ChannelNotificationSettings;
import com.android.settings.notification.ConfigureNotificationSettings;
@@ -211,6 +213,8 @@
DreamSettings.class.getName(),
UserSettings.class.getName(),
NotificationAccessSettings.class.getName(),
+ BubbleNotificationSettings.class.getName(),
+ AppBubbleNotificationSettings.class.getName(),
ZenAccessSettings.class.getName(),
ZenAccessDetails.class.getName(),
ZenModeAutomationSettings.class.getName(),
diff --git a/src/com/android/settings/deviceinfo/hardwareinfo/DeviceModelPreferenceController.java b/src/com/android/settings/deviceinfo/hardwareinfo/DeviceModelPreferenceController.java
index 42c7b01..fbd1e9e 100644
--- a/src/com/android/settings/deviceinfo/hardwareinfo/DeviceModelPreferenceController.java
+++ b/src/com/android/settings/deviceinfo/hardwareinfo/DeviceModelPreferenceController.java
@@ -39,4 +39,9 @@
public boolean isSliceable() {
return true;
}
+
+ @Override
+ public CharSequence getSummary() {
+ return HardwareInfoPreferenceController.getDeviceModel();
+ }
}
diff --git a/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelper.java b/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelper.java
index 5bdf587..5599a94 100644
--- a/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelper.java
+++ b/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelper.java
@@ -55,7 +55,7 @@
public class ActionDisabledByAdminDialogHelper {
private static final String TAG = ActionDisabledByAdminDialogHelper.class.getName();
- private EnforcedAdmin mEnforcedAdmin;
+ @VisibleForTesting EnforcedAdmin mEnforcedAdmin;
private ViewGroup mDialogView;
private String mRestriction = null;
private Activity mActivity;
@@ -80,20 +80,28 @@
EnforcedAdmin enforcedAdmin) {
mEnforcedAdmin = enforcedAdmin;
mRestriction = restriction;
-
final AlertDialog.Builder builder = new AlertDialog.Builder(mActivity);
mDialogView = (ViewGroup) LayoutInflater.from(builder.getContext()).inflate(
R.layout.admin_support_details_dialog, null);
initializeDialogViews(mDialogView, mEnforcedAdmin.component, getEnforcementAdminUserId(),
mRestriction);
- return builder
- .setPositiveButton(R.string.okay, null)
- .setNeutralButton(R.string.learn_more,
- (dialog, which) -> {
- showAdminPolicies(mEnforcedAdmin, mActivity);
- mActivity.finish();
- })
- .setView(mDialogView);
+ builder.setPositiveButton(R.string.okay, null).setView(mDialogView);
+ maybeSetLearnMoreButton(builder);
+ return builder;
+ }
+
+ @VisibleForTesting
+ void maybeSetLearnMoreButton(AlertDialog.Builder builder) {
+ // The "Learn more" button appears only if the restriction is enforced by an admin in the
+ // same profile group. Otherwise the admin package and its policies are not accessible to
+ // the current user.
+ final UserManager um = UserManager.get(mActivity.getApplicationContext());
+ if (um.isSameProfileGroup(getEnforcementAdminUserId(mEnforcedAdmin), um.getUserHandle())) {
+ builder.setNeutralButton(R.string.learn_more, (dialog, which) -> {
+ showAdminPolicies(mEnforcedAdmin, mActivity);
+ mActivity.finish();
+ });
+ }
}
public void updateDialog(String restriction, EnforcedAdmin admin) {
diff --git a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsController.java b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsController.java
index 796df46..57bae45 100644
--- a/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsController.java
+++ b/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsController.java
@@ -20,6 +20,8 @@
import android.os.PowerManager;
import android.provider.Settings;
import android.provider.Settings.Global;
+import android.text.TextUtils;
+import com.android.settingslib.fuelgauge.BatterySaverUtils;
/**
* Responds to user actions in the Settings > Battery > Set a Schedule Screen
@@ -66,24 +68,34 @@
public boolean setDefaultKey(String key) {
final ContentResolver resolver = mContext.getContentResolver();
- switch(key) {
- case KEY_NO_SCHEDULE:
- Settings.Global.putInt(resolver, Global.AUTOMATIC_POWER_SAVE_MODE,
- PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
- Settings.Global.putInt(resolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 0);
- break;
- case KEY_PERCENTAGE:
- Settings.Global.putInt(resolver, Global.AUTOMATIC_POWER_SAVE_MODE,
- PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE);
- Settings.Global.putInt(resolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, 5);
- break;
- case KEY_ROUTINE:
- Settings.Global.putInt(resolver, Global.AUTOMATIC_POWER_SAVE_MODE,
- PowerManager.POWER_SAVE_MODE_TRIGGER_DYNAMIC);
- break;
- default:
- throw new IllegalStateException(
- "Not a valid key for " + this.getClass().getSimpleName());
+
+ int mode = PowerManager.POWER_SAVE_MODE_TRIGGER_PERCENTAGE;
+ int triggerLevel = 0;
+ if (!TextUtils.equals(key, KEY_NO_SCHEDULE)
+ && BatterySaverUtils.maybeShowBatterySaverConfirmation(
+ mContext, true /* confirmOnly */)) {
+ return true;
+ } else {
+ switch (key) {
+ case KEY_NO_SCHEDULE:
+ break;
+ case KEY_PERCENTAGE:
+ triggerLevel = 5;
+ break;
+ case KEY_ROUTINE:
+ mode = PowerManager.POWER_SAVE_MODE_TRIGGER_DYNAMIC;
+ break;
+ default:
+ throw new IllegalStateException(
+ "Not a valid key for " + this.getClass().getSimpleName());
+ }
+ }
+
+ // Trigger level is intentionally left alone when going between dynamic and percentage modes
+ // so that a users percentage based schedule is preserved when they toggle between the two.
+ Settings.Global.putInt(resolver, Global.AUTOMATIC_POWER_SAVE_MODE, mode);
+ if (mode != PowerManager.POWER_SAVE_MODE_TRIGGER_DYNAMIC) {
+ Settings.Global.putInt(resolver, Global.LOW_POWER_MODE_TRIGGER_LEVEL, triggerLevel);
}
mSeekBarController.updateSeekBar();
return true;
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCard.java b/src/com/android/settings/homepage/contextualcards/ContextualCard.java
index 7b8a0c3..ede12fb 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCard.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCard.java
@@ -71,6 +71,7 @@
private final Drawable mIconDrawable;
@LayoutRes
private final int mViewType;
+ private final boolean mIsPendingDismiss;
public String getName() {
return mName;
@@ -156,6 +157,10 @@
return mViewType;
}
+ public boolean isPendingDismiss() {
+ return mIsPendingDismiss;
+ }
+
public Builder mutate() {
return mBuilder;
}
@@ -181,6 +186,7 @@
mIconDrawable = builder.mIconDrawable;
mIsLargeCard = builder.mIsLargeCard;
mViewType = builder.mViewType;
+ mIsPendingDismiss = builder.mIsPendingDismiss;
}
ContextualCard(Cursor c) {
@@ -226,6 +232,8 @@
mBuilder.setIconDrawable(mIconDrawable);
mViewType = getViewTypeByCardType(mCardType);
mBuilder.setViewType(mViewType);
+ mIsPendingDismiss = false;
+ mBuilder.setIsPendingDismiss(mIsPendingDismiss);
}
@Override
@@ -277,6 +285,7 @@
private boolean mIsLargeCard;
@LayoutRes
private int mViewType;
+ private boolean mIsPendingDismiss;
public Builder setName(String name) {
mName = name;
@@ -373,6 +382,11 @@
return this;
}
+ public Builder setIsPendingDismiss(boolean isPendingDismiss) {
+ mIsPendingDismiss = isPendingDismiss;
+ return this;
+ }
+
public ContextualCard build() {
return new ContextualCard(this);
}
diff --git a/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapter.java b/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapter.java
index d6df380..7be0e8e 100644
--- a/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapter.java
+++ b/src/com/android/settings/homepage/contextualcards/ContextualCardsAdapter.java
@@ -28,7 +28,7 @@
import androidx.recyclerview.widget.RecyclerView;
import com.android.settings.homepage.contextualcards.conditional.ConditionContextualCardRenderer;
-import com.android.settings.homepage.contextualcards.slices.SwipeDismissalDelegate.DismissalItemTouchHelperListener;
+import com.android.settings.homepage.contextualcards.slices.SwipeDismissalDelegate;
import com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer;
import java.util.ArrayList;
@@ -36,7 +36,7 @@
import java.util.Map;
public class ContextualCardsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
- implements ContextualCardUpdateListener, DismissalItemTouchHelperListener {
+ implements ContextualCardUpdateListener, SwipeDismissalDelegate.Listener {
static final int SPAN_COUNT = 2;
private static final String TAG = "ContextualCardsAdapter";
@@ -140,6 +140,9 @@
@Override
public void onSwiped(int position) {
-
+ final ContextualCard card = mContextualCards.get(position).mutate()
+ .setIsPendingDismiss(true).build();
+ mContextualCards.set(position, card);
+ notifyItemChanged(position);
}
}
diff --git a/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSlice.java b/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSlice.java
index d174156..0278f90 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSlice.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSlice.java
@@ -176,15 +176,10 @@
.setSubtitle(getSubTitle(mPackageName, mUid))
.setPrimaryAction(getPrimarySliceAction(icon, title, getIntent())));
- // Get rows by notification channel.
+ // Add notification channel rows.
final List<ListBuilder.RowBuilder> rows = getNotificationChannelRows(packageInfo, icon);
-
- // Get displayable notification channel count.
- final int channelCount = Math.min(rows.size(), DEFAULT_EXPANDED_ROW_COUNT);
-
- // According to the displayable channel count to add rows.
- for (int i = 0; i < channelCount; i++) {
- listBuilder.addRow(rows.get(i));
+ for (ListBuilder.RowBuilder rowBuilder : rows) {
+ listBuilder.addRow(rowBuilder);
}
return listBuilder.build();
@@ -279,10 +274,9 @@
private List<ListBuilder.RowBuilder> getNotificationChannelRows(PackageInfo packageInfo,
IconCompat icon) {
final List<ListBuilder.RowBuilder> notificationChannelRows = new ArrayList<>();
- final List<NotificationChannel> enabledChannels = getEnabledChannels(mPackageName, mUid,
- mAppRow);
+ final List<NotificationChannel> displayableChannels = getDisplayableChannels(mAppRow);
- for (NotificationChannel channel : enabledChannels) {
+ for (NotificationChannel channel : displayableChannels) {
notificationChannelRows.add(new ListBuilder.RowBuilder()
.setTitle(channel.getName())
.setSubtitle(NotificationBackend.getSentSummary(
@@ -356,10 +350,9 @@
title);
}
- private List<NotificationChannel> getEnabledChannels(String packageName, int uid,
- NotificationBackend.AppRow appRow) {
+ private List<NotificationChannel> getDisplayableChannels(NotificationBackend.AppRow appRow) {
final List<NotificationChannelGroup> channelGroupList =
- mNotificationBackend.getGroups(packageName, uid).getList();
+ mNotificationBackend.getGroups(appRow.pkg, appRow.uid).getList();
final List<NotificationChannel> channels = channelGroupList.stream()
.flatMap(group -> group.getChannels().stream().filter(
channel -> isChannelEnabled(group, channel, appRow)))
@@ -376,8 +369,11 @@
}
// Sort the notification channels with notification sent count by descending.
- return channelStates.stream().sorted(CHANNEL_STATE_COMPARATOR).map(
- state -> state.getNotificationChannel()).collect(Collectors.toList());
+ return channelStates.stream()
+ .sorted(CHANNEL_STATE_COMPARATOR)
+ .map(state -> state.getNotificationChannel())
+ .limit(DEFAULT_EXPANDED_ROW_COUNT)
+ .collect(Collectors.toList());
}
private PackageInfo getMaxSentNotificationsPackage(List<PackageInfo> packageInfoList) {
@@ -391,10 +387,14 @@
for (PackageInfo packageInfo : packageInfoList) {
final NotificationBackend.AppRow appRow = mNotificationBackend.loadAppRow(mContext,
mContext.getPackageManager(), packageInfo);
+ // Ignore packages which are banned notifications or block all displayable channels.
+ if (appRow.banned || isAllChannelsBlocked(getDisplayableChannels(appRow))) {
+ continue;
+ }
+
// Get sent notification count from app.
final int sentCount = appRow.sentByApp.sentCount;
- if (!appRow.banned && sentCount >= MIN_NOTIFICATION_SENT_COUNT
- && sentCount > maxSentCount) {
+ if (sentCount >= MIN_NOTIFICATION_SENT_COUNT && sentCount > maxSentCount) {
maxSentCount = sentCount;
maxSentCountPackage = packageInfo;
mAppRow = appRow;
@@ -404,6 +404,15 @@
return maxSentCountPackage;
}
+ private boolean isAllChannelsBlocked(List<NotificationChannel> channels) {
+ for (NotificationChannel channel : channels) {
+ if (channel.getImportance() != IMPORTANCE_NONE) {
+ return false;
+ }
+ }
+ return true;
+ }
+
protected CharSequence getSubTitle(String packageName, int uid) {
final int channelCount = mNotificationBackend.getChannelCount(packageName, uid);
diff --git a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
index 3ecfcae..590afd2 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRenderer.java
@@ -135,23 +135,19 @@
// Deferred setup is never dismissible.
break;
case VIEW_TYPE_HALF_WIDTH:
- initDismissalActions(holder, card, R.id.content);
+ initDismissalActions(holder, card);
break;
default:
- initDismissalActions(holder, card, R.id.slice_view);
+ initDismissalActions(holder, card);
+ }
+
+ if (card.isPendingDismiss()) {
+ flipCardToDismissalView(holder);
+ mFlippedCardSet.add(holder);
}
}
- private void initDismissalActions(RecyclerView.ViewHolder holder, ContextualCard card,
- int initialViewId) {
- // initialView is the first view in the ViewFlipper.
- final View initialView = holder.itemView.findViewById(initialViewId);
- initialView.setOnLongClickListener(v -> {
- flipCardToDismissalView(holder);
- mFlippedCardSet.add(holder);
- return true;
- });
-
+ private void initDismissalActions(RecyclerView.ViewHolder holder, ContextualCard card) {
final Button btnKeep = holder.itemView.findViewById(R.id.keep);
btnKeep.setOnClickListener(v -> {
mFlippedCardSet.remove(holder);
diff --git a/src/com/android/settings/homepage/contextualcards/slices/SwipeDismissalDelegate.java b/src/com/android/settings/homepage/contextualcards/slices/SwipeDismissalDelegate.java
index a4186b0..3564189 100644
--- a/src/com/android/settings/homepage/contextualcards/slices/SwipeDismissalDelegate.java
+++ b/src/com/android/settings/homepage/contextualcards/slices/SwipeDismissalDelegate.java
@@ -18,31 +18,74 @@
import android.content.Context;
import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.graphics.drawable.Drawable;
+import android.view.View;
+import android.widget.ViewFlipper;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.RecyclerView;
+import com.android.settings.R;
+import com.android.settings.homepage.contextualcards.ContextualCard;
+
public class SwipeDismissalDelegate extends ItemTouchHelper.Callback {
- private static final String TAG = "DismissItemTouchHelper";
+ private static final String TAG = "SwipeDismissalDelegate";
- public interface DismissalItemTouchHelperListener {
+ public interface Listener {
void onSwiped(int position);
}
private final Context mContext;
- private final DismissalItemTouchHelperListener mListener;
+ private final SwipeDismissalDelegate.Listener mListener;
+ private final Drawable mIconDelete;
+ private final Paint mBgPaint;
+ private final int mBgCornerRadius;
- public SwipeDismissalDelegate(Context context, DismissalItemTouchHelperListener listener) {
+ public SwipeDismissalDelegate(Context context, SwipeDismissalDelegate.Listener listener) {
mContext = context;
mListener = listener;
+ mIconDelete = mContext.getDrawable(R.drawable.ic_delete);
+ mBgPaint = new Paint();
+ mBgPaint.setColor(mContext.getColor(R.color.homepage_card_dismissal_background));
+ mBgCornerRadius = mContext.getResources()
+ .getDimensionPixelSize(R.dimen.homepage_card_corner_radius);
}
+ /**
+ * Determine whether the ability to drag or swipe should be enabled or not.
+ *
+ * Only allow swipe on {@link ContextualCard} built with view type
+ * {@link SliceContextualCardRenderer#VIEW_TYPE_FULL_WIDTH} or
+ * {@link SliceContextualCardRenderer#VIEW_TYPE_HALF_WIDTH}.
+ *
+ * When the dismissal view is displayed, the swipe will also be disabled.
+ */
@Override
public int getMovementFlags(@NonNull RecyclerView recyclerView,
@NonNull RecyclerView.ViewHolder viewHolder) {
- return 0;
+ switch (viewHolder.getItemViewType()) {
+ case SliceContextualCardRenderer.VIEW_TYPE_FULL_WIDTH:
+ case SliceContextualCardRenderer.VIEW_TYPE_HALF_WIDTH:
+ //TODO(b/129438972): Convert this to a regular view.
+ final ViewFlipper viewFlipper = viewHolder.itemView.findViewById(R.id.view_flipper);
+
+ // As we are using ViewFlipper to switch between the initial view and
+ // dismissal view, here we are making sure the current displayed view is the
+ // initial view of either slice full card or half card, and only allow swipe on
+ // these two types.
+ if (viewFlipper.getCurrentView().getId() != getInitialViewId(viewHolder)) {
+ // Disable swiping when we are in the dismissal view
+ return 0;
+ }
+ return makeMovementFlags(0 /*dragFlags*/,
+ ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT /*swipeFlags*/);
+ default:
+ return 0;
+ }
}
@Override
@@ -62,5 +105,36 @@
@NonNull RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState,
boolean isCurrentlyActive) {
super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive);
+
+ final View itemView = viewHolder.itemView;
+ final int iconMargin = mContext.getResources()
+ .getDimensionPixelSize(R.dimen.homepage_card_dismissal_side_margin);
+ final int iconTop =
+ itemView.getTop() + (itemView.getHeight() - mIconDelete.getIntrinsicHeight()) / 2;
+ final int iconBottom = iconTop + mIconDelete.getIntrinsicHeight();
+
+ if (dX > 0) { //swipe to the right
+ final int iconLeft = itemView.getLeft() + iconMargin;
+ final int iconRight = iconLeft + mIconDelete.getIntrinsicWidth();
+ final RectF rect = new RectF(itemView.getLeft(), itemView.getTop(),
+ itemView.getLeft() + ((int) dX) + mBgCornerRadius, itemView.getBottom());
+ mIconDelete.setBounds(iconLeft, iconTop, iconRight, iconBottom);
+ c.drawRoundRect(rect, mBgCornerRadius, mBgCornerRadius, mBgPaint);
+ } else if (dX < 0) {
+ final int iconRight = itemView.getRight() - iconMargin;
+ final int iconLeft = iconRight - mIconDelete.getIntrinsicWidth();
+ final RectF rect = new RectF(itemView.getRight() + ((int) dX), itemView.getTop(),
+ itemView.getRight(), itemView.getBottom());
+ mIconDelete.setBounds(iconLeft, iconTop, iconRight, iconBottom);
+ c.drawRoundRect(rect, mBgCornerRadius, mBgCornerRadius, mBgPaint);
+ }
+ mIconDelete.draw(c);
+ }
+
+ private int getInitialViewId(RecyclerView.ViewHolder viewHolder) {
+ if (viewHolder.getItemViewType() == SliceContextualCardRenderer.VIEW_TYPE_HALF_WIDTH) {
+ return R.id.content;
+ }
+ return R.id.slice_view;
}
}
\ No newline at end of file
diff --git a/src/com/android/settings/media/MediaOutputSlice.java b/src/com/android/settings/media/MediaOutputSlice.java
index e76bc88..53324e9 100644
--- a/src/com/android/settings/media/MediaOutputSlice.java
+++ b/src/com/android/settings/media/MediaOutputSlice.java
@@ -18,11 +18,11 @@
import static com.android.settings.slices.CustomSliceRegistry.MEDIA_OUTPUT_SLICE_URI;
-import android.annotation.ColorInt;
import android.app.PendingIntent;
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
+import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.text.TextUtils;
import android.util.Log;
@@ -82,10 +82,9 @@
}
final List<MediaDevice> devices = getMediaDevices();
- @ColorInt final int color = Utils.getColorAccentDefaultColor(mContext);
final MediaDevice connectedDevice = getWorker().getCurrentConnectedMediaDevice();
- final ListBuilder listBuilder = buildActiveDeviceHeader(color, connectedDevice);
+ final ListBuilder listBuilder = buildActiveDeviceHeader(connectedDevice);
for (MediaDevice device : devices) {
if (!TextUtils.equals(connectedDevice.getId(), device.getId())) {
@@ -96,9 +95,9 @@
return listBuilder.build();
}
- private ListBuilder buildActiveDeviceHeader(@ColorInt int color, MediaDevice device) {
+ private ListBuilder buildActiveDeviceHeader(MediaDevice device) {
final String title = device.getName();
- final IconCompat icon = IconCompat.createWithResource(mContext, device.getIcon());
+ final IconCompat icon = getDeviceIconCompat(device);
final PendingIntent broadcastAction =
getBroadcastIntent(mContext, device.getId(), device.hashCode());
@@ -107,7 +106,7 @@
final ListBuilder listBuilder = new ListBuilder(mContext, MEDIA_OUTPUT_SLICE_URI,
ListBuilder.INFINITY)
- .setAccentColor(color)
+ .setAccentColor(COLOR_NOT_TINTED)
.addRow(new ListBuilder.RowBuilder()
.setTitleItem(icon, ListBuilder.ICON_IMAGE)
.setTitle(title)
@@ -117,6 +116,17 @@
return listBuilder;
}
+ private IconCompat getDeviceIconCompat(MediaDevice device) {
+ Drawable drawable = device.getIcon();
+ if (drawable == null) {
+ Log.d(TAG, "getDeviceIconCompat() device : " + device.getName() + ", drawable is null");
+ // Use default Bluetooth device icon to handle getIcon() is null case.
+ drawable = mContext.getDrawable(com.android.internal.R.drawable.ic_bt_headphones_a2dp);
+ }
+
+ return Utils.createIconWithDrawable(drawable);
+ }
+
private MediaDeviceUpdateWorker getWorker() {
if (mWorker == null) {
mWorker = (MediaDeviceUpdateWorker) SliceBackgroundWorker.getInstance(getUri());
@@ -136,7 +146,8 @@
final String title = device.getName();
final PendingIntent broadcastAction =
getBroadcastIntent(mContext, device.getId(), device.hashCode());
- final IconCompat deviceIcon = IconCompat.createWithResource(mContext, device.getIcon());
+ final IconCompat deviceIcon = getDeviceIconCompat(device);
+
final ListBuilder.RowBuilder rowBuilder = new ListBuilder.RowBuilder()
.setTitleItem(deviceIcon, ListBuilder.ICON_IMAGE)
.setPrimaryAction(SliceAction.create(broadcastAction, deviceIcon,
diff --git a/src/com/android/settings/notification/AppBubbleNotificationSettings.java b/src/com/android/settings/notification/AppBubbleNotificationSettings.java
new file mode 100644
index 0000000..17909c0
--- /dev/null
+++ b/src/com/android/settings/notification/AppBubbleNotificationSettings.java
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2019 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.notification;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.provider.SearchIndexableResource;
+import android.text.TextUtils;
+import android.util.Log;
+
+import com.android.settings.R;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.search.SearchIndexable;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+@SearchIndexable
+public class AppBubbleNotificationSettings extends NotificationSettingsBase {
+ private static final String TAG = "AppBubNotiSettings";
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.APP_BUBBLE_SETTINGS;
+ }
+
+ @Override
+ protected String getLogTag() {
+ return TAG;
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.app_bubble_notification_settings;
+ }
+
+ @Override
+ protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
+ mControllers = getPreferenceControllers(context, this);
+ return new ArrayList<>(mControllers);
+ }
+
+ protected static List<NotificationPreferenceController> getPreferenceControllers(
+ Context context, AppBubbleNotificationSettings fragment) {
+ List<NotificationPreferenceController> controllers = new ArrayList<>();
+ controllers.add(new HeaderPreferenceController(context, fragment));
+ controllers.add(new BubblePreferenceController(context, new NotificationBackend()));
+ return controllers;
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ if (mUid < 0 || TextUtils.isEmpty(mPkg) || mPkgInfo == null) {
+ Log.w(TAG, "Missing package or uid or packageinfo");
+ finish();
+ return;
+ }
+
+ for (NotificationPreferenceController controller : mControllers) {
+ controller.onResume(mAppRow, mChannel, mChannelGroup, mSuspendedAppsAdmin);
+ controller.displayPreference(getPreferenceScreen());
+ }
+ updatePreferenceStates();
+ }
+
+ /**
+ * For Search.
+ */
+ public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider() {
+ @Override
+ public List<SearchIndexableResource> getXmlResourcesToIndex(
+ Context context, boolean enabled) {
+ final SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = R.xml.app_bubble_notification_settings;
+ return Arrays.asList(sir);
+ }
+
+ @Override
+ public List<AbstractPreferenceController> createPreferenceControllers(Context
+ context) {
+ return new ArrayList<>(AppBubbleNotificationSettings.getPreferenceControllers(
+ context, null));
+ }
+ };
+}
diff --git a/src/com/android/settings/notification/AppNotificationSettings.java b/src/com/android/settings/notification/AppNotificationSettings.java
index 3ccca00..24d85e2 100644
--- a/src/com/android/settings/notification/AppNotificationSettings.java
+++ b/src/com/android/settings/notification/AppNotificationSettings.java
@@ -152,7 +152,7 @@
mControllers.add(new DescriptionPreferenceController(context));
mControllers.add(new NotificationsOffPreferenceController(context));
mControllers.add(new DeletedChannelsPreferenceController(context, mBackend));
- mControllers.add(new BubblePreferenceController(context, mBackend));
+ mControllers.add(new BubbleSummaryPreferenceController(context, mBackend));
return new ArrayList<>(mControllers);
}
diff --git a/src/com/android/settings/notification/BubbleNotificationPreferenceController.java b/src/com/android/settings/notification/BubbleNotificationPreferenceController.java
index caba7d9..83e73e9 100644
--- a/src/com/android/settings/notification/BubbleNotificationPreferenceController.java
+++ b/src/com/android/settings/notification/BubbleNotificationPreferenceController.java
@@ -56,7 +56,7 @@
@Override
public void displayPreference(PreferenceScreen screen) {
super.displayPreference(screen);
- Preference preference = screen.findPreference(NOTIFICATION_BUBBLES);
+ Preference preference = screen.findPreference(getPreferenceKey());
if (preference != null) {
mSettingObserver = new SettingObserver(preference);
}
diff --git a/src/com/android/settings/notification/BubbleNotificationSettings.java b/src/com/android/settings/notification/BubbleNotificationSettings.java
new file mode 100644
index 0000000..7044293
--- /dev/null
+++ b/src/com/android/settings/notification/BubbleNotificationSettings.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2019 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.notification;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.provider.SearchIndexableResource;
+
+import com.android.settings.R;
+import com.android.settings.core.OnActivityResultListener;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.search.SearchIndexable;
+
+import java.util.Arrays;
+import java.util.List;
+
+@SearchIndexable
+public class BubbleNotificationSettings extends DashboardFragment implements
+ OnActivityResultListener {
+ private static final String TAG = "BubbleNotiSettings";
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.BUBBLE_SETTINGS;
+ }
+
+ @Override
+ protected String getLogTag() {
+ return TAG;
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.bubble_notification_settings;
+ }
+
+ /**
+ * For Search.
+ */
+ public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider() {
+ @Override
+ public List<SearchIndexableResource> getXmlResourcesToIndex(
+ Context context, boolean enabled) {
+ final SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = R.xml.bubble_notification_settings;
+ return Arrays.asList(sir);
+ }
+ };
+}
diff --git a/src/com/android/settings/notification/BubblePreferenceController.java b/src/com/android/settings/notification/BubblePreferenceController.java
index 5b3be44..5dab374 100644
--- a/src/com/android/settings/notification/BubblePreferenceController.java
+++ b/src/com/android/settings/notification/BubblePreferenceController.java
@@ -21,6 +21,7 @@
import android.content.Context;
import android.provider.Settings;
+import com.android.settings.R;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.RestrictedSwitchPreference;
@@ -74,6 +75,8 @@
pref.setEnabled(isChannelConfigurable() && !pref.isDisabledByAdmin());
} else {
pref.setChecked(mAppRow.allowBubbles);
+ pref.setSummary(mContext.getString(
+ R.string.bubbles_app_toggle_summary, mAppRow.label));
}
}
}
diff --git a/src/com/android/settings/notification/BubbleSummaryNotificationPreferenceController.java b/src/com/android/settings/notification/BubbleSummaryNotificationPreferenceController.java
new file mode 100644
index 0000000..e26d9a8
--- /dev/null
+++ b/src/com/android/settings/notification/BubbleSummaryNotificationPreferenceController.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2019 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.notification;
+
+import static android.provider.Settings.Secure.NOTIFICATION_BUBBLES;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+
+import androidx.annotation.VisibleForTesting;
+
+public class BubbleSummaryNotificationPreferenceController extends BasePreferenceController {
+
+ @VisibleForTesting
+ static final int ON = 1;
+
+ public BubbleSummaryNotificationPreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ return mContext.getString(
+ areBubblesEnabled() ? R.string.switch_on_text : R.string.switch_off_text);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+
+ private boolean areBubblesEnabled() {
+ return Settings.Secure.getInt(mContext.getContentResolver(),
+ NOTIFICATION_BUBBLES, ON) == ON;
+ }
+}
diff --git a/src/com/android/settings/notification/BubbleSummaryPreferenceController.java b/src/com/android/settings/notification/BubbleSummaryPreferenceController.java
new file mode 100644
index 0000000..708bbcd
--- /dev/null
+++ b/src/com/android/settings/notification/BubbleSummaryPreferenceController.java
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2019 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.notification;
+
+import static android.provider.Settings.Secure.NOTIFICATION_BUBBLES;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.os.Bundle;
+import android.provider.Settings;
+
+import com.android.settings.R;
+import com.android.settings.applications.AppInfoBase;
+import com.android.settings.core.SubSettingLauncher;
+
+import androidx.preference.Preference;
+
+public class BubbleSummaryPreferenceController extends NotificationPreferenceController {
+
+ private static final String KEY = "bubble_link_pref";
+ private static final int SYSTEM_WIDE_ON = 1;
+ private static final int SYSTEM_WIDE_OFF = 0;
+
+ public BubbleSummaryPreferenceController(Context context, NotificationBackend backend) {
+ super(context, backend);
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ if (!super.isAvailable()) {
+ return false;
+ }
+ if (mAppRow == null && mChannel == null) {
+ return false;
+ }
+ if (Settings.Secure.getInt(mContext.getContentResolver(),
+ NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON) == SYSTEM_WIDE_OFF) {
+ return false;
+ }
+ if (mChannel != null) {
+ if (isDefaultChannel()) {
+ return true;
+ } else {
+ return mAppRow == null ? false : mAppRow.allowBubbles;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+
+ if (mAppRow != null) {
+ Bundle args = new Bundle();
+ args.putString(AppInfoBase.ARG_PACKAGE_NAME, mAppRow.pkg);
+ args.putInt(AppInfoBase.ARG_PACKAGE_UID, mAppRow.uid);
+
+ preference.setIntent(new SubSettingLauncher(mContext)
+ .setDestination(AppBubbleNotificationSettings.class.getName())
+ .setArguments(args)
+ .setSourceMetricsCategory(
+ SettingsEnums.NOTIFICATION_APP_NOTIFICATION)
+ .toIntent());
+ }
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ boolean canBubble = false;
+ if (mAppRow != null) {
+ if (mChannel != null) {
+ canBubble |= mChannel.canBubble();
+ } else {
+ canBubble |= mAppRow.allowBubbles;
+ }
+ }
+ return mContext.getString(canBubble ? R.string.switch_on_text : R.string.switch_off_text);
+ }
+}
diff --git a/src/com/android/settings/notification/NotificationPreferenceController.java b/src/com/android/settings/notification/NotificationPreferenceController.java
index 3f535fb..d2b7c43 100644
--- a/src/com/android/settings/notification/NotificationPreferenceController.java
+++ b/src/com/android/settings/notification/NotificationPreferenceController.java
@@ -126,6 +126,11 @@
return mChannel.getImportance() == IMPORTANCE_NONE;
}
+ if (mChannel.isImportanceLockedByOEM()
+ || mChannel.isImportanceLockedByCriticalDeviceFunction()) {
+ return false;
+ }
+
return mChannel.isBlockableSystem() || !mAppRow.systemApp
|| mChannel.getImportance() == IMPORTANCE_NONE;
}
diff --git a/src/com/android/settings/notification/SoundPreferenceController.java b/src/com/android/settings/notification/SoundPreferenceController.java
index e53a560..73cbad3 100644
--- a/src/com/android/settings/notification/SoundPreferenceController.java
+++ b/src/com/android/settings/notification/SoundPreferenceController.java
@@ -16,10 +16,14 @@
package com.android.settings.notification;
+import static android.media.AudioAttributes.USAGE_ALARM;
+import static android.media.AudioAttributes.USAGE_NOTIFICATION_RINGTONE;
+
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
+import android.media.RingtoneManager;
import android.net.Uri;
import android.preference.PreferenceManager;
@@ -91,6 +95,16 @@
public boolean handlePreferenceTreeClick(Preference preference) {
if (KEY_SOUND.equals(preference.getKey()) && mFragment != null) {
NotificationSoundPreference pref = (NotificationSoundPreference) preference;
+ if (mChannel != null && mChannel.getAudioAttributes() != null) {
+ if (USAGE_ALARM == mChannel.getAudioAttributes().getUsage()) {
+ pref.setRingtoneType(RingtoneManager.TYPE_ALARM);
+ } else if (USAGE_NOTIFICATION_RINGTONE
+ == mChannel.getAudioAttributes().getUsage()) {
+ pref.setRingtoneType(RingtoneManager.TYPE_RINGTONE);
+ } else {
+ pref.setRingtoneType(RingtoneManager.TYPE_NOTIFICATION);
+ }
+ }
pref.onPrepareRingtonePickerIntent(pref.getIntent());
mFragment.startActivityForResult(preference.getIntent(), CODE);
return true;
diff --git a/src/com/android/settings/notification/VibrateWhenRingPreferenceController.java b/src/com/android/settings/notification/VibrateWhenRingPreferenceController.java
index cbf909f..b043cb1 100644
--- a/src/com/android/settings/notification/VibrateWhenRingPreferenceController.java
+++ b/src/com/android/settings/notification/VibrateWhenRingPreferenceController.java
@@ -39,6 +39,8 @@
public class VibrateWhenRingPreferenceController extends TogglePreferenceController
implements LifecycleObserver, OnResume, OnPause {
+ /** Flag for whether or not to apply ramping ringer on incoming phone calls. */
+ private static final String RAMPING_RINGER_ENABLED = "ramping_ringer_enabled";
private static final String KEY_VIBRATE_WHEN_RINGING = "vibrate_when_ringing";
private final int DEFAULT_VALUE = 0;
private final int NOTIFICATION_VIBRATE_WHEN_RINGING = 1;
@@ -130,8 +132,8 @@
}
private boolean isRampingRingerEnabled() {
- return DeviceConfig.getBoolean(DeviceConfig.Telephony.NAMESPACE,
- DeviceConfig.Telephony.RAMPING_RINGER_ENABLED, false);
+ return DeviceConfig.getBoolean(
+ DeviceConfig.NAMESPACE_TELEPHONY, RAMPING_RINGER_ENABLED, false);
}
}
diff --git a/src/com/android/settings/password/ChooseLockGeneric.java b/src/com/android/settings/password/ChooseLockGeneric.java
index 4a758be..580c7ba 100644
--- a/src/com/android/settings/password/ChooseLockGeneric.java
+++ b/src/com/android/settings/password/ChooseLockGeneric.java
@@ -183,6 +183,7 @@
super.onCreate(savedInstanceState);
final Activity activity = getActivity();
if (!Utils.isDeviceProvisioned(activity) && !canRunBeforeDeviceProvisioned()) {
+ Log.i(TAG, "Refusing to start because device is not provisioned");
activity.finish();
return;
}
diff --git a/src/com/android/settings/privacy/PermissionBarChartPreferenceController.java b/src/com/android/settings/privacy/PermissionBarChartPreferenceController.java
index b47ad9c..9358392 100644
--- a/src/com/android/settings/privacy/PermissionBarChartPreferenceController.java
+++ b/src/com/android/settings/privacy/PermissionBarChartPreferenceController.java
@@ -16,6 +16,10 @@
package com.android.settings.privacy;
+import static android.Manifest.permission_group.CAMERA;
+import static android.Manifest.permission_group.LOCATION;
+import static android.Manifest.permission_group.MICROPHONE;
+
import static com.android.settingslib.widget.BarChartPreference.MAXIMUM_BAR_VIEWS;
import static java.util.concurrent.TimeUnit.DAYS;
@@ -131,8 +135,28 @@
@Override
public void onPermissionUsageResult(@NonNull List<RuntimePermissionUsageInfo> usageInfos) {
- usageInfos.sort(Comparator.comparingInt(
- RuntimePermissionUsageInfo::getAppAccessCount).reversed());
+ usageInfos.sort((x, y) -> {
+ int usageDiff = y.getAppAccessCount() - x.getAppAccessCount();
+ if (usageDiff != 0) {
+ return usageDiff;
+ }
+ String xName = x.getName();
+ String yName = y.getName();
+ if (xName.equals(LOCATION)) {
+ return -1;
+ } else if (yName.equals(LOCATION)) {
+ return 1;
+ } else if (xName.equals(MICROPHONE)) {
+ return -1;
+ } else if (yName.equals(MICROPHONE)) {
+ return 1;
+ } else if (xName.equals(CAMERA)) {
+ return -1;
+ } else if (yName.equals(CAMERA)) {
+ return 1;
+ }
+ return x.getName().compareTo(y.getName());
+ });
// If the result is different, we need to update bar views.
if (!areSamePermissionGroups(usageInfos)) {
@@ -176,6 +200,7 @@
barViewInfos[index].setClickListener((View v) -> {
final Intent intent = new Intent(Intent.ACTION_REVIEW_PERMISSION_USAGE);
intent.putExtra(Intent.EXTRA_PERMISSION_GROUP_NAME, permissionGroupInfo.getName());
+ intent.putExtra(Intent.EXTRA_DURATION_MILLIS, DAYS.toMillis(1));
mContext.startActivity(intent);
});
}
diff --git a/src/com/android/settings/sim/SimDialogActivity.java b/src/com/android/settings/sim/SimDialogActivity.java
index 13148c8..487dace 100644
--- a/src/com/android/settings/sim/SimDialogActivity.java
+++ b/src/com/android/settings/sim/SimDialogActivity.java
@@ -254,7 +254,7 @@
builder.setTitle(R.string.select_sim_for_calls);
break;
case SMS_PICK:
- builder.setTitle(R.string.sim_card_select_title);
+ builder.setTitle(R.string.select_sim_for_sms);
break;
default:
throw new IllegalArgumentException("Invalid dialog type "
diff --git a/src/com/android/settings/sim/SimSelectNotification.java b/src/com/android/settings/sim/SimSelectNotification.java
index 4f3b9bc..a1e942a 100644
--- a/src/com/android/settings/sim/SimSelectNotification.java
+++ b/src/com/android/settings/sim/SimSelectNotification.java
@@ -30,6 +30,7 @@
import android.content.Intent;
import android.content.res.Resources;
import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
import com.android.settings.R;
import com.android.settings.Settings.SimSettingsActivity;
@@ -45,6 +46,9 @@
@Override
public void onReceive(Context context, Intent intent) {
+ if (!TelephonyManager.ACTION_PRIMARY_SUBSCRIPTION_LIST_CHANGED.equals(intent.getAction())) {
+ return;
+ }
// Cancel any previous notifications
cancelNotification(context);
// Create a notification to tell the user that some defaults are missing
diff --git a/src/com/android/settings/system/SystemDashboardFragment.java b/src/com/android/settings/system/SystemDashboardFragment.java
index 5c642b2..3ab31e3 100644
--- a/src/com/android/settings/system/SystemDashboardFragment.java
+++ b/src/com/android/settings/system/SystemDashboardFragment.java
@@ -20,12 +20,14 @@
import android.os.Bundle;
import android.provider.SearchIndexableResource;
+import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.overlay.FeatureFactory;
import com.android.settings.search.BaseSearchIndexProvider;
import com.android.settings.search.Indexable;
import com.android.settingslib.search.SearchIndexable;
@@ -40,6 +42,8 @@
private static final String KEY_RESET = "reset_dashboard";
+ public static final String EXTRA_SHOW_AWARE_DISABLED = "show_aware_dialog_disabled";
+
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
@@ -49,6 +53,17 @@
if (getVisiblePreferenceCount(screen) == screen.getInitialExpandedChildrenCount() + 1) {
screen.setInitialExpandedChildrenCount(Integer.MAX_VALUE);
}
+
+ showRestrictionDialog();
+ }
+
+ @VisibleForTesting
+ public void showRestrictionDialog() {
+ final Bundle args = getArguments();
+ if (args != null && args.getBoolean(EXTRA_SHOW_AWARE_DISABLED, false)) {
+ FeatureFactory.getFactory(getContext()).getAwareFeatureProvider()
+ .showRestrictionDialog(this);
+ }
}
@Override
diff --git a/src/com/android/settings/vpn2/ConfigDialog.java b/src/com/android/settings/vpn2/ConfigDialog.java
index 07e957d..9f2176c 100644
--- a/src/com/android/settings/vpn2/ConfigDialog.java
+++ b/src/com/android/settings/vpn2/ConfigDialog.java
@@ -143,6 +143,7 @@
}
mMppe.setChecked(mProfile.mppe);
mL2tpSecret.setText(mProfile.l2tpSecret);
+ mL2tpSecret.setTextAppearance(android.R.style.TextAppearance_DeviceDefault_Medium);
mIpsecIdentifier.setText(mProfile.ipsecIdentifier);
mIpsecSecret.setText(mProfile.ipsecSecret);
loadCertificates(mIpsecUserCert, Credentials.USER_PRIVATE_KEY, 0, mProfile.ipsecUserCert);
@@ -152,6 +153,7 @@
R.string.vpn_no_server_cert, mProfile.ipsecServerCert);
mSaveLogin.setChecked(mProfile.saveLogin);
mAlwaysOnVpn.setChecked(mProfile.key.equals(VpnUtils.getLockdownVpn()));
+ mPassword.setTextAppearance(android.R.style.TextAppearance_DeviceDefault_Medium);
// Hide lockdown VPN on devices that require IMS authentication
if (SystemProperties.getBoolean("persist.radio.imsregrequired", false)) {
diff --git a/src/com/android/settings/wallpaper/WallpaperSuggestionActivity.java b/src/com/android/settings/wallpaper/WallpaperSuggestionActivity.java
index 14564b1..0713872 100644
--- a/src/com/android/settings/wallpaper/WallpaperSuggestionActivity.java
+++ b/src/com/android/settings/wallpaper/WallpaperSuggestionActivity.java
@@ -28,10 +28,18 @@
import com.android.settings.R;
import com.android.settings.core.SubSettingLauncher;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settings.search.Indexable;
+import com.android.settings.search.SearchIndexableRaw;
+import com.android.settingslib.search.SearchIndexable;
import com.google.android.setupcompat.util.WizardManagerHelper;
-public class WallpaperSuggestionActivity extends Activity {
+import java.util.ArrayList;
+import java.util.List;
+
+@SearchIndexable
+public class WallpaperSuggestionActivity extends Activity implements Indexable {
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -79,4 +87,30 @@
return context.getResources().getBoolean(
com.android.internal.R.bool.config_enableWallpaperService);
}
+
+ public static final Indexable.SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider() {
+ private static final String SUPPORT_SEARCH_INDEX_KEY = "wallpaper_type";
+
+ @Override
+ public List<SearchIndexableRaw> getRawDataToIndex(Context context,
+ boolean enabled) {
+
+ final List<SearchIndexableRaw> result = new ArrayList<>();
+
+ SearchIndexableRaw data = new SearchIndexableRaw(context);
+ data.title = context.getString(R.string.wallpaper_settings_fragment_title);
+ data.screenTitle = context.getString(
+ R.string.wallpaper_settings_fragment_title);
+ data.intentTargetPackage = context.getString(
+ R.string.config_wallpaper_picker_package);
+ data.intentTargetClass = context.getString(
+ R.string.config_wallpaper_picker_class);
+ data.intentAction = Intent.ACTION_MAIN;
+ data.key = SUPPORT_SEARCH_INDEX_KEY;
+ result.add(data);
+
+ return result;
+ }
+ };
}
diff --git a/src/com/android/settings/wallpaper/WallpaperTypeSettings.java b/src/com/android/settings/wallpaper/WallpaperTypeSettings.java
index 0e0f8df..2d4a16f 100644
--- a/src/com/android/settings/wallpaper/WallpaperTypeSettings.java
+++ b/src/com/android/settings/wallpaper/WallpaperTypeSettings.java
@@ -17,21 +17,11 @@
package com.android.settings.wallpaper;
import android.app.settings.SettingsEnums;
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
-import com.android.settings.search.BaseSearchIndexProvider;
-import com.android.settings.search.SearchIndexableRaw;
-import com.android.settingslib.search.SearchIndexable;
-import java.util.ArrayList;
-import java.util.List;
-@SearchIndexable(forTarget = SearchIndexable.ALL & ~SearchIndexable.ARC)
public class WallpaperTypeSettings extends DashboardFragment {
private static final String TAG = "WallpaperTypeSettings";
@@ -54,42 +44,4 @@
protected int getPreferenceScreenResId() {
return R.xml.wallpaper_settings;
}
-
- public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
- new BaseSearchIndexProvider() {
- @Override
- public List<SearchIndexableRaw> getRawDataToIndex(Context context, boolean enabled) {
- final List<SearchIndexableRaw> result = new ArrayList<>();
-
- final Intent intent = new Intent(Intent.ACTION_SET_WALLPAPER);
- final PackageManager pm = context.getPackageManager();
- final List<ResolveInfo> rList = pm.queryIntentActivities(intent,
- PackageManager.MATCH_DEFAULT_ONLY);
-
- // Add indexable data for package that is in config_wallpaper_picker_package
- final String wallpaperPickerPackage =
- context.getString(R.string.config_wallpaper_picker_package);
- for (ResolveInfo info : rList) {
- if (!wallpaperPickerPackage.equals(info.activityInfo.packageName)) {
- continue;
- }
- CharSequence label = info.loadLabel(pm);
- if (label == null) {
- label = info.activityInfo.packageName;
- }
- final SearchIndexableRaw data = new SearchIndexableRaw(context);
- data.title = label.toString();
- data.key = "wallpaper_type_settings";
- data.screenTitle = context.getResources().getString(
- R.string.wallpaper_settings_fragment_title);
- data.intentAction = Intent.ACTION_SET_WALLPAPER;
- data.intentTargetPackage = info.activityInfo.packageName;
- data.intentTargetClass = info.activityInfo.name;
- data.keywords = context.getString(R.string.keywords_wallpaper);
- result.add(data);
- }
-
- return result;
- }
- };
}
diff --git a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
index e9057e6..2a7ac17 100644
--- a/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
+++ b/src/com/android/settings/wifi/NetworkRequestDialogFragment.java
@@ -138,9 +138,9 @@
.setOnItemClickListener(
(parent, view, position, id) -> this.onClick(dialog, position));
- // Don't dismiss dialog when touching outside. User report it is easy to touch outside.
- // This causes dialog to close. Which is concerned as a bad UX (b/128877712).
- dialog.setCanceledOnTouchOutside(false);
+ // Don't dismiss dialog when touching outside. User reports it is easy to touch outside.
+ // This causes dialog to close.
+ setCancelable(false);
dialog.setOnShowListener((dialogInterface) -> {
// Replace NeutralButton onClickListener to avoid closing dialog
diff --git a/src/com/android/settings/wifi/WifiConfigController.java b/src/com/android/settings/wifi/WifiConfigController.java
index 0887fc5..ac11510 100644
--- a/src/com/android/settings/wifi/WifiConfigController.java
+++ b/src/com/android/settings/wifi/WifiConfigController.java
@@ -55,6 +55,7 @@
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
+import android.widget.ImageButton;
import android.widget.ScrollView;
import android.widget.Spinner;
import android.widget.TextView;
@@ -64,6 +65,7 @@
import com.android.settings.ProxySelector;
import com.android.settings.R;
import com.android.settings.wifi.details.WifiPrivacyPreferenceController;
+import com.android.settings.wifi.dpp.WifiDppUtils;
import com.android.settingslib.Utils;
import com.android.settingslib.utils.ThreadUtils;
import com.android.settingslib.wifi.AccessPoint;
@@ -129,6 +131,8 @@
@VisibleForTesting
int mAccessPointSecurity;
private TextView mPasswordView;
+ private ImageButton mSsidScanButton;
+ private ImageButton mPasswordScanButton;
private String mUnspecifiedCertString;
private String mMultipleCertSetString;
@@ -239,6 +243,8 @@
mDoNotValidateEapServerString =
mContext.getString(R.string.wifi_do_not_validate_eap_server);
+ mSsidScanButton = (ImageButton) mView.findViewById(R.id.ssid_scanner_button);
+ mPasswordScanButton = (ImageButton) mView.findViewById(R.id.password_scanner_button);
mDialogContainer = mView.findViewById(R.id.dialog_scrollview);
mIpSettingsSpinner = (Spinner) mView.findViewById(R.id.ip_settings);
mIpSettingsSpinner.setOnItemSelectedListener(this);
@@ -264,6 +270,7 @@
if (mAccessPoint == null) { // new network
configureSecuritySpinner();
mConfigUi.setSubmitButton(res.getString(R.string.wifi_save));
+ mPasswordScanButton.setVisibility(View.GONE);
} else {
mConfigUi.setTitle(mAccessPoint.getTitle());
@@ -408,6 +415,11 @@
mConfigUi.setForgetButton(res.getString(R.string.wifi_forget));
}
}
+
+ if (!WifiDppUtils.isSupportEnrolleeQrCodeScanner(mContext, mAccessPointSecurity)) {
+ mPasswordScanButton.setVisibility(View.GONE);
+ }
+ mSsidScanButton.setVisibility(View.GONE);
}
if (!isSplitSystemUser()) {
@@ -1444,6 +1456,12 @@
// Convert menu position to actual Wi-Fi security type
mAccessPointSecurity = mSecurityInPosition[position];
showSecurityFields();
+
+ if (WifiDppUtils.isSupportEnrolleeQrCodeScanner(mContext, mAccessPointSecurity)) {
+ mSsidScanButton.setVisibility(View.VISIBLE);
+ } else {
+ mSsidScanButton.setVisibility(View.GONE);
+ }
} else if (parent == mEapMethodSpinner || parent == mEapCaCertSpinner) {
showSecurityFields();
} else if (parent == mPhase2Spinner
diff --git a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
index 955525d..92132e8 100644
--- a/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiDetailPreferenceController.java
@@ -115,6 +115,8 @@
@VisibleForTesting
static final String KEY_SECURITY_PREF = "security";
@VisibleForTesting
+ static final String KEY_SSID_PREF = "ssid";
+ @VisibleForTesting
static final String KEY_MAC_ADDRESS_PREF = "mac_address";
@VisibleForTesting
static final String KEY_IP_ADDRESS_PREF = "ip_address";
@@ -158,6 +160,7 @@
private final WifiTracker mWifiTracker;
private final MetricsFeatureProvider mMetricsFeatureProvider;
private boolean mIsOutOfRange;
+ private boolean mIsEphemeral;
private boolean mConnected;
private int mConnectingState;
private WifiManager.ActionListener mConnectListener;
@@ -170,6 +173,7 @@
private Preference mRxLinkSpeedPref;
private Preference mFrequencyPref;
private Preference mSecurityPref;
+ private Preference mSsidPref;
private Preference mMacAddressPref;
private Preference mIpAddressPref;
private Preference mGatewayPref;
@@ -248,12 +252,14 @@
@Override
public void onLost(Network network) {
- // If support detail page for saved network, should update as disconnect but not exit.
- if (SavedAccessPointsWifiSettings.usingDetailsFragment(mContext)) {
- return;
- }
+ final boolean lostCurrentNetwork = network.equals(mNetwork);
+ if (lostCurrentNetwork) {
+ // If support detail page for saved network, should update as disconnect but not
+ // exit. Except for ephemeral network which should not show on saved network list.
+ if (SavedAccessPointsWifiSettings.usingDetailsFragment(mContext) && !mIsEphemeral) {
+ return;
+ }
- if (network.equals(mNetwork)) {
exitActivity();
}
}
@@ -347,6 +353,9 @@
mWifiTracker = null;
}
mConnected = mAccessPoint.isActive();
+ // When lost the network connection, WifiInfo/NetworkInfo will be clear. So causes we
+ // could not check if the AccessPoint is ephemeral. Need to cache it in first.
+ mIsEphemeral = mAccessPoint.isEphemeral();
mConnectingState = STATE_NONE;
mConnectListener = new WifiManager.ActionListener() {
@Override
@@ -399,6 +408,7 @@
mFrequencyPref = screen.findPreference(KEY_FREQUENCY_PREF);
mSecurityPref = screen.findPreference(KEY_SECURITY_PREF);
+ mSsidPref = screen.findPreference(KEY_SSID_PREF);
mMacAddressPref = screen.findPreference(KEY_MAC_ADDRESS_PREF);
mIpAddressPref = screen.findPreference(KEY_IP_ADDRESS_PREF);
mGatewayPref = screen.findPreference(KEY_GATEWAY_PREF);
@@ -497,6 +507,8 @@
refreshRxSpeed();
// IP related information
refreshIpLayerInfo();
+ // SSID Pref
+ refreshSsid();
// MAC Address Pref
refreshMacAddress();
}
@@ -645,6 +657,15 @@
R.string.rx_link_speed, mWifiInfo.getRxLinkSpeedMbps()));
}
+ private void refreshSsid() {
+ if (mAccessPoint.isPasspoint() || mAccessPoint.isOsuProvider()) {
+ mSsidPref.setVisible(true);
+ mSsidPref.setSummary(mAccessPoint.getSsidStr());
+ } else {
+ mSsidPref.setVisible(false);
+ }
+ }
+
private void refreshMacAddress() {
String macAddress = getMacAddress();
if (macAddress == null) {
@@ -663,7 +684,8 @@
}
// return randomized MAC address
- if (mWifiConfig.macRandomizationSetting == WifiConfiguration.RANDOMIZATION_PERSISTENT) {
+ if (mWifiConfig != null &&
+ mWifiConfig.macRandomizationSetting == WifiConfiguration.RANDOMIZATION_PERSISTENT) {
return mWifiConfig.getRandomizedMacAddress().toString();
}
@@ -687,6 +709,10 @@
}
private void refreshButtons() {
+ // Ephemeral network won't be removed permanently, but be putted in blacklist.
+ mButtonsPref.setButton1Text(
+ mIsEphemeral ? R.string.wifi_disconnect_button_text : R.string.forget);
+
mButtonsPref.setButton1Visible(canForgetNetwork());
mButtonsPref.setButton2Visible(canSignIntoNetwork());
mButtonsPref.setButton3Visible(canConnectNetwork());
diff --git a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
index ee4cc29..10d1d48 100644
--- a/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
+++ b/src/com/android/settings/wifi/details/WifiNetworkDetailsFragment.java
@@ -140,6 +140,8 @@
context);
privacyController.setWifiConfiguration(mAccessPoint.getConfig());
privacyController.setIsEphemeral(mAccessPoint.isEphemeral());
+ privacyController.setIsPasspoint(
+ mAccessPoint.isPasspoint() || mAccessPoint.isPasspointConfig());
controllers.add(privacyController);
return controllers;
diff --git a/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java b/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java
index a549e21..7bec411 100644
--- a/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java
+++ b/src/com/android/settings/wifi/details/WifiPrivacyPreferenceController.java
@@ -41,6 +41,7 @@
private WifiConfiguration mWifiConfiguration;
private WifiManager mWifiManager;
private boolean mIsEphemeral = false;
+ private boolean mIsPasspoint = false;
public WifiPrivacyPreferenceController(Context context) {
super(context, KEY_WIFI_PRIVACY);
@@ -56,6 +57,10 @@
mIsEphemeral = isEphemeral;
}
+ public void setIsPasspoint(boolean isPasspoint) {
+ mIsPasspoint = isPasspoint;
+ }
+
@Override
public int getAvailabilityStatus() {
return mContext.getResources().getBoolean(
@@ -71,7 +76,7 @@
updateSummary(dropDownPreference, randomizationLevel);
// Makes preference not selectable, when this is a ephemeral network.
- if (mIsEphemeral) {
+ if (mIsEphemeral || mIsPasspoint) {
preference.setSelectable(false);
dropDownPreference.setSummary(R.string.wifi_privacy_settings_ephemeral_summary);
}
diff --git a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
index 905d3a0..0fb56fa 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppQrCodeScannerFragment.java
@@ -134,6 +134,7 @@
if (msg.arg1 == ARG_RESTART_CAMERA) {
mProgressBar.setVisibility(View.INVISIBLE);
+ mDecorateView.setFocused(false);
restartCamera();
}
break;
diff --git a/src/com/android/settings/wifi/dpp/WifiDppUtils.java b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
index 6c6444c..42e88a5 100644
--- a/src/com/android/settings/wifi/dpp/WifiDppUtils.java
+++ b/src/com/android/settings/wifi/dpp/WifiDppUtils.java
@@ -323,31 +323,36 @@
}
}
+ /**
+ * Checks if QR code scanner supports to config other devices with the Wi-Fi network
+ *
+ * @param context The context to use for {@link WifiManager#isEasyConnectSupported()}
+ * @param accessPoint The {@link AccessPoint} of the Wi-Fi network
+ */
public static boolean isSupportConfiguratorQrCodeScanner(Context context,
AccessPoint accessPoint) {
- if (!isWifiDppEnabled(context)) {
- return false;
- }
-
- // DPP 1.0 only supports SAE and PSK.
- final int security = accessPoint.getSecurity();
- if (security == AccessPoint.SECURITY_SAE || security == AccessPoint.SECURITY_PSK) {
- return true;
- }
-
- return false;
+ return isSupportWifiDpp(context, accessPoint.getSecurity());
}
+ /**
+ * Checks if QR code generator supports to config other devices with the Wi-Fi network
+ *
+ * @param accessPoint The {@link AccessPoint} of the Wi-Fi network
+ */
public static boolean isSupportConfiguratorQrCodeGenerator(AccessPoint accessPoint) {
- // QR code generator produces QR code with ZXing's Wi-Fi network config format,
- // it supports PSK and WEP and non security
- final int security = accessPoint.getSecurity();
- if (security == AccessPoint.SECURITY_PSK || security == AccessPoint.SECURITY_WEP ||
- security == AccessPoint.SECURITY_NONE) {
- return true;
- }
+ return isSupportZxing(accessPoint.getSecurity());
+ }
- return false;
+ /**
+ * Checks if this device supports to be configured by the Wi-Fi network of the security
+ *
+ * @param context The context to use for {@link WifiManager#isEasyConnectSupported()}
+ * @param accesspointSecurity The security constants defined in {@link AccessPoint}
+ */
+ public static boolean isSupportEnrolleeQrCodeScanner(Context context,
+ int accesspointSecurity) {
+ return isSupportWifiDpp(context, accesspointSecurity) ||
+ isSupportZxing(accesspointSecurity);
}
private static boolean isSupportHotspotConfiguratorQrCodeGenerator(
@@ -358,4 +363,27 @@
return wifiConfiguration.allowedKeyManagement.get(KeyMgmt.WPA2_PSK) ||
wifiConfiguration.allowedKeyManagement.get(KeyMgmt.NONE);
}
+
+ private static boolean isSupportWifiDpp(Context context, int accesspointSecurity) {
+ if (!isWifiDppEnabled(context)) {
+ return false;
+ }
+
+ // DPP 1.0 only supports SAE and PSK.
+ if (accesspointSecurity == AccessPoint.SECURITY_SAE ||
+ accesspointSecurity == AccessPoint.SECURITY_PSK) {
+ return true;
+ }
+ return false;
+ }
+
+ // TODO (b/124131581 b/129396816): TO support WPA3 securities (SAE & OWE), change here at first
+ private static boolean isSupportZxing(int accesspointSecurity) {
+ if (accesspointSecurity == AccessPoint.SECURITY_PSK ||
+ accesspointSecurity == AccessPoint.SECURITY_WEP ||
+ accesspointSecurity == AccessPoint.SECURITY_NONE) {
+ return true;
+ }
+ return false;
+ }
}
diff --git a/src/com/android/settings/wifi/qrcode/QrPreviewLayout.java b/src/com/android/settings/wifi/qrcode/QrPreviewLayout.java
deleted file mode 100644
index ad17146..0000000
--- a/src/com/android/settings/wifi/qrcode/QrPreviewLayout.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright (C) 2018 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.wifi.qrcode;
-
-import android.content.Context;
-import android.util.AttributeSet;
-import android.widget.FrameLayout;
-
-/**
- * A customize square {@link FrameLayout}.
- * This is used for camera preview. Choose the smaller size of both dimensions as length and width.
- */
-public class QrPreviewLayout extends FrameLayout {
- public QrPreviewLayout(Context context) {
- super(context);
- }
-
- public QrPreviewLayout(Context context, AttributeSet attrs) {
- super(context, attrs);
- }
-
- public QrPreviewLayout(Context context, AttributeSet attrs, int defStyle) {
- super(context, attrs, defStyle);
- }
-
- @Override
- protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
- // Choose the smaller size of the two dimensions.
- if (MeasureSpec.getSize(widthMeasureSpec) > MeasureSpec.getSize(heightMeasureSpec)) {
- super.onMeasure(heightMeasureSpec, heightMeasureSpec);
- } else {
- super.onMeasure(widthMeasureSpec, widthMeasureSpec);
- }
- }
-}
diff --git a/tests/robotests/assets/grandfather_not_implementing_index_provider b/tests/robotests/assets/grandfather_not_implementing_index_provider
index 8ca65ff..d7e5585 100644
--- a/tests/robotests/assets/grandfather_not_implementing_index_provider
+++ b/tests/robotests/assets/grandfather_not_implementing_index_provider
@@ -75,6 +75,7 @@
com.android.settings.users.UserDetailsSettings
com.android.settings.vpn2.AppManagementFragment
com.android.settings.vpn2.VpnSettings
+com.android.settings.wallpaper.WallpaperTypeSettings
com.android.settings.wifi.calling.WifiCallingSettingsForSub
com.android.settings.wifi.ChangeWifiStateDetails
com.android.settings.wifi.details.WifiNetworkDetailsFragment
diff --git a/tests/robotests/res/values/themes.xml b/tests/robotests/res/values/themes.xml
index 41ace18..92edb17 100644
--- a/tests/robotests/res/values/themes.xml
+++ b/tests/robotests/res/values/themes.xml
@@ -23,7 +23,7 @@
<item name="android:textColorPrimary">@android:color/white</item>
<item name="switchBarMarginStart">@dimen/switchbar_subsettings_margin_start</item>
<item name="switchBarMarginEnd">@dimen/switchbar_subsettings_margin_end</item>
- <item name="switchBarBackgroundColor">@color/switch_bar_background</item>
+ <item name="switchBarBackgroundColor">?android:attr/textColorSecondary</item>
<item name="switchBarBackgroundActivatedColor">?android:attr/colorAccent</item>
<item name="switchBarRestrictionIcon">@drawable/ic_help</item>
</style>
diff --git a/tests/robotests/src/com/android/settings/SetupWizardUtilsTest.java b/tests/robotests/src/com/android/settings/SetupWizardUtilsTest.java
index f718a67..b965d78 100644
--- a/tests/robotests/src/com/android/settings/SetupWizardUtilsTest.java
+++ b/tests/robotests/src/com/android/settings/SetupWizardUtilsTest.java
@@ -31,24 +31,27 @@
@RunWith(RobolectricTestRunner.class)
public class SetupWizardUtilsTest {
+ private static final String EXTRA_IS_SETUP_FLOW = "isSetupFlow";
+ private static final String EXTRA_IS_FIRST_RUN = "firstRun";
+
@Test
public void testCopySetupExtras() {
Intent fromIntent = new Intent();
final String theme = "TEST_THEME";
fromIntent.putExtra(WizardManagerHelper.EXTRA_THEME, theme);
- fromIntent.putExtra(WizardManagerHelper.EXTRA_USE_IMMERSIVE_MODE, true);
+ fromIntent.putExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, true);
Intent toIntent = new Intent();
SetupWizardUtils.copySetupExtras(fromIntent, toIntent);
assertThat(theme).isEqualTo(toIntent.getStringExtra(WizardManagerHelper.EXTRA_THEME));
- assertThat(toIntent.getBooleanExtra(WizardManagerHelper.EXTRA_USE_IMMERSIVE_MODE, false))
+ assertThat(toIntent.getBooleanExtra(WizardManagerHelper.EXTRA_IS_SETUP_FLOW, false))
.isTrue();
}
@Test
public void testGetTheme_withIntentExtra_shouldReturnExtraTheme() {
SetupWizardProperties.theme(ThemeHelper.THEME_GLIF);
- Intent intent = new Intent();
+ Intent intent = createSetupWizardIntent();
intent.putExtra(WizardManagerHelper.EXTRA_THEME, ThemeHelper.THEME_GLIF_V2);
assertThat(SetupWizardUtils.getTheme(intent)).isEqualTo(R.style.GlifV2Theme);
@@ -57,7 +60,7 @@
@Test
public void testGetTheme_withEmptyIntent_shouldReturnSystemProperty() {
SetupWizardProperties.theme(ThemeHelper.THEME_GLIF_V2_LIGHT);
- Intent intent = new Intent();
+ Intent intent = createSetupWizardIntent();
assertThat(SetupWizardUtils.getTheme(intent)).isEqualTo(R.style.GlifV2Theme_Light);
}
@@ -65,10 +68,26 @@
@Test
public void testGetTheme_glifV3Light_shouldReturnThemeResource() {
SetupWizardProperties.theme(ThemeHelper.THEME_GLIF_V3_LIGHT);
- Intent intent = new Intent();
+ Intent intent = createSetupWizardIntent();
assertThat(SetupWizardUtils.getTheme(intent)).isEqualTo(R.style.GlifV3Theme_Light);
assertThat(SetupWizardUtils.getTransparentTheme(intent))
.isEqualTo(R.style.GlifV3Theme_Light_Transparent);
}
+
+ @Test
+ public void testGetTheme_nonSuw_shouldReturnDayNightTheme() {
+ SetupWizardProperties.theme(ThemeHelper.THEME_GLIF_V3_LIGHT);
+ Intent intent = new Intent();
+
+ assertThat(SetupWizardUtils.getTheme(intent)).isEqualTo(R.style.GlifV3Theme);
+ assertThat(SetupWizardUtils.getTransparentTheme(intent))
+ .isEqualTo(R.style.GlifV3Theme_Transparent);
+ }
+
+ private Intent createSetupWizardIntent() {
+ return new Intent()
+ .putExtra(EXTRA_IS_SETUP_FLOW, true)
+ .putExtra(EXTRA_IS_FIRST_RUN, true);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
index 8c53019..0cc9dc4 100644
--- a/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
+++ b/tests/robotests/src/com/android/settings/accessibility/AccessibilitySettingsTest.java
@@ -156,7 +156,7 @@
@Test
public void testDarkUIModePreferenceSummary_shouldUpdateSummary() {
- final ListPreference darkUIModePreference = new ListPreference(mContext);
+ final Preference darkUIModePreference = new Preference(mContext);
final DarkUIPreferenceController mController;
doReturn(darkUIModePreference).when(mSettings).findPreference(
DARK_UI_MODE_PREFERENCE);
diff --git a/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java
index 59aea3d..6d9430c 100644
--- a/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/applications/appinfo/AppButtonsPreferenceControllerTest.java
@@ -119,7 +119,6 @@
mController = spy(new AppButtonsPreferenceController(mSettingsActivity, mFragment,
mLifecycle, PACKAGE_NAME, mState, REQUEST_UNINSTALL, REQUEST_REMOVE_DEVICE_ADMIN));
- doReturn(false).when(mController).isFallbackPackage(anyString());
mAppEntry.info = mAppInfo;
mAppInfo.packageName = PACKAGE_NAME;
diff --git a/tests/robotests/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelperTest.java b/tests/robotests/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelperTest.java
index c01ef3f..ff3a36f 100644
--- a/tests/robotests/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelperTest.java
+++ b/tests/robotests/src/com/android/settings/enterprise/ActionDisabledByAdminDialogHelperTest.java
@@ -20,6 +20,11 @@
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
import android.app.Activity;
import android.app.admin.DevicePolicyManager;
@@ -33,6 +38,8 @@
import android.widget.FrameLayout;
import android.widget.TextView;
+import androidx.appcompat.app.AlertDialog;
+
import com.android.settings.R;
import com.android.settings.Settings;
import com.android.settings.applications.specialaccess.deviceadmin.DeviceAdminAdd;
@@ -179,5 +186,28 @@
mHelper.setAdminSupportDetails(mActivity, null, admin);
assertNull(admin.component);
}
-}
+ @Test
+ public void testMaybeSetLearnMoreButton() {
+ final UserManager userManager = RuntimeEnvironment.application.getSystemService(
+ UserManager.class);
+ final ShadowUserManager userManagerShadow = Shadow.extract(userManager);
+ final ComponentName component = new ComponentName("some.package.name",
+ "some.package.name.SomeClass");
+ mHelper.mEnforcedAdmin = new EnforcedAdmin(component, UserHandle.of(123));
+
+ // Set up for shadow call.
+ userManagerShadow.getSameProfileGroupIds().put(123, 0);
+
+ // Test that the button is shown when user IDs are in the same profile group
+ AlertDialog.Builder builder = mock(AlertDialog.Builder.class);
+ mHelper.maybeSetLearnMoreButton(builder);
+ verify(builder).setNeutralButton(anyInt(), any());
+
+ // Test that the button is not shown when user IDs are not in the same profile group
+ userManagerShadow.getSameProfileGroupIds().clear();
+ builder = mock(AlertDialog.Builder.class);
+ mHelper.maybeSetLearnMoreButton(builder);
+ verify(builder, never()).setNeutralButton(anyInt(), any());
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsControllerTest.java b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsControllerTest.java
index 6012dbb..8654a4e 100644
--- a/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsControllerTest.java
+++ b/tests/robotests/src/com/android/settings/fuelgauge/batterysaver/BatterySaverScheduleRadioButtonsControllerTest.java
@@ -7,6 +7,7 @@
import android.os.PowerManager;
import android.provider.Settings;
import android.provider.Settings.Global;
+import android.provider.Settings.Secure;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -54,4 +55,13 @@
assertThat(mController.getDefaultKey())
.isEqualTo(BatterySaverScheduleRadioButtonsController.KEY_NO_SCHEDULE);
}
+
+ @Test
+ public void setDefaultKey_any_defaultsToNoScheduleIfWarningNotSeen() {
+ Secure.putString(
+ mContext.getContentResolver(), Secure.LOW_POWER_WARNING_ACKNOWLEDGED, "null");
+ mController.setDefaultKey(BatterySaverScheduleRadioButtonsController.KEY_ROUTINE);
+ assertThat(mController.getDefaultKey())
+ .isEqualTo(BatterySaverScheduleRadioButtonsController.KEY_NO_SCHEDULE);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSliceTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSliceTest.java
index a744e68..12513f6 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSliceTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/NotificationChannelSliceTest.java
@@ -16,6 +16,7 @@
package com.android.settings.homepage.contextualcards.slices;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.app.slice.Slice.HINT_LIST_ITEM;
import static android.app.slice.SliceItem.FORMAT_SLICE;
@@ -116,7 +117,8 @@
public void getSlice_hasSuggestedApp_shouldHaveNotificationChannelTitle() {
addMockPackageToPackageManager(true /* isRecentlyInstalled */,
ApplicationInfo.FLAG_INSTALLED);
- mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */);
+ mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */,
+ false /* isChannelBlocked */);
final Slice slice = mNotificationChannelSlice.getSlice();
@@ -130,7 +132,8 @@
public void getSlice_hasSuggestedApp_shouldSortByNotificationSentCount() {
addMockPackageToPackageManager(true /* isRecentlyInstalled */,
ApplicationInfo.FLAG_INSTALLED);
- mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */);
+ mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */,
+ false /* isChannelBlocked */);
final Slice slice = mNotificationChannelSlice.getSlice();
@@ -157,7 +160,8 @@
public void getSlice_noRecentlyInstalledApp_shouldHaveNoSuggestedAppTitle() {
addMockPackageToPackageManager(false /* isRecentlyInstalled */,
ApplicationInfo.FLAG_INSTALLED);
- mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */);
+ mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */,
+ false /* isChannelBlocked */);
final Slice slice = mNotificationChannelSlice.getSlice();
@@ -169,7 +173,8 @@
public void getSlice_noMultiChannelApp_shouldHaveNoSuggestedAppTitle() {
addMockPackageToPackageManager(true /* isRecentlyInstalled */,
ApplicationInfo.FLAG_INSTALLED);
- mockNotificationBackend(1 /* channelCount */, NOTIFICATION_COUNT, false /* banned */);
+ mockNotificationBackend(1 /* channelCount */, NOTIFICATION_COUNT, false /* banned */,
+ false /* isChannelBlocked */);
final Slice slice = mNotificationChannelSlice.getSlice();
@@ -178,10 +183,12 @@
}
@Test
+ @Config(shadows = ShadowRestrictedLockUtilsInternal.class)
public void getSlice_insufficientNotificationSentCount_shouldHaveNoSuggestedAppTitle() {
addMockPackageToPackageManager(true /* isRecentlyInstalled */,
ApplicationInfo.FLAG_INSTALLED);
- mockNotificationBackend(CHANNEL_COUNT, 1 /* notificationCount */, false /* banned */);
+ mockNotificationBackend(CHANNEL_COUNT, 1 /* notificationCount */, false /* banned */,
+ false /* isChannelBlocked */);
final Slice slice = mNotificationChannelSlice.getSlice();
@@ -192,7 +199,8 @@
@Test
public void getSlice_isSystemApp_shouldHaveNoSuggestedAppTitle() {
addMockPackageToPackageManager(true /* isRecentlyInstalled */, ApplicationInfo.FLAG_SYSTEM);
- mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */);
+ mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */,
+ false /* isChannelBlocked */);
final Slice slice = mNotificationChannelSlice.getSlice();
@@ -204,7 +212,8 @@
public void getSlice_isNotificationBanned_shouldHaveNoSuggestedAppTitle() {
addMockPackageToPackageManager(true /* isRecentlyInstalled */,
ApplicationInfo.FLAG_INSTALLED);
- mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, true /* banned */);
+ mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, true /* banned */,
+ false /* isChannelBlocked */);
final Slice slice = mNotificationChannelSlice.getSlice();
@@ -218,7 +227,7 @@
addMockPackageToPackageManager(true /* isRecentlyInstalled */,
ApplicationInfo.FLAG_INSTALLED);
mockNotificationBackend(NotificationChannelSlice.DEFAULT_EXPANDED_ROW_COUNT * 2,
- NOTIFICATION_COUNT, false /* banned */);
+ NOTIFICATION_COUNT, false /* banned */, false /* isChannelBlocked */);
final Slice slice = mNotificationChannelSlice.getSlice();
@@ -234,7 +243,8 @@
public void getSlice_channelCountIsLessThanDefaultRows_subTitleShouldNotHaveTapToManagerAll() {
addMockPackageToPackageManager(true /* isRecentlyInstalled */,
ApplicationInfo.FLAG_INSTALLED);
- mockNotificationBackend(CHANNEL_COUNT - 1, NOTIFICATION_COUNT, false /* banned */);
+ mockNotificationBackend(CHANNEL_COUNT - 1, NOTIFICATION_COUNT, false /* banned */,
+ false /* isChannelBlocked */);
final Slice slice = mNotificationChannelSlice.getSlice();
@@ -249,7 +259,8 @@
public void getSlice_channelCountIsEqualToDefaultRows_subTitleShouldNotHaveTapToManagerAll() {
addMockPackageToPackageManager(true /* isRecentlyInstalled */,
ApplicationInfo.FLAG_INSTALLED);
- mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */);
+ mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */,
+ false /* isChannelBlocked */);
final Slice slice = mNotificationChannelSlice.getSlice();
@@ -263,7 +274,8 @@
public void getSlice_channelCountIsMoreThanDefaultRows_subTitleShouldHaveTapToManagerAll() {
addMockPackageToPackageManager(true /* isRecentlyInstalled */,
ApplicationInfo.FLAG_INSTALLED);
- mockNotificationBackend(CHANNEL_COUNT + 1, NOTIFICATION_COUNT, false /* banned */);
+ mockNotificationBackend(CHANNEL_COUNT + 1, NOTIFICATION_COUNT, false /* banned */,
+ false /* isChannelBlocked */);
final Slice slice = mNotificationChannelSlice.getSlice();
@@ -273,6 +285,20 @@
CHANNEL_COUNT + 1));
}
+ @Test
+ @Config(shadows = ShadowRestrictedLockUtilsInternal.class)
+ public void getSlice_isAllDisplayableChannelBlocked_shouldHaveNoSuggestedAppTitle() {
+ addMockPackageToPackageManager(true /* isRecentlyInstalled */,
+ ApplicationInfo.FLAG_INSTALLED);
+ mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */,
+ true /* isChannelBlocked */);
+
+ final Slice slice = mNotificationChannelSlice.getSlice();
+
+ final SliceMetadata metadata = SliceMetadata.from(mContext, slice);
+ assertThat(metadata.getTitle()).isEqualTo(mContext.getString(R.string.no_suggested_app));
+ }
+
private void addMockPackageToPackageManager(boolean isRecentlyInstalled, int flags) {
final ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.name = APP_LABEL;
@@ -294,8 +320,10 @@
return System.currentTimeMillis();
}
- private void mockNotificationBackend(int channelCount, int notificationCount, boolean banned) {
- final List<NotificationChannel> channels = buildNotificationChannel(channelCount);
+ private void mockNotificationBackend(int channelCount, int notificationCount, boolean banned,
+ boolean isChannelBlocked) {
+ final List<NotificationChannel> channels = buildNotificationChannel(channelCount,
+ isChannelBlocked);
final AppRow appRow = buildAppRow(channelCount, notificationCount, banned);
doReturn(buildNotificationChannelGroups(channels)).when(mNotificationBackend).getGroups(
@@ -308,6 +336,8 @@
private AppRow buildAppRow(int channelCount, int sentCount, boolean banned) {
final AppRow appRow = new AppRow();
+ appRow.pkg = PACKAGE_NAME;
+ appRow.uid = UID;
appRow.banned = banned;
appRow.channelCount = channelCount;
appRow.sentByApp = new NotificationsSentState();
@@ -317,11 +347,12 @@
return appRow;
}
- private List<NotificationChannel> buildNotificationChannel(int channelCount) {
+ private List<NotificationChannel> buildNotificationChannel(int channelCount,
+ boolean isChannelBlock) {
final List<NotificationChannel> channels = new ArrayList<>();
for (int i = 0; i < channelCount; i++) {
channels.add(new NotificationChannel(CHANNEL_NAME_PREFIX + i, CHANNEL_NAME_PREFIX + i,
- IMPORTANCE_NONE));
+ isChannelBlock ? IMPORTANCE_NONE : IMPORTANCE_LOW));
}
return channels;
@@ -369,4 +400,4 @@
// Index 0: title; Index 1: summary.
return rowSliceItems.get(1).getText();
}
-}
\ No newline at end of file
+}
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
index e08d845..706f238 100644
--- a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SliceContextualCardRendererTest.java
@@ -16,13 +16,11 @@
package com.android.settings.homepage.contextualcards.slices;
-import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_DEFERRED_SETUP;
import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_FULL_WIDTH;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.verify;
import android.app.Activity;
@@ -118,34 +116,25 @@
}
@Test
- public void longClick_shouldFlipCard() {
+ public void bindView_isPendingDismiss_shouldFlipToDismissalView() {
final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
- final View card = viewHolder.itemView.findViewById(R.id.slice_view);
final ViewFlipper viewFlipper = viewHolder.itemView.findViewById(R.id.view_flipper);
final View dismissalView = viewHolder.itemView.findViewById(R.id.dismissal_view);
- mRenderer.bindView(viewHolder, buildContextualCard(TEST_SLICE_URI));
+ final ContextualCard card = buildContextualCard(
+ TEST_SLICE_URI).mutate().setIsPendingDismiss(true).build();
- card.performLongClick();
+ mRenderer.bindView(viewHolder, card);
assertThat(viewFlipper.getCurrentView()).isEqualTo(dismissalView);
}
@Test
- public void longClick_deferredSetupCard_shouldNotBeClickable() {
- final RecyclerView.ViewHolder viewHolder = getDeferredSetupViewHolder();
- final View contentView = viewHolder.itemView.findViewById(R.id.content);
- mRenderer.bindView(viewHolder, buildContextualCard(TEST_SLICE_URI));
-
- assertThat(contentView.isLongClickable()).isFalse();
- }
-
- @Test
- public void longClick_shouldAddViewHolderToSet() {
+ public void bindView_isPendingDismiss_shouldAddViewHolderToSet() {
final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
- final View card = viewHolder.itemView.findViewById(R.id.slice_view);
- mRenderer.bindView(viewHolder, buildContextualCard(TEST_SLICE_URI));
+ final ContextualCard card = buildContextualCard(
+ TEST_SLICE_URI).mutate().setIsPendingDismiss(true).build();
- card.performLongClick();
+ mRenderer.bindView(viewHolder, card);
assertThat(mRenderer.mFlippedCardSet).contains(viewHolder);
}
@@ -153,12 +142,11 @@
@Test
public void viewClick_keepCard_shouldFlipBackToSlice() {
final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
- final View card = viewHolder.itemView.findViewById(R.id.slice_view);
final Button btnKeep = viewHolder.itemView.findViewById(R.id.keep);
final ViewFlipper viewFlipper = viewHolder.itemView.findViewById(R.id.view_flipper);
mRenderer.bindView(viewHolder, buildContextualCard(TEST_SLICE_URI));
+ viewFlipper.setDisplayedChild(1);
- card.performLongClick();
btnKeep.performClick();
assertThat(viewFlipper.getCurrentView()).isInstanceOf(SliceView.class);
@@ -167,11 +155,10 @@
@Test
public void viewClick_keepCard_shouldRemoveViewHolderFromSet() {
final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
- final View card = viewHolder.itemView.findViewById(R.id.slice_view);
final Button btnKeep = viewHolder.itemView.findViewById(R.id.keep);
mRenderer.bindView(viewHolder, buildContextualCard(TEST_SLICE_URI));
+ mRenderer.mFlippedCardSet.add(viewHolder);
- card.performLongClick();
btnKeep.performClick();
assertThat(mRenderer.mFlippedCardSet).doesNotContain(viewHolder);
@@ -180,14 +167,13 @@
@Test
public void viewClick_removeCard_shouldRemoveViewHolderFromSet() {
final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
- final View card = viewHolder.itemView.findViewById(R.id.slice_view);
final Button btnRemove = viewHolder.itemView.findViewById(R.id.remove);
final ContextualCard contextualCard = buildContextualCard(TEST_SLICE_URI);
mRenderer.bindView(viewHolder, contextualCard);
doReturn(mController).when(mControllerRendererPool).getController(mActivity,
ContextualCard.CardType.SLICE);
+ mRenderer.mFlippedCardSet.add(viewHolder);
- card.performLongClick();
btnRemove.performClick();
assertThat(mRenderer.mFlippedCardSet).doesNotContain(viewHolder);
@@ -196,7 +182,6 @@
@Test
public void viewClick_removeCard_sliceLiveDataShouldRemoveObservers() {
final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
- final View card = viewHolder.itemView.findViewById(R.id.slice_view);
final Button btnRemove = viewHolder.itemView.findViewById(R.id.remove);
final ContextualCard contextualCard = buildContextualCard(TEST_SLICE_URI);
mRenderer.mSliceLiveDataMap.put(TEST_SLICE_URI, mSliceLiveData);
@@ -204,7 +189,6 @@
doReturn(mController).when(mControllerRendererPool).getController(mActivity,
ContextualCard.CardType.SLICE);
- card.performLongClick();
btnRemove.performClick();
assertThat(mRenderer.mSliceLiveDataMap.get(TEST_SLICE_URI).hasObservers()).isFalse();
@@ -213,11 +197,11 @@
@Test
public void onStop_cardIsFlipped_shouldFlipBack() {
final RecyclerView.ViewHolder viewHolder = getSliceViewHolder();
- final View card = viewHolder.itemView.findViewById(R.id.slice_view);
final ViewFlipper viewFlipper = viewHolder.itemView.findViewById(R.id.view_flipper);
mRenderer.bindView(viewHolder, buildContextualCard(TEST_SLICE_URI));
+ viewFlipper.setDisplayedChild(1);
+ mRenderer.mFlippedCardSet.add(viewHolder);
- card.performLongClick();
mRenderer.onStop();
assertThat(viewFlipper.getCurrentView()).isInstanceOf(SliceView.class);
@@ -232,18 +216,6 @@
return mRenderer.createViewHolder(view, VIEW_TYPE_FULL_WIDTH);
}
- private RecyclerView.ViewHolder getDeferredSetupViewHolder() {
- final RecyclerView recyclerView = new RecyclerView(mActivity);
- recyclerView.setLayoutManager(new LinearLayoutManager(mActivity));
- final View view = LayoutInflater.from(mActivity).inflate(VIEW_TYPE_DEFERRED_SETUP,
- recyclerView, false);
- final RecyclerView.ViewHolder viewHolder = spy(
- mRenderer.createViewHolder(view, VIEW_TYPE_DEFERRED_SETUP));
- doReturn(VIEW_TYPE_DEFERRED_SETUP).when(viewHolder).getItemViewType();
-
- return viewHolder;
- }
-
private ContextualCard buildContextualCard(Uri sliceUri) {
return new ContextualCard.Builder()
.setName("test_name")
diff --git a/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SwipeDismissalDelegateTest.java b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SwipeDismissalDelegateTest.java
new file mode 100644
index 0000000..00b7815
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/homepage/contextualcards/slices/SwipeDismissalDelegateTest.java
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2019 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.homepage.contextualcards.slices;
+
+import static com.android.settings.homepage.contextualcards.slices.SliceContextualCardRenderer.VIEW_TYPE_DEFERRED_SETUP;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+import android.app.Activity;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ViewFlipper;
+
+import androidx.recyclerview.widget.LinearLayoutManager;
+import androidx.recyclerview.widget.RecyclerView;
+
+import com.android.settings.R;
+import com.android.settings.homepage.contextualcards.conditional.ConditionContextualCardRenderer;
+import com.android.settings.homepage.contextualcards.conditional.ConditionContextualCardRenderer.ConditionalCardHolder;
+import com.android.settings.homepage.contextualcards.slices.SliceDeferredSetupCardRendererHelper.DeferredSetupCardViewHolder;
+import com.android.settings.homepage.contextualcards.slices.SliceFullCardRendererHelper.SliceViewHolder;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.Robolectric;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.android.controller.ActivityController;
+
+@RunWith(RobolectricTestRunner.class)
+public class SwipeDismissalDelegateTest {
+
+ @Mock
+ private SwipeDismissalDelegate.Listener mDismissalDelegateListener;
+
+ private Activity mActivity;
+ private RecyclerView mRecyclerView;
+ private SwipeDismissalDelegate mDismissalDelegate;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ final ActivityController<Activity> activityController = Robolectric.buildActivity(
+ Activity.class);
+ mActivity = activityController.get();
+ mActivity.setTheme(R.style.Theme_Settings_Home);
+ activityController.create();
+ mRecyclerView = new RecyclerView(mActivity);
+ mRecyclerView.setLayoutManager(new LinearLayoutManager(mActivity));
+ mDismissalDelegate = new SwipeDismissalDelegate(mActivity, mDismissalDelegateListener);
+ }
+
+ @Test
+ public void getMovementFlags_conditionalViewHolder_shouldDisableSwipe() {
+ assertThat(mDismissalDelegate.getMovementFlags(mRecyclerView, getConditionalViewHolder()))
+ .isEqualTo(0);
+ }
+
+ @Test
+ public void getMovementFlags_deferredSetupViewHolder_shouldDisableSwipe() {
+ assertThat(mDismissalDelegate.getMovementFlags(mRecyclerView, getDeferredSetupViewHolder()))
+ .isEqualTo(0);
+ }
+
+ @Test
+ public void getMovementFlags_dismissalView_shouldDisableSwipe() {
+ final RecyclerView.ViewHolder holder = getSliceViewHolder();
+ final ViewFlipper viewFlipper = holder.itemView.findViewById(R.id.view_flipper);
+ viewFlipper.showNext();
+ final View dismissalView = holder.itemView.findViewById(R.id.dismissal_view);
+
+ assertThat(viewFlipper.getCurrentView()).isEqualTo(dismissalView);
+ assertThat(mDismissalDelegate.getMovementFlags(mRecyclerView, holder)).isEqualTo(0);
+ }
+
+ @Test
+ public void getMovementFlags_SliceViewHolder_shouldEnableSwipe() {
+ final RecyclerView.ViewHolder holder = getSliceViewHolder();
+ final ViewFlipper viewFlipper = holder.itemView.findViewById(R.id.view_flipper);
+ viewFlipper.setDisplayedChild(0);
+ final View sliceView = holder.itemView.findViewById(R.id.slice_view);
+
+ assertThat(viewFlipper.getCurrentView()).isEqualTo(sliceView);
+ assertThat(mDismissalDelegate.getMovementFlags(mRecyclerView, getSliceViewHolder()))
+ .isNotEqualTo(0);
+ }
+
+ @Test
+ public void onSwipe_shouldNotifyListener() {
+ mDismissalDelegate.onSwiped(getSliceViewHolder(), 1);
+
+ verify(mDismissalDelegateListener).onSwiped(anyInt());
+ }
+
+ private RecyclerView.ViewHolder getSliceViewHolder() {
+ final View view = LayoutInflater.from(mActivity)
+ .inflate(SliceContextualCardRenderer.VIEW_TYPE_FULL_WIDTH, mRecyclerView, false);
+ final RecyclerView.ViewHolder viewHolder = spy(new SliceViewHolder(view));
+ doReturn(SliceContextualCardRenderer.VIEW_TYPE_FULL_WIDTH).when(
+ viewHolder).getItemViewType();
+
+ return viewHolder;
+ }
+
+ private RecyclerView.ViewHolder getConditionalViewHolder() {
+ final View view = LayoutInflater.from(mActivity)
+ .inflate(ConditionContextualCardRenderer.VIEW_TYPE_FULL_WIDTH, mRecyclerView,
+ false);
+ final RecyclerView.ViewHolder viewHolder = spy(new ConditionalCardHolder(view));
+ doReturn(ConditionContextualCardRenderer.VIEW_TYPE_FULL_WIDTH).when(
+ viewHolder).getItemViewType();
+
+ return viewHolder;
+ }
+
+ private RecyclerView.ViewHolder getDeferredSetupViewHolder() {
+ final View view = LayoutInflater.from(mActivity)
+ .inflate(VIEW_TYPE_DEFERRED_SETUP, mRecyclerView, false);
+ final RecyclerView.ViewHolder viewHolder = spy(new DeferredSetupCardViewHolder(view));
+ doReturn(VIEW_TYPE_DEFERRED_SETUP).when(viewHolder).getItemViewType();
+
+ return viewHolder;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java b/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java
index d26a458..205f295 100644
--- a/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java
+++ b/tests/robotests/src/com/android/settings/media/MediaOutputSliceTest.java
@@ -30,6 +30,7 @@
import android.bluetooth.BluetoothAdapter;
import android.content.Context;
import android.content.Intent;
+import android.graphics.drawable.Drawable;
import androidx.slice.Slice;
import androidx.slice.SliceMetadata;
@@ -66,6 +67,8 @@
@Mock
private LocalMediaManager mLocalMediaManager;
+ @Mock
+ private Drawable mTestDrawable;
private final List<MediaDevice> mDevices = new ArrayList<>();
@@ -105,7 +108,7 @@
mDevices.clear();
final MediaDevice device = mock(MediaDevice.class);
when(device.getName()).thenReturn(TEST_DEVICE_1_NAME);
- when(device.getIcon()).thenReturn(TEST_DEVICE_1_ICON);
+ when(device.getIcon()).thenReturn(mTestDrawable);
when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(device);
final Slice mediaSlice = mMediaOutputSlice.getSlice();
diff --git a/tests/robotests/src/com/android/settings/notification/BubblePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/BubblePreferenceControllerTest.java
index 99787d8..6d13798 100644
--- a/tests/robotests/src/com/android/settings/notification/BubblePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/BubblePreferenceControllerTest.java
@@ -23,6 +23,7 @@
import static android.provider.Settings.Secure.NOTIFICATION_BUBBLES;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -223,6 +224,7 @@
@Test
public void testUpdateState_app() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+ appRow.label = "App!";
appRow.allowBubbles = true;
mController.onResume(appRow, null, null, null);
@@ -235,6 +237,9 @@
mController.updateState(pref);
assertFalse(pref.isChecked());
+
+ assertNotNull(pref.getSummary());
+ assertTrue(pref.getSummary().toString().contains(appRow.label));
}
@Test
diff --git a/tests/robotests/src/com/android/settings/notification/BubbleSummaryNotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/BubbleSummaryNotificationPreferenceControllerTest.java
new file mode 100644
index 0000000..4bdb2cc
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/BubbleSummaryNotificationPreferenceControllerTest.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2019 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.notification;
+
+import static android.provider.Settings.Secure.NOTIFICATION_BUBBLES;
+
+import static com.android.settings.notification.BadgingNotificationPreferenceController.OFF;
+import static com.android.settings.notification.BadgingNotificationPreferenceController.ON;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+import androidx.preference.Preference;
+
+@RunWith(RobolectricTestRunner.class)
+public class BubbleSummaryNotificationPreferenceControllerTest {
+
+ private Context mContext;
+
+ private BubbleSummaryNotificationPreferenceController mController;
+ private Preference mPreference;
+
+ private static final String KEY_NOTIFICATION_BUBBLES = "notification_bubbles";
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mController = new BubbleSummaryNotificationPreferenceController(mContext,
+ KEY_NOTIFICATION_BUBBLES);
+ mPreference = new Preference(RuntimeEnvironment.application);
+ }
+
+ @Test
+ public void display_shouldDisplay() {
+ assertThat(mPreference.isVisible()).isTrue();
+ }
+
+ @Test
+ public void getSummary() {
+ Settings.Secure.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, OFF);
+
+ assertThat(mController.getSummary()).isEqualTo("Off");
+
+ Settings.Secure.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, ON);
+
+ assertThat(mController.getSummary()).isEqualTo("On");
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/BubbleSummaryPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/BubbleSummaryPreferenceControllerTest.java
new file mode 100644
index 0000000..5158e82
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/BubbleSummaryPreferenceControllerTest.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2019 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.notification;
+
+import static android.app.NotificationChannel.DEFAULT_CHANNEL_ID;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+import static android.app.NotificationManager.IMPORTANCE_NONE;
+import static android.provider.Settings.Secure.NOTIFICATION_BUBBLES;
+
+import static junit.framework.TestCase.assertEquals;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.os.UserManager;
+import android.provider.Settings;
+
+import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedSwitchPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.shadows.ShadowApplication;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+@RunWith(RobolectricTestRunner.class)
+public class BubbleSummaryPreferenceControllerTest {
+
+ private Context mContext;
+ @Mock
+ private NotificationBackend mBackend;
+
+ private BubbleSummaryPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ mContext = RuntimeEnvironment.application;
+ mController = spy(new BubbleSummaryPreferenceController(mContext, mBackend));
+ }
+
+ @Test
+ public void testNoCrashIfNoOnResume() {
+ mController.isAvailable();
+ mController.updateState(mock(Preference.class));
+ }
+
+ @Test
+ public void testIsAvailable_notIfAppBlocked() {
+ NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+ appRow.banned = true;
+ mController.onResume(appRow, mock(NotificationChannel.class), null, null);
+ assertFalse(mController.isAvailable());
+ }
+
+ @Test
+ public void testIsAvailable_notIfOffGlobally() {
+ NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+ NotificationChannel channel = mock(NotificationChannel.class);
+ when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
+ mController.onResume(appRow, channel, null, null);
+ Settings.Secure.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 0);
+
+ assertFalse(mController.isAvailable());
+ }
+
+ @Test
+ public void testIsAvailable_app() {
+ NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+ mController.onResume(appRow, null, null, null);
+ Settings.Secure.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 1);
+
+ assertTrue(mController.isAvailable());
+ }
+
+ @Test
+ public void testIsAvailable_defaultChannel() {
+ NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+ appRow.allowBubbles = true;
+ NotificationChannel channel = mock(NotificationChannel.class);
+ when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
+ when(channel.getId()).thenReturn(DEFAULT_CHANNEL_ID);
+ mController.onResume(appRow, channel, null, null);
+ Settings.Secure.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, 1);
+
+ assertTrue(mController.isAvailable());
+ }
+
+ @Test
+ public void testUpdateState() {
+ NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+ appRow.allowBubbles = true;
+ mController.onResume(appRow, null, null, null);
+
+ Preference pref = new Preference(mContext);
+ mController.updateState(pref);
+ assertNotNull(pref.getIntent());
+ }
+
+ @Test
+ public void testGetSummary() {
+ NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+ appRow.allowBubbles = true;
+ mController.onResume(appRow, null, null, null);
+
+ assertEquals("On", mController.getSummary());
+
+ appRow.allowBubbles = false;
+ mController.onResume(appRow, null, null, null);
+
+ assertEquals("Off", mController.getSummary());
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/NotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/NotificationPreferenceControllerTest.java
index 2368af5..9c53a7b 100644
--- a/tests/robotests/src/com/android/settings/notification/NotificationPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/NotificationPreferenceControllerTest.java
@@ -318,6 +318,30 @@
}
@Test
+ public void testIsChannelBlockable_oemLocked() {
+ NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+ appRow.systemApp = false;
+ NotificationChannel channel = mock(NotificationChannel.class);
+ when(channel.isImportanceLockedByOEM()).thenReturn(true);
+ when(channel.getImportance()).thenReturn(IMPORTANCE_DEFAULT);
+
+ mController.onResume(appRow, channel, null, null);
+ assertFalse(mController.isChannelBlockable());
+ }
+
+ @Test
+ public void testIsChannelBlockable_criticalDeviceFunction() {
+ NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+ appRow.systemApp = false;
+ NotificationChannel channel = mock(NotificationChannel.class);
+ when(channel.isImportanceLockedByCriticalDeviceFunction()).thenReturn(true);
+ when(channel.getImportance()).thenReturn(IMPORTANCE_DEFAULT);
+
+ mController.onResume(appRow, channel, null, null);
+ assertFalse(mController.isChannelBlockable());
+ }
+
+ @Test
public void testIsChannelGroupBlockable_SystemNotBlockable() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.systemApp = true;
diff --git a/tests/robotests/src/com/android/settings/notification/SoundPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/SoundPreferenceControllerTest.java
index 1b4ede5..866f866 100644
--- a/tests/robotests/src/com/android/settings/notification/SoundPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/SoundPreferenceControllerTest.java
@@ -39,6 +39,8 @@
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
+import android.media.AudioAttributes;
+import android.media.RingtoneManager;
import android.net.Uri;
import android.os.UserManager;
import android.provider.Settings;
@@ -54,6 +56,7 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
@@ -231,6 +234,69 @@
}
@Test
+ public void testOnPreferenceTreeClick_alarmSound() {
+ NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+ NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
+ channel.setSound(null, new AudioAttributes.Builder().setUsage(
+ AudioAttributes.USAGE_ALARM).build());
+ mController.onResume(appRow, channel, null, null);
+
+ AttributeSet attributeSet = Robolectric.buildAttributeSet().build();
+ NotificationSoundPreference pref =
+ spy(new NotificationSoundPreference(mContext, attributeSet));
+ pref.setKey(mController.getPreferenceKey());
+ mController.handlePreferenceTreeClick(pref);
+
+ ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(pref, times(1)).onPrepareRingtonePickerIntent(intentArgumentCaptor.capture());
+ assertEquals(RingtoneManager.TYPE_ALARM,
+ intentArgumentCaptor.getValue().getIntExtra(
+ RingtoneManager.EXTRA_RINGTONE_TYPE, 0));
+ }
+
+ @Test
+ public void testOnPreferenceTreeClick_ringtoneSound() {
+ NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+ NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
+ channel.setSound(null, new AudioAttributes.Builder().setUsage(
+ AudioAttributes.USAGE_NOTIFICATION_RINGTONE).build());
+ mController.onResume(appRow, channel, null, null);
+
+ AttributeSet attributeSet = Robolectric.buildAttributeSet().build();
+ NotificationSoundPreference pref =
+ spy(new NotificationSoundPreference(mContext, attributeSet));
+ pref.setKey(mController.getPreferenceKey());
+ mController.handlePreferenceTreeClick(pref);
+
+ ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(pref, times(1)).onPrepareRingtonePickerIntent(intentArgumentCaptor.capture());
+ assertEquals(RingtoneManager.TYPE_RINGTONE,
+ intentArgumentCaptor.getValue().getIntExtra(
+ RingtoneManager.EXTRA_RINGTONE_TYPE, 0));
+ }
+
+ @Test
+ public void testOnPreferenceTreeClick_otherSound() {
+ NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+ NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
+ channel.setSound(null, new AudioAttributes.Builder().setUsage(
+ AudioAttributes.USAGE_UNKNOWN).build());
+ mController.onResume(appRow, channel, null, null);
+
+ AttributeSet attributeSet = Robolectric.buildAttributeSet().build();
+ NotificationSoundPreference pref =
+ spy(new NotificationSoundPreference(mContext, attributeSet));
+ pref.setKey(mController.getPreferenceKey());
+ mController.handlePreferenceTreeClick(pref);
+
+ ArgumentCaptor<Intent> intentArgumentCaptor = ArgumentCaptor.forClass(Intent.class);
+ verify(pref, times(1)).onPrepareRingtonePickerIntent(intentArgumentCaptor.capture());
+ assertEquals(RingtoneManager.TYPE_NOTIFICATION,
+ intentArgumentCaptor.getValue().getIntExtra(
+ RingtoneManager.EXTRA_RINGTONE_TYPE, 0));
+ }
+
+ @Test
public void testOnActivityResult() {
NotificationSoundPreference pref = mock(NotificationSoundPreference.class);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
diff --git a/tests/robotests/src/com/android/settings/privacy/PermissionBarChartPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/privacy/PermissionBarChartPreferenceControllerTest.java
index 332156e..9888168 100644
--- a/tests/robotests/src/com/android/settings/privacy/PermissionBarChartPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/privacy/PermissionBarChartPreferenceControllerTest.java
@@ -16,6 +16,14 @@
package com.android.settings.privacy;
+import static android.Manifest.permission_group.CALENDAR;
+import static android.Manifest.permission_group.CAMERA;
+import static android.Manifest.permission_group.CONTACTS;
+import static android.Manifest.permission_group.LOCATION;
+import static android.Manifest.permission_group.MICROPHONE;
+import static android.Manifest.permission_group.PHONE;
+import static android.Manifest.permission_group.SMS;
+
import static com.android.settings.core.BasePreferenceController.AVAILABLE_UNSEARCHABLE;
import static com.android.settings.core.BasePreferenceController.UNSUPPORTED_ON_DEVICE;
@@ -221,4 +229,27 @@
verify(mFragment).setLoadingEnabled(false /* enabled */);
verify(mPreference).updateLoadingState(false /* isLoading */);
}
+
+ @Test
+ public void onPermissionUsageResult_shouldBeSorted() {
+ final List<RuntimePermissionUsageInfo> infos = new ArrayList<>();
+ infos.add(new RuntimePermissionUsageInfo(PHONE, 10));
+ infos.add(new RuntimePermissionUsageInfo(LOCATION, 10));
+ infos.add(new RuntimePermissionUsageInfo(CAMERA, 10));
+ infos.add(new RuntimePermissionUsageInfo(SMS, 1));
+ infos.add(new RuntimePermissionUsageInfo(MICROPHONE, 10));
+ infos.add(new RuntimePermissionUsageInfo(CONTACTS, 42));
+ infos.add(new RuntimePermissionUsageInfo(CALENDAR, 10));
+ mController.displayPreference(mScreen);
+
+ mController.onPermissionUsageResult(infos);
+
+ assertThat(infos.get(0).getName()).isEqualTo(CONTACTS);
+ assertThat(infos.get(1).getName()).isEqualTo(LOCATION);
+ assertThat(infos.get(2).getName()).isEqualTo(MICROPHONE);
+ assertThat(infos.get(3).getName()).isEqualTo(CAMERA);
+ assertThat(infos.get(4).getName()).isEqualTo(CALENDAR);
+ assertThat(infos.get(5).getName()).isEqualTo(PHONE);
+ assertThat(infos.get(6).getName()).isEqualTo(SMS);
+ }
}
diff --git a/tests/robotests/src/com/android/settings/system/SystemDashboardFragmentTest.java b/tests/robotests/src/com/android/settings/system/SystemDashboardFragmentTest.java
index 75cd552..7bdc368 100644
--- a/tests/robotests/src/com/android/settings/system/SystemDashboardFragmentTest.java
+++ b/tests/robotests/src/com/android/settings/system/SystemDashboardFragmentTest.java
@@ -18,8 +18,17 @@
import static com.google.common.truth.Truth.assertThat;
-import android.content.Context;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import android.content.Context;
+import android.os.Bundle;
+
+import com.android.settings.aware.AwareFeatureProvider;
+import com.android.settings.testutils.FakeFeatureFactory;
import com.android.settings.testutils.XmlTestUtils;
import com.android.settings.testutils.shadow.SettingsShadowResources;
import com.android.settings.testutils.shadow.ShadowUserManager;
@@ -38,11 +47,17 @@
@Config(shadows = {SettingsShadowResources.class, ShadowUserManager.class})
public class SystemDashboardFragmentTest {
+ private Context mContext;
+ private SystemDashboardFragment mFragment;
+
@Before
public void setup() {
SettingsShadowResources.overrideResource(
com.android.internal.R.bool.config_supportSystemNavigationKeys, true);
ShadowUserManager.getShadow().setIsAdminUser(true);
+ mContext = RuntimeEnvironment.application;
+ mFragment = spy(new SystemDashboardFragment());
+ when(mFragment.getContext()).thenReturn(mContext);
}
@After
@@ -52,13 +67,35 @@
@Test
public void testNonIndexableKeys_existInXmlLayout() {
- final Context context = RuntimeEnvironment.application;
final List<String> niks = SystemDashboardFragment.SEARCH_INDEX_DATA_PROVIDER
- .getNonIndexableKeys(context);
+ .getNonIndexableKeys(mContext);
final int xmlId = (new SystemDashboardFragment()).getPreferenceScreenResId();
- final List<String> keys = XmlTestUtils.getKeysFromPreferenceXml(context, xmlId);
+ final List<String> keys = XmlTestUtils.getKeysFromPreferenceXml(mContext, xmlId);
assertThat(keys).containsAllIn(niks);
}
+
+ @Test
+ public void showRestrictionDialog_hasValidExtra_shouldShowDialog() {
+ final AwareFeatureProvider mProvider =
+ FakeFeatureFactory.setupForTest().mAwareFeatureProvider;
+ final Bundle bundle = new Bundle();
+ bundle.putBoolean(SystemDashboardFragment.EXTRA_SHOW_AWARE_DISABLED, true);
+ when(mFragment.getArguments()).thenReturn(bundle);
+
+ mFragment.showRestrictionDialog();
+
+ verify(mProvider).showRestrictionDialog(any());
+ }
+
+ @Test
+ public void showRestrictionDialog_hasInvalidExtra_shouldNotShowDialog() {
+ final AwareFeatureProvider mProvider =
+ FakeFeatureFactory.setupForTest().mAwareFeatureProvider;
+
+ mFragment.showRestrictionDialog();
+
+ verify(mProvider, never()).showRestrictionDialog(any());
+ }
}
diff --git a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
index bceba3c..a85fe10 100644
--- a/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
+++ b/tests/robotests/src/com/android/settings/testutils/shadow/ShadowUserManager.java
@@ -22,6 +22,8 @@
import android.os.UserManager;
import android.os.UserManager.EnforcingUser;
+import com.google.android.collect.Maps;
+
import org.robolectric.RuntimeEnvironment;
import org.robolectric.annotation.Implementation;
import org.robolectric.annotation.Implements;
@@ -48,6 +50,7 @@
private boolean mIsQuietModeEnabled = false;
private int[] profileIdsForUser = new int[0];
private boolean mUserSwitchEnabled;
+ private final Map<Integer, Integer> mSameProfileGroupIds = Maps.newHashMap();
public void addProfile(UserInfo userInfo) {
mUserProfileInfos.add(userInfo);
@@ -138,6 +141,18 @@
return sIsSupportsMultipleUsers;
}
+ @Implementation
+ protected boolean isSameProfileGroup(@UserIdInt int userId, int otherUserId) {
+ return mSameProfileGroupIds.containsKey(userId)
+ && mSameProfileGroupIds.get(userId) == otherUserId
+ || mSameProfileGroupIds.containsKey(otherUserId)
+ && mSameProfileGroupIds.get(otherUserId) == userId;
+ }
+
+ public Map<Integer, Integer> getSameProfileGroupIds() {
+ return mSameProfileGroupIds;
+ }
+
public void setSupportsMultipleUsers(boolean supports) {
sIsSupportsMultipleUsers = supports;
}
diff --git a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
index 0a565cd..f177b5e 100644
--- a/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/details/WifiDetailPreferenceControllerTest.java
@@ -105,6 +105,7 @@
private static final int RSSI = -55;
private static final int TX_LINK_SPEED = 123;
private static final int RX_LINK_SPEED = 54;
+ private static final String SSID = "ssid";
private static final String MAC_ADDRESS = WifiInfo.DEFAULT_MAC_ADDRESS;
private static final String SECURITY = "None";
@@ -154,6 +155,8 @@
@Mock
private Preference mockSecurityPref;
@Mock
+ private Preference mockSsidPref;
+ @Mock
private Preference mockMacAddressPref;
@Mock
private Preference mockIpAddressPref;
@@ -245,6 +248,7 @@
when(mockAccessPoint.getConfig()).thenReturn(mockWifiConfig);
when(mockAccessPoint.getLevel()).thenReturn(LEVEL);
when(mockAccessPoint.getSecurityString(false)).thenReturn(SECURITY);
+ when(mockAccessPoint.getSsidStr()).thenReturn(SSID);
when(mockConnectivityManager.getNetworkInfo(any(Network.class)))
.thenReturn(mockNetworkInfo);
doNothing().when(mockConnectivityManager).registerNetworkCallback(
@@ -314,6 +318,8 @@
.thenReturn(mockFrequencyPref);
when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_SECURITY_PREF))
.thenReturn(mockSecurityPref);
+ when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_SSID_PREF))
+ .thenReturn(mockSsidPref);
when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_MAC_ADDRESS_PREF))
.thenReturn(mockMacAddressPref);
when(mockScreen.findPreference(WifiDetailPreferenceController.KEY_IP_ADDRESS_PREF))
@@ -463,6 +469,50 @@
}
@Test
+ public void ssidPref_shouldHaveDetailTextSet() {
+ when(mockAccessPoint.isPasspoint()).thenReturn(true);
+ when(mockAccessPoint.isOsuProvider()).thenReturn(false);
+
+ displayAndResume();
+
+ verify(mockSsidPref, times(1)).setSummary(SSID);
+
+ when(mockAccessPoint.isPasspoint()).thenReturn(false);
+ when(mockAccessPoint.isOsuProvider()).thenReturn(true);
+
+ displayAndResume();
+
+ verify(mockSsidPref, times(2)).setSummary(SSID);
+ }
+
+ @Test
+ public void ssidPref_shouldShowIfPasspointOrOsu() {
+ when(mockAccessPoint.isPasspoint()).thenReturn(true);
+ when(mockAccessPoint.isOsuProvider()).thenReturn(false);
+
+ displayAndResume();
+
+ verify(mockSsidPref, times(1)).setVisible(true);
+
+ when(mockAccessPoint.isPasspoint()).thenReturn(false);
+ when(mockAccessPoint.isOsuProvider()).thenReturn(true);
+
+ displayAndResume();
+
+ verify(mockSsidPref, times(2)).setVisible(true);
+ }
+
+ @Test
+ public void ssidPref_shouldNotShowIfNotPasspoint() {
+ when(mockAccessPoint.isPasspoint()).thenReturn(false);
+ when(mockAccessPoint.isOsuProvider()).thenReturn(false);
+
+ displayAndResume();
+
+ verify(mockSsidPref).setVisible(false);
+ }
+
+ @Test
public void macAddressPref_shouldHaveDetailTextSet() {
displayAndResume();
diff --git a/tests/robotests/src/com/android/settings/wifi/details/WifiPrivacyPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/wifi/details/WifiPrivacyPreferenceControllerTest.java
index a1af8bf..2e588b5 100644
--- a/tests/robotests/src/com/android/settings/wifi/details/WifiPrivacyPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/wifi/details/WifiPrivacyPreferenceControllerTest.java
@@ -109,4 +109,20 @@
assertThat(mDropDownPreference.isSelectable()).isFalse();
}
+
+ @Test
+ public void testUpdateState_isNotPasspointNetwork_shouldBeSelectable() {
+ mPreferenceController.setIsPasspoint(false);
+ mPreferenceController.updateState(mDropDownPreference);
+
+ assertThat(mDropDownPreference.isSelectable()).isTrue();
+ }
+
+ @Test
+ public void testUpdateState_isPasspointNetwork_shouldNotSelectable() {
+ mPreferenceController.setIsPasspoint(true);
+ mPreferenceController.updateState(mDropDownPreference);
+
+ assertThat(mDropDownPreference.isSelectable()).isFalse();
+ }
}