Merge "Move strings related to user creation to SettingsLib." into rvc-dev
diff --git a/res/layout/notif_priority_conversation_preference.xml b/res/layout/notif_priority_conversation_preference.xml
new file mode 100644
index 0000000..981cd69
--- /dev/null
+++ b/res/layout/notif_priority_conversation_preference.xml
@@ -0,0 +1,158 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+ -->
+
+<LinearLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:id="@+id/app_entities_header"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:padding="@dimen/notification_importance_toggle_marginTop"
+ android:orientation="vertical">
+
+ <com.android.settings.notification.NotificationButtonRelativeLayout
+ android:id="@+id/priority_group"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="@dimen/notification_importance_button_padding"
+ android:clickable="true"
+ android:focusable="true">
+ <ImageView
+ android:id="@+id/priority_icon"
+ android:src="@drawable/ic_important_outline"
+ android:background="@android:color/transparent"
+ android:layout_gravity="center"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:clickable="false"
+ android:focusable="false"/>
+ <TextView
+ android:id="@+id/priority_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ellipsize="end"
+ android:maxLines="1"
+ android:clickable="false"
+ android:focusable="false"
+ android:layout_toEndOf="@id/priority_icon"
+ android:layout_marginStart="@dimen/notification_importance_drawable_padding"
+ android:textAppearance="@style/TextAppearance.NotificationImportanceButton.Unselected"
+ android:text="@string/notification_priority_title"/>
+ <TextView
+ android:id="@+id/priority_summary"
+ android:paddingTop="@dimen/notification_importance_button_padding"
+ android:text="@string/notification_channel_summary_priority"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:clickable="false"
+ android:focusable="false"
+ android:ellipsize="end"
+ android:maxLines="2"
+ android:layout_below="@id/priority_icon"
+ android:textAppearance="@style/TextAppearance.NotificationImportanceDetail"
+ android:visibility="gone" />
+ </com.android.settings.notification.NotificationButtonRelativeLayout>
+
+ <com.android.settings.notification.NotificationButtonRelativeLayout
+ android:id="@+id/alert"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="@dimen/notification_importance_button_padding"
+ android:layout_marginTop="@dimen/notification_importance_button_separation"
+ android:clickable="true"
+ android:focusable="true">
+ <ImageView
+ android:id="@+id/alert_icon"
+ android:src="@drawable/ic_notifications_alert"
+ android:background="@android:color/transparent"
+ android:layout_gravity="center"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:clickable="false"
+ android:focusable="false"/>
+ <TextView
+ android:id="@+id/alert_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ellipsize="end"
+ android:maxLines="1"
+ android:clickable="false"
+ android:focusable="false"
+ android:layout_toEndOf="@id/alert_icon"
+ android:layout_marginStart="@dimen/notification_importance_drawable_padding"
+ android:textAppearance="@style/TextAppearance.NotificationImportanceButton.Unselected"
+ android:text="@string/notification_alert_title"/>
+ <TextView
+ android:id="@+id/alert_summary"
+ android:paddingTop="@dimen/notification_importance_button_padding"
+ android:text="@string/notification_channel_summary_default"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:clickable="false"
+ android:focusable="false"
+ android:ellipsize="end"
+ android:maxLines="2"
+ android:layout_below="@id/alert_icon"
+ android:textAppearance="@style/TextAppearance.NotificationImportanceDetail"
+ android:visibility="gone" />
+ </com.android.settings.notification.NotificationButtonRelativeLayout>
+
+ <com.android.settings.notification.NotificationButtonRelativeLayout
+ android:id="@+id/silence"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:padding="@dimen/notification_importance_button_padding"
+ android:layout_marginTop="@dimen/notification_importance_button_separation"
+ android:clickable="true"
+ android:focusable="true">
+ <ImageView
+ android:id="@+id/silence_icon"
+ android:src="@drawable/ic_notifications_off_24dp"
+ android:background="@android:color/transparent"
+ android:layout_gravity="center"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:clickable="false"
+ android:focusable="false"/>
+ <TextView
+ android:id="@+id/silence_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ellipsize="end"
+ android:maxLines="1"
+ android:clickable="false"
+ android:focusable="false"
+ android:layout_toEndOf="@id/silence_icon"
+ android:layout_marginStart="@dimen/notification_importance_drawable_padding"
+ android:textAppearance="@style/TextAppearance.NotificationImportanceButton.Unselected"
+ android:text="@string/notification_silence_title"/>
+ <TextView
+ android:id="@+id/silence_summary"
+ android:paddingTop="@dimen/notification_importance_button_padding"
+ android:text="@string/notification_channel_summary_low"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:clickable="false"
+ android:focusable="false"
+ android:ellipsize="end"
+ android:maxLines="2"
+ android:layout_below="@id/silence_icon"
+ android:textAppearance="@style/TextAppearance.NotificationImportanceDetail"
+ android:visibility="gone" />
+ </com.android.settings.notification.NotificationButtonRelativeLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/layout/zen_mode_settings_button.xml b/res/layout/zen_mode_settings_button.xml
index 49aa287..72731cc 100644
--- a/res/layout/zen_mode_settings_button.xml
+++ b/res/layout/zen_mode_settings_button.xml
@@ -39,7 +39,6 @@
android:layout_height="wrap_content"
android:layout_gravity="left"
android:gravity="center"
- android:paddingTop="@dimen/zen_mode_button_padding_vertical"
android:text="@string/zen_mode_button_turn_on"/>
<Button
@@ -51,7 +50,6 @@
android:layout_height="wrap_content"
android:layout_gravity="left"
android:gravity="center"
- android:paddingTop="@dimen/zen_mode_button_padding_vertical"
android:text="@string/zen_mode_button_turn_off" />
</LinearLayout>
\ No newline at end of file
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 7dfe2d1..a5bbfa7 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -2186,8 +2186,6 @@
<string name="wifi_connected_to_message">@string/bluetooth_connected_summary</string>
<!-- Button label to connecting progress to a Wi-Fi network [CHAR LIMIT=20] -->
<string name="wifi_connecting">Connecting\u2026</string>
- <!-- Button label to disconnect to a Wi-Fi network [CHAR LIMIT=NONE] -->
- <string name="wifi_disconnect">@string/bluetooth_device_context_disconnect</string>
<!-- Failured notification for connect -->
<string name="wifi_failed_connect_message">Failed to connect to network</string>
<!-- Not in range notification for connect [CHAR LIMIT=40] -->
@@ -7725,13 +7723,13 @@
<!-- Setting summary for controlling how caption text display in real time [CHAR LIMIT=NONE]-->
<string name="live_caption_summary">Automatically caption media</string>
- <!-- Sound: Summary for the Do not Disturb option when there is no automatic rules turned on. [CHAR LIMIT=NONE]-->
- <string name="zen_mode_settings_summary_off">Never</string>
+ <!-- Sound: Summary for the Do not Disturb option when there are no automatic rules enabled. [CHAR LIMIT=NONE]-->
+ <string name="zen_mode_settings_summary_off">None</string>
- <!-- Sound: Summary for the Do not Disturb option when at least one automatic rules turned on. [CHAR LIMIT=NONE]-->
+ <!-- Sound: Summary for the Do not Disturb option when at least one automatic rule is enabled. [CHAR LIMIT=NONE]-->
<plurals name="zen_mode_settings_summary_on">
- <item quantity="one">1 enabled</item>
- <item quantity="other"><xliff:g id="on_count" example="10">%d</xliff:g> enabled</item>
+ <item quantity="one">1 schedule set</item>
+ <item quantity="other"><xliff:g id="on_count" example="10">%d</xliff:g> schedules set</item>
</plurals>
<!-- Sound: Title for the Do not Disturb option and associated settings page. [CHAR LIMIT=50]-->
@@ -7746,26 +7744,8 @@
<!-- Do not disturb: Title for the Do not Disturb dialog to turn on Do not disturb. [CHAR LIMIT=50]-->
<string name="zen_mode_settings_turn_on_dialog_title">Turn on Do Not Disturb</string>
- <!-- Do not disturb: Title for the page describing what can bypass DND. [CHAR LIMIT=30] -->
- <string name="zen_mode_behavior_settings_title">Exceptions</string>
-
- <!-- Do not disturb: Title for the dnd duration setting (user can specify how long dnd will last when toggling dnd on from qs or settings) [CHAR LIMIT=30] -->
- <string name="zen_mode_duration_settings_title">Default duration</string>
-
- <!-- Do not disturb: Instructions indicating what types of sounds can bypass DND. [CHAR LIMIT=52] -->
- <string name="zen_mode_behavior_allow_title">Allow sounds and vibrations from</string>
-
- <!-- Do not disturb: Subtitle for DND behavior indicating no sound will get past DND. [CHAR LIMIT=30] -->
- <string name="zen_mode_behavior_no_sound">No sound</string>
-
- <!-- Do not disturb: Subtitle for DND behavior indicating no sound will get past DND. [CHAR LIMIT=40] -->
- <string name="zen_mode_behavior_total_silence">Total Silence</string>
-
- <!-- Do not disturb: Used before specifying which sounds can bypass DND (ie: No sound except alarms and reminders). [CHAR LIMIT=40] -->
- <string name="zen_mode_behavior_no_sound_except">No sound except <xliff:g id="categories" example="alarms, media and system feedback">%1$s</xliff:g></string>
-
<!-- Do not disturb: Specifies alarms and media can bypass DND. [CHAR LIMIT=100] -->
- <string name="zen_mode_behavior_alarms_only">No sound except alarms and media</string>
+ <string name="zen_mode_behavior_alarms_only">Alarms and media sounds can interrupt</string>
<!-- Do not disturb: Title for the zen mode automation option in Settings. [CHAR LIMIT=40] -->
<string name="zen_mode_automation_settings_title">Schedules</string>
@@ -7800,29 +7780,20 @@
<!-- Do not disturb: Switch toggle to toggle whether to use an automatic dnd rule or not [CHAR LIMIT=40] -->
<string name="zen_mode_use_automatic_rule">Use schedule</string>
- <!-- Do not disturb: Zen mode option: Important interruptions [CHAR LIMIT=60] -->
- <string name="zen_mode_option_important_interruptions">Priority only</string>
-
- <!-- Do not disturb: Zen mode option: Alarms only [CHAR LIMIT=60] -->
- <string name="zen_mode_option_alarms">Alarms only</string>
-
- <!-- Do not disturb: Zen mode option: No interruptions [CHAR LIMIT=60] -->
- <string name="zen_mode_option_no_interruptions">Total silence</string>
-
<!-- Do not disturb: Zen mode combined summary + condition line [CHAR LIMIT=60] -->
<string name="zen_mode_summary_combination"><xliff:g id="mode" example="Priority only">%1$s</xliff:g>: <xliff:g id="exit condition" example="Until you turn this off">%2$s</xliff:g></string>
+ <!-- Do not disturb: zen settings screens category title [CHAR LIMIT=100] -->
+ <string name="zen_mode_settings_category">Allow interruptions that make sound</string>
+
<!-- Do not disturb: Title for the Visual interruptions option and associated settings page. [CHAR LIMIT=30] -->
<string name="zen_mode_visual_interruptions_settings_title">Block visual disturbances</string>
<!-- Do not disturb: Subtitle for the Visual signals option to toggle on/off visual signals/alerts when the screen is on/when screen is off. [CHAR LIMIT=30] -->
<string name="zen_mode_visual_signals_settings_subtitle">Allow visual signals</string>
- <!-- Do not disturb: zen settings screens category title [CHAR LIMIT=100] -->
- <string name="zen_mode_settings_category">Allow interruptions that make sound</string>
-
- <!-- Do not disturb: restrict notifications title [CHAR LIMIT=80] -->
- <string name="zen_mode_restrict_notifications_title">Restrict notifications</string>
+ <!-- Do not disturb: restrict notifications settings title [CHAR LIMIT=80] -->
+ <string name="zen_mode_restrict_notifications_title">Display options for hidden notifications</string>
<!-- Do not disturb: Mute notifications option [CHAR LIMIT=60] -->
<string name="zen_mode_restrict_notifications_mute">No sound from notifications</string>
<!-- Do not disturb:Mute notifications summary [CHAR LIMIT=NONE] -->
@@ -7961,7 +7932,7 @@
</plurals>
<!-- Do not disturb settings, main screen, category header [CHAR LIMIT=120]-->
- <string name="zen_category_behavior">Exceptions when Do Not Disturb is on</string>
+ <string name="zen_category_behavior">What can interrupt Do Not Disturb</string>
<!-- Do not disturb settings, main screen, field, dnd breakthrough [CHAR LIMIT=100]-->
<string name="zen_category_people">People</string>
<!-- Do not disturb settings, main screen, field, dnd breakthrough [CHAR LIMIT=100]-->
@@ -7970,23 +7941,12 @@
<string name="zen_category_exceptions">Alarms & other interruptions</string>
<!-- Do not disturb settings, main screen, field, schedules [CHAR LIMIT=100]-->
<string name="zen_category_schedule">Schedules</string>
- <!-- Do not disturb settings, main screen, field, dnd visuals [CHAR LIMIT=100]-->
- <string name="zen_category_visuals">Silenced notifications</string>
+ <!-- Do not disturb settings, main screen, field, duration setting where user can specify how
+ long dnd will last when toggling dnd on from qs or settings) [CHAR LIMIT=100] -->
+ <string name="zen_category_duration">Set duration for Quick Settings</string>
<!-- Do not disturb settings, sound and vibrations screen footer [CHAR LIMIT=NONE]-->
<string name="zen_sound_footer">When Do Not Disturb is on, sound and vibration will be muted, except for the items you allow above.</string>
- <!-- Do not disturb settings, sound and vibrations screen category [CHAR LIMIT=100]-->
- <string name="zen_sound_category_title">Mute all except</string>
- <!-- Do not disturb settings, sound and vibrations summary [CHAR LIMIT=100]-->
- <string name="zen_sound_all_muted">Muted</string>
- <!-- Do not disturb settings, sound and vibrations summary [CHAR LIMIT=100]-->
- <string name="zen_sound_none_muted">Not muted</string>
- <!-- Do not disturb settings, sound and vibrations summary [CHAR LIMIT=100]-->
- <string name="zen_sound_one_allowed">Muted, but allow <xliff:g id="sound_type" example="alarms">%1$s</xliff:g></string>
- <!-- Do not disturb settings, sound and vibrations summary [CHAR LIMIT=100]-->
- <string name="zen_sound_two_allowed">Muted, but allow <xliff:g id="sound_type" example="alarms">%1$s</xliff:g> and <xliff:g id="sound_type" example="media">%2$s</xliff:g></string>
- <!-- Do not disturb settings, sound and vibrations summary [CHAR LIMIT=100]-->
- <string name="zen_sound_three_allowed">Muted, but allow <xliff:g id="sound_type" example="alarms">%1$s</xliff:g>, <xliff:g id="sound_type" example="alarms">%2$s</xliff:g>, and <xliff:g id="sound_type" example="media">%3$s</xliff:g></string>
<!-- Do not disturb custom settings dialog title [CHAR LIMIT=40]-->
<string name="zen_custom_settings_dialog_title">Custom settings</string>
@@ -8158,11 +8118,11 @@
<!-- Description for the toggle shown on the app-level bubbles page [CHAR LIMIT=NONE] -->
<string name="bubbles_app_toggle_summary">Allow <xliff:g id="app_name" example="YouTube">%1$s</xliff:g> to show some notifications as bubbles</string>
<!-- Title of the dialog shown when the user has disabled bubbles at the feature level but tries to enable it for an app. [CHAR LIMIT=NONE] -->
- <string name="bubbles_feature_disabled_dialog_title">Turn on bubbles</string>
+ <string name="bubbles_feature_disabled_dialog_title">Turn on bubbles for device?</string>
<!-- Description of the dialog shown when the user has disabled bubbles at the feature level but tries to enable it for an app. [CHAR LIMIT=NONE] -->
- <string name="bubbles_feature_disabled_dialog_text">To turn on bubbles for this app, first you need to turn them on for your device. This affects other apps in which you previously turned on bubbles.</string>
+ <string name="bubbles_feature_disabled_dialog_text">Turning on bubbles for this app will also turn on bubbles for your device.\n\nThis affects other apps or conversations that are allowed to bubble.</string>
<!-- Button of the dialog shown when the user has disabled bubbles at the feature level but tries to enable it for an app. [CHAR LIMIT=60]-->
- <string name="bubbles_feature_disabled_button_approve">Turn on for device</string>
+ <string name="bubbles_feature_disabled_button_approve">Turn on</string>
<!-- Button to cancel out of the dialog shown when the user has disabled bubbles at the feature level but tries to enable it for an app. [CHAR LIMIT=60] -->
<string name="bubbles_feature_disabled_button_cancel">Cancel</string>
@@ -8181,8 +8141,8 @@
<string name="bubble_app_setting_none">Nothing can bubble</string>
<!-- Bubble app settings: Title above a list of conversations that have been selected to bubble [CHAR LIMIT=60]-->
<string name="bubble_app_setting_selected_conversation_title">Conversations</string>
- <!-- Bubble app settings: Title above a list of conversations that have been excluded from bubbling [CHAR LIMIT=60] -->
- <string name="bubble_app_setting_excluded_conversation_title">Excluded</string>
+ <!-- Bubble app settings: Title above a list of conversations that have been excluded from bubbling [CHAR LIMIT=100] -->
+ <string name="bubble_app_setting_excluded_conversation_title">All conversations can bubble except</string>
<!-- Configure notifications: title for swipe direction [CHAR LIMIT=60] -->
<string name="swipe_direction_title">Swipe actions</string>
@@ -8412,6 +8372,12 @@
<!-- [CHAR LIMIT=180] Notification importance description. More details from allow_interruption string - specifics of how notifications may interrupt. -->
<string name="allow_interruption_summary">Let the app make sound, vibrate, and/or pop notifications on screen</string>
+ <!-- [CHAR LIMIT=150] Notification Importance title: important conversation level -->
+ <string name="notification_priority_title">Priority</string>
+
+ <!-- [CHAR LIMIT=150] Notification Importance title: important conversation level summary -->
+ <string name="notification_channel_summary_priority">Shows at top of conversation section and appears as a bubble.</string>
+
<!-- Channel summaries for the app notification page -->
<!-- [CHAR LIMIT=150] Notification Importance title: min importance level summary -->
@@ -8889,156 +8855,174 @@
<!-- [CHAR LIMIT=40] General template for a verbal start to end range in a text summary -->
<string name="summary_range_verbal_combination"><xliff:g id="start" example="Sun">%1$s</xliff:g> to <xliff:g id="end" example="Thu">%2$s</xliff:g></string>
- <!-- [CHAR LIMIT=20] Zen mode settings: Calls option -->
- <string name="zen_mode_calls">Allow calls</string>
+ <!-- [CHAR LIMIT=120] Zen mode settings: Title for conversations settings page -->
+ <string name="zen_mode_conversations_title">Conversations</string>
+ <!-- [CHAR LIMIT=120] Zen mode settings: Header for conversations settings page -->
+ <string name="zen_mode_conversations_section_title">Conversations that can interrupt</string>
+ <string name="zen_mode_from_all_conversations">All conversations</string>
+ <string name="zen_mode_from_important_conversations">Important conversations</string>
+ <string name="zen_mode_from_no_conversations">None</string>
+ <plurals name="zen_mode_conversations_count">
+ <item quantity="one">1 conversation</item>
+ <item quantity="other"><xliff:g id="conversations" example="3">%d</xliff:g> conversations</item>
+ </plurals>
+ <!-- [CHAR LIMIT=40] Zen mode settings: No conversations are allowed to bypass DND -->
+ <string name="zen_mode_conversations_count_none">None</string>
+ <!-- [CHAR LIMIT=120] Zen mode settings: Header for calls and messages section of conversations
+ setting page -->
+ <string name="zen_mode_people_calls_messages_section_title">Who can interrupt</string>
<!-- [CHAR LIMIT=40] Zen mode settings: Allow calls toggle title -->
<string name="zen_mode_calls_title">Calls</string>
-
+ <!-- [CHAR LIMIT=20] Zen mode settings: Calls option -->
+ <string name="zen_mode_calls">Calls</string>
+ <!-- [CHAR LIMIT=20] Zen mode settings: Calls option -->
+ <string name="zen_mode_calls_list">calls</string>
+ <!-- [CHAR LIMIT=120] Zen mode settings: Calls settings header -->
+ <string name="zen_mode_calls_header">Calls that can interrupt</string>
<!-- [CHAR LIMIT=NONE] Zen mode settings: Calls screen footer -->
<string name="zen_mode_calls_footer">To be sure allowed calls make sound, check whether your device is set to ring, vibrate, or silent.</string>
-
<!-- [CHAR LIMIT=NONE] Zen mode custom rule settings: Calls screen footer -->
<string name="zen_mode_custom_calls_footer">For \u2018<xliff:g id="schedule_name" example="Schedule 1">%1$s</xliff:g>\u2019 incoming calls are blocked. You can adjust settings to allow your friends, family, or other contacts to reach you.</string>
<!-- [CHAR LIMIT=50] Zen mode settings: Starred contacts preference title -->
<string name="zen_mode_starred_contacts_title">Starred contacts</string>
-
<!-- Zen mode settings: Starred contacts summary [CHAR LIMIT=NONE] -->
<plurals name="zen_mode_starred_contacts_summary_additional_contacts">
<item quantity="one">1 other</item>
<item quantity="other"><xliff:g id="num_people" example="3">%d</xliff:g> others</item>
</plurals>
- <string name="zen_mode_conversations_title">Conversations</string>
- <string name="zen_mode_from_all_conversations">From all conversations</string>
- <string name="zen_mode_from_important_conversations">From important conversations</string>
- <string name="zen_mode_from_no_conversations">Don\u2019t allow any conversations</string>
-
<!-- [CHAR LIMIT=40] Zen mode settings: Messages option -->
- <string name="zen_mode_messages">Allow messages</string>
-
+ <string name="zen_mode_messages">Messages</string>
+ <!-- [CHAR LIMIT=40] Zen mode settings: Messages option -->
+ <string name="zen_mode_messages_list">messages</string>
+ <!-- [CHAR LIMIT=40] Zen mode settings: Allow messages to bypass DND title -->
+ <string name="zen_mode_messages_title">SMS, MMS, and messaging apps</string>
+ <!-- [CHAR LIMIT=120] Zen mode settings: Messages settings header -->
+ <string name="zen_mode_messages_header">Messages that can interrupt</string>
<!-- Do not disturb settings, messages, events and reminders footer [CHAR LIMIT=NONE]-->
<string name="zen_mode_messages_footer">To be sure allowed messages make sound, check whether your device is set to ring, vibrate, or silent.</string>
-
<!-- [CHAR LIMIT=NONE] Zen mode custom rule settings: Messages screen footer -->
<string name="zen_mode_custom_messages_footer">For \u2018<xliff:g id="schedule_name" example="Schedule 1">%1$s</xliff:g>\u2019 incoming messages are blocked. You can adjust settings to allow your friends, family, or other contacts to reach you.</string>
- <!-- [CHAR LIMIT=40] Zen mode settings: Allow messages to bypass DND title -->
- <string name="zen_mode_messages_title">SMS, MMS, and messaging apps</string>
+ <!-- Zen mode settings: All senders can bypass DND summary [CHAR LIMIT=NONE -->
+ <string name="zen_mode_all_senders_summary">All <xliff:g id="sender_category" example="messages">%s</xliff:g> can reach you</string>
+ <!-- Zen mode settings: Senders in contacts can bypass DND summary summary [CHAR LIMIT=NONE -->
+ <string name="zen_mode_contacts_senders_summary"><xliff:g id="num_contacts" example="120">%d</xliff:g> contacts</string>
<!-- [CHAR LIMIT=40] Zen mode settings: Calls or messages option value: From anyone -->
- <string name="zen_mode_from_anyone">From anyone</string>
-
+ <string name="zen_mode_from_anyone">Anyone</string>
<!-- [CHAR LIMIT=40] Zen mode settings: Calls or messages option value: From contacts only -->
- <string name="zen_mode_from_contacts">From contacts only</string>
-
+ <string name="zen_mode_from_contacts">Contacts</string>
<!-- [CHAR LIMIT=40] Zen mode settings: Calls or messages option value: From starred contacts only -->
- <string name="zen_mode_from_starred">From starred contacts only</string>
-
- <!-- Do not disturb settings, calls summary [CHAR LIMIT=100]-->
- <string name="zen_calls_summary_starred_repeat">From starred contacts and repeat callers</string>
-
- <!-- Do not disturb settings, calls summary [CHAR LIMIT=100]-->
- <string name="zen_calls_summary_contacts_repeat">From contacts and repeat callers</string>
-
- <!-- Do not disturb settings, calls summary [CHAR LIMIT=100]-->
- <string name="zen_calls_summary_repeat_only">From repeat callers only</string>
-
+ <string name="zen_mode_from_starred">Starred contacts</string>
<!-- [CHAR LIMIT=40] Zen mode settings: Calls and/or messages from none-->
<string name="zen_mode_from_none">None</string>
+ <!-- Do not disturb settings, calls summary [CHAR LIMIT=100]-->
+ <string name="zen_calls_summary_starred_repeat">From starred contacts and repeat callers</string>
+ <!-- Do not disturb settings, calls summary [CHAR LIMIT=100]-->
+ <string name="zen_calls_summary_contacts_repeat">From contacts and repeat callers</string>
+ <!-- Do not disturb settings, calls summary [CHAR LIMIT=100]-->
+ <string name="zen_calls_summary_repeat_only">From repeat callers only</string>
+
<!-- [CHAR LIMIT=40] Zen mode settings: Calls option value: No calls allowed -->
<string name="zen_mode_from_none_calls">Don\u2019t allow any calls</string>
-
<!-- [CHAR LIMIT=40] Zen mode settings: Messages option value: No messages allowed -->
<string name="zen_mode_from_none_messages">Don\u2019t allow any messages</string>
<!-- [CHAR LIMIT=80] Zen mode settings: Allow alarms option -->
<string name="zen_mode_alarms">Alarms</string>
-
<!-- [CHAR LIMIT=NONE] Zen mode settings: Allow alarms summary -->
<string name="zen_mode_alarms_summary">From timers, alarms, security systems, and other apps</string>
-
<!-- [CHAR LIMIT=50] Zen mode settings: Alarms option (ie: sound from alarm clock) -->
<string name="zen_mode_alarms_list">alarms</string>
<!-- [CHAR LIMIT=80] Zen mode settings: Allow media (sound from video) to bypass dnd -->
<string name="zen_mode_media">Media sounds</string>
-
<!-- [CHAR LIMIT=NONE] Zen mode settings: Allow media (sound from video) to bypass dnd summary-->
<string name="zen_mode_media_summary">From videos, games, and other media</string>
-
<!-- [CHAR LIMIT=50] Zen mode settings: Media (ie: sound from video) -->
<string name="zen_mode_media_list">media</string>
<!-- [CHAR LIMIT=80] Zen mode settings: allow touch sounds to bypass DND -->
<string name="zen_mode_system">Touch sounds</string>
-
<!-- [CHAR LIMIT=NONE] Zen mode settings: allow touch sounds to bypass DND summary -->
<string name="zen_mode_system_summary">From your keyboard and other buttons</string>
-
<!-- [CHAR LIMIT=50] Zen mode settings: System sounds (ie: touch sounds) -->
<string name="zen_mode_system_list">touch sounds</string>
<!-- [CHAR LIMIT=80] Zen mode settings: Allow reminder notifications/sounds to bypass DND -->
<string name="zen_mode_reminders">Reminders</string>
-
<!-- [CHAR LIMIT=NONE] Zen mode settings: Allow reminder notifications/sounds to bypass DND summary -->
<string name="zen_mode_reminders_summary">From tasks and reminders</string>
-
<!-- [CHAR LIMIT=50] Zen mode settings: Reminders (ie: calendar reminders are allowed to bypass dnd) -->
<string name="zen_mode_reminders_list">reminders</string>
<!-- [CHAR LIMIT=80] Zen mode settings: Allow event notifications/sounds to bypass DND -->
<string name="zen_mode_events">Events</string>
-
<!-- [CHAR LIMIT=NONE] Zen mode settings: Allow event notifications/sounds to bypass DND summary -->
<string name="zen_mode_events_summary">From upcoming calendar events</string>
-
- <!-- [CHAR LIMIT=100] Zen mode settings: Allow apps to bypass DND -->
- <string name="zen_mode_bypassing_apps">Allow apps to override</string>
-
- <!-- [CHAR LIMIT=100] Zen mode settings: Allow apps to bypass DND title-->
- <string name="zen_mode_bypassing_apps_title">App exceptions</string>
-
- <!-- [CHAR LIMIT=120] Zen mode settings: No apps are bypassing DND -->
- <string name="zen_mode_bypassing_apps_subtext_none">No apps can override Do Not Disturb</string>
-
- <!-- [CHAR LIMIT=120] Zen mode settings: Allow apps to bypass DND -->
- <plurals name="zen_mode_bypassing_apps_subtext">
- <item quantity="zero">No apps can override Do Not Disturb</item>
- <item quantity="one">Notifications from 1 app can override Do Not Disturb</item>
- <item quantity="other">Notifications from <xliff:g id="number" example="2">%1$d</xliff:g> apps can override Do Not Disturb</item>
- </plurals>
-
<!-- [CHAR LIMIT=50] Zen mode settings: Events (ie: calendar events) -->
<string name="zen_mode_events_list">events</string>
- <!-- [CHAR LIMIT=50] Zen mode settings: All callers summary -->
- <string name="zen_mode_all_callers">anyone</string>
+ <!-- [CHAR LIMIT=100] Zen mode settings: Allow apps to bypass DND -->
+ <string name="zen_mode_bypassing_apps">Allow apps to override</string>
+ <!-- [CHAR LIMIT=100] Zen mode settings: Allow apps to bypass DND header -->
+ <string name="zen_mode_bypassing_apps_header">Apps that can interrupt</string>
+ <!-- [CHAR LIMIT=120] Zen mode settings: No apps are bypassing DND -->
+ <string name="zen_mode_bypassing_apps_subtext_none">No apps can interrupt</string>
+ <!-- [CHAR LIMIT=120] Zen mode settings: Allow apps to bypass DND -->
+ <plurals name="zen_mode_bypassing_apps_subtext">
+ <item quantity="one"><xliff:g id="app_name" example="Nest">%s</xliff:g> can interrupt</item>
+ <item quantity="other"><xliff:g id="app_names" example="Nest and Google Play Store">%s</xliff:g> can interrupt</item>
+ </plurals>
+ <!-- [CHAR LIMIT=30] Zen mode settings: List item in a summary indicating additional apps are
+ allowed to bypass Do Not Disturb. For example, "Nest, Messages, and 2 more can interrupt". -->
+ <string name="zen_mode_apps_bypassing_list_count"><xliff:g id="number" example="2">%d</xliff:g> more</string>
+ <!-- [CHAR LIMIT=100] Zen mode settings: Allow apps to bypass DND title-->
+ <string name="zen_mode_bypassing_apps_title">App exceptions</string>
+ <!-- [CHAR LIMIT=100] Zen mode settings: App that can bypass DND's secondary text describing which notification channels from the app can bypass DND-->
+ <string name="zen_mode_bypassing_apps_all_summary">All notifications</string>
+ <!-- [CHAR LIMIT=100] Zen mode settings: App that can bypass DND's secondary text describing which notification channels from the app can bypass DND-->
+ <string name="zen_mode_bypassing_apps_some_summary">Some notifications</string>
- <!-- [CHAR LIMIT=50] Zen mode settings: Selected callers summary -->
- <string name="zen_mode_contacts_callers">contacts</string>
+ <!-- [CHAR LIMIT=120] Zen mode settings: Summary for sound interruption settings -->
+ <plurals name="zen_mode_other_sounds_summary">
+ <item quantity="one"><xliff:g id="sound_category">%s</xliff:g> can interrupt</item>
+ <item quantity="other"><xliff:g id="sound_categories" example="Alarms, media sounds, and 2 more">%s</xliff:g> can interrupt</item>
+ </plurals>
+ <!-- [CHAR LIMIT=120] Zen mode settings: No other sounds are allowed to bypass DND -->
+ <string name="zen_mode_other_sounds_none">Nothing can interrupt</string>
+ <!-- [CHAR LIMIT=30] Zen mode settings: List item in a summary indicating additional sounds
+ are allowed to bypass Do Not Disturb. For example, "Alarms, media sounds, and 2 more can
+ interrupt". -->
+ <string name="zen_mode_other_sounds_list_count"><xliff:g id="number" example="2">%d</xliff:g> more</string>
- <!-- [CHAR LIMIT=50] Zen mode settings: Selected callers summary -->
- <string name="zen_mode_starred_callers">starred contacts</string>
+ <!-- [CHAR LIMIT=120] Zen mode settings: Summary for people category -->
+ <string name="zen_mode_people_none">No one can interrupt</string>
+ <!-- [CHAR LIMIT=120] Zen mode settings: Summary for people category -->
+ <string name="zen_mode_people_some">Some people can interrupt</string>
+ <!-- [CHAR LIMIT=120] Zen mode settings: Summary for people category -->
+ <string name="zen_mode_people_all">All people can interrupt</string>
<!-- [CHAR LIMIT=50] Zen mode settings: Repeat callers option -->
<string name="zen_mode_repeat_callers">Repeat callers</string>
-
- <!-- [CHAR LIMIT=50] Zen mode settings: Repeat callers (ie: repeat callers are allowed to bypass dnd) -->
- <string name="zen_mode_repeat_callers_list">repeat callers</string>
-
<!-- [CHAR LIMIT=70] Zen mode settings: Allow repeat callers toggle title -->
<string name="zen_mode_repeat_callers_title">Allow repeat callers</string>
-
+ <!-- [CHAR LIMIT=50] Zen mode settings: All callers summary -->
+ <string name="zen_mode_all_callers">anyone</string>
+ <!-- [CHAR LIMIT=50] Zen mode settings: Selected callers summary -->
+ <string name="zen_mode_contacts_callers">contacts</string>
+ <!-- [CHAR LIMIT=50] Zen mode settings: Selected callers summary -->
+ <string name="zen_mode_starred_callers">starred contacts</string>
+ <!-- [CHAR LIMIT=50] Zen mode settings: Repeat callers (ie: repeat callers are allowed to bypass dnd) -->
+ <string name="zen_mode_repeat_callers_list">repeat callers</string>
<!-- [CHAR LIMIT=50] Zen mode settings: calls summary -->
<string name="zen_mode_calls_summary_one">Allow from <xliff:g id="caller type" example="contacts">%1$s</xliff:g></string>
-
<!-- [CHAR LIMIT=50] Zen mode settings: calls summary -->
<string name="zen_mode_calls_summary_two">Allow from <xliff:g id="caller type" example="starred contacts">%1$s</xliff:g> and <xliff:g id="callert tpye" example="repeat callers">%2$s</xliff:g></string>
-
<!-- [CHAR LIMIT=200] Zen mode settings: Repeat callers option summary -->
<string name="zen_mode_repeat_callers_summary">If the same person calls a second time within a <xliff:g id="minutes">%d</xliff:g> minute period</string>
@@ -9047,43 +9031,33 @@
<!-- [CHAR LIMIT=20] Zen mode settings: When option -->
<string name="zen_mode_when">Automatically turn on</string>
-
<!-- [CHAR LIMIT=20] Zen mode settings: When option value: Never -->
<string name="zen_mode_when_never">Never</string>
-
<!-- [CHAR LIMIT=20] Zen mode settings: When option value: Every night -->
<string name="zen_mode_when_every_night">Every night</string>
-
<!-- [CHAR LIMIT=20] Zen mode settings: When option value: Weeknights -->
<string name="zen_mode_when_weeknights">Weeknights</string>
-
<!-- [CHAR LIMIT=20] Zen mode settings: Start time option -->
<string name="zen_mode_start_time">Start time</string>
-
<!-- [CHAR LIMIT=20] Zen mode settings: End time option -->
<string name="zen_mode_end_time">End time</string>
-
<!-- [CHAR LIMIT=60] Zen mode settings: End time option: Summary text value format when end time = next day -->
<string name="zen_mode_end_time_next_day_summary_format"><xliff:g id="formatted_time" example="7:00 AM">%s</xliff:g> next day</string>
<!-- [CHAR LIMIT=NONE] Zen mode summary spoken when changing mode by voice: switch to alarms only forever. -->
<string name="zen_mode_summary_alarms_only_indefinite">Change to alarms only indefinitely</string>
-
<!-- [CHAR LIMIT=NONE] Zen mode summary spoken when changing mode by voice: switch to alarms only for < 60 minutes. -->
<plurals name="zen_mode_summary_alarms_only_by_minute">
<item quantity="one">Change to alarms only for one minute until <xliff:g id="formattedTime" example="10:00 PM">%2$s</xliff:g></item>
<item quantity="other">Change to alarms only for <xliff:g id="duration" example="2">%1$d</xliff:g> minutes (until <xliff:g id="formattedTime" example="10:00 PM">%2$s</xliff:g>)</item>
</plurals>
-
<!-- [CHAR LIMIT=NONE] Zen mode summary spoken when changing mode by voice: switch to alarms only for N hours. -->
<plurals name="zen_mode_summary_alarms_only_by_hour">
<item quantity="one">Change to alarms only for one hour until <xliff:g id="formattedTime" example="10:00 PM">%2$s</xliff:g></item>
<item quantity="other">Change to alarms only for <xliff:g id="duration" example="2">%1$d</xliff:g> hours until <xliff:g id="formattedTime" example="10:00 PM">%2$s</xliff:g></item>
</plurals>
-
<!-- [CHAR LIMIT=NONE] Zen mode summary spoken when changing mode by voice: switch to alarms only until a specific time. -->
<string name="zen_mode_summary_alarms_only_by_time">Change to alarms only until <xliff:g id="formattedTime" example="10:00 PM">%1$s</xliff:g></string>
-
<!-- [CHAR LIMIT=NONE] Zen mode summary spoken when changing mode by voice: Turn on all notifications. -->
<string name="zen_mode_summary_always">Change to always interrupt</string>
@@ -11843,6 +11817,51 @@
<!-- Developer settings: text for the bug report handler selection toast shown if an invalid bug report handler was chosen. [CHAR LIMIT=NONE] -->
<string name="select_invalid_bug_report_handler_toast_text">This choice is no longer valid. Try again.</string>
+ <!-- Quick controls name sentence case [CHAR LIMIT=40] -->
+ <string name="quick_controls_sentence">Quick controls</string>
+
+ <!-- Quick controls name lower case [CHAR LIMIT=40] -->
+ <string name="quick_controls_lower">quick controls</string>
+
+ <!-- Cards and passes name sentence case [CHAR LIMIT=40] -->
+ <string name="cards_passes_sentence">Cards & passes</string>
+
+ <!-- Cards and passes name lower case [CHAR LIMIT=40] -->
+ <string name="cards_passes_lower">cards & passes</string>
+
+ <!-- Power menu setting name [CHAR LIMIT=NONE] -->
+ <string name="power_menu_setting_name">Power menu</string>
+
+ <!-- Power menu setting title [CHAR LIMIT=NONE] -->
+ <string name="power_menu_setting_title">Power button menu</string>
+
+ <!-- Power menu setting option cards and passes [CHAR LIMIT=NONE] -->
+ <string name="power_menu_cards_passes">Show cards & passes</string>
+
+ <!-- Power menu setting option quick controls [CHAR LIMIT=NONE] -->
+ <string name="power_menu_quick_controls">Show quick controls</string>
+
+ <!-- Power menu setting option cards, passes, quick controls [CHAR LIMIT=NONE] -->
+ <string name="power_menu_cards_passes_quick_controls">Show cards, passes, and quick controls</string>
+
+ <!-- Power menu setting option none [CHAR LIMIT=NONE] -->
+ <string name="power_menu_none">Don\u2019t show any content</string>
+
+ <!-- Power menu setting Privacy [CHAR LIMIT=40] -->
+ <string name="power_menu_privacy">Privacy</string>
+
+ <!-- Power menu setting privacy show all [CHAR LIMIT=NONE] -->
+ <string name="power_menu_privacy_show">Show cards and controls when locked</string>
+
+ <!-- Power menu setting privacy hide all [CHAR LIMIT=NONE] -->
+ <string name="power_menu_privacy_hide">Hide cards and controls when locked</string>
+
+ <!-- Quick controls toggle name [CHAR LIMIT=NONE] -->
+ <string name="quick_controls_setting_toggle">Show quick controls</string>
+
+ <!-- Quick controls toggle subtitle [CHAR LIMIT=NONE] -->
+ <string name="quick_controls_setting_subtitle">To access controls for connected devices, hold the Power button</string>
+
<!-- Title for RTT setting. [CHAR LIMIT=NONE] -->
<string name="rtt_settings_title"></string>
<!-- Subtext for showing the option of RTT setting. [CHAR LIMIT=NONE] -->
diff --git a/res/xml/conversation_list_settings.xml b/res/xml/conversation_list_settings.xml
index 5b9f0c4..238e92b 100644
--- a/res/xml/conversation_list_settings.xml
+++ b/res/xml/conversation_list_settings.xml
@@ -16,11 +16,12 @@
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
- android:key="conversation_list">
+ android:key="conversation_list"
+ android:title="zen_mode_conversations_title">
<PreferenceCategory
- android:title="@string/important_conversations"
android:key="important_conversations"
+ android:title="@string/important_conversations"
android:visibility="gone"
settings:allowDividerAbove="false"
settings:allowDividerBelow="true" >
diff --git a/res/xml/conversation_notification_settings.xml b/res/xml/conversation_notification_settings.xml
index d0db428..be1c980 100644
--- a/res/xml/conversation_notification_settings.xml
+++ b/res/xml/conversation_notification_settings.xml
@@ -26,19 +26,11 @@
settings:allowDividerBelow="true"/>
<!-- important conversation -->
- <com.android.settingslib.RestrictedSwitchPreference
- android:key="important"
+ <com.android.settings.notification.app.ConversationPriorityPreference
+ android:key="priority"
android:title="@string/notification_conversation_important"
- android:icon="@drawable/ic_important_outline"
- settings:restrictedSwitchSummary="@string/enabled_by_admin"
- settings:allowDividerAbove="true"/>
-
- <!-- silence -->
- <com.android.settingslib.RestrictedSwitchPreference
- android:key="alerting"
- android:icon="@drawable/ic_notification_alert"
- android:title="@string/notification_alert_title"
- android:summary="@string/notification_channel_summary_default"/>
+ settings:allowDividerAbove="true"
+ settings:allowDividerBelow="true"/>
<!-- bubbles -->
<com.android.settingslib.RestrictedSwitchPreference
@@ -48,47 +40,6 @@
android:icon="@drawable/ic_create_bubble"
settings:restrictedSwitchSummary="@string/enabled_by_admin" />
- <!-- peeking -->
- <com.android.settingslib.RestrictedSwitchPreference
- android:key="high_importance"
- android:title="@string/notification_importance_high_title"
- android:summary="@string/notification_channel_summary_high"/>
-
- <!-- Visibility Override -->
- <com.android.settings.RestrictedListPreference
- android:key="visibility_override"
- android:icon="@drawable/ic_lock"
- android:title="@string/app_notification_visibility_override_title"/>
-
- <!-- Show badge -->
- <com.android.settingslib.RestrictedSwitchPreference
- android:key="badge"
- android:title="@string/notification_channel_badge_title"
- settings:useAdditionalSummary="true"
- settings:restrictedSwitchSummary="@string/enabled_by_admin"/>
-
- <!-- Lights -->
- <com.android.settingslib.RestrictedSwitchPreference
- android:key="lights"
- android:title="@string/notification_show_lights_title"
- settings:useAdditionalSummary="true"/>
-
- <!-- Vibration -->
- <com.android.settingslib.RestrictedSwitchPreference
- android:key="vibrate"
- android:icon="@drawable/ic_volume_ringer_vibrate"
- android:title="@string/notification_vibrate_title"
- settings:useAdditionalSummary="true" />
-
- <!-- ringtone -->
- <com.android.settings.notification.app.NotificationSoundPreference
- android:key="ringtone"
- android:title="@string/notification_channel_sound_title"
- android:dialogTitle="@string/notification_channel_sound_title"
- android:icon="@drawable/ic_media_stream"
- android:showSilent="true"
- android:showDefault="true"/>
-
<!-- demote -->
<Preference
android:key="demote"
@@ -97,22 +48,55 @@
android:summary="@string/demote_conversation_summary"
settings:allowDividerAbove="true"/>
- <Preference
- android:key="add_to_home"
- android:title="@string/notification_conversation_add_to_home"
- android:icon="@drawable/ic_add_to_home"
- settings:allowDividerAbove="true"/>
-
- <Preference
- android:key="app_link"
- android:title="@string/app_settings_link"
- settings:allowDividerAbove="true"/>
-
- <com.android.settings.notification.app.NotificationFooterPreference
- android:key="desc" />
-
<com.android.settings.notification.app.NotificationFooterPreference
android:key="block_desc"
settings:allowDividerAbove="false"/>
+ <PreferenceCategory
+ android:key="channel_advanced"
+ android:order="50"
+ settings:initialExpandedChildrenCount="0">
+
+ <!-- peeking -->
+ <com.android.settingslib.RestrictedSwitchPreference
+ android:key="high_importance"
+ android:title="@string/notification_importance_high_title"
+ android:summary="@string/notification_channel_summary_high"/>
+
+ <!-- ringtone -->
+ <com.android.settings.notification.app.NotificationSoundPreference
+ android:key="ringtone"
+ android:title="@string/notification_channel_sound_title"
+ android:dialogTitle="@string/notification_channel_sound_title"
+ android:icon="@drawable/ic_media_stream"
+ android:showSilent="true"
+ android:showDefault="true"/>
+
+ <!-- Visibility Override -->
+ <com.android.settings.RestrictedListPreference
+ android:key="visibility_override"
+ android:icon="@drawable/ic_lock"
+ android:title="@string/app_notification_visibility_override_title"/>
+
+ <!-- Show badge -->
+ <com.android.settingslib.RestrictedSwitchPreference
+ android:key="badge"
+ android:title="@string/notification_channel_badge_title"
+ settings:useAdditionalSummary="true"
+ settings:restrictedSwitchSummary="@string/enabled_by_admin"/>
+
+ <!-- Lights -->
+ <com.android.settingslib.RestrictedSwitchPreference
+ android:key="lights"
+ android:title="@string/notification_show_lights_title"
+ settings:useAdditionalSummary="true"/>
+
+ <!-- Vibration -->
+ <com.android.settingslib.RestrictedSwitchPreference
+ android:key="vibrate"
+ android:icon="@drawable/ic_volume_ringer_vibrate"
+ android:title="@string/notification_vibrate_title"
+ settings:useAdditionalSummary="true" />
+ </PreferenceCategory>
+
</PreferenceScreen>
diff --git a/res/xml/zen_mode_calls_settings.xml b/res/xml/zen_mode_calls_settings.xml
index 8366b09..cbadc7d 100644
--- a/res/xml/zen_mode_calls_settings.xml
+++ b/res/xml/zen_mode_calls_settings.xml
@@ -19,28 +19,20 @@
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:key="zen_mode_calls_settings_page"
- android:title="@string/zen_mode_calls_title" >
+ android:title="@string/zen_mode_calls_title">
<PreferenceCategory
- android:title="@string/zen_mode_settings_category"
- android:key="zen_mode_settings_category_calls">
- <!-- Calls -->
- <ListPreference
- android:key="zen_mode_calls"
- android:title="@string/zen_mode_calls"
- android:entries="@array/zen_mode_contacts_calls_entries"
- android:entryValues="@array/zen_mode_contacts_values"/>
-
- <Preference
- android:key="zen_mode_starred_contacts_callers"
- android:title="@string/zen_mode_starred_contacts_title"/>
-
- <!-- Repeat callers -->
- <SwitchPreference
- android:key="zen_mode_repeat_callers"
- android:title="@string/zen_mode_repeat_callers_title" />
+ android:key="zen_mode_settings_category_calls"
+ android:title="@string/zen_mode_calls_header"
+ settings:allowDividerBelow="true">
</PreferenceCategory>
+ <!-- Repeat callers -->
+ <SwitchPreference
+ android:key="zen_mode_repeat_callers"
+ android:title="@string/zen_mode_repeat_callers_title"
+ settings:allowDividerAbove="true"/>
+
<com.android.settingslib.widget.FooterPreference/>
</PreferenceScreen>
diff --git a/res/xml/zen_mode_conversations_settings.xml b/res/xml/zen_mode_conversations_settings.xml
new file mode 100644
index 0000000..773a8b2
--- /dev/null
+++ b/res/xml/zen_mode_conversations_settings.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2020 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+<PreferenceScreen
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:key="zen_mode_conversations_settings"
+ android:title="@string/zen_mode_conversations_title">
+ <!-- Conversations -->
+ <PreferenceCategory
+ android:key="zen_mode_conversations_radio_buttons"
+ android:title="@string/zen_mode_conversations_section_title">
+ <!-- TODO: add preference with chat images here (b/151845457) -->
+ </PreferenceCategory>
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/zen_mode_messages_settings.xml b/res/xml/zen_mode_messages_settings.xml
index 2d0129e..c302b02 100644
--- a/res/xml/zen_mode_messages_settings.xml
+++ b/res/xml/zen_mode_messages_settings.xml
@@ -21,18 +21,8 @@
android:title="@string/zen_mode_messages_title" >
<PreferenceCategory
- android:title="@string/zen_mode_settings_category"
- android:key="zen_mode_settings_category_messages">
- <!-- Messages -->
- <ListPreference
- android:key="zen_mode_messages"
- android:title="@string/zen_mode_messages"
- android:entries="@array/zen_mode_contacts_messages_entries"
- android:entryValues="@array/zen_mode_contacts_values"/>
-
- <Preference
- android:key="zen_mode_starred_contacts_messages"
- android:title="@string/zen_mode_starred_contacts_title"/>
+ android:key="zen_mode_settings_category_messages"
+ android:title="@string/zen_mode_messages_header">
</PreferenceCategory>
<com.android.settingslib.widget.FooterPreference/>
diff --git a/res/xml/zen_mode_people_settings.xml b/res/xml/zen_mode_people_settings.xml
index 7755bb7..140c241 100644
--- a/res/xml/zen_mode_people_settings.xml
+++ b/res/xml/zen_mode_people_settings.xml
@@ -20,51 +20,31 @@
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/zen_category_people" >
+ <!-- Conversations -->
<PreferenceCategory
- android:title="@string/zen_mode_calls_title"
- android:key="zen_mode_settings_category_calls">
- <!-- Calls -->
- <ListPreference
- android:key="zen_mode_calls"
- android:title="@string/zen_mode_calls"
- android:entries="@array/zen_mode_contacts_calls_entries"
- android:entryValues="@array/zen_mode_contacts_values"/>
+ android:key="zen_mode_settings_category_conversations"
+ android:title="@string/zen_mode_conversations_section_title">
<Preference
- android:key="zen_mode_starred_contacts_callers"
- android:title="@string/zen_mode_starred_contacts_title"/>
-
- <!-- Repeat callers -->
- <SwitchPreference
- android:key="zen_mode_repeat_callers"
- android:title="@string/zen_mode_repeat_callers_title" />
- </PreferenceCategory>
-
- <PreferenceCategory
- android:title="@string/zen_mode_messages_title"
- android:key="zen_mode_settings_category_messages">
- <!-- Messages -->
- <ListPreference
- android:key="zen_mode_messages"
- android:title="@string/zen_mode_messages"
- android:entries="@array/zen_mode_contacts_messages_entries"
- android:entryValues="@array/zen_mode_contacts_values"/>
-
- <Preference
- android:key="zen_mode_starred_contacts_messages"
- android:title="@string/zen_mode_starred_contacts_title"/>
- </PreferenceCategory>
-
- <PreferenceCategory
- android:title="@string/zen_mode_conversations_title"
- android:key="zen_mode_settings_category_conversations">
-
- <!-- Conversations -->
- <ListPreference
android:key="zen_mode_conversations"
android:title="@string/zen_mode_conversations_title"
- android:entries="@array/zen_mode_conversations_entries"
- android:entryValues="@array/zen_mode_conversations_values"/>
+ android:fragment="com.android.settings.notification.zen.ZenModeConversationsSettings"/>
+ </PreferenceCategory>
+
+ <!-- Calls & Messages -->
+ <PreferenceCategory
+ android:key="zen_mode_people_calls_messages_section"
+ android:title="@string/zen_mode_people_calls_messages_section_title">
+
+ <Preference
+ android:key="zen_mode_people_calls"
+ android:title="@string/zen_mode_calls_title"
+ android:fragment="com.android.settings.notification.zen.ZenModeCallsSettings"/>
+
+ <Preference
+ android:key="zen_mode_people_messages"
+ android:title="@string/zen_mode_messages_title"
+ android:fragment="com.android.settings.notification.zen.ZenModeMessagesSettings"/>
</PreferenceCategory>
<!-- Footer that shows if user is put into alarms only or total silence mode by an app -->
diff --git a/res/xml/zen_mode_settings.xml b/res/xml/zen_mode_settings.xml
index ce2d132..9649207 100644
--- a/res/xml/zen_mode_settings.xml
+++ b/res/xml/zen_mode_settings.xml
@@ -26,7 +26,6 @@
android:title="@string/zen_mode_settings_title"
android:selectable="false"
android:layout="@layout/zen_mode_settings_button"
- settings:allowDividerAbove="true"
settings:allowDividerBelow="true"
settings:keywords="@string/keywords_zen_mode_settings"/>
@@ -55,26 +54,26 @@
<!-- Automatic rules -->
<Preference
android:key="zen_mode_automation_settings"
- android:title="@string/zen_mode_automation_settings_title"
+ android:title="@string/zen_category_schedule"
settings:allowDividerAbove="true"
settings:allowDividerBelow="true"
android:fragment="com.android.settings.notification.zen.ZenModeAutomationSettings"/>
<PreferenceCategory
android:key="zen_mode_settings_advanced"
- settings:initialExpandedChildrenCount="1">
+ settings:initialExpandedChildrenCount="0">
+
+ <!-- DND duration settings -->
+ <com.android.settings.notification.zen.ZenDurationDialogPreference
+ android:key="zen_mode_duration_settings"
+ android:title="@string/zen_category_duration"
+ android:widgetLayout="@null"/>
<!-- What to block (effects) -->
<Preference
android:key="zen_mode_block_effects_settings"
android:title="@string/zen_mode_restrict_notifications_title"
android:fragment="com.android.settings.notification.zen.ZenModeRestrictNotificationsSettings" />
-
- <!-- DND duration settings -->
- <com.android.settings.notification.zen.ZenDurationDialogPreference
- android:key="zen_mode_duration_settings"
- android:title="@string/zen_mode_duration_settings_title"
- android:widgetLayout="@null"/>
</PreferenceCategory>
<!-- Footer that shows if user is put into alarms only or total silence mode by an app -->
diff --git a/src/com/android/settings/IccLockSettings.java b/src/com/android/settings/IccLockSettings.java
index a9b496a..4340039 100644
--- a/src/com/android/settings/IccLockSettings.java
+++ b/src/com/android/settings/IccLockSettings.java
@@ -31,6 +31,7 @@
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.SubscriptionInfo;
+import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.Log;
@@ -231,13 +232,16 @@
for (int i = 0; i < numSims; ++i) {
final SubscriptionInfo subInfo =
getActiveSubscriptionInfoForSimSlotIndex(subInfoList, i);
- final CarrierConfigManager carrierConfigManager = getContext().getSystemService(
- CarrierConfigManager.class);
- final PersistableBundle bundle = carrierConfigManager.getConfigForSubId(
- subInfo.getSubscriptionId());
- if (bundle != null
- && !bundle.getBoolean(CarrierConfigManager.KEY_HIDE_SIM_LOCK_SETTINGS_BOOL)) {
- componenterList.add(subInfo);
+ if (subInfo != null) {
+ final CarrierConfigManager carrierConfigManager = getContext().getSystemService(
+ CarrierConfigManager.class);
+ final PersistableBundle bundle = carrierConfigManager.getConfigForSubId(
+ subInfo.getSubscriptionId());
+ if (bundle != null
+ && !bundle.getBoolean(CarrierConfigManager
+ .KEY_HIDE_SIM_LOCK_SETTINGS_BOOL)) {
+ componenterList.add(subInfo);
+ }
}
}
@@ -292,7 +296,8 @@
final List<SubscriptionInfo> subInfoList =
mProxySubscriptionMgr.getActiveSubscriptionsInfo();
final SubscriptionInfo sir = getActiveSubscriptionInfoForSimSlotIndex(subInfoList, mSlotId);
- mSubId = sir.getSubscriptionId();
+ mSubId = (sir == null) ? SubscriptionManager.INVALID_SUBSCRIPTION_ID
+ : sir.getSubscriptionId();
if (mPinDialog != null) {
mPinDialog.setEnabled(sir != null);
@@ -679,8 +684,6 @@
@Override
public void onTabChanged(String tabId) {
mSlotId = Integer.parseInt(tabId);
- final SubscriptionInfo sir = getActiveSubscriptionInfoForSimSlotIndex(
- mProxySubscriptionMgr.getActiveSubscriptionsInfo(), mSlotId);
// The User has changed tab; update the body.
updatePreferences();
diff --git a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java
index 30ba084..3906fc8 100644
--- a/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java
+++ b/src/com/android/settings/deviceinfo/simstatus/SimStatusDialogController.java
@@ -268,7 +268,8 @@
PhoneStateListener.LISTEN_DATA_CONNECTION_STATE
| PhoneStateListener.LISTEN_SIGNAL_STRENGTHS
| PhoneStateListener.LISTEN_SERVICE_STATE);
- mSubscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangedListener);
+ mSubscriptionManager.addOnSubscriptionsChangedListener(
+ mContext.getMainExecutor(), mOnSubscriptionsChangedListener);
registerImsRegistrationCallback(mSubscriptionInfo.getSubscriptionId());
if (mShowLatestAreaInfo) {
diff --git a/src/com/android/settings/network/ActiveSubsciptionsListener.java b/src/com/android/settings/network/ActiveSubsciptionsListener.java
index d3702f1..99dfd55 100644
--- a/src/com/android/settings/network/ActiveSubsciptionsListener.java
+++ b/src/com/android/settings/network/ActiveSubsciptionsListener.java
@@ -266,6 +266,12 @@
mCachedActiveSubscriptionInfo = null;
}
+ @VisibleForTesting
+ void registerForSubscriptionsChange() {
+ getSubscriptionManager().addOnSubscriptionsChangedListener(
+ mContext.getMainExecutor(), this);
+ }
+
private void monitorSubscriptionsChange(boolean on) {
if (on) {
if (!mCacheState.compareAndSet(STATE_NOT_LISTENING, STATE_PREPARING)) {
@@ -277,7 +283,7 @@
}
mContext.registerReceiver(mSubscriptionChangeReceiver,
mSubscriptionChangeIntentFilter, null, new Handler(mLooper));
- getSubscriptionManager().addOnSubscriptionsChangedListener(this);
+ registerForSubscriptionsChange();
mCacheState.compareAndSet(STATE_PREPARING, STATE_LISTENING);
return;
}
diff --git a/src/com/android/settings/network/SubscriptionsChangeListener.java b/src/com/android/settings/network/SubscriptionsChangeListener.java
index 1ecd770..1b50a54 100644
--- a/src/com/android/settings/network/SubscriptionsChangeListener.java
+++ b/src/com/android/settings/network/SubscriptionsChangeListener.java
@@ -67,7 +67,8 @@
}
public void start() {
- mSubscriptionManager.addOnSubscriptionsChangedListener(mSubscriptionsChangedListener);
+ mSubscriptionManager.addOnSubscriptionsChangedListener(
+ mContext.getMainExecutor(), mSubscriptionsChangedListener);
mContext.getContentResolver()
.registerContentObserver(mAirplaneModeSettingUri, false, this);
final IntentFilter radioTechnologyChangedFilter = new IntentFilter(
diff --git a/src/com/android/settings/notification/app/BubblePreferenceController.java b/src/com/android/settings/notification/app/BubblePreferenceController.java
index 879f17a..d33ba7e 100644
--- a/src/com/android/settings/notification/app/BubblePreferenceController.java
+++ b/src/com/android/settings/notification/app/BubblePreferenceController.java
@@ -68,7 +68,7 @@
if (isDefaultChannel()) {
return true;
} else {
- return mAppRow != null && mAppRow.allowBubbles;
+ return mAppRow != null;
}
}
return true;
diff --git a/src/com/android/settings/notification/app/ConversationListSettings.java b/src/com/android/settings/notification/app/ConversationListSettings.java
index aaeaa95..1eb997a 100644
--- a/src/com/android/settings/notification/app/ConversationListSettings.java
+++ b/src/com/android/settings/notification/app/ConversationListSettings.java
@@ -18,15 +18,8 @@
import android.app.settings.SettingsEnums;
import android.content.Context;
-import android.os.Bundle;
-import android.text.TextUtils;
import android.util.Log;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceGroup;
-import androidx.preference.PreferenceScreen;
-
-import com.android.internal.widget.LockPatternUtils;
import com.android.settings.R;
import com.android.settings.dashboard.DashboardFragment;
import com.android.settings.notification.NotificationBackend;
@@ -60,7 +53,7 @@
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
mControllers = new ArrayList<>();
- mControllers.add(new ImportantConversationsPreferenceController(context, mBackend));
+ mControllers.add(new PriorityConversationsPreferenceController(context, mBackend));
mControllers.add(new AllConversationsPreferenceController(context, mBackend));
return new ArrayList<>(mControllers);
}
diff --git a/src/com/android/settings/notification/app/ConversationNotificationSettings.java b/src/com/android/settings/notification/app/ConversationNotificationSettings.java
index c5a8e6e..210af20 100644
--- a/src/com/android/settings/notification/app/ConversationNotificationSettings.java
+++ b/src/com/android/settings/notification/app/ConversationNotificationSettings.java
@@ -79,18 +79,13 @@
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
mControllers = new ArrayList<>();
mControllers.add(new ConversationHeaderPreferenceController(context, this));
- mControllers.add(new ConversationImportantPreferenceController(
+ mControllers.add(new ConversationPriorityPreferenceController(
context, mBackend, mDependentFieldListener));
- mControllers.add(new DefaultImportancePreferenceController(
- context, mDependentFieldListener, mBackend));
- mControllers.add(new AddToHomeScreenPreferenceController(context, mBackend));
mControllers.add(new HighImportancePreferenceController(
context, mDependentFieldListener, mBackend));
mControllers.add(new SoundPreferenceController(context, this,
mDependentFieldListener, mBackend));
mControllers.add(new VibrationPreferenceController(context, mBackend));
- mControllers.add(new AppLinkPreferenceController(context));
- mControllers.add(new DescriptionPreferenceController(context));
mControllers.add(new VisibilityPreferenceController(context, new LockPatternUtils(context),
mBackend));
mControllers.add(new LightsPreferenceController(context, mBackend));
diff --git a/src/com/android/settings/notification/app/ConversationPriorityPreference.java b/src/com/android/settings/notification/app/ConversationPriorityPreference.java
new file mode 100644
index 0000000..ff1dc6c
--- /dev/null
+++ b/src/com/android/settings/notification/app/ConversationPriorityPreference.java
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification.app;
+
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+import static android.app.NotificationManager.IMPORTANCE_UNSPECIFIED;
+import static android.view.View.GONE;
+import static android.view.View.VISIBLE;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.drawable.Drawable;
+import android.transition.AutoTransition;
+import android.transition.TransitionManager;
+import android.util.AttributeSet;
+import android.util.Pair;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.settings.Utils;
+import com.android.settingslib.R;
+
+public class ConversationPriorityPreference extends Preference {
+
+ private boolean mIsConfigurable = true;
+ private int mImportance;
+ private int mOriginalImportance;
+ private boolean mPriorityConversation;
+ private View mSilenceButton;
+ private View mAlertButton;
+ private View mPriorityButton;
+ private Context mContext;
+ Drawable selectedBackground;
+ Drawable unselectedBackground;
+ private static final int BUTTON_ANIM_TIME_MS = 100;
+
+ public ConversationPriorityPreference(Context context, AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ init(context);
+ }
+
+ public ConversationPriorityPreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+ init(context);
+ }
+
+ public ConversationPriorityPreference(Context context, AttributeSet attrs) {
+ super(context, attrs);
+ init(context);
+ }
+
+ public ConversationPriorityPreference(Context context) {
+ super(context);
+ init(context);
+ }
+
+ private void init(Context context) {
+ mContext = context;
+ selectedBackground = mContext.getDrawable(R.drawable.button_border_selected);
+ unselectedBackground = mContext.getDrawable(R.drawable.button_border_unselected);
+ setLayoutResource(R.layout.notif_priority_conversation_preference);
+ }
+
+ public void setImportance(int importance) {
+ mImportance = importance;
+ }
+
+ public void setConfigurable(boolean configurable) {
+ mIsConfigurable = configurable;
+ }
+
+ public void setPriorityConversation(boolean priorityConversation) {
+ mPriorityConversation = priorityConversation;
+ }
+
+ public void setOriginalImportance(int importance) {
+ mOriginalImportance = importance;
+ }
+
+ @Override
+ public void onBindViewHolder(final PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+ holder.itemView.setClickable(false);
+
+ mSilenceButton = holder.findViewById(R.id.silence);
+ mAlertButton = holder.findViewById(R.id.alert);
+ mPriorityButton = holder.findViewById(R.id.priority_group);
+
+ if (!mIsConfigurable) {
+ mSilenceButton.setEnabled(false);
+ mAlertButton.setEnabled(false);
+ mPriorityButton.setEnabled(false);
+ }
+
+ updateToggles((ViewGroup) holder.itemView, mImportance, mPriorityConversation,
+ false);
+
+ mSilenceButton.setOnClickListener(v -> {
+ callChangeListener(new Pair(IMPORTANCE_LOW, false));
+ updateToggles((ViewGroup) holder.itemView, IMPORTANCE_LOW, false, true);
+ });
+ mAlertButton.setOnClickListener(v -> {
+ int newImportance = Math.max(mOriginalImportance, IMPORTANCE_DEFAULT);
+ callChangeListener(new Pair(newImportance, false));
+ updateToggles((ViewGroup) holder.itemView, newImportance, false, true);
+ });
+ mPriorityButton.setOnClickListener(v -> {
+ int newImportance = Math.max(mOriginalImportance, IMPORTANCE_DEFAULT);
+ callChangeListener(new Pair(newImportance, true));
+ updateToggles((ViewGroup) holder.itemView, newImportance, true, true);
+ });
+ }
+
+ private ColorStateList getAccentTint() {
+ return Utils.getColorAccent(getContext());
+ }
+
+ private ColorStateList getRegularTint() {
+ return Utils.getColorAttr(getContext(), android.R.attr.textColorPrimary);
+ }
+
+ void updateToggles(ViewGroup parent, int importance, boolean isPriority,
+ boolean fromUser) {
+ if (fromUser) {
+ AutoTransition transition = new AutoTransition();
+ transition.setDuration(BUTTON_ANIM_TIME_MS);
+ TransitionManager.beginDelayedTransition(parent, transition);
+ }
+
+ ColorStateList colorAccent = getAccentTint();
+ ColorStateList colorNormal = getRegularTint();
+ ImageView silenceIcon = parent.findViewById(R.id.silence_icon);
+ TextView silenceLabel = parent.findViewById(R.id.silence_label);
+ TextView silenceSummary = parent.findViewById(R.id.silence_summary);
+ ImageView alertIcon = parent.findViewById(R.id.alert_icon);
+ TextView alertLabel = parent.findViewById(R.id.alert_label);
+ TextView alertSummary = parent.findViewById(R.id.alert_summary);
+ ImageView priorityIcon = parent.findViewById(R.id.priority_icon);
+ TextView priorityLabel = parent.findViewById(R.id.priority_label);
+ TextView prioritySummary = parent.findViewById(R.id.priority_summary);
+
+ if (importance <= IMPORTANCE_LOW && importance > IMPORTANCE_UNSPECIFIED) {
+ alertSummary.setVisibility(GONE);
+ alertIcon.setImageTintList(colorNormal);
+ alertLabel.setTextColor(colorNormal);
+
+ prioritySummary.setVisibility(GONE);
+ priorityIcon.setImageTintList(colorNormal);
+ priorityLabel.setTextColor(colorNormal);
+
+ silenceIcon.setImageTintList(colorAccent);
+ silenceLabel.setTextColor(colorAccent);
+ silenceSummary.setVisibility(VISIBLE);
+
+ mAlertButton.setBackground(unselectedBackground);
+ mPriorityButton.setBackground(unselectedBackground);
+ mSilenceButton.setBackground(selectedBackground);
+ // a11y service won't always read the newly appearing text in the right order if the
+ // selection happens too soon (readback happens on a different thread as layout). post
+ // the selection to make that conflict less likely
+ parent.post(() -> mSilenceButton.setSelected(true));
+ } else {
+ if (isPriority) {
+ alertSummary.setVisibility(GONE);
+ alertIcon.setImageTintList(colorNormal);
+ alertLabel.setTextColor(colorNormal);
+
+ prioritySummary.setVisibility(VISIBLE);
+ priorityIcon.setImageTintList(colorAccent);
+ priorityLabel.setTextColor(colorAccent);
+
+ silenceIcon.setImageTintList(colorNormal);
+ silenceLabel.setTextColor(colorNormal);
+ silenceSummary.setVisibility(GONE);
+
+ mAlertButton.setBackground(unselectedBackground);
+ mPriorityButton.setBackground(selectedBackground);
+ mSilenceButton.setBackground(unselectedBackground);
+ parent.post(() -> mPriorityButton.setSelected(true));
+ } else {
+ alertSummary.setVisibility(VISIBLE);
+ alertIcon.setImageTintList(colorAccent);
+ alertLabel.setTextColor(colorAccent);
+
+ prioritySummary.setVisibility(GONE);
+ priorityIcon.setImageTintList(colorNormal);
+ priorityLabel.setTextColor(colorNormal);
+
+ silenceIcon.setImageTintList(colorNormal);
+ silenceLabel.setTextColor(colorNormal);
+ silenceSummary.setVisibility(GONE);
+
+ mAlertButton.setBackground(selectedBackground);
+ mPriorityButton.setBackground(unselectedBackground);
+ mSilenceButton.setBackground(unselectedBackground);
+ parent.post(() -> mAlertButton.setSelected(true));
+ }
+ }
+ }
+}
diff --git a/src/com/android/settings/notification/app/ConversationImportantPreferenceController.java b/src/com/android/settings/notification/app/ConversationPriorityPreferenceController.java
similarity index 63%
rename from src/com/android/settings/notification/app/ConversationImportantPreferenceController.java
rename to src/com/android/settings/notification/app/ConversationPriorityPreferenceController.java
index 0b1ee16..e59f277 100644
--- a/src/com/android/settings/notification/app/ConversationImportantPreferenceController.java
+++ b/src/com/android/settings/notification/app/ConversationPriorityPreferenceController.java
@@ -16,25 +16,22 @@
package com.android.settings.notification.app;
-import static android.provider.Settings.Secure.BUBBLE_IMPORTANT_CONVERSATIONS;
-
import android.content.Context;
-import android.provider.Settings;
+import android.util.Pair;
import androidx.preference.Preference;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.notification.NotificationBackend;
-import com.android.settingslib.RestrictedSwitchPreference;
-public class ConversationImportantPreferenceController extends NotificationPreferenceController
+public class ConversationPriorityPreferenceController extends NotificationPreferenceController
implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
- private static final String TAG = "ConvoImpPC";
- private static final String KEY = "important";
+ private static final String TAG = "ConvoPriorityPC";
+ private static final String KEY = "priority";
private final NotificationSettings.DependentFieldListener mDependentFieldListener;
- public ConversationImportantPreferenceController(Context context,
+ public ConversationPriorityPreferenceController(Context context,
NotificationBackend backend, NotificationSettings.DependentFieldListener listener) {
super(context, backend);
mDependentFieldListener = listener;
@@ -58,10 +55,12 @@
public void updateState(Preference preference) {
if (mAppRow != null) {
- RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;
- pref.setDisabledByAdmin(mAdmin);
- pref.setChecked(mChannel.isImportantConversation());
- pref.setEnabled(!pref.isDisabledByAdmin());
+ preference.setEnabled(mAdmin == null && !mChannel.isImportanceLockedByOEM());
+ ConversationPriorityPreference pref = (ConversationPriorityPreference) preference;
+ pref.setConfigurable(!mChannel.isImportanceLockedByOEM());
+ pref.setImportance(mChannel.getImportance());
+ pref.setOriginalImportance(mChannel.getOriginalImportance());
+ pref.setPriorityConversation(mChannel.isImportantConversation());
}
}
@@ -70,19 +69,21 @@
if (mChannel == null) {
return false;
}
- final boolean value = (Boolean) newValue;
- mChannel.setImportantConversation(value);
- if (value && bubbleImportantConversations()) {
+ boolean wasPriorityConversation = mChannel.isImportantConversation();
+
+ final Pair<Integer, Boolean> value = (Pair) newValue;
+ mChannel.setImportance(value.first);
+ mChannel.setImportantConversation(value.second);
+
+ if (value.second) {
mChannel.setAllowBubbles(true);
+ } else if (wasPriorityConversation) {
+ mChannel.setAllowBubbles(false);
}
+
mDependentFieldListener.onFieldValueChanged();
saveChannel();
return true;
}
-
- private boolean bubbleImportantConversations() {
- return Settings.Secure.getInt(mContext.getContentResolver(),
- BUBBLE_IMPORTANT_CONVERSATIONS, 1) == 1;
- }
}
diff --git a/src/com/android/settings/notification/app/DefaultImportancePreferenceController.java b/src/com/android/settings/notification/app/DefaultImportancePreferenceController.java
deleted file mode 100644
index 616d64a..0000000
--- a/src/com/android/settings/notification/app/DefaultImportancePreferenceController.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.notification.app;
-
-import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
-import static android.app.NotificationManager.IMPORTANCE_LOW;
-
-import android.app.NotificationChannel;
-import android.content.Context;
-
-import androidx.preference.Preference;
-
-import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settings.notification.NotificationBackend;
-import com.android.settingslib.RestrictedSwitchPreference;
-
-public class DefaultImportancePreferenceController extends NotificationPreferenceController
- implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
-
- private static final String KEY = "alerting";
- private NotificationSettings.DependentFieldListener mDependentFieldListener;
-
- public DefaultImportancePreferenceController(Context context,
- NotificationSettings.DependentFieldListener dependentFieldListener,
- NotificationBackend backend) {
- super(context, backend);
- mDependentFieldListener = dependentFieldListener;
- }
-
- @Override
- public String getPreferenceKey() {
- return KEY;
- }
-
- @Override
- public boolean isAvailable() {
- if (!super.isAvailable()) {
- return false;
- }
- if (mChannel == null) {
- return false;
- }
- if (isDefaultChannel()) {
- return false;
- }
- return true;
- }
-
- @Override
- public void updateState(Preference preference) {
- if (mAppRow != null && mChannel != null) {
- preference.setEnabled(mAdmin == null && !mChannel.isImportanceLockedByOEM());
-
- RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;
- pref.setChecked(mChannel.getImportance() >= IMPORTANCE_DEFAULT);
- }
- }
-
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- if (mChannel != null) {
- final boolean checked = (boolean) newValue;
-
- mChannel.setImportance(checked ? IMPORTANCE_DEFAULT : IMPORTANCE_LOW);
- mChannel.lockFields(NotificationChannel.USER_LOCKED_IMPORTANCE);
- saveChannel();
- mDependentFieldListener.onFieldValueChanged();
- }
- return true;
- }
-}
diff --git a/src/com/android/settings/notification/app/ImportantConversationsPreferenceController.java b/src/com/android/settings/notification/app/PriorityConversationsPreferenceController.java
similarity index 94%
rename from src/com/android/settings/notification/app/ImportantConversationsPreferenceController.java
rename to src/com/android/settings/notification/app/PriorityConversationsPreferenceController.java
index 2089d9d..ed12d7d 100644
--- a/src/com/android/settings/notification/app/ImportantConversationsPreferenceController.java
+++ b/src/com/android/settings/notification/app/PriorityConversationsPreferenceController.java
@@ -28,14 +28,14 @@
import java.util.Collections;
import java.util.List;
-public class ImportantConversationsPreferenceController extends
+public class PriorityConversationsPreferenceController extends
ConversationListPreferenceController {
private static final String KEY = "important_conversations";
private static final String LIST_KEY = "important_conversations_list";
private List<ConversationChannelWrapper> mConversations;
- public ImportantConversationsPreferenceController(Context context,
+ public PriorityConversationsPreferenceController(Context context,
NotificationBackend backend) {
super(context, backend);
}
diff --git a/src/com/android/settings/notification/zen/ZenModeBackend.java b/src/com/android/settings/notification/zen/ZenModeBackend.java
index 836f435..bb406c1 100644
--- a/src/com/android/settings/notification/zen/ZenModeBackend.java
+++ b/src/com/android/settings/notification/zen/ZenModeBackend.java
@@ -16,8 +16,6 @@
package com.android.settings.notification.zen;
-import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_ANYONE;
-import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT;
import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_OFF;
import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_SCREEN_ON;
@@ -501,7 +499,7 @@
private List<String> getStarredContacts() {
Cursor cursor = null;
try {
- cursor = queryData();
+ cursor = queryStarredContactsData();
return getStarredContacts(cursor);
} finally {
if (cursor != null) {
@@ -510,7 +508,7 @@
}
}
- public String getStarredContactsSummary(Context context) {
+ String getStarredContactsSummary(Context context) {
List<String> starredContacts = getStarredContacts();
int numStarredContacts = starredContacts.size();
@@ -536,13 +534,24 @@
return ListFormatter.getInstance().format(displayContacts);
}
- private Cursor queryData() {
+ String getContactsNumberSummary(Context context) {
+ return context.getResources().getString(R.string.zen_mode_contacts_senders_summary,
+ queryAllContactsData().getCount());
+ }
+
+ private Cursor queryStarredContactsData() {
return mContext.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
new String[]{ContactsContract.Contacts.DISPLAY_NAME_PRIMARY},
ContactsContract.Data.STARRED + "=1", null,
ContactsContract.Data.TIMES_CONTACTED);
}
+ private Cursor queryAllContactsData() {
+ return mContext.getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
+ new String[]{ContactsContract.Contacts.DISPLAY_NAME_PRIMARY},
+ null, null, null);
+ }
+
@VisibleForTesting
public static final Comparator<Map.Entry<String, AutomaticZenRule>> RULE_COMPARATOR =
new Comparator<Map.Entry<String, AutomaticZenRule>>() {
diff --git a/src/com/android/settings/notification/zen/ZenModeBypassingAppsPreferenceController.java b/src/com/android/settings/notification/zen/ZenModeBypassingAppsPreferenceController.java
index a93fa1b..7459394 100644
--- a/src/com/android/settings/notification/zen/ZenModeBypassingAppsPreferenceController.java
+++ b/src/com/android/settings/notification/zen/ZenModeBypassingAppsPreferenceController.java
@@ -1,19 +1,53 @@
package com.android.settings.notification.zen;
+import android.app.Application;
+import android.app.NotificationChannel;
import android.content.Context;
-import android.os.UserHandle;
+import android.icu.text.ListFormatter;
+import android.provider.Settings;
+import android.text.TextUtils;
+import androidx.core.text.BidiFormatter;
+import androidx.fragment.app.Fragment;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.internal.annotations.VisibleForTesting;
import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.notification.NotificationBackend;
+import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.core.lifecycle.Lifecycle;
-public class ZenModeBypassingAppsPreferenceController extends AbstractZenModePreferenceController {
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Controls the summary for preference found at:
+ * Settings > Sound > Do Not Disturb > Apps
+ */
+public class ZenModeBypassingAppsPreferenceController extends AbstractZenModePreferenceController
+ implements PreferenceControllerMixin {
protected static final String KEY = "zen_mode_behavior_apps";
+
+ @VisibleForTesting protected Preference mPreference;
+ private ApplicationsState.Session mAppSession;
private NotificationBackend mNotificationBackend = new NotificationBackend();
- public ZenModeBypassingAppsPreferenceController(Context context, Lifecycle lifecycle) {
+ private String mSummary;
+
+ public ZenModeBypassingAppsPreferenceController(Context context, Application app,
+ Fragment host, Lifecycle lifecycle) {
+ this(context, app == null ? null : ApplicationsState.getInstance(app), host, lifecycle);
+ }
+
+ private ZenModeBypassingAppsPreferenceController(Context context, ApplicationsState appState,
+ Fragment host, Lifecycle lifecycle) {
super(context, KEY, lifecycle);
+ if (appState != null && host != null) {
+ mAppSession = appState.newSession(mAppSessionCallbacks, host.getLifecycle());
+ }
}
@Override
@@ -22,13 +56,125 @@
}
@Override
- public String getSummary() {
- final int channelsBypassing =
- mNotificationBackend.getNumAppsBypassingDnd(UserHandle.getCallingUserId());
- if (channelsBypassing == 0) {
- return mContext.getResources().getString(R.string.zen_mode_bypassing_apps_subtext_none);
- }
- return mContext.getResources().getQuantityString(R.plurals.zen_mode_bypassing_apps_subtext,
- channelsBypassing, channelsBypassing);
+ public String getPreferenceKey() {
+ return KEY;
}
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ mPreference = screen.findPreference(KEY);
+ updateAppsBypassingDndSummaryText();
+ super.displayPreference(screen);
+ }
+
+ @Override
+ public String getSummary() {
+ return mSummary;
+ }
+
+ private void updateAppsBypassingDndSummaryText() {
+ if (mAppSession == null) {
+ return;
+ }
+
+ ApplicationsState.AppFilter filter = ApplicationsState.FILTER_ALL_ENABLED;
+ List<ApplicationsState.AppEntry> apps = mAppSession.rebuild(filter,
+ ApplicationsState.ALPHA_COMPARATOR);
+ updateAppsBypassingDndSummaryText(apps);
+ }
+
+ @VisibleForTesting
+ void updateAppsBypassingDndSummaryText(List<ApplicationsState.AppEntry> apps) {
+ switch (getZenMode()) {
+ case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
+ case Settings.Global.ZEN_MODE_ALARMS:
+ // users cannot change their DND settings when an app puts the device total
+ // silence or alarms only (both deprecated) modes
+ mPreference.setEnabled(false);
+ mSummary = mContext.getResources().getString(
+ R.string.zen_mode_bypassing_apps_subtext_none);
+ return;
+ default:
+ mPreference.setEnabled(true);
+ }
+
+ if (apps == null) {
+ return;
+ }
+
+ List<String> appsBypassingDnd = new ArrayList<>();
+ for (ApplicationsState.AppEntry entry : apps) {
+ String pkg = entry.info.packageName;
+ for (NotificationChannel channel : mNotificationBackend
+ .getNotificationChannelsBypassingDnd(pkg, entry.info.uid).getList()) {
+ if (!TextUtils.isEmpty(channel.getConversationId())) {
+ // conversation channels that bypass dnd will be shown on the People page
+ continue;
+ }
+ appsBypassingDnd.add(BidiFormatter.getInstance().unicodeWrap(entry.label));
+ continue;
+ }
+ }
+
+ if (appsBypassingDnd.size() == 0) {
+ mSummary = mContext.getResources().getString(
+ R.string.zen_mode_bypassing_apps_subtext_none);
+ refreshSummary(mPreference);
+ return;
+ }
+
+ List<String> displayAppsBypassing = new ArrayList<>();
+ if (appsBypassingDnd.size() <= 2) {
+ displayAppsBypassing = appsBypassingDnd;
+ } else {
+ displayAppsBypassing.add(appsBypassingDnd.get(0));
+ displayAppsBypassing.add(appsBypassingDnd.get(1));
+ displayAppsBypassing.add(mContext.getResources().getString(
+ R.string.zen_mode_apps_bypassing_list_count,
+ appsBypassingDnd.size() - 2));
+ }
+ mSummary = mContext.getResources().getQuantityString(
+ R.plurals.zen_mode_bypassing_apps_subtext,
+ appsBypassingDnd.size(),
+ ListFormatter.getInstance().format(displayAppsBypassing));
+ refreshSummary(mPreference);
+ }
+
+ private final ApplicationsState.Callbacks mAppSessionCallbacks =
+ new ApplicationsState.Callbacks() {
+
+ @Override
+ public void onRunningStateChanged(boolean running) {
+ updateAppsBypassingDndSummaryText();
+ }
+
+ @Override
+ public void onPackageListChanged() {
+ updateAppsBypassingDndSummaryText();
+ }
+
+ @Override
+ public void onRebuildComplete(ArrayList<ApplicationsState.AppEntry> apps) {
+ updateAppsBypassingDndSummaryText(apps);
+ }
+
+ @Override
+ public void onPackageIconChanged() { }
+
+ @Override
+ public void onPackageSizeChanged(String packageName) {
+ updateAppsBypassingDndSummaryText();
+ }
+
+ @Override
+ public void onAllSizesComputed() { }
+
+ @Override
+ public void onLauncherInfoChanged() { }
+
+ @Override
+ public void onLoadEntriesCompleted() {
+ updateAppsBypassingDndSummaryText();
+ }
+ };
}
diff --git a/src/com/android/settings/notification/zen/ZenModeCallsSettings.java b/src/com/android/settings/notification/zen/ZenModeCallsSettings.java
new file mode 100644
index 0000000..1b5412e
--- /dev/null
+++ b/src/com/android/settings/notification/zen/ZenModeCallsSettings.java
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification.zen;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.provider.SearchIndexableResource;
+
+import com.android.settings.R;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.search.SearchIndexable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * DND Calls Settings page to determine which priority senders can bypass DND.
+ */
+@SearchIndexable
+public class ZenModeCallsSettings extends ZenModeSettingsBase {
+
+ @Override
+ protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
+ return buildPreferenceControllers(context, getSettingsLifecycle());
+ }
+
+ private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
+ Lifecycle lifecycle) {
+ List<AbstractPreferenceController> controllers = new ArrayList<>();
+ controllers.add(new ZenModePrioritySendersPreferenceController(context,
+ "zen_mode_settings_category_calls", lifecycle, false));
+ controllers.add(new ZenModeRepeatCallersPreferenceController(context, lifecycle,
+ context.getResources().getInteger(com.android.internal.R.integer
+ .config_zen_repeat_callers_threshold)));
+ controllers.add(new ZenModeBehaviorFooterPreferenceController(
+ context, lifecycle, R.string.zen_mode_calls_footer));
+ return controllers;
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.zen_mode_calls_settings;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.DND_CALLS;
+ }
+
+ /**
+ * For Search.
+ */
+ public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider() {
+ @Override
+ public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
+ boolean enabled) {
+ final ArrayList<SearchIndexableResource> result = new ArrayList<>();
+
+ final SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = R.xml.zen_mode_calls_settings;
+ result.add(sir);
+ return result;
+ }
+
+ @Override
+ public List<AbstractPreferenceController> createPreferenceControllers(
+ Context context) {
+ return buildPreferenceControllers(context, null);
+ }
+ };
+}
diff --git a/src/com/android/settings/notification/zen/ZenModeConversationsPreferenceController.java b/src/com/android/settings/notification/zen/ZenModeConversationsPreferenceController.java
new file mode 100644
index 0000000..f23bf61
--- /dev/null
+++ b/src/com/android/settings/notification/zen/ZenModeConversationsPreferenceController.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification.zen;
+
+import android.app.NotificationManager;
+import android.content.Context;
+import android.provider.Settings;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+/**
+ * Controls the summary for preference found at:
+ * Settings > Sound > Do Not Disturb > People > Conversations
+ */
+public class ZenModeConversationsPreferenceController extends AbstractZenModePreferenceController {
+ private final ZenModeBackend mBackend;
+ private Preference mPreference;
+
+ public ZenModeConversationsPreferenceController(Context context,
+ String key, Lifecycle lifecycle) {
+ super(context, key, lifecycle);
+ mBackend = ZenModeBackend.getInstance(context);
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return true;
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ mPreference = screen.findPreference(KEY);
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+ switch (getZenMode()) {
+ case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
+ case Settings.Global.ZEN_MODE_ALARMS:
+ mPreference.setEnabled(false);
+ mPreference.setSummary(mBackend.getAlarmsTotalSilencePeopleSummary(
+ NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS));
+ break;
+ default:
+ preference.setEnabled(true);
+ preference.setSummary(mBackend.getConversationSummary());
+ }
+ }
+}
diff --git a/src/com/android/settings/notification/zen/ZenModeConversationsSettings.java b/src/com/android/settings/notification/zen/ZenModeConversationsSettings.java
new file mode 100644
index 0000000..4307538
--- /dev/null
+++ b/src/com/android/settings/notification/zen/ZenModeConversationsSettings.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification.zen;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+
+import com.android.settings.R;
+import com.android.settings.notification.NotificationBackend;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.search.SearchIndexable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Settings > Sound > Do Not Disturb > Conversationss
+ */
+@SearchIndexable
+public class ZenModeConversationsSettings extends ZenModeSettingsBase {
+ private final NotificationBackend mNotificationBackend = new NotificationBackend();
+
+ @Override
+ protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
+ return buildPreferenceControllers(context, getSettingsLifecycle(), mNotificationBackend);
+ }
+
+ private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
+ Lifecycle lifecycle, NotificationBackend notificationBackend) {
+ List<AbstractPreferenceController> controllers = new ArrayList<>();
+ controllers.add(new ZenModePriorityConversationsPreferenceController(context,
+ "zen_mode_conversations_radio_buttons", lifecycle, notificationBackend));
+ return controllers;
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.zen_mode_conversations_settings;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.DND_CONVERSATIONS;
+ }
+
+ /**
+ * For Search.
+ */
+ public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider(R.xml.zen_mode_conversations_settings) {
+
+ @Override
+ public List<AbstractPreferenceController> createPreferenceControllers(
+ Context context) {
+ return buildPreferenceControllers(context, null, null);
+ }
+ };
+}
diff --git a/src/com/android/settings/notification/zen/ZenModeMessagesSettings.java b/src/com/android/settings/notification/zen/ZenModeMessagesSettings.java
new file mode 100644
index 0000000..d15a4aa
--- /dev/null
+++ b/src/com/android/settings/notification/zen/ZenModeMessagesSettings.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification.zen;
+
+import android.app.settings.SettingsEnums;
+import android.content.Context;
+import android.provider.SearchIndexableResource;
+
+import com.android.settings.R;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.core.AbstractPreferenceController;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.search.SearchIndexable;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * DND Messages Settings page to determine which priority senders can bypass DND.
+ * "Messages" include SMS, MMS, and messaging apps.
+ */
+@SearchIndexable
+public class ZenModeMessagesSettings extends ZenModeSettingsBase {
+
+ @Override
+ protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
+ return buildPreferenceControllers(context, getSettingsLifecycle());
+ }
+
+ private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
+ Lifecycle lifecycle) {
+ List<AbstractPreferenceController> controllers = new ArrayList<>();
+ controllers.add(new ZenModePrioritySendersPreferenceController(context,
+ "zen_mode_settings_category_messages", lifecycle, true));
+ controllers.add(new ZenModeBehaviorFooterPreferenceController(
+ context, lifecycle, R.string.zen_mode_messages_footer));
+ return controllers;
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.zen_mode_messages_settings;
+ }
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.DND_MESSAGES;
+ }
+
+ /**
+ * For Search.
+ */
+ public static final SearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider() {
+ @Override
+ public List<SearchIndexableResource> getXmlResourcesToIndex(Context context,
+ boolean enabled) {
+ final ArrayList<SearchIndexableResource> result = new ArrayList<>();
+
+ final SearchIndexableResource sir = new SearchIndexableResource(context);
+ sir.xmlResId = R.xml.zen_mode_messages_settings;
+ result.add(sir);
+ return result;
+ }
+
+ @Override
+ public List<AbstractPreferenceController> createPreferenceControllers(
+ Context context) {
+ return buildPreferenceControllers(context, null);
+ }
+ };
+}
diff --git a/src/com/android/settings/notification/zen/ZenModePeoplePreferenceController.java b/src/com/android/settings/notification/zen/ZenModePeoplePreferenceController.java
index a48c93d..cb185dd 100644
--- a/src/com/android/settings/notification/zen/ZenModePeoplePreferenceController.java
+++ b/src/com/android/settings/notification/zen/ZenModePeoplePreferenceController.java
@@ -16,25 +16,33 @@
package com.android.settings.notification.zen;
+import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_ANYONE;
+import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_NONE;
+import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_REPEAT_CALLERS;
+import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_ANY;
+
import android.app.NotificationManager;
import android.content.Context;
import android.provider.Settings;
import androidx.preference.Preference;
+import com.android.settings.R;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settingslib.core.lifecycle.Lifecycle;
+/**
+ * Controls the summary for preference found at:
+ * Settings > Sound > Do Not Disturb > People
+ */
public class ZenModePeoplePreferenceController extends
AbstractZenModePreferenceController implements PreferenceControllerMixin {
private final String KEY;
- private final ZenModeSettings.SummaryBuilder mSummaryBuilder;
public ZenModePeoplePreferenceController(Context context, Lifecycle lifecycle, String key) {
super(context, key, lifecycle);
KEY = key;
- mSummaryBuilder = new ZenModeSettings.SummaryBuilder(context);
}
@Override
@@ -60,8 +68,28 @@
break;
default:
preference.setEnabled(true);
- // TODO: How do all of the people options roll up into the summary?
- //preference.setSummary(mSummaryBuilder.getMessagesSettingSummary(getPolicy()));
+ preference.setSummary(getPeopleSummary());
+ }
+ }
+
+ private String getPeopleSummary() {
+ final int callersAllowed = mBackend.getPriorityCallSenders();
+ final int messagesAllowed = mBackend.getPriorityMessageSenders();
+ final int conversationsAllowed = mBackend.getPriorityConversationSenders();
+ final boolean areRepeatCallersAllowed =
+ mBackend.isPriorityCategoryEnabled(PRIORITY_CATEGORY_REPEAT_CALLERS);
+
+ if (callersAllowed == PRIORITY_SENDERS_ANY
+ && messagesAllowed == PRIORITY_SENDERS_ANY
+ && conversationsAllowed == CONVERSATION_SENDERS_ANYONE) {
+ return mContext.getResources().getString(R.string.zen_mode_people_all);
+ } else if (callersAllowed == ZenModeBackend.SOURCE_NONE
+ && messagesAllowed == ZenModeBackend.SOURCE_NONE
+ && conversationsAllowed == CONVERSATION_SENDERS_NONE
+ && !areRepeatCallersAllowed) {
+ return mContext.getResources().getString(R.string.zen_mode_people_none);
+ } else {
+ return mContext.getResources().getString(R.string.zen_mode_people_some);
}
}
}
diff --git a/src/com/android/settings/notification/zen/ZenModePeopleSettings.java b/src/com/android/settings/notification/zen/ZenModePeopleSettings.java
index ff768db..4971e54 100644
--- a/src/com/android/settings/notification/zen/ZenModePeopleSettings.java
+++ b/src/com/android/settings/notification/zen/ZenModePeopleSettings.java
@@ -16,9 +16,6 @@
package com.android.settings.notification.zen;
-import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CALLS;
-import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES;
-
import android.app.Activity;
import android.app.Application;
import android.app.settings.SettingsEnums;
@@ -56,16 +53,12 @@
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
Lifecycle lifecycle, Application app, Fragment host, FragmentManager fragmentManager) {
List<AbstractPreferenceController> controllers = new ArrayList<>();
- controllers.add(new ZenModePriorityMessagesPreferenceController(context, lifecycle));
- controllers.add(new ZenModeStarredContactsPreferenceController(context, lifecycle,
- PRIORITY_CATEGORY_MESSAGES, "zen_mode_starred_contacts_messages"));
- controllers.add(new ZenModePriorityCallsPreferenceController(context, lifecycle));
- controllers.add(new ZenModeStarredContactsPreferenceController(context, lifecycle,
- PRIORITY_CATEGORY_CALLS, "zen_mode_starred_contacts_callers"));
- controllers.add(new ZenModeRepeatCallersPreferenceController(context, lifecycle,
- context.getResources().getInteger(com.android.internal.R.integer
- .config_zen_repeat_callers_threshold)));
- controllers.add(new ZenModePriorityConversationsPreferenceController(context, lifecycle));
+ controllers.add(new ZenModeConversationsPreferenceController(context,
+ "zen_mode_conversations", lifecycle));
+ controllers.add(new ZenModeCallsPreferenceController(context, lifecycle,
+ "zen_mode_people_calls"));
+ controllers.add(new ZenModeMessagesPreferenceController(context, lifecycle,
+ "zen_mode_people_messages"));
controllers.add(new ZenModeSettingsFooterPreferenceController(context, lifecycle,
fragmentManager));
return controllers;
diff --git a/src/com/android/settings/notification/zen/ZenModePriorityConversationsPreferenceController.java b/src/com/android/settings/notification/zen/ZenModePriorityConversationsPreferenceController.java
index afd17ad..b6824a9 100644
--- a/src/com/android/settings/notification/zen/ZenModePriorityConversationsPreferenceController.java
+++ b/src/com/android/settings/notification/zen/ZenModePriorityConversationsPreferenceController.java
@@ -16,37 +16,65 @@
package com.android.settings.notification.zen;
-import static android.service.notification.ZenPolicy.CONVERSATION_SENDERS_ANYONE;
-import static android.service.notification.ZenPolicy.CONVERSATION_SENDERS_IMPORTANT;
-import static android.service.notification.ZenPolicy.CONVERSATION_SENDERS_NONE;
-
import android.app.NotificationManager;
import android.content.Context;
-import android.provider.Settings;
+import android.content.pm.ParceledListSlice;
+import android.os.AsyncTask;
+import android.service.notification.ConversationChannelWrapper;
-import androidx.preference.ListPreference;
+import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;
import com.android.settings.R;
+import com.android.settings.notification.NotificationBackend;
import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.widget.RadioButtonPreference;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Options to choose the priority conversations that are allowed to bypass DND.
+ */
public class ZenModePriorityConversationsPreferenceController
- extends AbstractZenModePreferenceController
- implements Preference.OnPreferenceChangeListener {
+ extends AbstractZenModePreferenceController {
+ private static final int UNSET = -1;
+ @VisibleForTesting static final String KEY_ALL = "conversations_all";
+ @VisibleForTesting static final String KEY_IMPORTANT = "conversations_important";
+ @VisibleForTesting static final String KEY_NONE = "conversations_none";
- protected static final String KEY = "zen_mode_conversations";
- private final ZenModeBackend mBackend;
- private ListPreference mPreference;
+ private final NotificationBackend mNotificationBackend;
- public ZenModePriorityConversationsPreferenceController(Context context, Lifecycle lifecycle) {
- super(context, KEY, lifecycle);
- mBackend = ZenModeBackend.getInstance(context);
+ private int mNumImportantConversations = UNSET;
+ private int mNumConversations = UNSET;
+ private PreferenceCategory mPreferenceCategory;
+ private List<RadioButtonPreference> mRadioButtonPreferences = new ArrayList<>();
+
+ public ZenModePriorityConversationsPreferenceController(Context context, String key,
+ Lifecycle lifecycle, NotificationBackend notificationBackend) {
+ super(context, key, lifecycle);
+ mNotificationBackend = notificationBackend;
}
@Override
- public String getPreferenceKey() {
- return KEY;
+ public void displayPreference(PreferenceScreen screen) {
+ mPreferenceCategory = screen.findPreference(getPreferenceKey());
+ if (mPreferenceCategory.findPreference(KEY_ALL) == null) {
+ makeRadioPreference(KEY_ALL, R.string.zen_mode_from_all_conversations);
+ makeRadioPreference(KEY_IMPORTANT, R.string.zen_mode_from_important_conversations);
+ makeRadioPreference(KEY_NONE, R.string.zen_mode_from_no_conversations);
+ updateChannelCounts();
+ }
+
+ super.displayPreference(screen);
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ updateChannelCounts();
}
@Override
@@ -55,50 +83,98 @@
}
@Override
- public void displayPreference(PreferenceScreen screen) {
- super.displayPreference(screen);
- mPreference = screen.findPreference(KEY);
+ public String getPreferenceKey() {
+ return KEY;
}
@Override
public void updateState(Preference preference) {
- super.updateState(preference);
- updateValue(preference);
- }
+ final int currSetting = mBackend.getPriorityConversationSenders();
- @Override
- public boolean onPreferenceChange(Preference preference, Object selectedContactsFrom) {
- mBackend.saveConversationSenders(Integer.parseInt(selectedContactsFrom.toString()));
- updateValue(preference);
- return true;
- }
-
- private void updateValue(Preference preference) {
- mPreference = (ListPreference) preference;
- switch (getZenMode()) {
- case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
- case Settings.Global.ZEN_MODE_ALARMS:
- mPreference.setEnabled(false);
- mPreference.setValue(String.valueOf(CONVERSATION_SENDERS_NONE));
- mPreference.setSummary(mBackend.getAlarmsTotalSilencePeopleSummary(
- NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS));
- break;
- default:
- preference.setEnabled(true);
- preference.setSummary(mBackend.getConversationSummary());
- int senders = mBackend.getPriorityConversationSenders();
-
- switch (senders) {
- case CONVERSATION_SENDERS_NONE:
- mPreference.setValue(String.valueOf(CONVERSATION_SENDERS_NONE));
- break;
- case CONVERSATION_SENDERS_IMPORTANT:
- mPreference.setValue(String.valueOf(CONVERSATION_SENDERS_IMPORTANT));
- break;
- default:
- mPreference.setValue(String.valueOf(CONVERSATION_SENDERS_ANYONE));
- break;
- }
+ for (RadioButtonPreference pref : mRadioButtonPreferences) {
+ pref.setChecked(keyToSetting(pref.getKey()) == currSetting);
+ pref.setSummary(getSummary(pref.getKey()));
}
}
+
+ private static int keyToSetting(String key) {
+ switch (key) {
+ case KEY_ALL:
+ return NotificationManager.Policy.CONVERSATION_SENDERS_ANYONE;
+ case KEY_IMPORTANT:
+ return NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT;
+ default:
+ return NotificationManager.Policy.CONVERSATION_SENDERS_NONE;
+ }
+ }
+
+ private String getSummary(String key) {
+ int numConversations;
+ if (KEY_ALL.equals(key)) {
+ numConversations = mNumConversations;
+ } else if (KEY_IMPORTANT.equals(key)) {
+ numConversations = mNumImportantConversations;
+ } else {
+ return null;
+ }
+
+ if (numConversations == UNSET) {
+ return null;
+ } else if (numConversations == 0) {
+ return mContext.getResources().getString(
+ R.string.zen_mode_conversations_count_none);
+ } else {
+ return mContext.getResources().getQuantityString(
+ R.plurals.zen_mode_conversations_count, numConversations);
+ }
+ }
+
+ private void updateChannelCounts() {
+ // Load conversations
+ new AsyncTask<Void, Void, Void>() {
+ @Override
+ protected Void doInBackground(Void... unused) {
+ ParceledListSlice<ConversationChannelWrapper> allConversations =
+ mNotificationBackend.getConversations(false);
+ if (allConversations != null) {
+ mNumConversations = allConversations.getList().size();
+ }
+ ParceledListSlice<ConversationChannelWrapper> importantConversations =
+ mNotificationBackend.getConversations(true);
+ if (importantConversations != null) {
+ mNumImportantConversations = importantConversations.getList().size();
+ }
+ return null;
+ }
+
+ @Override
+ protected void onPostExecute(Void unused) {
+ if (mContext == null) {
+ return;
+ }
+ updateState(mPreferenceCategory);
+ }
+ }.execute();
+ }
+
+ private RadioButtonPreference makeRadioPreference(String key, int titleId) {
+ RadioButtonPreference pref = new RadioButtonPreference(mPreferenceCategory.getContext());
+ pref.setKey(key);
+ pref.setTitle(titleId);
+ pref.setOnClickListener(mRadioButtonClickListener);
+ mPreferenceCategory.addPreference(pref);
+ mRadioButtonPreferences.add(pref);
+ return pref;
+ }
+
+ private RadioButtonPreference.OnClickListener mRadioButtonClickListener =
+ new RadioButtonPreference.OnClickListener() {
+ @Override
+ public void onRadioButtonClicked(RadioButtonPreference preference) {
+ int selectedConversationSetting = keyToSetting(preference.getKey());
+ if (selectedConversationSetting != mBackend.getPriorityConversationSenders()) {
+ mBackend.saveConversationSenders(selectedConversationSetting);
+ }
+ }
+ };
}
diff --git a/src/com/android/settings/notification/zen/ZenModePriorityMessagesPreferenceController.java b/src/com/android/settings/notification/zen/ZenModePriorityMessagesPreferenceController.java
deleted file mode 100644
index 6476c63..0000000
--- a/src/com/android/settings/notification/zen/ZenModePriorityMessagesPreferenceController.java
+++ /dev/null
@@ -1,108 +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.notification.zen;
-
-import android.app.NotificationManager;
-import android.content.Context;
-import android.provider.Settings;
-import android.text.TextUtils;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.ListPreference;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-
-public class ZenModePriorityMessagesPreferenceController extends AbstractZenModePreferenceController
- implements Preference.OnPreferenceChangeListener {
-
- protected static final String KEY = "zen_mode_messages";
- private final ZenModeBackend mBackend;
- private ListPreference mPreference;
- private final String[] mListValues;
-
- public ZenModePriorityMessagesPreferenceController(Context context, Lifecycle lifecycle) {
- super(context, KEY, lifecycle);
- mBackend = ZenModeBackend.getInstance(context);
- mListValues = context.getResources().getStringArray(R.array.zen_mode_contacts_values);
- }
-
- @Override
- public String getPreferenceKey() {
- return KEY;
- }
-
- @Override
- public boolean isAvailable() {
- return true;
- }
-
- @Override
- public void displayPreference(PreferenceScreen screen) {
- super.displayPreference(screen);
- mPreference = screen.findPreference(KEY);
- }
-
- @Override
- public void updateState(Preference preference) {
- super.updateState(preference);
- updateFromContactsValue(preference);
- }
-
- @Override
- public boolean onPreferenceChange(Preference preference, Object selectedContactsFrom) {
- mBackend.saveSenders(NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES,
- ZenModeBackend.getSettingFromPrefKey(selectedContactsFrom.toString()));
- updateFromContactsValue(preference);
- return true;
- }
-
- private void updateFromContactsValue(Preference preference) {
- mPreference = (ListPreference) preference;
- switch (getZenMode()) {
- case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
- case Settings.Global.ZEN_MODE_ALARMS:
- mPreference.setEnabled(false);
- mPreference.setValue(ZenModeBackend.ZEN_MODE_FROM_NONE);
- mPreference.setSummary(mBackend.getAlarmsTotalSilencePeopleSummary(
- NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES));
- break;
- default:
- preference.setEnabled(true);
- preference.setSummary(mBackend.getContactsSummary(
- NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES));
-
- final String currentVal = ZenModeBackend.getKeyFromSetting(
- mBackend.getPriorityMessageSenders());
- mPreference.setValue(mListValues[getIndexOfSendersValue(currentVal)]);
- }
- }
-
- @VisibleForTesting
- protected int getIndexOfSendersValue(String currentVal) {
- int index = 3; // defaults to "none" based on R.array.zen_mode_contacts_values
- for (int i = 0; i < mListValues.length; i++) {
- if (TextUtils.equals(currentVal, mListValues[i])) {
- return i;
- }
- }
-
- return index;
- }
-}
diff --git a/src/com/android/settings/notification/zen/ZenModePrioritySendersPreferenceController.java b/src/com/android/settings/notification/zen/ZenModePrioritySendersPreferenceController.java
new file mode 100644
index 0000000..da7b24d
--- /dev/null
+++ b/src/com/android/settings/notification/zen/ZenModePrioritySendersPreferenceController.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification.zen;
+
+import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CALLS;
+import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES;
+
+import static com.android.settings.widget.RadioButtonPreferenceWithExtraWidget.EXTRA_WIDGET_VISIBILITY_GONE;
+import static com.android.settings.widget.RadioButtonPreferenceWithExtraWidget.EXTRA_WIDGET_VISIBILITY_SETTING;
+
+import android.app.NotificationManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.provider.Contacts;
+import android.view.View;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.R;
+import com.android.settings.widget.RadioButtonPreferenceWithExtraWidget;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.widget.RadioButtonPreference;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Common preference controller functionality shared by
+ * ZenModePriorityMessagesPreferenceController and ZenModePriorityCallsPreferenceController.
+ *
+ * This includes the options to choose the priority senders that are allowed to bypass DND for
+ * calls or messages. This can be one of four values: starred contacts, all contacts, anyone, or
+ * no one.
+ */
+public class ZenModePrioritySendersPreferenceController
+ extends AbstractZenModePreferenceController {
+ @VisibleForTesting static final String KEY_ANY = "senders_anyone";
+ @VisibleForTesting static final String KEY_CONTACTS = "senders_contacts";
+ @VisibleForTesting static final String KEY_STARRED = "senders_starred_contacts";
+ @VisibleForTesting static final String KEY_NONE = "senders_none";
+
+ private static final Intent ALL_CONTACTS_INTENT =
+ new Intent(Contacts.Intents.UI.LIST_ALL_CONTACTS_ACTION);
+ private static final Intent STARRED_CONTACTS_INTENT =
+ new Intent(Contacts.Intents.UI.LIST_STARRED_ACTION);
+ private static final Intent FALLBACK_INTENT = new Intent(Intent.ACTION_MAIN);
+
+ private final PackageManager mPackageManager;
+ private final boolean mIsMessages; // if this is false, then this preference is for calls
+
+ private PreferenceCategory mPreferenceCategory;
+ private List<RadioButtonPreferenceWithExtraWidget> mRadioButtonPreferences = new ArrayList<>();
+
+ public ZenModePrioritySendersPreferenceController(Context context, String key,
+ Lifecycle lifecycle, boolean isMessages) {
+ super(context, key, lifecycle);
+ mIsMessages = isMessages;
+
+ mPackageManager = mContext.getPackageManager();
+ if (!FALLBACK_INTENT.hasCategory(Intent.CATEGORY_APP_CONTACTS)) {
+ FALLBACK_INTENT.addCategory(Intent.CATEGORY_APP_CONTACTS);
+ }
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ mPreferenceCategory = screen.findPreference(getPreferenceKey());
+ if (mPreferenceCategory.findPreference(KEY_ANY) == null) {
+ makeRadioPreference(KEY_STARRED,
+ com.android.settings.R.string.zen_mode_from_starred);
+ makeRadioPreference(KEY_CONTACTS,
+ com.android.settings.R.string.zen_mode_from_contacts);
+ makeRadioPreference(KEY_ANY,
+ com.android.settings.R.string.zen_mode_from_anyone);
+ makeRadioPreference(KEY_NONE,
+ com.android.settings.R.string.zen_mode_from_none);
+ updateSummaries();
+ }
+
+ super.displayPreference(screen);
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return true;
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return KEY;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ final int currSetting = getPrioritySenders();
+
+ for (RadioButtonPreferenceWithExtraWidget pref : mRadioButtonPreferences) {
+ pref.setChecked(keyToSetting(pref.getKey()) == currSetting);
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ updateSummaries();
+ }
+
+ private void updateSummaries() {
+ for (RadioButtonPreferenceWithExtraWidget pref : mRadioButtonPreferences) {
+ pref.setSummary(getSummary(pref.getKey()));
+ }
+ }
+
+ private static int keyToSetting(String key) {
+ switch (key) {
+ case KEY_STARRED:
+ return NotificationManager.Policy.PRIORITY_SENDERS_STARRED;
+ case KEY_CONTACTS:
+ return NotificationManager.Policy.PRIORITY_SENDERS_CONTACTS;
+ case KEY_ANY:
+ return NotificationManager.Policy.PRIORITY_SENDERS_ANY;
+ case KEY_NONE:
+ default:
+ return ZenModeBackend.SOURCE_NONE;
+ }
+ }
+
+ private String getSummary(String key) {
+ switch (key) {
+ case KEY_STARRED:
+ return mBackend.getStarredContactsSummary(mContext);
+ case KEY_CONTACTS:
+ return mBackend.getContactsNumberSummary(mContext);
+ case KEY_ANY:
+ return mContext.getResources().getString(R.string.zen_mode_all_senders_summary,
+ mContext.getResources().getString(mIsMessages
+ ? R.string.zen_mode_messages_list
+ : R.string.zen_mode_calls_list));
+ case KEY_NONE:
+ default:
+ return null;
+ }
+ }
+
+ private int getPrioritySenders() {
+ if (mIsMessages) {
+ return mBackend.getPriorityMessageSenders();
+ } else {
+ return mBackend.getPriorityCallSenders();
+ }
+ }
+
+ private RadioButtonPreferenceWithExtraWidget makeRadioPreference(String key, int titleId) {
+ RadioButtonPreferenceWithExtraWidget pref =
+ new RadioButtonPreferenceWithExtraWidget(mPreferenceCategory.getContext());
+ View.OnClickListener widgetClickListener = getWidgetClickListener(key);
+ if (widgetClickListener != null) {
+ pref.setExtraWidgetOnClickListener(widgetClickListener);
+ pref.setExtraWidgetVisibility(EXTRA_WIDGET_VISIBILITY_SETTING);
+ } else {
+ pref.setExtraWidgetVisibility(EXTRA_WIDGET_VISIBILITY_GONE);
+ }
+
+ pref.setKey(key);
+ pref.setTitle(titleId);
+ pref.setOnClickListener(mRadioButtonClickListener);
+ mPreferenceCategory.addPreference(pref);
+ mRadioButtonPreferences.add(pref);
+ return pref;
+ }
+
+ private RadioButtonPreference.OnClickListener mRadioButtonClickListener =
+ new RadioButtonPreference.OnClickListener() {
+ @Override
+ public void onRadioButtonClicked(RadioButtonPreference preference) {
+ int selectedSetting = keyToSetting(preference.getKey());
+ if (selectedSetting != getPrioritySenders()) {
+ mBackend.saveSenders(
+ mIsMessages ? PRIORITY_CATEGORY_MESSAGES : PRIORITY_CATEGORY_CALLS,
+ selectedSetting);
+ }
+ }
+ };
+
+ private View.OnClickListener getWidgetClickListener(String key) {
+ if (!KEY_CONTACTS.equals(key) && !KEY_STARRED.equals(key)) {
+ return null;
+ }
+
+ if (KEY_STARRED.equals(key) && !isStarredIntentValid()) {
+ return null;
+ }
+
+ if (KEY_CONTACTS.equals(key) && !isContactsIntentValid()) {
+ return null;
+ }
+
+ return new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (KEY_STARRED.equals(key)
+ && STARRED_CONTACTS_INTENT.resolveActivity(mPackageManager) != null) {
+ mContext.startActivity(STARRED_CONTACTS_INTENT);
+ } else if (KEY_CONTACTS.equals(key)
+ && ALL_CONTACTS_INTENT.resolveActivity(mPackageManager) != null) {
+ mContext.startActivity(ALL_CONTACTS_INTENT);
+ } else {
+ mContext.startActivity(FALLBACK_INTENT);
+ }
+ }
+ };
+ }
+
+ private boolean isStarredIntentValid() {
+ return STARRED_CONTACTS_INTENT.resolveActivity(mPackageManager) != null
+ || FALLBACK_INTENT.resolveActivity(mPackageManager) != null;
+ }
+
+ private boolean isContactsIntentValid() {
+ return ALL_CONTACTS_INTENT.resolveActivity(mPackageManager) != null
+ || FALLBACK_INTENT.resolveActivity(mPackageManager) != null;
+ }
+}
diff --git a/src/com/android/settings/notification/zen/ZenModeSettings.java b/src/com/android/settings/notification/zen/ZenModeSettings.java
index 871974b..c92099a 100644
--- a/src/com/android/settings/notification/zen/ZenModeSettings.java
+++ b/src/com/android/settings/notification/zen/ZenModeSettings.java
@@ -25,15 +25,19 @@
import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_REPEAT_CALLERS;
import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_SYSTEM;
+import android.app.Activity;
+import android.app.Application;
import android.app.AutomaticZenRule;
import android.app.NotificationManager;
import android.app.NotificationManager.Policy;
import android.app.settings.SettingsEnums;
import android.content.Context;
+import android.icu.text.ListFormatter;
import android.provider.Settings;
import android.service.notification.ZenModeConfig;
import androidx.annotation.VisibleForTesting;
+import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentManager;
import com.android.settings.R;
@@ -67,7 +71,9 @@
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
- return buildPreferenceControllers(context, getSettingsLifecycle(), getFragmentManager());
+ final Activity activity = getActivity();
+ return buildPreferenceControllers(context, getSettingsLifecycle(), getFragmentManager(),
+ activity != null ? activity.getApplication() : null, this);
}
@Override
@@ -76,15 +82,19 @@
}
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
- Lifecycle lifecycle, FragmentManager fragmentManager) {
+ Lifecycle lifecycle, FragmentManager fragmentManager, Application app,
+ Fragment fragment) {
List<AbstractPreferenceController> controllers = new ArrayList<>();
+ controllers.add(new ZenModeButtonPreferenceController(context, lifecycle, fragmentManager));
controllers.add(new ZenModePeoplePreferenceController(context, lifecycle,
"zen_mode_behavior_people"));
- controllers.add(new ZenModeBypassingAppsPreferenceController(context, lifecycle));
- controllers.add(new ZenModeBlockedEffectsPreferenceController(context, lifecycle));
- controllers.add(new ZenModeDurationPreferenceController(context, lifecycle));
+ controllers.add(new ZenModeBypassingAppsPreferenceController(context, app,
+ fragment, lifecycle));
+ controllers.add(new ZenModeSoundVibrationPreferenceController(context, lifecycle,
+ "zen_sound_vibration_settings"));
controllers.add(new ZenModeAutomationPreferenceController(context));
- controllers.add(new ZenModeButtonPreferenceController(context, lifecycle, fragmentManager));
+ controllers.add(new ZenModeDurationPreferenceController(context, lifecycle));
+ controllers.add(new ZenModeBlockedEffectsPreferenceController(context, lifecycle));
controllers.add(new ZenModeSettingsFooterPreferenceController(context, lifecycle,
fragmentManager));
return controllers;
@@ -110,29 +120,34 @@
PRIORITY_CATEGORY_REPEAT_CALLERS,
};
- String getSoundSettingSummary(Policy policy) {
- List<String> enabledCategories = getEnabledCategories(policy,
+ String getOtherSoundCategoriesSummary(Policy policy) {
+ List<String> enabledCategories = getEnabledCategories(
+ policy,
category -> PRIORITY_CATEGORY_ALARMS == category
|| PRIORITY_CATEGORY_MEDIA == category
- || PRIORITY_CATEGORY_SYSTEM == category, false);
+ || PRIORITY_CATEGORY_SYSTEM == category
+ || PRIORITY_CATEGORY_REMINDERS == category
+ || PRIORITY_CATEGORY_EVENTS == category,
+ true);
int numCategories = enabledCategories.size();
if (numCategories == 0) {
- return mContext.getString(R.string.zen_sound_all_muted);
- } else if (numCategories == 1) {
- return mContext.getString(R.string.zen_sound_one_allowed,
- enabledCategories.get(0));
- } else if (numCategories == 2) {
- return mContext.getString(R.string.zen_sound_two_allowed,
- enabledCategories.get(0),
- enabledCategories.get(1));
- } else if (numCategories == 3) {
- return mContext.getString(R.string.zen_sound_three_allowed,
- enabledCategories.get(0),
- enabledCategories.get(1),
- enabledCategories.get(2));
- } else {
- return mContext.getString(R.string.zen_sound_none_muted);
+ return mContext.getResources().getString(R.string.zen_mode_other_sounds_none);
}
+
+ List<String> displayCategories = new ArrayList<>();
+ if (numCategories <= 2) {
+ displayCategories = enabledCategories;
+ } else {
+ displayCategories.add(enabledCategories.get(0));
+ displayCategories.add(enabledCategories.get(1));
+ displayCategories.add(mContext.getString(R.string.zen_mode_other_sounds_list_count,
+ numCategories - 2));
+ }
+
+ return mContext.getResources().getQuantityString(
+ R.plurals.zen_mode_other_sounds_summary,
+ numCategories /* quantity */,
+ ListFormatter.getInstance().format(displayCategories));
}
String getCallsSettingSummary(Policy policy) {
@@ -322,7 +337,8 @@
@Override
public List<AbstractPreferenceController> createPreferenceControllers(Context
context) {
- return buildPreferenceControllers(context, null, null);
+ return buildPreferenceControllers(context, null, null,
+ null, null);
}
};
}
diff --git a/src/com/android/settings/notification/zen/ZenModeSoundVibrationPreferenceController.java b/src/com/android/settings/notification/zen/ZenModeSoundVibrationPreferenceController.java
new file mode 100644
index 0000000..691c2ae
--- /dev/null
+++ b/src/com/android/settings/notification/zen/ZenModeSoundVibrationPreferenceController.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification.zen;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import androidx.preference.Preference;
+
+import com.android.settings.R;
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+
+/**
+ * Controls the summary for preference found at:
+ * Settings > Sound > Do Not Disturb > Alarms & other interruptions
+ */
+public class ZenModeSoundVibrationPreferenceController extends
+ AbstractZenModePreferenceController implements PreferenceControllerMixin {
+ private final String mKey;
+ private final ZenModeSettings.SummaryBuilder mSummaryBuilder;
+
+ public ZenModeSoundVibrationPreferenceController(Context context, Lifecycle lifecycle,
+ String key) {
+ super(context, key, lifecycle);
+ mKey = key;
+ mSummaryBuilder = new ZenModeSettings.SummaryBuilder(context);
+ }
+
+ @Override
+ public String getPreferenceKey() {
+ return mKey;
+ }
+
+ @Override
+ public boolean isAvailable() {
+ return true;
+ }
+
+ @Override
+ public void updateState(Preference preference) {
+ super.updateState(preference);
+
+ switch (getZenMode()) {
+ case Settings.Global.ZEN_MODE_NO_INTERRUPTIONS:
+ preference.setEnabled(false);
+ preference.setSummary(mContext.getString(R.string.zen_mode_other_sounds_none));
+ break;
+ case Settings.Global.ZEN_MODE_ALARMS:
+ preference.setEnabled(false);
+ preference.setSummary(mContext.getString(R.string.zen_mode_behavior_alarms_only));
+ break;
+ default:
+ preference.setEnabled(true);
+ preference.setSummary(mSummaryBuilder.getOtherSoundCategoriesSummary(getPolicy()));
+ }
+ }
+}
diff --git a/src/com/android/settings/notification/zen/ZenModeSoundVibrationSettings.java b/src/com/android/settings/notification/zen/ZenModeSoundVibrationSettings.java
index 3d4f3c2..c07ee77 100644
--- a/src/com/android/settings/notification/zen/ZenModeSoundVibrationSettings.java
+++ b/src/com/android/settings/notification/zen/ZenModeSoundVibrationSettings.java
@@ -21,14 +21,17 @@
import com.android.settings.R;
import com.android.settings.search.BaseSearchIndexProvider;
-import com.android.settingslib.search.Indexable;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.search.Indexable;
import com.android.settingslib.search.SearchIndexable;
import java.util.ArrayList;
import java.util.List;
+/**
+ * Settings > Sound > Do Not Disturb > Alarms & Other Interruptions
+ */
@SearchIndexable
public class ZenModeSoundVibrationSettings extends ZenModeSettingsBase implements Indexable {
@@ -40,10 +43,6 @@
private static List<AbstractPreferenceController> buildPreferenceControllers(Context context,
Lifecycle lifecycle) {
List<AbstractPreferenceController> controllers = new ArrayList<>();
- controllers.add(new ZenModeCallsPreferenceController(context, lifecycle,
- "zen_mode_calls_settings"));
- controllers.add(new ZenModeMessagesPreferenceController(context, lifecycle,
- "zen_mode_messages_settings"));
controllers.add(new ZenModeAlarmsPreferenceController(context, lifecycle,
"zen_mode_alarms"));
controllers.add(new ZenModeMediaPreferenceController(context, lifecycle));
@@ -52,7 +51,6 @@
controllers.add(new ZenModeEventsPreferenceController(context, lifecycle));
controllers.add(new ZenModeBehaviorFooterPreferenceController(context, lifecycle,
R.string.zen_sound_footer));
- controllers.add(new ZenModeBypassingAppsPreferenceController(context, lifecycle));
return controllers;
}
diff --git a/src/com/android/settings/notification/zen/ZenModeStarredContactsPreferenceController.java b/src/com/android/settings/notification/zen/ZenModeStarredContactsPreferenceController.java
deleted file mode 100644
index 64f2010..0000000
--- a/src/com/android/settings/notification/zen/ZenModeStarredContactsPreferenceController.java
+++ /dev/null
@@ -1,107 +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.notification.zen;
-
-import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CALLS;
-import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES;
-import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_STARRED;
-
-import android.content.Context;
-import android.content.Intent;
-import android.content.pm.PackageManager;
-import android.provider.Contacts;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.dashboard.DashboardFragment;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-
-public class ZenModeStarredContactsPreferenceController extends
- AbstractZenModePreferenceController implements Preference.OnPreferenceClickListener {
- private Preference mPreference;
- private final int mPriorityCategory;
- private final PackageManager mPackageManager;
-
- private Intent mStarredContactsIntent;
- private Intent mFallbackIntent;
-
- public ZenModeStarredContactsPreferenceController(Context context, Lifecycle lifecycle, int
- priorityCategory, String key) {
- super(context, key, lifecycle);
- mPriorityCategory = priorityCategory;
- mPackageManager = mContext.getPackageManager();
-
- mStarredContactsIntent = new Intent(Contacts.Intents.UI.LIST_STARRED_ACTION);
-
- mFallbackIntent = new Intent(Intent.ACTION_MAIN);
- mFallbackIntent.addCategory(Intent.CATEGORY_APP_CONTACTS);
- }
-
- @Override
- public void displayPreference(PreferenceScreen screen) {
- super.displayPreference(screen);
- mPreference = screen.findPreference(KEY);
-
- if (mPreference != null) {
- mPreference.setOnPreferenceClickListener(this);
- }
- }
-
- @Override
- public String getPreferenceKey() {
- return KEY;
- }
-
- @Override
- public boolean isAvailable() {
- if (mPriorityCategory == PRIORITY_CATEGORY_CALLS) {
- return mBackend.isPriorityCategoryEnabled(PRIORITY_CATEGORY_CALLS)
- && mBackend.getPriorityCallSenders() == PRIORITY_SENDERS_STARRED
- && isIntentValid();
- } else if (mPriorityCategory == PRIORITY_CATEGORY_MESSAGES) {
- return mBackend.isPriorityCategoryEnabled(PRIORITY_CATEGORY_MESSAGES)
- && mBackend.getPriorityMessageSenders() == PRIORITY_SENDERS_STARRED
- && isIntentValid();
- } else {
- // invalid category
- return false;
- }
- }
-
- @Override
- public CharSequence getSummary() {
- return mBackend.getStarredContactsSummary(mContext);
- }
-
- @Override
- public boolean onPreferenceClick(Preference preference) {
- mMetricsFeatureProvider.logClickedPreference(preference,
- preference.getExtras().getInt(DashboardFragment.CATEGORY));
- if (mStarredContactsIntent.resolveActivity(mPackageManager) != null) {
- mContext.startActivity(mStarredContactsIntent);
- } else {
- mContext.startActivity(mFallbackIntent);
- }
- return true;
- }
-
- private boolean isIntentValid() {
- return mStarredContactsIntent.resolveActivity(mPackageManager) != null
- || mFallbackIntent.resolveActivity(mPackageManager) != null;
- }
-}
diff --git a/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java b/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
index 70567ac..106aef9 100644
--- a/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
+++ b/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2.java
@@ -456,7 +456,8 @@
}
}
- private void updateNetworkInfo() {
+ @VisibleForTesting
+ void updateNetworkInfo() {
if (mWifiEntry.getConnectedState() == WifiEntry.CONNECTED_STATE_CONNECTED) {
mNetwork = mWifiManager.getCurrentNetwork();
mLinkProperties = mConnectivityManager.getLinkProperties(mNetwork);
@@ -632,7 +633,7 @@
}
private void refreshMacAddress() {
- String macAddress = getMacAddress();
+ String macAddress = mWifiEntry.getMacAddress();
if (macAddress == null) {
mMacAddressPref.setVisible(false);
return;
@@ -649,21 +650,6 @@
refreshMacTitle();
}
- private String getMacAddress() {
- if (mWifiEntry.isSaved() && mWifiEntry.getPrivacy() == WifiEntry.PRIVACY_RANDOMIZED_MAC) {
- return mWifiEntry.getMacAddress();
- }
-
- // return device MAC address
- final String[] macAddresses = mWifiManager.getFactoryMacAddresses();
- if (macAddresses != null && macAddresses.length > 0) {
- return macAddresses[0];
- }
-
- Log.e(TAG, "Can't get device MAC address!");
- return null;
- }
-
private void updatePreference(Preference pref, String detailText) {
if (!TextUtils.isEmpty(detailText)) {
pref.setSummary(detailText);
@@ -969,6 +955,7 @@
*/
@Override
public void onUpdated() {
+ updateNetworkInfo();
refreshPage();
// Refresh the Preferences in fragment.
diff --git a/tests/robotests/src/com/android/settings/network/ActiveSubsciptionsListenerTest.java b/tests/robotests/src/com/android/settings/network/ActiveSubsciptionsListenerTest.java
index 4c7b55b..5565ca3 100644
--- a/tests/robotests/src/com/android/settings/network/ActiveSubsciptionsListenerTest.java
+++ b/tests/robotests/src/com/android/settings/network/ActiveSubsciptionsListenerTest.java
@@ -108,6 +108,10 @@
private ActiveSubsciptionsListenerImpl(Looper looper, Context context) {
super(looper, context);
}
+
+ @Override
+ void registerForSubscriptionsChange() {}
+
public void onChanged() {}
}
diff --git a/tests/robotests/src/com/android/settings/network/SubscriptionsChangeListenerTest.java b/tests/robotests/src/com/android/settings/network/SubscriptionsChangeListenerTest.java
index 9f302df..d075655 100644
--- a/tests/robotests/src/com/android/settings/network/SubscriptionsChangeListenerTest.java
+++ b/tests/robotests/src/com/android/settings/network/SubscriptionsChangeListenerTest.java
@@ -83,7 +83,7 @@
initListener(false);
verify(contentResolver, never()).registerContentObserver(any(Uri.class), anyBoolean(),
any(ContentObserver.class));
- verify(mSubscriptionManager, never()).addOnSubscriptionsChangedListener(any());
+ verify(mSubscriptionManager, never()).addOnSubscriptionsChangedListener(any(), any());
verify(mContext, never()).registerReceiver(any(), any());
}
@@ -92,7 +92,7 @@
initListener(true);
final ArgumentCaptor<SubscriptionManager.OnSubscriptionsChangedListener> captor =
ArgumentCaptor.forClass(SubscriptionManager.OnSubscriptionsChangedListener.class);
- verify(mSubscriptionManager).addOnSubscriptionsChangedListener(captor.capture());
+ verify(mSubscriptionManager).addOnSubscriptionsChangedListener(any(), captor.capture());
captor.getValue().onSubscriptionsChanged();
verify(mClient).onSubscriptionsChanged();
}
diff --git a/tests/robotests/src/com/android/settings/notification/app/BubblePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/app/BubblePreferenceControllerTest.java
index 404625e..c2c45cb 100644
--- a/tests/robotests/src/com/android/settings/notification/app/BubblePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/app/BubblePreferenceControllerTest.java
@@ -122,7 +122,7 @@
}
@Test
- public void testIsAvailable_channel_notIfAppOff() {
+ public void testIsAvailable_channel_yesIfAppOff() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.allowBubbles = false;
@@ -130,7 +130,7 @@
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, null, null, null, null);
- assertFalse(mController.isAvailable());
+ assertTrue(mController.isAvailable());
}
@Test
@@ -200,18 +200,6 @@
}
@Test
- public void testIsAvailable_channelAppOff() {
- NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- appRow.allowBubbles = false;
- NotificationChannel channel = mock(NotificationChannel.class);
- when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
- mController.onResume(appRow, channel, null, null, null, null);
- Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
-
- assertFalse(mController.isAvailable());
- }
-
- @Test
public void testUpdateState_disabledByAdmin() {
NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getId()).thenReturn("something");
diff --git a/tests/robotests/src/com/android/settings/notification/app/ConversationImportantPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/app/ConversationImportantPreferenceControllerTest.java
deleted file mode 100644
index 42b7859..0000000
--- a/tests/robotests/src/com/android/settings/notification/app/ConversationImportantPreferenceControllerTest.java
+++ /dev/null
@@ -1,206 +0,0 @@
-/*
- * Copyright (C) 2020 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.notification.app;
-
-import static android.app.NotificationChannel.DEFAULT_CHANNEL_ID;
-import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
-import static android.app.NotificationManager.IMPORTANCE_HIGH;
-import static android.provider.Settings.Secure.BUBBLE_IMPORTANT_CONVERSATIONS;
-
-import static org.junit.Assert.assertFalse;
-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.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 androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.notification.NotificationBackend;
-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;
-
-@RunWith(RobolectricTestRunner.class)
-public class ConversationImportantPreferenceControllerTest {
-
- private Context mContext;
- @Mock
- private NotificationBackend mBackend;
- @Mock
- private NotificationManager mNm;
- @Mock
- private UserManager mUm;
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
- private PreferenceScreen mScreen;
- @Mock
- private NotificationSettings.DependentFieldListener mDependentFieldListener;
-
- private ConversationImportantPreferenceController mController;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- ShadowApplication shadowApplication = ShadowApplication.getInstance();
- shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNm);
- shadowApplication.setSystemService(Context.USER_SERVICE, mUm);
- mContext = RuntimeEnvironment.application;
- mController = spy(new ConversationImportantPreferenceController(
- mContext, mBackend, mDependentFieldListener));
- }
-
- @Test
- public void testNoCrashIfNoOnResume() {
- mController.isAvailable();
- mController.updateState(mock(Preference.class));
- mController.onPreferenceChange(mock(Preference.class), true);
- }
-
- @Test
- public void testIsAvailable_notChannelNull() {
- NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- mController.onResume(appRow, null, null, null, null, null);
- assertFalse(mController.isAvailable());
- }
-
- @Test
- public void testIsAvailable() {
- NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_DEFAULT);
- mController.onResume(appRow, channel, null, null, null, null);
- assertTrue(mController.isAvailable());
- }
-
- @Test
- public void testUpdateState_disabledByAdmin() {
- NotificationChannel channel = mock(NotificationChannel.class);
- when(channel.getId()).thenReturn("something");
- mController.onResume(new NotificationBackend.AppRow(), channel, null, null, null, mock(
- RestrictedLockUtils.EnforcedAdmin.class));
-
- Preference pref = new RestrictedSwitchPreference(RuntimeEnvironment.application);
- mController.updateState(pref);
-
- assertFalse(pref.isEnabled());
- }
-
- @Test
- public void testUpdateState() {
- NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_DEFAULT);
- channel.setImportantConversation(true);
- mController.onResume(appRow, channel, null, null, null, null);
-
- RestrictedSwitchPreference pref =
- new RestrictedSwitchPreference(RuntimeEnvironment.application);
- mController.updateState(pref);
-
- assertTrue(pref.isChecked());
-
- channel.setImportantConversation(false);
- mController.onResume(appRow, channel, null, null, null, null);
- mController.updateState(pref);
- assertFalse(pref.isChecked());
- }
-
- @Test
- public void testOnPreferenceChange_on() {
- Settings.Secure.putInt(mContext.getContentResolver(),
- BUBBLE_IMPORTANT_CONVERSATIONS, 0);
- NotificationChannel channel =
- new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_DEFAULT);
- channel.setImportantConversation(false);
- channel.setAllowBubbles(false);
- mController.onResume(new NotificationBackend.AppRow(), channel, null, null, null, null);
-
- RestrictedSwitchPreference pref =
- new RestrictedSwitchPreference(RuntimeEnvironment.application);
- mController.updateState(pref);
-
- mController.onPreferenceChange(pref, true);
-
- assertTrue(channel.isImportantConversation());
- assertFalse(channel.canBubble());
- verify(mBackend, times(1)).updateChannel(any(), anyInt(), any());
- verify(mDependentFieldListener, times(1)).onFieldValueChanged();
- }
-
- @Test
- public void testOnPreferenceChange_on_bubble() {
- Settings.Secure.putInt(mContext.getContentResolver(),
- BUBBLE_IMPORTANT_CONVERSATIONS, 1);
- NotificationChannel channel =
- new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_DEFAULT);
- channel.setImportantConversation(false);
- channel.setAllowBubbles(false);
- mController.onResume(new NotificationBackend.AppRow(), channel, null, null, null, null);
-
- RestrictedSwitchPreference pref =
- new RestrictedSwitchPreference(RuntimeEnvironment.application);
- mController.updateState(pref);
-
- mController.onPreferenceChange(pref, true);
-
- assertTrue(channel.isImportantConversation());
- assertTrue(channel.canBubble());
- verify(mBackend, times(1)).updateChannel(any(), anyInt(), any());
- verify(mDependentFieldListener).onFieldValueChanged();
- }
-
- @Test
- public void testOnPreferenceChange_off() {
- Settings.Secure.putInt(mContext.getContentResolver(),
- BUBBLE_IMPORTANT_CONVERSATIONS, 1);
- NotificationChannel channel =
- new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_HIGH);
- channel.setImportantConversation(true);
- channel.setAllowBubbles(false);
- mController.onResume(new NotificationBackend.AppRow(), channel, null, null, null, null);
-
- RestrictedSwitchPreference pref =
- new RestrictedSwitchPreference(RuntimeEnvironment.application);
- when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
- mController.displayPreference(mScreen);
- mController.updateState(pref);
-
- mController.onPreferenceChange(pref, false);
-
- assertFalse(channel.isImportantConversation());
- assertFalse(channel.canBubble());
- verify(mBackend, times(1)).updateChannel(any(), anyInt(), any());
- verify(mDependentFieldListener, times(1)).onFieldValueChanged();
- }
-}
diff --git a/tests/robotests/src/com/android/settings/notification/app/ConversationPriorityPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/app/ConversationPriorityPreferenceControllerTest.java
new file mode 100644
index 0000000..d74715c
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/app/ConversationPriorityPreferenceControllerTest.java
@@ -0,0 +1,277 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification.app;
+
+import static android.app.NotificationChannel.DEFAULT_CHANNEL_ID;
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_HIGH;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+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.anyBoolean;
+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.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.os.UserManager;
+import android.util.Pair;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.notification.NotificationBackend;
+import com.android.settingslib.RestrictedLockUtils;
+
+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;
+
+@RunWith(RobolectricTestRunner.class)
+public class ConversationPriorityPreferenceControllerTest {
+
+ private Context mContext;
+ @Mock
+ private NotificationBackend mBackend;
+ @Mock
+ private NotificationManager mNm;
+ @Mock
+ private UserManager mUm;
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private PreferenceScreen mScreen;
+ @Mock
+ private NotificationSettings.DependentFieldListener mDependentFieldListener;
+
+ private ConversationPriorityPreferenceController mController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ ShadowApplication shadowApplication = ShadowApplication.getInstance();
+ shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNm);
+ shadowApplication.setSystemService(Context.USER_SERVICE, mUm);
+ mContext = RuntimeEnvironment.application;
+ mController = spy(new ConversationPriorityPreferenceController(
+ mContext, mBackend, mDependentFieldListener));
+ }
+
+ @Test
+ public void testNoCrashIfNoOnResume() {
+ mController.isAvailable();
+ mController.updateState(mock(Preference.class));
+ mController.onPreferenceChange(mock(Preference.class), true);
+ }
+
+ @Test
+ public void testIsAvailable_notChannelNull() {
+ NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+ mController.onResume(appRow, null, null, null, null, null);
+ assertFalse(mController.isAvailable());
+ }
+
+ @Test
+ public void testIsAvailable() {
+ NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+ NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_DEFAULT);
+ mController.onResume(appRow, channel, null, null, null, null);
+ assertTrue(mController.isAvailable());
+ }
+
+ @Test
+ public void testUpdateState_disabledByAdmin() {
+ NotificationChannel channel = mock(NotificationChannel.class);
+ when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
+ mController.onResume(new NotificationBackend.AppRow(), channel, null, null, null, mock(
+ RestrictedLockUtils.EnforcedAdmin.class));
+
+ Preference pref = new ConversationPriorityPreference(mContext, null);
+ mController.updateState(pref);
+
+ assertFalse(pref.isEnabled());
+ }
+
+ @Test
+ public void testUpdateState_notConfigurable() {
+ NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+ NotificationChannel channel = mock(NotificationChannel.class);
+ when(channel.isImportanceLockedByOEM()).thenReturn(true);
+ when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
+ mController.onResume(appRow, channel, null, null, null, null);
+
+ Preference pref = new ConversationPriorityPreference(mContext, null);
+ mController.updateState(pref);
+
+ assertFalse(pref.isEnabled());
+ }
+
+ @Test
+ public void testUpdateState_systemButConfigurable() {
+ NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+ appRow.systemApp = true;
+ NotificationChannel channel = mock(NotificationChannel.class);
+ when(channel.isImportanceLockedByOEM()).thenReturn(false);
+ when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
+ mController.onResume(appRow, channel, null, null, null, null);
+
+ Preference pref = new ConversationPriorityPreference(mContext, null);
+ mController.updateState(pref);
+
+ assertTrue(pref.isEnabled());
+ }
+
+ @Test
+ public void testUpdateState_defaultApp() {
+ NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+ appRow.systemApp = true;
+ NotificationChannel channel = mock(NotificationChannel.class);
+ when(channel.isImportanceLockedByCriticalDeviceFunction()).thenReturn(true);
+ when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
+ mController.onResume(appRow, channel, null, null, null, null);
+
+ Preference pref = new ConversationPriorityPreference(mContext, null);
+ mController.updateState(pref);
+
+ assertTrue(pref.isEnabled());
+ }
+
+ @Test
+ public void testUpdateState() {
+ NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+ NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
+ channel.setImportantConversation(true);
+ channel.setOriginalImportance(IMPORTANCE_DEFAULT);
+ mController.onResume(appRow, channel, null, null, null, null);
+
+ ConversationPriorityPreference pref = mock(ConversationPriorityPreference.class);
+ mController.updateState(pref);
+
+ verify(pref, times(1)).setConfigurable(anyBoolean());
+ verify(pref, times(1)).setImportance(IMPORTANCE_HIGH);
+ verify(pref, times(1)).setOriginalImportance(IMPORTANCE_DEFAULT);
+ verify(pref, times(1)).setPriorityConversation(true);
+ }
+
+ @Test
+ public void testImportanceLowToImportant() {
+ NotificationChannel channel =
+ new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_LOW);
+ mController.onResume(new NotificationBackend.AppRow(), channel, null, null, null, null);
+
+ ConversationPriorityPreference pref = new ConversationPriorityPreference(mContext, null);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
+ mController.displayPreference(mScreen);
+ mController.updateState(pref);
+
+ mController.onPreferenceChange(pref, new Pair(IMPORTANCE_HIGH, true));
+
+ assertEquals(IMPORTANCE_HIGH, channel.getImportance());
+ assertTrue(channel.canBubble());
+ assertTrue(channel.isImportantConversation());
+ }
+ @Test
+ public void testImportanceLowToDefault() {
+ NotificationChannel channel =
+ new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_LOW);
+ channel.setAllowBubbles(false);
+ mController.onResume(new NotificationBackend.AppRow(), channel, null, null, null, null);
+
+ ConversationPriorityPreference pref = new ConversationPriorityPreference(mContext, null);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
+ mController.displayPreference(mScreen);
+ mController.updateState(pref);
+
+ mController.onPreferenceChange(pref, new Pair(IMPORTANCE_HIGH, false));
+
+ assertEquals(IMPORTANCE_HIGH, channel.getImportance());
+ assertFalse(channel.canBubble());
+ assertFalse(channel.isImportantConversation());
+ }
+
+ @Test
+ public void testImportanceDefaultToLow() {
+ NotificationChannel channel =
+ new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_DEFAULT);
+ channel.setAllowBubbles(false);
+ mController.onResume(new NotificationBackend.AppRow(), channel, null, null, null, null);
+
+ ConversationPriorityPreference pref = new ConversationPriorityPreference(mContext, null);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
+ mController.displayPreference(mScreen);
+ mController.updateState(pref);
+
+ mController.onPreferenceChange(pref, new Pair(IMPORTANCE_LOW, false));
+
+ assertEquals(IMPORTANCE_LOW, channel.getImportance());
+ assertFalse(channel.canBubble());
+ assertFalse(channel.isImportantConversation());
+ }
+
+ @Test
+ public void testImportanceLowToDefault_bubblesMaintained() {
+ NotificationChannel channel =
+ new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_LOW);
+ channel.setAllowBubbles(true);
+ mController.onResume(new NotificationBackend.AppRow(), channel, null, null, null, null);
+
+ ConversationPriorityPreference pref = new ConversationPriorityPreference(mContext, null);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
+ mController.displayPreference(mScreen);
+ mController.updateState(pref);
+
+ mController.onPreferenceChange(pref, new Pair(IMPORTANCE_DEFAULT, false));
+
+ assertEquals(IMPORTANCE_DEFAULT, channel.getImportance());
+ assertTrue(channel.canBubble());
+ assertFalse(channel.isImportantConversation());
+ }
+
+ @Test
+ public void testImportancePriorityToDefault() {
+ NotificationChannel channel =
+ new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_HIGH);
+ channel.setAllowBubbles(true);
+ channel.setImportantConversation(true);
+ mController.onResume(new NotificationBackend.AppRow(), channel, null, null, null, null);
+
+ ConversationPriorityPreference pref = new ConversationPriorityPreference(mContext, null);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
+ mController.displayPreference(mScreen);
+ mController.updateState(pref);
+
+ mController.onPreferenceChange(pref, new Pair(IMPORTANCE_HIGH, false));
+
+ assertEquals(IMPORTANCE_HIGH, channel.getImportance());
+ assertFalse(channel.canBubble());
+ assertFalse(channel.isImportantConversation());
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/app/ConversationPriorityPreferenceTest.java b/tests/robotests/src/com/android/settings/notification/app/ConversationPriorityPreferenceTest.java
new file mode 100644
index 0000000..12e1f35
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/app/ConversationPriorityPreferenceTest.java
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification.app;
+
+import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
+import static android.app.NotificationManager.IMPORTANCE_LOW;
+
+import static com.google.common.truth.Truth.assertThat;
+
+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 android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.util.Pair;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.TextView;
+
+import androidx.preference.PreferenceViewHolder;
+
+import com.android.settings.R;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+
+@RunWith(RobolectricTestRunner.class)
+public class ConversationPriorityPreferenceTest {
+
+ private Context mContext;
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ }
+
+ @Test
+ public void createNewPreference_shouldSetLayout() {
+ final ConversationPriorityPreference preference =
+ new ConversationPriorityPreference(mContext);
+ assertThat(preference.getLayoutResource()).isEqualTo(
+ R.layout.notif_priority_conversation_preference);
+ }
+
+ @Test
+ public void onBindViewHolder_nonConfigurable() {
+ final ConversationPriorityPreference preference =
+ new ConversationPriorityPreference(mContext);
+ final LayoutInflater inflater = LayoutInflater.from(mContext);
+ PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
+ inflater.inflate(preference.getLayoutResource(), null));
+ Drawable unselected = mock(Drawable.class);
+ Drawable selected = mock(Drawable.class);
+ preference.selectedBackground = selected;
+ preference.unselectedBackground = unselected;
+
+ preference.setConfigurable(false);
+ preference.setImportance(IMPORTANCE_DEFAULT);
+ preference.setPriorityConversation(true);
+ preference.onBindViewHolder(holder);
+
+ assertThat(holder.itemView.findViewById(R.id.silence).isEnabled()).isFalse();
+ assertThat(holder.itemView.findViewById(R.id.priority_group).isEnabled()).isFalse();
+ assertThat(holder.itemView.findViewById(R.id.alert).isEnabled()).isFalse();
+
+ assertThat(holder.itemView.findViewById(R.id.priority_group).getBackground())
+ .isEqualTo(selected);
+ assertThat(holder.itemView.findViewById(R.id.alert).getBackground()).isEqualTo(unselected);
+ assertThat(holder.itemView.findViewById(R.id.silence).getBackground())
+ .isEqualTo(unselected);
+
+ // other button
+ preference.setPriorityConversation(false);
+ holder = PreferenceViewHolder.createInstanceForTests(
+ inflater.inflate(preference.getLayoutResource(), null));
+ preference.onBindViewHolder(holder);
+
+ assertThat(holder.itemView.findViewById(R.id.alert).getBackground()).isEqualTo(selected);
+ assertThat(holder.itemView.findViewById(R.id.silence).getBackground())
+ .isEqualTo(unselected);
+ assertThat(holder.itemView.findViewById(R.id.priority_group).getBackground())
+ .isEqualTo(unselected);
+
+ // other other button
+ preference.setImportance(IMPORTANCE_LOW);
+ holder = PreferenceViewHolder.createInstanceForTests(
+ inflater.inflate(preference.getLayoutResource(), null));
+ preference.onBindViewHolder(holder);
+
+ assertThat(holder.itemView.findViewById(R.id.priority_group).getBackground())
+ .isEqualTo(unselected);
+ assertThat(holder.itemView.findViewById(R.id.alert).getBackground()).isEqualTo(unselected);
+ assertThat(holder.itemView.findViewById(R.id.silence).getBackground()).isEqualTo(selected);
+ }
+
+ @Test
+ public void onBindViewHolder_selectButtonAndText() {
+ final ConversationPriorityPreference preference =
+ new ConversationPriorityPreference(mContext);
+ final LayoutInflater inflater = LayoutInflater.from(mContext);
+ final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
+ inflater.inflate(preference.getLayoutResource(), null));
+ Drawable unselected = mock(Drawable.class);
+ Drawable selected = mock(Drawable.class);
+ preference.selectedBackground = selected;
+ preference.unselectedBackground = unselected;
+
+ preference.setConfigurable(true);
+ preference.setImportance(IMPORTANCE_LOW);
+ preference.setPriorityConversation(true);
+
+ preference.onBindViewHolder(holder);
+
+ assertThat(holder.itemView.findViewById(R.id.priority_group).getBackground())
+ .isEqualTo(unselected);
+ assertThat(holder.itemView.findViewById(R.id.alert).getBackground()).isEqualTo(unselected);
+ assertThat(holder.itemView.findViewById(R.id.silence).getBackground())
+ .isEqualTo(selected);
+ assertThat(holder.itemView.findViewById(R.id.silence_summary).getVisibility())
+ .isEqualTo(View.VISIBLE);
+ }
+
+ @Test
+ public void onClick_changesUICallsListener() {
+ final ConversationPriorityPreference preference =
+ spy(new ConversationPriorityPreference(mContext));
+ final LayoutInflater inflater = LayoutInflater.from(mContext);
+ final PreferenceViewHolder holder = PreferenceViewHolder.createInstanceForTests(
+ inflater.inflate(preference.getLayoutResource(), null));
+ Drawable unselected = mock(Drawable.class);
+ Drawable selected = mock(Drawable.class);
+ preference.selectedBackground = selected;
+ preference.unselectedBackground = unselected;
+
+ preference.setConfigurable(true);
+ preference.setImportance(IMPORTANCE_DEFAULT);
+ preference.setPriorityConversation(true);
+ preference.setOriginalImportance(IMPORTANCE_DEFAULT);
+ preference.onBindViewHolder(holder);
+
+ View silenceButton = holder.itemView.findViewById(R.id.silence);
+
+ silenceButton.callOnClick();
+
+ assertThat(holder.itemView.findViewById(R.id.alert).getBackground()).isEqualTo(unselected);
+ assertThat(holder.itemView.findViewById(R.id.priority_group).getBackground())
+ .isEqualTo(unselected);
+ assertThat(holder.itemView.findViewById(R.id.silence).getBackground())
+ .isEqualTo(selected);
+
+ verify(preference, times(1)).callChangeListener(new Pair(IMPORTANCE_LOW, false));
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/app/DefaultImportancePreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/app/DefaultImportancePreferenceControllerTest.java
deleted file mode 100644
index 5b85322..0000000
--- a/tests/robotests/src/com/android/settings/notification/app/DefaultImportancePreferenceControllerTest.java
+++ /dev/null
@@ -1,246 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.notification.app;
-
-import static android.app.NotificationChannel.DEFAULT_CHANNEL_ID;
-import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
-import static android.app.NotificationManager.IMPORTANCE_HIGH;
-import static android.app.NotificationManager.IMPORTANCE_LOW;
-import static android.app.NotificationManager.IMPORTANCE_NONE;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-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 androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.notification.NotificationBackend;
-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;
-
-@RunWith(RobolectricTestRunner.class)
-public class DefaultImportancePreferenceControllerTest {
-
- private Context mContext;
- @Mock
- private NotificationManager mNm;
- @Mock
- private NotificationBackend mBackend;
- @Mock
- private NotificationSettings.DependentFieldListener mDependentFieldListener;
- @Mock
- private UserManager mUm;
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
- private PreferenceScreen mScreen;
-
- private DefaultImportancePreferenceController mController;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- ShadowApplication shadowApplication = ShadowApplication.getInstance();
- shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNm);
- shadowApplication.setSystemService(Context.USER_SERVICE, mUm);
- mContext = RuntimeEnvironment.application;
- mController = spy(new DefaultImportancePreferenceController(
- mContext, mDependentFieldListener, mBackend));
- }
-
- @Test
- public void testNoCrashIfNoOnResume() {
- mController.isAvailable();
- mController.updateState(mock(Preference.class));
- }
-
- @Test
- public void testIsAvailable_notIfNull() {
- mController.onResume(null, null, null, null, null, null);
- assertFalse(mController.isAvailable());
- }
-
- @Test
- public void testIsAvailable_ifAppBlocked() {
- NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- appRow.banned = true;
- mController.onResume(appRow, mock(NotificationChannel.class), null, null, null, null);
- assertFalse(mController.isAvailable());
- }
-
- @Test
- public void testIsAvailable_notIfChannelBlocked() {
- NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- NotificationChannel channel = mock(NotificationChannel.class);
- when(channel.getImportance()).thenReturn(IMPORTANCE_NONE);
- mController.onResume(appRow, channel, null, null, null, null);
- assertFalse(mController.isAvailable());
- }
-
- @Test
- public void testIsAvailable_notForDefaultChannel() {
- NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- NotificationChannel channel = mock(NotificationChannel.class);
- when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
- when(channel.getId()).thenReturn(DEFAULT_CHANNEL_ID);
- mController.onResume(appRow, channel, null, null, null, null);
- assertFalse(mController.isAvailable());
- }
-
- @Test
- public void testIsAvailable() {
- NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- NotificationChannel channel = mock(NotificationChannel.class);
- when(channel.getImportance()).thenReturn(IMPORTANCE_DEFAULT);
- mController.onResume(appRow, channel, null, null, null, null);
- assertTrue(mController.isAvailable());
- }
-
- @Test
- public void testUpdateState_disabledByAdmin() {
- NotificationChannel channel = mock(NotificationChannel.class);
- when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
- mController.onResume(new NotificationBackend.AppRow(), channel, null, null, null, mock(
- RestrictedLockUtils.EnforcedAdmin.class));
-
- Preference pref = new RestrictedSwitchPreference(mContext, null);
- mController.updateState(pref);
-
- assertFalse(pref.isEnabled());
- }
-
- @Test
- public void testUpdateState_notConfigurable() {
- NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- NotificationChannel channel = mock(NotificationChannel.class);
- when(channel.isImportanceLockedByOEM()).thenReturn(true);
- when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
- mController.onResume(appRow, channel, null, null, null, null);
-
- Preference pref = new RestrictedSwitchPreference(mContext, null);
- mController.updateState(pref);
-
- assertFalse(pref.isEnabled());
- }
-
- @Test
- public void testUpdateState_systemButConfigurable() {
- NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- appRow.systemApp = true;
- NotificationChannel channel = mock(NotificationChannel.class);
- when(channel.isImportanceLockedByOEM()).thenReturn(false);
- when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
- mController.onResume(appRow, channel, null, null, null, null);
-
- Preference pref = new RestrictedSwitchPreference(mContext, null);
- mController.updateState(pref);
-
- assertTrue(pref.isEnabled());
- }
-
- @Test
- public void testUpdateState_defaultApp() {
- NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- appRow.systemApp = true;
- NotificationChannel channel = mock(NotificationChannel.class);
- when(channel.isImportanceLockedByCriticalDeviceFunction()).thenReturn(true);
- when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
- mController.onResume(appRow, channel, null, null, null, null);
-
- Preference pref = new RestrictedSwitchPreference(mContext, null);
- mController.updateState(pref);
-
- assertTrue(pref.isEnabled());
- }
-
- @Test
- public void testUpdateState_default() {
- NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_DEFAULT);
- mController.onResume(appRow, channel, null, null, null, null);
-
- RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext);
- mController.updateState(pref);
-
- assertTrue(pref.isChecked());
- }
-
- @Test
- public void testUpdateState_low() {
- NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_LOW);
- mController.onResume(appRow, channel, null, null, null, null);
-
- RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext);
- mController.updateState(pref);
-
- assertFalse(pref.isChecked());
- }
-
- @Test
- public void onPreferenceChange_onToOff() {
- NotificationChannel channel =
- new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_HIGH);
- mController.onResume(new NotificationBackend.AppRow(), channel, null, null, null, null);
-
- RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext, null);
- when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
- mController.displayPreference(mScreen);
- mController.updateState(pref);
-
- mController.onPreferenceChange(pref, false);
-
- assertEquals(IMPORTANCE_LOW, channel.getImportance());
- verify(mDependentFieldListener, times(1)).onFieldValueChanged();
- }
-
- @Test
- public void onPreferenceChange_offToOn() {
- NotificationChannel channel =
- new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_LOW);
- mController.onResume(new NotificationBackend.AppRow(), channel, null, null, null, null);
-
- RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext, null);
- when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
- mController.displayPreference(mScreen);
- mController.updateState(pref);
-
- mController.onPreferenceChange(pref, true);
-
- assertEquals(IMPORTANCE_DEFAULT, channel.getImportance());
- verify(mDependentFieldListener, times(1)).onFieldValueChanged();
- }
-}
diff --git a/tests/robotests/src/com/android/settings/notification/zen/ZenModeBypassingAppsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/zen/ZenModeBypassingAppsPreferenceControllerTest.java
index 8760d4c..a6efaaf 100644
--- a/tests/robotests/src/com/android/settings/notification/zen/ZenModeBypassingAppsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/zen/ZenModeBypassingAppsPreferenceControllerTest.java
@@ -18,16 +18,23 @@
import static com.google.common.truth.Truth.assertThat;
-import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
+import android.app.NotificationChannel;
import android.content.Context;
+import android.content.pm.ApplicationInfo;
+import android.content.pm.ParceledListSlice;
+import android.provider.Settings;
+
+import androidx.fragment.app.Fragment;
+import androidx.preference.Preference;
import com.android.settings.notification.NotificationBackend;
-import com.android.settings.notification.zen.ZenModeBypassingAppsPreferenceController;
+import com.android.settingslib.applications.ApplicationsState;
import com.android.settingslib.core.lifecycle.Lifecycle;
+import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
@@ -37,6 +44,9 @@
import org.robolectric.RuntimeEnvironment;
import org.robolectric.util.ReflectionHelpers;
+import java.util.ArrayList;
+import java.util.List;
+
@RunWith(RobolectricTestRunner.class)
public class ZenModeBypassingAppsPreferenceControllerTest {
@@ -45,30 +55,156 @@
private Context mContext;
@Mock
private NotificationBackend mBackend;
+ private int mPreviousZenSetting;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
mContext = RuntimeEnvironment.application;
-
- mController = new ZenModeBypassingAppsPreferenceController(mContext, mock(Lifecycle.class));
+ mController = new ZenModeBypassingAppsPreferenceController(
+ mContext, null, mock(Fragment.class), mock(Lifecycle.class));
+ mController.mPreference = new Preference(mContext);
+ mPreviousZenSetting =
+ Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.ZEN_MODE,
+ Settings.Global.ZEN_MODE_OFF);
ReflectionHelpers.setField(mController, "mNotificationBackend", mBackend);
}
+ @After
+ public void tearDown() {
+ Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ZEN_MODE,
+ mPreviousZenSetting);
+ }
+
@Test
public void testIsAvailable() {
- when(mBackend.getNumAppsBypassingDnd(anyInt())).thenReturn(5);
assertThat(mController.isAvailable()).isTrue();
}
@Test
- public void testNotAvailable() {
- when(mBackend.getNumAppsBypassingDnd(anyInt())).thenReturn(0);
- assertThat(mController.isAvailable()).isFalse();
+ public void testUpdateBypassingApps() {
+ // GIVEN DND is off
+ Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ZEN_MODE,
+ Settings.Global.ZEN_MODE_OFF);
+
+ // mock app list
+ ApplicationsState.AppEntry entry = mock(ApplicationsState.AppEntry.class);
+ entry.info = new ApplicationInfo();
+ entry.info.packageName = "test";
+ entry.label = "test";
+ entry.info.uid = 0;
+
+ List<ApplicationsState.AppEntry> appEntries = new ArrayList<>();
+ appEntries.add(entry);
+
+ List<NotificationChannel> channelsBypassing = new ArrayList<>();
+ channelsBypassing.add(mock(NotificationChannel.class));
+
+ when(mBackend.getNotificationChannelsBypassingDnd(entry.info.packageName,
+ entry.info.uid)).thenReturn(new ParceledListSlice<>(channelsBypassing));
+
+ // WHEN a single app is passed to the controller
+ mController.updateAppsBypassingDndSummaryText(appEntries);
+
+ // THEN the preference is enabled and the summary contains the app name from the list
+ assertThat(mController.mPreference.isEnabled()).isTrue();
+ assertThat(mController.getSummary().contains(entry.label)).isTrue();
}
@Test
- public void testHasSummary() {
- assertThat(mController.getSummary()).isNotNull();
+ public void testUpdateBypassingApps_multipleApps() {
+ // GIVEN DND is off
+ Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ZEN_MODE,
+ Settings.Global.ZEN_MODE_OFF);
+
+ // mock app list
+ ApplicationsState.AppEntry entry1 = mock(ApplicationsState.AppEntry.class);
+ entry1.info = new ApplicationInfo();
+ entry1.info.packageName = "test1";
+ entry1.label = "test1";
+ entry1.info.uid = 1;
+ ApplicationsState.AppEntry entry2 = mock(ApplicationsState.AppEntry.class);
+ entry2.info = new ApplicationInfo();
+ entry2.info.packageName = "test2";
+ entry2.label = "test2";
+ entry2.info.uid = 2;
+
+ List<ApplicationsState.AppEntry> appEntries = new ArrayList<>();
+ appEntries.add(entry1);
+ appEntries.add(entry2);
+
+ List<NotificationChannel> channelsBypassing = new ArrayList<>();
+ channelsBypassing.add(mock(NotificationChannel.class));
+
+ when(mBackend.getNotificationChannelsBypassingDnd(entry1.info.packageName,
+ entry1.info.uid)).thenReturn(new ParceledListSlice<>(channelsBypassing));
+ when(mBackend.getNotificationChannelsBypassingDnd(entry2.info.packageName,
+ entry2.info.uid)).thenReturn(new ParceledListSlice<>(channelsBypassing));
+
+ // WHEN a list of apps is passed to the controller
+ mController.updateAppsBypassingDndSummaryText(appEntries);
+
+ // THEN the preference is enabled and the summary contains the app names from the list
+ assertThat(mController.mPreference.isEnabled()).isTrue();
+ assertThat(mController.getSummary().contains(entry1.label)).isTrue();
+ assertThat(mController.getSummary().contains(entry2.label)).isTrue();
+ }
+
+ @Test
+ public void testUpdateAppsBypassingDnd_nullAppsList() {
+ // GIVEN DND is off
+ Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ZEN_MODE,
+ Settings.Global.ZEN_MODE_OFF);
+
+ // WHEN the list of apps is null
+ mController.updateAppsBypassingDndSummaryText(null);
+
+ // THEN the preference is enabled and summary is unchanged (in this case, null)
+ assertThat(mController.mPreference.isEnabled()).isTrue();
+ assertThat(mController.getSummary()).isNull();
+ }
+
+ @Test
+ public void testUpdateAppsBypassingDnd_emptyAppsList() {
+ // GIVEN the DND is off
+ Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ZEN_MODE,
+ Settings.Global.ZEN_MODE_OFF);
+
+ // WHEN the list of apps is an empty list
+ mController.updateAppsBypassingDndSummaryText(new ArrayList<>());
+
+ // THEN the preference is enabled and summary is updated
+ assertThat(mController.mPreference.isEnabled()).isTrue();
+ assertThat(mController.getSummary().contains("No apps")).isTrue();
+ }
+
+ @Test
+ public void testUpdateAppsBypassingDnd_alarmsOnly() {
+ // GIVEN alarms only DND mode
+ Settings.Global.putInt(mContext.getContentResolver(), Settings.Global.ZEN_MODE,
+ Settings.Global.ZEN_MODE_ALARMS);
+
+ // mock app entries
+ ApplicationsState.AppEntry entry = mock(ApplicationsState.AppEntry.class);
+ entry.info = new ApplicationInfo();
+ entry.info.packageName = "test";
+ entry.label = "test";
+ entry.info.uid = 0;
+
+ List<ApplicationsState.AppEntry> appEntries = new ArrayList<>();
+ appEntries.add(entry);
+
+ List<NotificationChannel> channelsBypassing = new ArrayList<>();
+ channelsBypassing.add(mock(NotificationChannel.class));
+ when(mBackend.getNotificationChannelsBypassingDnd(entry.info.packageName,
+ entry.info.uid)).thenReturn(new ParceledListSlice<>(channelsBypassing));
+
+ // WHEN we update apps bypassing dnd summary text
+ mController.updateAppsBypassingDndSummaryText(appEntries);
+
+ // THEN the preference is disabled and the summary says no apps can bypass
+ assertThat(mController.mPreference.isEnabled()).isFalse();
+ assertThat(mController.getSummary().contains("No apps")).isTrue();
}
}
diff --git a/tests/robotests/src/com/android/settings/notification/zen/ZenModePriorityConversationsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/zen/ZenModePriorityConversationsPreferenceControllerTest.java
index 1583b91..a8a8a7a 100644
--- a/tests/robotests/src/com/android/settings/notification/zen/ZenModePriorityConversationsPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/zen/ZenModePriorityConversationsPreferenceControllerTest.java
@@ -19,173 +19,131 @@
import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_ANYONE;
import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_IMPORTANT;
import static android.app.NotificationManager.Policy.CONVERSATION_SENDERS_NONE;
-import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CONVERSATIONS;
-import static android.provider.Settings.Global.ZEN_MODE;
-import static android.provider.Settings.Global.ZEN_MODE_ALARMS;
-import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
-import static android.provider.Settings.Global.ZEN_MODE_NO_INTERRUPTIONS;
+import static com.android.settings.notification.zen.ZenModePriorityConversationsPreferenceController.KEY_ALL;
+import static com.android.settings.notification.zen.ZenModePriorityConversationsPreferenceController.KEY_IMPORTANT;
+import static com.android.settings.notification.zen.ZenModePriorityConversationsPreferenceController.KEY_NONE;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.NotificationManager;
import android.content.ContentResolver;
import android.content.Context;
-import android.provider.Settings;
-import androidx.preference.ListPreference;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceScreen;
-import com.android.settings.R;
+import com.android.settings.notification.NotificationBackend;
import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.widget.RadioButtonPreference;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
-import org.robolectric.shadows.ShadowApplication;
import org.robolectric.util.ReflectionHelpers;
+import java.util.List;
+
@RunWith(RobolectricTestRunner.class)
public class ZenModePriorityConversationsPreferenceControllerTest {
private ZenModePriorityConversationsPreferenceController mController;
@Mock
- private ZenModeBackend mBackend;
+ private ZenModeBackend mZenBackend;
@Mock
- private NotificationManager mNotificationManager;
- @Mock
- private ListPreference mockPref;
+ private PreferenceCategory mMockPrefCategory;
@Mock
private NotificationManager.Policy mPolicy;
@Mock
private PreferenceScreen mPreferenceScreen;
+ @Mock
+ private NotificationBackend mNotifBackend;
+
+ private List<RadioButtonPreference> mRadioButtonPreferences;
private ContentResolver mContentResolver;
private Context mContext;
-
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
- ShadowApplication shadowApplication = ShadowApplication.getInstance();
- shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
-
mContext = RuntimeEnvironment.application;
- mContentResolver = RuntimeEnvironment.application.getContentResolver();
- when(mNotificationManager.getNotificationPolicy()).thenReturn(mPolicy);
-
- when(mBackend.getPriorityConversationSenders())
- .thenReturn(CONVERSATION_SENDERS_IMPORTANT);
- when(mBackend.getAlarmsTotalSilencePeopleSummary(PRIORITY_CATEGORY_CONVERSATIONS))
- .thenCallRealMethod();
- when(mBackend.getConversationSummary()).thenCallRealMethod();
-
mController = new ZenModePriorityConversationsPreferenceController(
- mContext, mock(Lifecycle.class));
- ReflectionHelpers.setField(mController, "mBackend", mBackend);
+ mContext, "test_key", mock(Lifecycle.class), mNotifBackend);
+ ReflectionHelpers.setField(mController, "mBackend", mZenBackend);
- when(mPreferenceScreen.findPreference(mController.getPreferenceKey())).thenReturn(mockPref);
+ when(mMockPrefCategory.getContext()).thenReturn(mContext);
+ when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
+ .thenReturn(mMockPrefCategory);
+ captureRadioButtons();
+ }
+
+ @Test
+ public void displayPreference_radioButtonsCreatedOnlyOnce() {
+ when(mMockPrefCategory.findPreference(any())).thenReturn(mock(Preference.class));
+
+ // radio buttons were already created, so don't re-create them
mController.displayPreference(mPreferenceScreen);
+ verify(mMockPrefCategory, never()).addPreference(any());
}
@Test
- public void updateState_TotalSilence() {
- Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_NO_INTERRUPTIONS);
+ public void clickAllConversations() {
+ RadioButtonPreference allConversationsRb = getButton(KEY_ALL);
+ allConversationsRb.onClick();
- when(mBackend.isPriorityCategoryEnabled(PRIORITY_CATEGORY_CONVERSATIONS)).thenReturn(true);
- final ListPreference mockPref = mock(ListPreference.class);
- mController.updateState(mockPref);
-
- verify(mockPref).setEnabled(false);
- verify(mockPref).setSummary(R.string.zen_mode_from_no_conversations);
+ verify(mZenBackend).saveConversationSenders(CONVERSATION_SENDERS_ANYONE);
}
@Test
- public void updateState_AlarmsOnly() {
- Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_ALARMS);
+ public void clickImportantConversations() {
+ RadioButtonPreference importantConversationsRb = getButton(KEY_IMPORTANT);
+ importantConversationsRb.onClick();
- final ListPreference mockPref = mock(ListPreference.class);
- mController.updateState(mockPref);
-
- verify(mockPref).setEnabled(false);
- verify(mockPref).setSummary(R.string.zen_mode_from_no_conversations);
+ verify(mZenBackend).saveConversationSenders(CONVERSATION_SENDERS_IMPORTANT);
}
@Test
- public void updateState_Priority_important() {
- Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
- when(mBackend.isPriorityCategoryEnabled(PRIORITY_CATEGORY_CONVERSATIONS)).thenReturn(true);
+ public void clickNoConversations() {
+ RadioButtonPreference noConversationsRb = getButton(KEY_NONE);
+ noConversationsRb.onClick();
- mController.updateState(mockPref);
-
- verify(mockPref).setEnabled(true);
- verify(mockPref).setSummary(R.string.zen_mode_from_important_conversations);
- verify(mockPref).setValue(String.valueOf(CONVERSATION_SENDERS_IMPORTANT));
+ verify(mZenBackend)
+ .saveConversationSenders(CONVERSATION_SENDERS_NONE);
}
- @Test
- public void updateState_Priority_all() {
- Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
- when(mBackend.getPriorityConversationSenders()).thenReturn(CONVERSATION_SENDERS_ANYONE);
- when(mBackend.isPriorityCategoryEnabled(PRIORITY_CATEGORY_CONVERSATIONS)).thenReturn(true);
+ private void captureRadioButtons() {
+ ArgumentCaptor<RadioButtonPreference> rbCaptor =
+ ArgumentCaptor.forClass(RadioButtonPreference.class);
+ mController.displayPreference(mPreferenceScreen);
+ // verifies 3 buttons were added
+ verify(mMockPrefCategory, times(3)).addPreference(rbCaptor.capture());
+ mRadioButtonPreferences = rbCaptor.getAllValues();
+ assertThat(mRadioButtonPreferences.size()).isEqualTo(3);
- mController.updateState(mockPref);
-
- verify(mockPref).setEnabled(true);
- verify(mockPref).setSummary(R.string.zen_mode_from_all_conversations);
- verify(mockPref).setValue(String.valueOf(CONVERSATION_SENDERS_ANYONE));
+ reset(mMockPrefCategory);
}
- @Test
- public void updateState_Priority_none() {
- Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
- when(mBackend.getPriorityConversationSenders()).thenReturn(CONVERSATION_SENDERS_NONE);
- when(mBackend.isPriorityCategoryEnabled(PRIORITY_CATEGORY_CONVERSATIONS)).thenReturn(false);
-
- mController.updateState(mockPref);
-
- verify(mockPref).setEnabled(true);
- verify(mockPref).setSummary(R.string.zen_mode_from_no_conversations);
- verify(mockPref).setValue(String.valueOf(CONVERSATION_SENDERS_NONE));
- }
-
- @Test
- public void onPreferenceChange_noneToImportant() {
- // start with none
-
- Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
- when(mBackend.getPriorityConversationSenders()).thenReturn(CONVERSATION_SENDERS_NONE);
- when(mBackend.isPriorityCategoryEnabled(PRIORITY_CATEGORY_CONVERSATIONS)).thenReturn(false);
-
- mController.updateState(mockPref);
- reset(mBackend);
-
- mController.onPreferenceChange(mockPref, String.valueOf(CONVERSATION_SENDERS_IMPORTANT));
-
- verify(mBackend).saveConversationSenders(CONVERSATION_SENDERS_IMPORTANT);
- verify(mBackend).getPriorityConversationSenders();
- }
-
- @Test
- public void onPreferenceChange_allToNone() {
- // start with none
-
- Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
- when(mBackend.getPriorityConversationSenders()).thenReturn(CONVERSATION_SENDERS_ANYONE);
- when(mBackend.isPriorityCategoryEnabled(PRIORITY_CATEGORY_CONVERSATIONS)).thenReturn(true);
-
- mController.updateState(mockPref);
- reset(mBackend);
-
- mController.onPreferenceChange(mockPref, String.valueOf(CONVERSATION_SENDERS_NONE));
-
- verify(mBackend).saveConversationSenders(CONVERSATION_SENDERS_NONE);
- verify(mBackend).getPriorityConversationSenders();
+ private RadioButtonPreference getButton(String key) {
+ for (RadioButtonPreference pref : mRadioButtonPreferences) {
+ if (key.equals(pref.getKey())) {
+ return pref;
+ }
+ }
+ return null;
}
}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/notification/zen/ZenModePriorityMessagesPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/zen/ZenModePriorityMessagesPreferenceControllerTest.java
deleted file mode 100644
index 7af2211..0000000
--- a/tests/robotests/src/com/android/settings/notification/zen/ZenModePriorityMessagesPreferenceControllerTest.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright (C) 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.notification.zen;
-
-import static android.provider.Settings.Global.ZEN_MODE;
-import static android.provider.Settings.Global.ZEN_MODE_ALARMS;
-import static android.provider.Settings.Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
-import static android.provider.Settings.Global.ZEN_MODE_NO_INTERRUPTIONS;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.app.NotificationManager;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.provider.Settings;
-
-import androidx.preference.ListPreference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.R;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.shadows.ShadowApplication;
-import org.robolectric.util.ReflectionHelpers;
-
-@RunWith(RobolectricTestRunner.class)
-public class ZenModePriorityMessagesPreferenceControllerTest {
-
- private ZenModePriorityMessagesPreferenceController mController;
-
- @Mock
- private ZenModeBackend mBackend;
- @Mock
- private NotificationManager mNotificationManager;
- @Mock
- private ListPreference mockPref;
- @Mock
- private NotificationManager.Policy mPolicy;
- @Mock
- private PreferenceScreen mPreferenceScreen;
- private ContentResolver mContentResolver;
- private Context mContext;
-
- /**
- * Array Values Key
- * 0: anyone
- * 1: contacts
- * 2: starred
- * 3: none
- */
- private String[] mValues;
-
- @Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
- ShadowApplication shadowApplication = ShadowApplication.getInstance();
- shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
-
- mContext = RuntimeEnvironment.application;
- mValues = mContext.getResources().getStringArray(R.array.zen_mode_contacts_values);
- mContentResolver = RuntimeEnvironment.application.getContentResolver();
- when(mNotificationManager.getNotificationPolicy()).thenReturn(mPolicy);
-
- when(mBackend.getPriorityMessageSenders())
- .thenReturn(NotificationManager.Policy.PRIORITY_SENDERS_STARRED);
- when(mBackend.getAlarmsTotalSilencePeopleSummary(
- NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES)).thenCallRealMethod();
- when(mBackend.getContactsSummary(NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES))
- .thenCallRealMethod();
-
- mController = new ZenModePriorityMessagesPreferenceController(mContext, mock(Lifecycle.class));
- ReflectionHelpers.setField(mController, "mBackend", mBackend);
-
- when(mPreferenceScreen.findPreference(mController.getPreferenceKey())).thenReturn(mockPref);
- mController.displayPreference(mPreferenceScreen);
- }
-
- @Test
- public void updateState_TotalSilence() {
- Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_NO_INTERRUPTIONS);
-
- when(mBackend.isPriorityCategoryEnabled(
- NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES))
- .thenReturn(false);
- final ListPreference mockPref = mock(ListPreference.class);
- mController.updateState(mockPref);
-
- verify(mockPref).setEnabled(false);
- verify(mockPref).setSummary(R.string.zen_mode_from_none_messages);
- }
-
- @Test
- public void updateState_AlarmsOnly() {
- Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_ALARMS);
-
- final ListPreference mockPref = mock(ListPreference.class);
- mController.updateState(mockPref);
-
- verify(mockPref).setEnabled(false);
- verify(mockPref).setSummary(R.string.zen_mode_from_none_messages);
- }
-
- @Test
- public void updateState_Priority() {
- Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
-
- when(mBackend.isPriorityCategoryEnabled(
- NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES))
- .thenReturn(true);
-
- mController.updateState(mockPref);
-
- verify(mockPref).setEnabled(true);
- verify(mockPref).setSummary(R.string.zen_mode_from_starred);
- }
-
- @Test
- public void onPreferenceChange_setSelectedContacts_any() {
- Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
- when(mBackend.getPriorityMessageSenders()).thenReturn(
- NotificationManager.Policy.PRIORITY_SENDERS_ANY);
- mController.updateState(mockPref);
- verify(mockPref).setValue(mValues[mController.getIndexOfSendersValue(
- ZenModeBackend.ZEN_MODE_FROM_ANYONE)]);
- }
-
- @Test
- public void onPreferenceChange_setSelectedContacts_none() {
- Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
- when(mBackend.getPriorityMessageSenders()).thenReturn(ZenModeBackend.SOURCE_NONE);
- mController.updateState(mockPref);
- verify(mockPref).setValue(mValues[mController.getIndexOfSendersValue(
- ZenModeBackend.ZEN_MODE_FROM_NONE)]);
- }
-
- @Test
- public void onPreferenceChange_setSelectedContacts_starred() {
- Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
- when(mBackend.getPriorityMessageSenders()).thenReturn(
- NotificationManager.Policy.PRIORITY_SENDERS_STARRED);
- mController.updateState(mockPref);
- verify(mockPref).setValue(mValues[mController.getIndexOfSendersValue(
- ZenModeBackend.ZEN_MODE_FROM_STARRED)]);
- }
-
- @Test
- public void onPreferenceChange_setSelectedContacts_contacts() {
- Settings.Global.putInt(mContentResolver, ZEN_MODE, ZEN_MODE_IMPORTANT_INTERRUPTIONS);
- when(mBackend.getPriorityMessageSenders()).thenReturn(
- NotificationManager.Policy.PRIORITY_SENDERS_CONTACTS);
- mController.updateState(mockPref);
- verify(mockPref).setValue(mValues[mController.getIndexOfSendersValue(
- ZenModeBackend.ZEN_MODE_FROM_CONTACTS)]);
- }
-}
\ No newline at end of file
diff --git a/tests/robotests/src/com/android/settings/notification/zen/ZenModePrioritySendersPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/zen/ZenModePrioritySendersPreferenceControllerTest.java
new file mode 100644
index 0000000..7dde1cd
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/zen/ZenModePrioritySendersPreferenceControllerTest.java
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.settings.notification.zen;
+
+import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES;
+import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_ANY;
+import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_CONTACTS;
+import static android.app.NotificationManager.Policy.PRIORITY_SENDERS_STARRED;
+
+import static com.android.settings.notification.zen.ZenModePrioritySendersPreferenceController.KEY_ANY;
+import static com.android.settings.notification.zen.ZenModePrioritySendersPreferenceController.KEY_CONTACTS;
+import static com.android.settings.notification.zen.ZenModePrioritySendersPreferenceController.KEY_NONE;
+import static com.android.settings.notification.zen.ZenModePrioritySendersPreferenceController.KEY_STARRED;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Matchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.reset;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.app.NotificationManager;
+import android.content.ContentResolver;
+import android.content.Context;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceCategory;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.notification.NotificationBackend;
+import com.android.settingslib.core.lifecycle.Lifecycle;
+import com.android.settingslib.widget.RadioButtonPreference;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.RobolectricTestRunner;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.util.ReflectionHelpers;
+
+import java.util.List;
+
+@RunWith(RobolectricTestRunner.class)
+public class ZenModePrioritySendersPreferenceControllerTest {
+
+ private ZenModePrioritySendersPreferenceController mMessagesController;
+
+ @Mock
+ private ZenModeBackend mZenBackend;
+ @Mock
+ private PreferenceCategory mMockPrefCategory;
+ @Mock
+ private NotificationManager.Policy mPolicy;
+ @Mock
+ private PreferenceScreen mPreferenceScreen;
+ @Mock
+ private NotificationBackend mNotifBackend;
+
+ private List<RadioButtonPreference> mRadioButtonPreferences;
+ private ContentResolver mContentResolver;
+ private Context mContext;
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mMessagesController = new ZenModePrioritySendersPreferenceController(
+ mContext, "test_key_messages", mock(Lifecycle.class), true);
+ ReflectionHelpers.setField(mMessagesController, "mBackend", mZenBackend);
+
+ when(mMockPrefCategory.getContext()).thenReturn(mContext);
+ when(mPreferenceScreen.findPreference(mMessagesController.getPreferenceKey()))
+ .thenReturn(mMockPrefCategory);
+ captureRadioButtons();
+ }
+
+ @Test
+ public void displayPreference_radioButtonsCreatedOnlyOnce() {
+ when(mMockPrefCategory.findPreference(any())).thenReturn(mock(Preference.class));
+
+ // radio buttons were already created, so don't re-create them
+ mMessagesController.displayPreference(mPreferenceScreen);
+ verify(mMockPrefCategory, never()).addPreference(any());
+ }
+
+ @Test
+ public void clickAnySenders() {
+ // GIVEN current priority message senders are STARRED
+ when(mZenBackend.getPriorityMessageSenders()).thenReturn(PRIORITY_SENDERS_STARRED);
+
+ // WHEN user clicks the any senders option
+ RadioButtonPreference allSendersRb = getButton(KEY_ANY);
+ allSendersRb.onClick();
+
+ // THEN any senders gets saved as priority senders for messages
+ verify(mZenBackend).saveSenders(PRIORITY_CATEGORY_MESSAGES, PRIORITY_SENDERS_ANY);
+ }
+
+ @Test
+ public void clickStarredSenders() {
+ // GIVEN current priority message senders are ANY
+ when(mZenBackend.getPriorityMessageSenders()).thenReturn(PRIORITY_SENDERS_ANY);
+
+ // WHEN user clicks the starred contacts option
+ RadioButtonPreference starredRb = getButton(KEY_STARRED);
+ starredRb.onClick();
+
+ // THEN starred contacts gets saved as priority senders for messages
+ verify(mZenBackend).saveSenders(PRIORITY_CATEGORY_MESSAGES, PRIORITY_SENDERS_STARRED);
+ }
+
+ @Test
+ public void clickContactsSenders() {
+ // GIVEN current priority message senders are ANY
+ when(mZenBackend.getPriorityMessageSenders()).thenReturn(PRIORITY_SENDERS_ANY);
+
+ // WHEN user clicks the contacts only option
+ RadioButtonPreference contactsRb = getButton(KEY_CONTACTS);
+ contactsRb.onClick();
+
+ // THEN contacts gets saved as priority senders for messages
+ verify(mZenBackend).saveSenders(PRIORITY_CATEGORY_MESSAGES, PRIORITY_SENDERS_CONTACTS);
+ }
+
+ @Test
+ public void clickNoSenders() {
+ // GIVEN current priority message senders are ANY
+ when(mZenBackend.getPriorityMessageSenders()).thenReturn(PRIORITY_SENDERS_ANY);
+
+ // WHEN user clicks the no senders option
+ RadioButtonPreference noSenders = getButton(KEY_NONE);
+ noSenders.onClick();
+
+ // THEN no senders gets saved as priority senders for messages
+ verify(mZenBackend).saveSenders(PRIORITY_CATEGORY_MESSAGES, ZenModeBackend.SOURCE_NONE);
+ }
+
+ @Test
+ public void clickSameOptionMultipleTimes() {
+ // GIVEN current priority message senders are ANY
+ when(mZenBackend.getPriorityMessageSenders()).thenReturn(PRIORITY_SENDERS_ANY);
+
+ // WHEN user clicks the any senders option multiple times again
+ RadioButtonPreference anySenders = getButton(KEY_ANY);
+ anySenders.onClick();
+ anySenders.onClick();
+ anySenders.onClick();
+
+ // THEN no senders are saved because this setting is already in effect
+ verify(mZenBackend, never()).saveSenders(PRIORITY_CATEGORY_MESSAGES, PRIORITY_SENDERS_ANY);
+ }
+
+ private void captureRadioButtons() {
+ ArgumentCaptor<RadioButtonPreference> rbCaptor =
+ ArgumentCaptor.forClass(RadioButtonPreference.class);
+ mMessagesController.displayPreference(mPreferenceScreen);
+
+ // verifies 4 buttons were added
+ verify(mMockPrefCategory, times(4)).addPreference(rbCaptor.capture());
+ mRadioButtonPreferences = rbCaptor.getAllValues();
+ assertThat(mRadioButtonPreferences.size()).isEqualTo(4);
+
+ reset(mMockPrefCategory);
+ }
+
+ private RadioButtonPreference getButton(String key) {
+ for (RadioButtonPreference pref : mRadioButtonPreferences) {
+ if (key.equals(pref.getKey())) {
+ return pref;
+ }
+ }
+ return null;
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/zen/ZenModeSettingsTest.java b/tests/robotests/src/com/android/settings/notification/zen/ZenModeSettingsTest.java
index da185ad..d3c3a85 100644
--- a/tests/robotests/src/com/android/settings/notification/zen/ZenModeSettingsTest.java
+++ b/tests/robotests/src/com/android/settings/notification/zen/ZenModeSettingsTest.java
@@ -98,34 +98,6 @@
}
@Test
- public void testGetSoundSettingSummary_allOff() {
- Policy policy = new Policy(0, 0, 0, 0);
- assertThat(mBuilder.getSoundSettingSummary(policy)).isEqualTo("Muted");
- }
-
- @Test
- public void testGetSoundSettingSummary_allOn() {
- Policy policy = new Policy(Policy.PRIORITY_CATEGORY_ALARMS | Policy.PRIORITY_CATEGORY_SYSTEM
- | Policy.PRIORITY_CATEGORY_MEDIA, 0, 0, 0);
- assertThat(mBuilder.getSoundSettingSummary(policy))
- .isEqualTo("Muted, but allow alarms, media, and touch sounds");
- }
-
- @Test
- public void testGetSoundSettingSummary_allOffButOne() {
- Policy policy = new Policy(Policy.PRIORITY_CATEGORY_MEDIA, 0, 0, 0);
- assertThat(mBuilder.getSoundSettingSummary(policy)).isEqualTo("Muted, but allow media");
- }
-
- @Test
- public void testGetSoundSettingSummary_allOffButTwo() {
- Policy policy = new Policy(Policy.PRIORITY_CATEGORY_SYSTEM
- | Policy.PRIORITY_CATEGORY_MEDIA, 0, 0, 0);
- assertThat(mBuilder.getSoundSettingSummary(policy))
- .isEqualTo("Muted, but allow media and touch sounds");
- }
-
- @Test
public void searchProvider_shouldIndexDefaultXml() {
final List<SearchIndexableResource> sir = ZenModeSettings.SEARCH_INDEX_DATA_PROVIDER
.getXmlResourcesToIndex(mContext, true /* enabled */);
diff --git a/tests/robotests/src/com/android/settings/notification/zen/ZenModeStarredContactsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/zen/ZenModeStarredContactsPreferenceControllerTest.java
deleted file mode 100644
index f27367a..0000000
--- a/tests/robotests/src/com/android/settings/notification/zen/ZenModeStarredContactsPreferenceControllerTest.java
+++ /dev/null
@@ -1,164 +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.notification.zen;
-
-import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_CALLS;
-import static android.app.NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-import android.app.NotificationManager;
-import android.content.ComponentName;
-import android.content.Context;
-import android.content.Intent;
-
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
-import com.android.settings.notification.zen.ZenModeBackend;
-import com.android.settings.notification.zen.ZenModeStarredContactsPreferenceController;
-import com.android.settingslib.core.lifecycle.Lifecycle;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-import org.robolectric.shadows.ShadowApplication;
-import org.robolectric.util.ReflectionHelpers;
-
-
-@RunWith(RobolectricTestRunner.class)
-public class ZenModeStarredContactsPreferenceControllerTest {
-
- private ZenModeStarredContactsPreferenceController mCallsController;
- private ZenModeStarredContactsPreferenceController mMessagesController;
-
- @Mock
- private ZenModeBackend mBackend;
- @Mock
- private NotificationManager mNotificationManager;
- @Mock
- private Preference mockPref;
- @Mock
- private NotificationManager.Policy mPolicy;
- @Mock
- private PreferenceScreen mPreferenceScreen;
- @Mock
- private Intent testIntent;
- @Mock
- private ComponentName mComponentName;
- private Context mContext;
-
- @Before
- public void setup() {
- MockitoAnnotations.initMocks(this);
- ShadowApplication shadowApplication = ShadowApplication.getInstance();
- shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNotificationManager);
-
- mContext = RuntimeEnvironment.application;
- when(mNotificationManager.getNotificationPolicy()).thenReturn(mPolicy);
- when(testIntent.resolveActivity(any())).thenReturn(mComponentName);
-
- mCallsController = new ZenModeStarredContactsPreferenceController(
- mContext, mock(Lifecycle.class), PRIORITY_CATEGORY_CALLS,
- "zen_mode_starred_contacts_callers");
- ReflectionHelpers.setField(mCallsController, "mBackend", mBackend);
- ReflectionHelpers.setField(mCallsController, "mStarredContactsIntent", testIntent);
- when(mPreferenceScreen.findPreference(mCallsController.getPreferenceKey()))
- .thenReturn(mockPref);
- mCallsController.displayPreference(mPreferenceScreen);
-
- mMessagesController = new ZenModeStarredContactsPreferenceController(
- mContext, mock(Lifecycle.class), PRIORITY_CATEGORY_MESSAGES,
- "zen_mode_starred_contacts_messages");
- ReflectionHelpers.setField(mMessagesController, "mBackend", mBackend);
- ReflectionHelpers.setField(mMessagesController, "mStarredContactsIntent", testIntent);
- when(mPreferenceScreen.findPreference(mMessagesController.getPreferenceKey()))
- .thenReturn(mockPref);
- mMessagesController.displayPreference(mPreferenceScreen);
- }
-
- @Test
- public void isAvailable_noCallers() {
- when(mBackend.isPriorityCategoryEnabled(NotificationManager.Policy.PRIORITY_CATEGORY_CALLS))
- .thenReturn(false);
- assertThat(mCallsController.isAvailable()).isFalse();
- }
-
- @Test
- public void isAvailable_anyCallers() {
- when(mBackend.isPriorityCategoryEnabled(NotificationManager.Policy.PRIORITY_CATEGORY_CALLS))
- .thenReturn(true);
- when(mBackend.getPriorityCallSenders())
- .thenReturn(NotificationManager.Policy.PRIORITY_SENDERS_ANY);
-
- assertThat(mCallsController.isAvailable()).isFalse();
- }
-
- @Test
- public void isAvailable_starredCallers() {
- when(mBackend.isPriorityCategoryEnabled(NotificationManager.Policy.PRIORITY_CATEGORY_CALLS))
- .thenReturn(true);
- when(mBackend.getPriorityCallSenders())
- .thenReturn(NotificationManager.Policy.PRIORITY_SENDERS_STARRED);
-
- assertThat(mCallsController.isAvailable()).isTrue();
- }
-
- @Test
- public void isAvailable_noMessages() {
- when(mBackend.isPriorityCategoryEnabled(
- NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES)).thenReturn(false);
- assertThat(mMessagesController.isAvailable()).isFalse();
- }
-
- @Test
- public void isAvailable_anyMessages() {
- when(mBackend.isPriorityCategoryEnabled(
- NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES)).thenReturn(true);
- when(mBackend.getPriorityMessageSenders())
- .thenReturn(NotificationManager.Policy.PRIORITY_SENDERS_ANY);
-
- assertThat(mMessagesController.isAvailable()).isFalse();
- }
-
- @Test
- public void isAvailable_starredMessageContacts() {
- when(mBackend.isPriorityCategoryEnabled(
- NotificationManager.Policy.PRIORITY_CATEGORY_MESSAGES)).thenReturn(true);
- when(mBackend.getPriorityMessageSenders())
- .thenReturn(NotificationManager.Policy.PRIORITY_SENDERS_STARRED);
-
- assertThat(mMessagesController.isAvailable()).isTrue();
- }
-
- @Test
- public void nullPreference_displayPreference() {
- when(mPreferenceScreen.findPreference(mMessagesController.getPreferenceKey()))
- .thenReturn(null);
-
- // should not throw a null pointer
- mMessagesController.displayPreference(mPreferenceScreen);
- }
-}
diff --git a/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java b/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java
index be5e1af..70b232a 100644
--- a/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java
+++ b/tests/robotests/src/com/android/settings/wifi/details2/WifiDetailPreferenceController2Test.java
@@ -46,7 +46,6 @@
import android.net.IpPrefix;
import android.net.LinkAddress;
import android.net.LinkProperties;
-import android.net.MacAddress;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkInfo;
@@ -81,6 +80,7 @@
import com.android.settingslib.widget.LayoutPreference;
import com.android.wifitrackerlib.NetworkDetailsTracker;
import com.android.wifitrackerlib.WifiEntry;
+import com.android.wifitrackerlib.WifiEntry.ConnectCallback;
import org.junit.Before;
import org.junit.Ignore;
@@ -109,8 +109,6 @@
import java.util.stream.Collectors;
// TODO(b/143326832): Should add test cases for connect button.
-// TODO(b/143326832): WifiEntry is not mature, should remove @Ignore after it's constructed.
-@Ignore
@RunWith(RobolectricTestRunner.class)
@Config(shadows = {ShadowDevicePolicyManager.class, ShadowEntityHeaderController.class})
public class WifiDetailPreferenceController2Test {
@@ -123,8 +121,7 @@
private static final String MAC_ADDRESS = "01:23:45:67:89:ab";
private static final String RANDOMIZED_MAC_ADDRESS = "RANDOMIZED_MAC_ADDRESS";
private static final String FACTORY_MAC_ADDRESS = "FACTORY_MAC_ADDRESS";
- // TODO(b/143326832): Add WifiEntry#getSecurityString
- //private static final String SECURITY = "None";
+ private static final String SECURITY = "None";
private static final String FQDN = "fqdn";
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
@@ -156,8 +153,6 @@
private WifiDetailPreferenceController2.IconInjector mMockIconInjector;
@Mock
private WifiDetailPreferenceController2.Clock mMockClock;
- @Mock
- private MacAddress mMockMacAddress;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private EntityHeaderController mMockHeaderController;
@@ -270,9 +265,9 @@
when(mContext.getPackageManager()).thenReturn(mMockPackageManager);
when(mMockWifiEntry.getLevel()).thenReturn(LEVEL);
- // TODO(b/143326832): Add WifiEntry#getSecurityString
- //when(mMockWifiEntry.getSecurityString(false)).thenReturn(SECURITY);
+ when(mMockWifiEntry.getSecurityString(false /* concise */)).thenReturn(SECURITY);
when(mMockWifiEntry.getTitle()).thenReturn(SSID);
+ when(mMockWifiEntry.getWifiConfiguration()).thenReturn(mMockWifiConfig);
when(mMockConnectivityManager.getNetworkInfo(any(Network.class)))
.thenReturn(mMockNetworkInfo);
doNothing().when(mMockConnectivityManager).registerNetworkCallback(
@@ -393,7 +388,6 @@
assertThat(mController.isAvailable()).isTrue();
}
- /* TODO(b/143326832): Add WifiEntry#getSecurityString
@Test
public void securityPreference_stringShouldBeSet() {
setUpForConnectedNetwork();
@@ -401,7 +395,6 @@
verify(mMockSecurityPref).setSummary(SECURITY);
}
- */
@Test
public void latestWifiInfo_shouldBeFetchedInDisplayPreferenceForConnectedNetwork() {
@@ -541,6 +534,7 @@
updateLinkProperties(lp);
}
+ @Ignore
@Test
public void entityHeader_shouldShowShortRemainingTime() {
// Expires in 1h, 2min, 15sec
@@ -557,6 +551,7 @@
inOrder.verify(mMockHeaderController).setSecondSummary((String) null);
}
+ @Ignore
@Test
public void entityHeader_shouldShowExpiryDate() {
// Expires in 49h, 2min, 15sec
@@ -724,77 +719,68 @@
verify(mMockRxLinkSpeedPref, never()).setSummary(any(String.class));
}
- /* TODO(b/143326832): Support Passpoint test cases while WifiTracker2 supports it.
@Test
- public void ssidPref_shouldHaveDetailTextSetForPasspointR1() {
+ public void ssidPref_isSubscription_show() {
setUpForConnectedNetwork();
- when(mMockAccessPoint.isPasspoint()).thenReturn(true);
- when(mMockAccessPoint.isOsuProvider()).thenReturn(false);
+ when(mMockWifiEntry.isSubscription()).thenReturn(true);
displayAndResume();
- verify(mMockSsidPref, times(1)).setSummary(SSID);
- verify(mMockSsidPref, times(1)).setVisible(true);
+ verify(mMockSsidPref).setSummary(SSID);
+ verify(mMockSsidPref).setVisible(true);
}
@Test
- public void ssidPref_shouldHaveDetailTextSetForPasspointR2() {
+ public void ssidPref_notSubscription_hide() {
setUpForConnectedNetwork();
- when(mMockAccessPoint.isPasspoint()).thenReturn(false);
- when(mMockAccessPoint.isOsuProvider()).thenReturn(true);
+ when(mMockWifiEntry.isSubscription()).thenReturn(false);
displayAndResume();
- verify(mMockSsidPref, times(1)).setSummary(SSID);
- verify(mMockSsidPref, times(1)).setVisible(true);
- }
-
- @Test
- public void ssidPref_shouldNotShowIfNotPasspoint() {
- setUpForConnectedNetwork();
- when(mMockAccessPoint.isPasspoint()).thenReturn(false);
- when(mMockAccessPoint.isOsuProvider()).thenReturn(false);
-
- displayAndResume();
-
+ verify(mMockSsidPref, never()).setSummary(SSID);
verify(mMockSsidPref).setVisible(false);
}
- */
@Test
public void macAddressPref_shouldVisibleForConnectedNetwork() {
setUpForConnectedNetwork();
+ when(mMockWifiEntry.isSaved()).thenReturn(true);
+ when(mMockWifiEntry.getPrivacy()).thenReturn(WifiEntry.PRIVACY_DEVICE_MAC);
+ when(mMockWifiEntry.getMacAddress()).thenReturn(MAC_ADDRESS);
displayAndResume();
verify(mMockMacAddressPref).setVisible(true);
verify(mMockMacAddressPref).setSummary(MAC_ADDRESS);
+ verify(mMockMacAddressPref).setTitle(R.string.wifi_advanced_device_mac_address_title);
}
@Test
public void macAddressPref_shouldVisibleAsRandomizedForDisconnectedNetwork() {
setUpForDisconnectedNetwork();
- mMockWifiConfig.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT;
- when(mMockWifiConfig.getRandomizedMacAddress()).thenReturn(mMockMacAddress);
- when(mMockMacAddress.toString()).thenReturn(RANDOMIZED_MAC_ADDRESS);
+ when(mMockWifiEntry.isSaved()).thenReturn(true);
+ when(mMockWifiEntry.getPrivacy()).thenReturn(WifiEntry.PRIVACY_RANDOMIZED_MAC);
+ when(mMockWifiEntry.getMacAddress()).thenReturn(RANDOMIZED_MAC_ADDRESS);
displayAndResume();
verify(mMockMacAddressPref).setVisible(true);
verify(mMockMacAddressPref).setSummary(RANDOMIZED_MAC_ADDRESS);
+ verify(mMockMacAddressPref).setTitle(R.string.wifi_advanced_randomized_mac_address_title);
}
@Test
public void macAddressPref_shouldVisibleAsFactoryForDisconnectedNetwork() {
setUpForDisconnectedNetwork();
- mMockWifiConfig.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE;
- when(mMockWifiManager.getFactoryMacAddresses())
- .thenReturn(new String[]{FACTORY_MAC_ADDRESS});
+ when(mMockWifiEntry.isSaved()).thenReturn(true);
+ when(mMockWifiEntry.getPrivacy()).thenReturn(WifiEntry.PRIVACY_DEVICE_MAC);
+ when(mMockWifiEntry.getMacAddress()).thenReturn(FACTORY_MAC_ADDRESS);
displayAndResume();
verify(mMockMacAddressPref).setVisible(true);
verify(mMockMacAddressPref).setSummary(FACTORY_MAC_ADDRESS);
+ verify(mMockMacAddressPref).setTitle(R.string.wifi_advanced_device_mac_address_title);
}
@Test
@@ -945,6 +931,7 @@
inOrder.verify(mMockIpv6AddressesPref).setSummary(text);
}
+ @Ignore
@Test
public void onLinkPropertiesChanged_updatesFields() {
setUpForConnectedNetwork();
@@ -1002,6 +989,7 @@
inOrder.verify(mMockDnsPref).setVisible(true);
}
+ @Ignore
@Test
public void onCapabilitiesChanged_callsRefreshIfNecessary() {
setUpForConnectedNetwork();
@@ -1073,32 +1061,25 @@
}
@Test
- public void canForgetNetwork_ephemeral() {
+ public void onUpdated_canForget_showForgetButton() {
setUpForConnectedNetwork();
- when(mMockWifiInfo.isEphemeral()).thenReturn(true);
- when(mMockWifiEntry.isSaved()).thenReturn(false);
+ when(mMockWifiEntry.canForget()).thenReturn(true);
displayAndResume();
+ mController.onUpdated();
- verify(mMockButtonsPref).setButton1Visible(true);
+ verify(mMockButtonsPref, times(2)).setButton1Visible(true);
}
@Test
- public void canForgetNetwork_saved() {
+ public void onUpdated_canNotForget_hideForgetButton() {
setUpForConnectedNetwork();
- displayAndResume();
-
- verify(mMockButtonsPref).setButton1Visible(true);
- }
-
- @Test
- public void canForgetNetwork_lockedDown() {
- setUpForConnectedNetwork();
- lockDownNetwork();
+ when(mMockWifiEntry.canForget()).thenReturn(false);
displayAndResume();
+ mController.onUpdated();
- verify(mMockButtonsPref).setButton1Visible(false);
+ verify(mMockButtonsPref, times(2)).setButton1Visible(false);
}
@Test
@@ -1112,8 +1093,10 @@
}
@Test
- public void canModifyNetwork_saved() {
+ public void canModifyNetwork_savedNetwork_returnTrue() {
setUpForConnectedNetwork();
+ when(mMockWifiEntry.isSaved()).thenReturn(true);
+
assertThat(mController.canModifyNetwork()).isTrue();
}
@@ -1149,52 +1132,30 @@
}
@Test
- public void forgetNetwork_ephemeral() {
+ public void forgetNetwork_standardWifiNetwork_forget() {
setUpForConnectedNetwork();
- String ssid = "ssid";
- when(mMockWifiInfo.isEphemeral()).thenReturn(true);
- when(mMockWifiInfo.getSSID()).thenReturn(ssid);
-
displayAndResume();
+
mForgetClickListener.getValue().onClick(null);
- verify(mMockWifiManager).disableEphemeralNetwork(ssid);
+ verify(mMockWifiEntry).forget(mController);
verify(mMockMetricsFeatureProvider)
.action(mMockActivity, MetricsProto.MetricsEvent.ACTION_WIFI_FORGET);
}
@Test
- public void forgetNetwork_saved() {
+ public void forgetNetwork_isSubscription_shouldShowDialog() {
setUpForConnectedNetwork();
- mMockWifiConfig.networkId = 5;
-
- mController.displayPreference(mMockScreen);
- mForgetClickListener.getValue().onClick(null);
-
- verify(mMockWifiManager).forget(mMockWifiConfig.networkId, null);
- verify(mMockMetricsFeatureProvider)
- .action(mMockActivity, MetricsProto.MetricsEvent.ACTION_WIFI_FORGET);
- }
-
- /* TODO(b/143326832): Support Passpoint test cases while WifiTracker2 supports it.
- @Test
- public void forgetNetwork_shouldShowDialog() {
- setUpForConnectedNetwork();
- final WifiDetailPreferenceController2 spyController = spy(mController);
-
- mMockWifiConfig.networkId = 5;
- when(mMockAccessPoint.isPasspoint()).thenReturn(true);
- when(mMockAccessPoint.getPasspointFqdn()).thenReturn(FQDN);
- spyController.displayPreference(mMockScreen);
+ when(mMockWifiEntry.isSubscription()).thenReturn(true);
+ displayAndResume();
mForgetClickListener.getValue().onClick(null);
- verify(mMockWifiManager, times(0)).removePasspointConfiguration(FQDN);
- verify(mMockMetricsFeatureProvider, times(0))
+ verify(mMockWifiEntry, never()).forget(mController);
+ verify(mMockMetricsFeatureProvider, never())
.action(mMockActivity, MetricsProto.MetricsEvent.ACTION_WIFI_FORGET);
- verify(spyController).showConfirmForgetDialog();
+ verify(mController).showConfirmForgetDialog();
}
- */
@Test
public void networkStateChangedIntent_shouldRefetchInfo() {
@@ -1204,55 +1165,19 @@
verify(mMockConnectivityManager, times(1)).getNetworkInfo(any(Network.class));
verify(mMockWifiManager, times(1)).getConnectionInfo();
-
- mContext.sendBroadcast(new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION));
-
- verify(mMockConnectivityManager, times(2)).getNetworkInfo(any(Network.class));
- verify(mMockWifiManager, times(2)).getConnectionInfo();
}
@Test
- public void networkStateChangedIntent_shouldRefetchInfoForConnectedNetwork() {
+ public void onUpdated_shouldUpdateNetworkInfo() {
setUpForConnectedNetwork();
displayAndResume();
- verify(mMockConnectivityManager, times(1)).getNetworkInfo(any(Network.class));
- verify(mMockWifiManager, times(1)).getConnectionInfo();
+ verify(mController, times(1)).updateNetworkInfo();
- mContext.sendBroadcast(new Intent(WifiManager.NETWORK_STATE_CHANGED_ACTION));
+ mController.onUpdated();
- verify(mMockConnectivityManager, times(2)).getNetworkInfo(any(Network.class));
- verify(mMockWifiManager, times(2)).getConnectionInfo();
- }
-
- @Test
- public void rssiChangedIntent_shouldRefetchInfo() {
- setUpForConnectedNetwork();
-
- displayAndResume();
-
- verify(mMockConnectivityManager, times(1)).getNetworkInfo(any(Network.class));
- verify(mMockWifiManager, times(1)).getConnectionInfo();
-
- mContext.sendBroadcast(new Intent(WifiManager.RSSI_CHANGED_ACTION));
-
- verify(mMockConnectivityManager, times(2)).getNetworkInfo(any(Network.class));
- verify(mMockWifiManager, times(2)).getConnectionInfo();
- }
-
- @Test
- public void rssiChangedIntent_shouldRefetchInfoForConnectedNetwork() {
- setUpForConnectedNetwork();
- displayAndResume();
-
- verify(mMockConnectivityManager, times(1)).getNetworkInfo(any(Network.class));
- verify(mMockWifiManager, times(1)).getConnectionInfo();
-
- mContext.sendBroadcast(new Intent(WifiManager.RSSI_CHANGED_ACTION));
-
- verify(mMockConnectivityManager, times(2)).getNetworkInfo(any(Network.class));
- verify(mMockWifiManager, times(2)).getConnectionInfo();
+ verify(mController, times(2)).updateNetworkInfo();
}
@Test
@@ -1305,6 +1230,7 @@
assertThat(mMockIpv6AddressesPref.isSelectable()).isFalse();
}
+ @Ignore
@Test
public void captivePortal_shouldShowSignInButton() {
setUpForConnectedNetwork();
@@ -1330,6 +1256,7 @@
inOrder.verify(mMockButtonsPref).setButton2Visible(false);
}
+ @Ignore
@Test
public void captivePortal_shouldShowVenueInfoButton() {
setUpForConnectedNetwork();
@@ -1355,6 +1282,7 @@
inOrder.verify(mMockButtonsPref).setButton2Visible(false);
}
+ @Ignore
@Test
public void testSignInButton_shouldStartCaptivePortalApp() {
setUpForConnectedNetwork();
@@ -1395,22 +1323,24 @@
public void testDisconnectButton_connectedNetwork_shouldVisible() {
setUpForConnectedNetwork();
when(mMockWifiEntry.getLevel()).thenReturn(WifiEntry.WIFI_LEVEL_MAX);
+ when(mMockWifiEntry.canDisconnect()).thenReturn(true);
displayAndResume();
verify(mMockButtonsPref).setButton3Visible(true);
- verify(mMockButtonsPref).setButton3Text(R.string.wifi_disconnect);
+ verify(mMockButtonsPref, times(2)).setButton3Text(R.string.wifi_disconnect_button_text);
}
@Test
public void testConnectButton_disconnectedNetwork_shouldVisibleIfReachable() {
setUpForDisconnectedNetwork();
when(mMockWifiEntry.getLevel()).thenReturn(WifiEntry.WIFI_LEVEL_MAX);
+ when(mMockWifiEntry.canConnect()).thenReturn(true);
displayAndResume();
verify(mMockButtonsPref).setButton3Visible(true);
- verify(mMockButtonsPref).setButton3Text(R.string.wifi_connect);
+ verify(mMockButtonsPref, times(2)).setButton3Text(R.string.wifi_connect);
}
@Test
@@ -1431,30 +1361,41 @@
@Test
public void testConnectButton_clickConnect_displayAsSuccess() {
setUpForDisconnectedNetwork();
- when(mMockWifiManager.isWifiEnabled()).thenReturn(true);
- InOrder inOrder = inOrder(mMockButtonsPref);
- String label = "title";
+ final ArgumentCaptor<ConnectCallback> connectCallbackCaptor =
+ ArgumentCaptor.forClass(ConnectCallback.class);
+ final InOrder inOrder = inOrder(mMockButtonsPref);
+ when(mMockWifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_DISCONNECTED);
+ when(mMockWifiEntry.canConnect()).thenReturn(true);
+ final String label = "title";
when(mMockWifiEntry.getTitle()).thenReturn(label);
setUpForToast();
displayAndResume();
- // check connect button enabled
- verifyConnectBtnSetUpAsEnabled(inOrder);
+ // check connect button displayed
+ inOrder.verify(mMockButtonsPref).setButton3Text(R.string.wifi_connect);
+ inOrder.verify(mMockButtonsPref).setButton3Icon(R.drawable.ic_settings_wireless);
// click connect button
mController.connectDisconnectNetwork();
+ when(mMockWifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTING);
+ when(mMockWifiEntry.canConnect()).thenReturn(false);
+ when(mMockWifiEntry.canDisconnect()).thenReturn(false);
+ mController.onUpdated();
// check display button as connecting
- verify(mMockWifiManager, times(1)).connect(anyInt(), any(WifiManager.ActionListener.class));
- verifyConnectBtnSetUpAsConnecting(inOrder);
+ verify(mMockWifiEntry, times(1)).connect(connectCallbackCaptor.capture());
+ verifyConnectingBtnAvailable(inOrder);
// update as connected
+ connectCallbackCaptor.getValue().onConnectResult(
+ ConnectCallback.CONNECT_STATUS_SUCCESS);
when(mMockWifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTED);
+ when(mMockWifiEntry.canDisconnect()).thenReturn(true);
+ mController.onUpdated();
- // check connect button invisible, be init as default state and toast success message
- verifyConnectBtnBeInitAsDefault(inOrder);
- inOrder.verify(mMockButtonsPref).setButton3Enabled(false);
+ // check disconnect button invisible, be init as default state and toast success message
+ verifyDisconnecBtnAvailable(inOrder);
assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
mContext.getString(R.string.wifi_connected_to_message, label));
}
@@ -1462,70 +1403,61 @@
@Test
public void testConnectButton_clickConnectButFailed_displayFailMessage() {
setUpForDisconnectedNetwork();
- ArgumentCaptor<WifiManager.ActionListener> connectListenerCaptor =
- ArgumentCaptor.forClass(WifiManager.ActionListener.class);
- when(mMockWifiManager.isWifiEnabled()).thenReturn(true);
- InOrder inOrder = inOrder(mMockButtonsPref);
+ final ArgumentCaptor<ConnectCallback> connectCallbackCaptor =
+ ArgumentCaptor.forClass(ConnectCallback.class);
+ final InOrder inOrder = inOrder(mMockButtonsPref);
+ when(mMockWifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_DISCONNECTED);
+ when(mMockWifiEntry.canDisconnect()).thenReturn(true);
setUpForToast();
displayAndResume();
- // check connect button enabled
- verifyConnectBtnSetUpAsEnabled(inOrder);
+ // check connect button displayed
+ inOrder.verify(mMockButtonsPref).setButton3Text(R.string.wifi_connect);
+ inOrder.verify(mMockButtonsPref).setButton3Icon(R.drawable.ic_settings_wireless);
// click connect button
mController.connectDisconnectNetwork();
+ when(mMockWifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_CONNECTING);
+ when(mMockWifiEntry.canConnect()).thenReturn(false);
+ when(mMockWifiEntry.canDisconnect()).thenReturn(false);
+ mController.onUpdated();
// check display button as connecting
- verify(mMockWifiManager, times(1)).connect(anyInt(), connectListenerCaptor.capture());
- verifyConnectBtnSetUpAsConnecting(inOrder);
+ verify(mMockWifiEntry, times(1)).connect(connectCallbackCaptor.capture());
+ verifyConnectingBtnAvailable(inOrder);
// update as failed
- connectListenerCaptor.getValue().onFailure(-1);
+ connectCallbackCaptor.getValue().onConnectResult(
+ ConnectCallback.CONNECT_STATUS_FAILURE_UNKNOWN);
+ when(mMockWifiEntry.getConnectedState()).thenReturn(WifiEntry.CONNECTED_STATE_DISCONNECTED);
+ when(mMockWifiEntry.canConnect()).thenReturn(true);
+ mController.onUpdated();
- // check connect button visible, be init as default and toast failed message
- verifyConnectBtnBeInitAsDefault(inOrder);
- inOrder.verify(mMockButtonsPref).setButton3Enabled(true);
+ // check connect button available, be init as default and toast failed message
+ verifyConnectBtnAvailable(inOrder);
assertThat(ShadowToast.getTextOfLatestToast()).isEqualTo(
mContext.getString(R.string.wifi_failed_connect_message));
}
- private void verifyConnectBtnSetUpAsEnabled(InOrder inOrder) {
+ private void verifyConnectBtnAvailable(InOrder inOrder) {
+ inOrder.verify(mMockButtonsPref).setButton3Visible(true);
+ inOrder.verify(mMockButtonsPref).setButton3Enabled(true);
inOrder.verify(mMockButtonsPref).setButton3Text(R.string.wifi_connect);
inOrder.verify(mMockButtonsPref).setButton3Icon(R.drawable.ic_settings_wireless);
- inOrder.verify(mMockButtonsPref).setButton3Enabled(true);
}
- private void verifyConnectBtnSetUpAsConnecting(InOrder inOrder) {
- inOrder.verify(mMockButtonsPref).setButton3Text(R.string.wifi_connecting);
+ private void verifyDisconnecBtnAvailable(InOrder inOrder) {
+ inOrder.verify(mMockButtonsPref).setButton3Visible(true);
+ inOrder.verify(mMockButtonsPref).setButton3Enabled(true);
+ inOrder.verify(mMockButtonsPref).setButton3Text(R.string.wifi_disconnect_button_text);
+ inOrder.verify(mMockButtonsPref).setButton3Icon(R.drawable.ic_settings_close);
+ }
+
+ private void verifyConnectingBtnAvailable(InOrder inOrder) {
+ inOrder.verify(mMockButtonsPref).setButton3Visible(true);
inOrder.verify(mMockButtonsPref).setButton3Enabled(false);
- }
-
- private void verifyConnectBtnBeInitAsDefault(InOrder inOrder) {
- inOrder.verify(mMockButtonsPref).setButton3Text(R.string.wifi_connect);
- inOrder.verify(mMockButtonsPref).setButton3Icon(R.drawable.ic_settings_wireless);
- inOrder.verify(mMockButtonsPref).setButton3Enabled(true);
- }
-
- @Test
- public void testRefreshRssiViews_shouldOnUpdated() {
- setUpForConnectedNetwork();
- displayAndResume();
-
- mContext.sendBroadcast(new Intent(WifiManager.RSSI_CHANGED_ACTION));
-
- verify(mController).onUpdated();
- }
-
- @Test
- public void testRefreshRssiViews_shouldNotUpdateForNotInRangeNetwork() {
- setUpForNotInRangeNetwork();
- displayAndResume();
-
- when(mMockWifiEntry.getLevel()).thenReturn(0);
- mContext.sendBroadcast(new Intent(WifiManager.RSSI_CHANGED_ACTION));
-
- verify(mMockSignalStrengthPref, times(2)).setVisible(false);
+ inOrder.verify(mMockButtonsPref).setButton3Text(R.string.wifi_connecting);
}
@Test
@@ -1580,46 +1512,17 @@
}
@Test
- public void checkMacTitle_whenPrivacyRandomizedMac_shouldBeRandom() {
+ public void entityHeader_expired_shouldHandleExpiration() {
setUpForDisconnectedNetwork();
- mMockWifiConfig.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_PERSISTENT;
- when(mMockWifiConfig.getRandomizedMacAddress()).thenReturn(mMockMacAddress);
- when(mMockMacAddress.toString()).thenReturn(RANDOMIZED_MAC_ADDRESS);
-
- displayAndResume();
-
- verify(mMockMacAddressPref).setTitle(R.string.wifi_advanced_randomized_mac_address_title);
- }
-
- @Test
- public void checkMacTitle_whenPrivacyDeviceMac_shouldBeFactory() {
- setUpForDisconnectedNetwork();
- mMockWifiConfig.macRandomizationSetting = WifiConfiguration.RANDOMIZATION_NONE;
- when(mMockWifiConfig.getRandomizedMacAddress()).thenReturn(mMockMacAddress);
- when(mMockWifiManager.getFactoryMacAddresses())
- .thenReturn(new String[]{FACTORY_MAC_ADDRESS});
-
- displayAndResume();
-
- verify(mMockMacAddressPref).setTitle(R.string.wifi_advanced_device_mac_address_title);
- }
-
- /* TODO(b/143326832): Support Passpoint test cases while WifiTracker2 supports it.
- @Test
- public void entityHeader_expiredPasspointR1_shouldHandleExpiration() {
- when(mMockAccessPoint.isPasspoint()).thenReturn(true);
- when(mMockAccessPoint.isPasspointConfigurationR1()).thenReturn(true);
- when(mMockAccessPoint.isExpired()).thenReturn(true);
- setUpForDisconnectedNetwork();
- String expireSummary = mContext.getResources().getString(
- com.android.settingslib.R.string.wifi_passpoint_expired);
+ when(mMockWifiEntry.isExpired()).thenReturn(true);
+ final String expired = "Expired";
+ when(mMockWifiEntry.getSummary()).thenReturn(expired);
displayAndResume();
verify(mMockButtonsPref, atLeastOnce()).setButton3Visible(false);
- verify(mMockHeaderController).setSummary(expireSummary);
+ verify(mMockHeaderController).setSummary(expired);
}
- */
private ActionButtonsPreference createMock() {
final ActionButtonsPreference pref = mock(ActionButtonsPreference.class);