Bubble settings: feature, notification, app
* Removed setting from developer options
* Removed bubble settings from normal notifications /
channels
* Feature available via notification setting
* Feature screen with educational gif
* App level is now a tri-state choice of all / selected /
none
* App level bubble controls are accessible top-level in
app notifications
Test: make -j40 RunSettingsRoboTests ROBOTEST_FILTER="Bubble"
Bug: 138116133
Change-Id: Id103e9d3717fdc9b86a916be40c43cda9c35ac34
diff --git a/res/drawable/button_border_selected.xml b/res/drawable/button_border_selected.xml
index 65dfe1b..29acbce 100644
--- a/res/drawable/button_border_selected.xml
+++ b/res/drawable/button_border_selected.xml
@@ -20,6 +20,6 @@
android:color="@color/notification_importance_selection_bg" />
<stroke
android:width="2dp"
- android:color="@color/notification_importance_button_selected"/>
+ android:color="?android:attr/colorAccent"/>
<corners android:radius="@dimen/rect_button_radius" />
</shape>
diff --git a/res/drawable/ic_bubble_all.xml b/res/drawable/ic_bubble_all.xml
new file mode 100644
index 0000000..fdcf6dc
--- /dev/null
+++ b/res/drawable/ic_bubble_all.xml
@@ -0,0 +1,25 @@
+<!--
+ ~ 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.
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M16,11c1.66,0 2.99,-1.34 2.99,-3S17.66,5 16,5c-1.66,0 -3,1.34 -3,3s1.34,3 3,3zM8,11c1.66,0 2.99,-1.34 2.99,-3S9.66,5 8,5C6.34,5 5,6.34 5,8s1.34,3 3,3zM8,13c-2.33,0 -7,1.17 -7,3.5L1,19h14v-2.5c0,-2.33 -4.67,-3.5 -7,-3.5zM16,13c-0.29,0 -0.62,0.02 -0.97,0.05 1.16,0.84 1.97,1.97 1.97,3.45L17,19h6v-2.5c0,-2.33 -4.67,-3.5 -7,-3.5z"
+ android:fillColor="#000000"/>
+</vector>
diff --git a/res/drawable/ic_bubble_none.xml b/res/drawable/ic_bubble_none.xml
new file mode 100644
index 0000000..e8fd7df
--- /dev/null
+++ b/res/drawable/ic_bubble_none.xml
@@ -0,0 +1,25 @@
+<!--
+ ~ 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.
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M12,2C6.5,2 2,6.5 2,12s4.5,10 10,10 10,-4.5 10,-10S17.5,2 12,2zM4,12c0,-4.4 3.6,-8 8,-8 1.8,0 3.5,0.6 4.9,1.7L5.7,16.9C4.6,15.5 4,13.8 4,12zM12,20c-1.8,0 -3.5,-0.6 -4.9,-1.7L18.3,7.1C19.4,8.5 20,10.2 20,12c0,4.4 -3.6,8 -8,8z"
+ android:fillColor="#000000"/>
+</vector>
diff --git a/res/drawable/ic_bubble_selected.xml b/res/drawable/ic_bubble_selected.xml
new file mode 100644
index 0000000..f953328
--- /dev/null
+++ b/res/drawable/ic_bubble_selected.xml
@@ -0,0 +1,25 @@
+<!--
+ ~ 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.
+ -->
+
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24.0"
+ android:viewportHeight="24.0">
+ <path
+ android:pathData="M15,8c0,-1.42 -0.5,-2.73 -1.33,-3.76 0.42,-0.14 0.86,-0.24 1.33,-0.24 2.21,0 4,1.79 4,4s-1.79,4 -4,4c-0.43,0 -0.84,-0.09 -1.23,-0.21 -0.03,-0.01 -0.06,-0.02 -0.1,-0.03C14.5,10.73 15,9.42 15,8zM16.66,13.13C18.03,14.06 19,15.32 19,17v3h4v-3c0,-2.18 -3.58,-3.47 -6.34,-3.87zM9,6c-1.1,0 -2,0.9 -2,2s0.9,2 2,2 2,-0.9 2,-2 -0.9,-2 -2,-2m0,9c-2.7,0 -5.8,1.29 -6,2.01L3,18h12v-1c-0.2,-0.71 -3.3,-2 -6,-2M9,4c2.21,0 4,1.79 4,4s-1.79,4 -4,4 -4,-1.79 -4,-4 1.79,-4 4,-4zM9,13c2.67,0 8,1.34 8,4v3L1,20v-3c0,-2.66 5.33,-4 8,-4z"
+ android:fillColor="#000000"/>
+</vector>
diff --git a/res/drawable/ic_create_bubble.xml b/res/drawable/ic_create_bubble.xml
index e943355..82d5db8 100644
--- a/res/drawable/ic_create_bubble.xml
+++ b/res/drawable/ic_create_bubble.xml
@@ -14,17 +14,13 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
<vector xmlns:android="http://schemas.android.com/apk/res/android"
- android:width="24dp"
- android:height="24dp"
- android:viewportWidth="24"
- android:viewportHeight="24"
- android:tint="?android:attr/colorControlNormal">
- <path
- android:pathData="M12,3c-4.97,0 -9,4.03 -9,9c0,1.39 0.32,2.69 0.88,3.86l1.53,-1.53C5.15,13.6 5,12.82 5,12c0,-3.86 3.14,-7 7,-7s7,3.14 7,7s-3.14,7 -7,7c-0.83,0 -1.62,-0.15 -2.35,-0.42l-1.53,1.53C9.3,20.67 10.61,21 12,21c4.97,0 9,-4.03 9,-9C21,7.03 16.97,3 12,3z"
- android:fillColor="#000000"/>
- <path
- android:pathData="M12.99,15.99l2,0l0,-7l-7,0l0,2l3.59,0l-8.79,8.8l1.41,1.41l8.79,-8.79z"
- android:fillColor="#000000"/>
-</vector>
+ android:width="24dp"
+ android:height="24dp"
+ android:viewportWidth="24"
+ android:viewportHeight="24"
+ android:tint="?android:attr/colorControlNormal">
+ <path
+ android:fillColor="#FF000000"
+ android:pathData="M22,12C22,12 22,12 22,12C22,12 22,12 22,12c0,0.56 -0.06,1.1 -0.15,1.64l-1.97,-0.33c0.15,-0.91 0.15,-1.84 -0.02,-2.75c-0.01,-0.03 -0.01,-0.07 -0.02,-0.1c-0.03,-0.18 -0.08,-0.36 -0.13,-0.54c-0.02,-0.08 -0.04,-0.16 -0.06,-0.24c-0.04,-0.14 -0.09,-0.27 -0.14,-0.41c-0.04,-0.12 -0.08,-0.24 -0.13,-0.35c-0.04,-0.09 -0.08,-0.18 -0.13,-0.27c-0.07,-0.15 -0.14,-0.3 -0.22,-0.45c-0.03,-0.05 -0.06,-0.09 -0.08,-0.14c-0.72,-1.26 -1.77,-2.31 -3.03,-3.03c-0.05,-0.03 -0.09,-0.06 -0.14,-0.08c-0.15,-0.08 -0.3,-0.15 -0.45,-0.22c-0.09,-0.04 -0.18,-0.09 -0.27,-0.13c-0.11,-0.05 -0.23,-0.09 -0.35,-0.13c-0.14,-0.05 -0.27,-0.1 -0.41,-0.14c-0.08,-0.02 -0.16,-0.04 -0.23,-0.06c-0.18,-0.05 -0.36,-0.1 -0.54,-0.13c-0.03,-0.01 -0.07,-0.01 -0.1,-0.01c-0.95,-0.17 -1.93,-0.17 -2.88,0c-0.03,0.01 -0.07,0.01 -0.1,0.01c-0.18,0.04 -0.36,0.08 -0.54,0.13C9.85,4.3 9.77,4.32 9.69,4.34C9.55,4.38 9.42,4.44 9.28,4.49C9.17,4.53 9.05,4.57 8.93,4.61C8.84,4.65 8.75,4.7 8.66,4.74c-0.15,0.07 -0.3,0.14 -0.45,0.22C8.16,4.98 8.12,5.01 8.07,5.04C5.64,6.42 4,9.02 4,12c0,2.74 1.39,5.16 3.49,6.6c0.01,0.01 0.03,0.02 0.04,0.03c0.16,0.11 0.33,0.2 0.49,0.3c0.06,0.04 0.12,0.08 0.19,0.11c0.13,0.07 0.27,0.13 0.4,0.19c0.11,0.05 0.21,0.1 0.32,0.15c0.1,0.04 0.2,0.07 0.29,0.11c0.15,0.06 0.31,0.11 0.46,0.16c0.05,0.02 0.11,0.03 0.17,0.04c1.11,0.31 2.27,0.35 3.4,0.18l0.35,1.98c-0.54,0.09 -1.08,0.14 -1.62,0.14V22c-0.65,0 -1.28,-0.07 -1.9,-0.19c-0.01,0 -0.01,0 -0.02,0c-0.25,-0.05 -0.49,-0.11 -0.73,-0.18c-0.08,-0.02 -0.16,-0.04 -0.23,-0.06c-0.19,-0.06 -0.37,-0.13 -0.55,-0.19c-0.13,-0.05 -0.26,-0.09 -0.39,-0.14c-0.13,-0.05 -0.25,-0.12 -0.38,-0.18c-0.18,-0.08 -0.35,-0.16 -0.53,-0.25c-0.07,-0.04 -0.14,-0.08 -0.21,-0.13c-0.22,-0.12 -0.43,-0.25 -0.64,-0.39c-0.01,-0.01 -0.02,-0.02 -0.04,-0.03c-0.51,-0.35 -1,-0.74 -1.45,-1.2l0,0C3.12,17.26 2,14.76 2,12c0,-2.76 1.12,-5.26 2.93,-7.07l0,0c0.45,-0.45 0.93,-0.84 1.44,-1.19C6.39,3.73 6.4,3.72 6.42,3.71c0.2,-0.14 0.41,-0.26 0.62,-0.38c0.08,-0.05 0.15,-0.09 0.23,-0.14c0.17,-0.09 0.33,-0.16 0.5,-0.24c0.13,-0.06 0.27,-0.13 0.4,-0.19C8.3,2.71 8.42,2.67 8.55,2.63c0.19,-0.07 0.38,-0.14 0.58,-0.2c0.07,-0.02 0.14,-0.03 0.21,-0.05C10.18,2.14 11.07,2 12,2c0.65,0 1.29,0.07 1.91,0.19c0,0 0,0 0,0c0.25,0.05 0.5,0.11 0.75,0.18c0.07,0.02 0.14,0.03 0.22,0.06c0.19,0.06 0.38,0.13 0.57,0.2c0.12,0.05 0.25,0.09 0.37,0.14c0.14,0.06 0.27,0.12 0.4,0.18c0.17,0.08 0.34,0.16 0.51,0.25c0.08,0.04 0.15,0.09 0.23,0.14c0.21,0.12 0.42,0.24 0.62,0.38c0.01,0.01 0.03,0.02 0.04,0.03c0.51,0.35 0.99,0.74 1.45,1.19c0.24,0.24 0.47,0.49 0.68,0.75c0.04,0.04 0.06,0.09 0.1,0.13c0.17,0.22 0.34,0.45 0.5,0.68c0.01,0.01 0.02,0.03 0.03,0.04c0.69,1.05 1.17,2.21 1.42,3.44c0,0 0,0.01 0,0.01c0.06,0.29 0.1,0.58 0.13,0.87c0.01,0.04 0.01,0.09 0.02,0.13C21.98,11.32 22,11.66 22,12zM18.5,15c-1.93,0 -3.5,1.57 -3.5,3.5s1.57,3.5 3.5,3.5s3.5,-1.57 3.5,-3.5S20.43,15 18.5,15z"/>
+</vector>
\ No newline at end of file
diff --git a/res/layout/bubble_preference.xml b/res/layout/bubble_preference.xml
new file mode 100644
index 0000000..8a64716
--- /dev/null
+++ b/res/layout/bubble_preference.xml
@@ -0,0 +1,128 @@
+<?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:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center"
+ android:padding="@dimen/notification_importance_toggle_marginTop"
+ android:orientation="vertical">
+
+ <!-- If bubbles is managed by the admin this is used to inform the user. -->
+ <TextView
+ android:id="@android:id/summary"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="@dimen/notification_importance_button_padding"
+ android:textAppearance="@style/TextAppearance.Small"
+ android:visibility="gone"
+ />
+
+ <com.android.settings.notification.NotificationButtonRelativeLayout
+ android:id="@+id/bubble_all"
+ 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/bubble_all_icon"
+ android:src="@drawable/ic_bubble_all"
+ 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/bubble_all_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ellipsize="end"
+ android:maxLines="2"
+ android:clickable="false"
+ android:focusable="false"
+ android:layout_toEndOf="@id/bubble_all_icon"
+ android:layout_marginStart="@dimen/notification_importance_drawable_padding"
+ android:textAppearance="@style/TextAppearance.NotificationImportanceButton.Unselected"
+ android:text="@string/bubble_app_setting_all"/>
+ </com.android.settings.notification.NotificationButtonRelativeLayout>
+
+ <com.android.settings.notification.NotificationButtonRelativeLayout
+ android:id="@+id/bubble_selected"
+ 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/bubble_selected_icon"
+ android:src="@drawable/ic_bubble_selected"
+ 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/bubble_selected_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ellipsize="end"
+ android:maxLines="2"
+ android:clickable="false"
+ android:focusable="false"
+ android:layout_toEndOf="@id/bubble_selected_icon"
+ android:layout_marginStart="@dimen/notification_importance_drawable_padding"
+ android:textAppearance="@style/TextAppearance.NotificationImportanceButton.Unselected"
+ android:text="@string/bubble_app_setting_selected"/>
+ </com.android.settings.notification.NotificationButtonRelativeLayout>
+
+ <com.android.settings.notification.NotificationButtonRelativeLayout
+ android:id="@+id/bubble_none"
+ 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/bubble_none_icon"
+ android:src="@drawable/ic_bubble_none"
+ 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/bubble_none_label"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:ellipsize="end"
+ android:maxLines="2"
+ android:clickable="false"
+ android:focusable="false"
+ android:layout_toEndOf="@id/bubble_none_icon"
+ android:layout_marginStart="@dimen/notification_importance_drawable_padding"
+ android:textAppearance="@style/TextAppearance.NotificationImportanceButton.Unselected"
+ android:text="@string/bubble_app_setting_none"/>
+ </com.android.settings.notification.NotificationButtonRelativeLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/res/raw-night/bubble_notification_animation.mp4 b/res/raw-night/bubble_notification_animation.mp4
new file mode 100644
index 0000000..1a25e93
--- /dev/null
+++ b/res/raw-night/bubble_notification_animation.mp4
Binary files differ
diff --git a/res/raw/bubble_notification_animation.mp4 b/res/raw/bubble_notification_animation.mp4
new file mode 100644
index 0000000..2994548
--- /dev/null
+++ b/res/raw/bubble_notification_animation.mp4
Binary files differ
diff --git a/res/xml/app_bubble_notification_settings.xml b/res/xml/app_bubble_notification_settings.xml
index 8d97f8f..3f52ad3 100644
--- a/res/xml/app_bubble_notification_settings.xml
+++ b/res/xml/app_bubble_notification_settings.xml
@@ -13,22 +13,18 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
-
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:settings="http://schemas.android.com/apk/res-auto"
android:title="@string/bubbles_app_toggle_title"
android:key="app_bubble_notification_settings">
+
<com.android.settingslib.widget.LayoutPreference
android:key="pref_app_header"
android:layout="@layout/settings_entity_header"/>
- <com.android.settingslib.RestrictedSwitchPreference
+ <com.android.settings.notification.app.BubblePreference
android:key="bubble_pref"
- android:title="@string/notification_bubbles_title"/>
-
- <com.android.settingslib.widget.FooterPreference
- android:key="notification_bubbles_footer"
- android:title="@string/bubbles_feature_education"
- android:selectable="false" />
+ android:title="@string/notification_bubbles_title"
+ settings:allowDividerBelow="false"/>
</PreferenceScreen>
diff --git a/res/xml/app_notification_settings.xml b/res/xml/app_notification_settings.xml
index ceb08a2..f0200ce 100644
--- a/res/xml/app_notification_settings.xml
+++ b/res/xml/app_notification_settings.xml
@@ -29,6 +29,14 @@
<com.android.settings.notification.app.NotificationFooterPreference
android:key="block_desc" />
+ <!--Bubbles -->
+ <Preference
+ android:key="bubble_pref_link"
+ android:title="@string/notification_bubbles_title"
+ android:icon="@drawable/ic_create_bubble"
+ settings:controller="com.android.settings.notification.app.BubbleSummaryPreferenceController">
+ </Preference>
+
<!-- Conversations added here -->
<PreferenceCategory
android:title="@string/conversations_category_title"
@@ -74,10 +82,6 @@
android:order="1001"
settings:restrictedSwitchSummary="@string/enabled_by_admin" />
<Preference
- android:key="bubble_link_pref"
- android:title="@string/notification_bubbles_title"
- android:order="1002" />
- <Preference
android:key="app_link"
android:order="1003"
android:title="@string/app_settings_link" />
diff --git a/res/xml/bubble_notification_settings.xml b/res/xml/bubble_notification_settings.xml
new file mode 100644
index 0000000..4dc3e24
--- /dev/null
+++ b/res/xml/bubble_notification_settings.xml
@@ -0,0 +1,38 @@
+<?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"
+ xmlns:settings="http://schemas.android.com/apk/res-auto"
+ android:title="@string/bubbles_app_toggle_title"
+ android:key="bubble_notification_settings">
+
+ <com.android.settings.widget.VideoPreference
+ android:key="bubbles_illustration"
+ android:title="@string/summary_placeholder"
+ settings:animation="@raw/bubble_notification_animation"
+ settings:controller="com.android.settings.widget.VideoPreferenceController"
+ android:persistent="false" />
+
+ <!-- Notification bubbles -->
+ <SwitchPreference
+ android:key="global_notification_bubbles"
+ android:icon="@drawable/ic_create_bubble"
+ settings:allowDividerAbove="true"
+ android:title="@string/notifications_bubble_setting_title"
+ android:summary="@string/notifications_bubble_setting_description"
+ settings:controller="com.android.settings.notification.BubbleNotificationPreferenceController"/>
+
+</PreferenceScreen>
\ No newline at end of file
diff --git a/res/xml/configure_notification_settings.xml b/res/xml/configure_notification_settings.xml
index 3dcddc8..cb8357b 100644
--- a/res/xml/configure_notification_settings.xml
+++ b/res/xml/configure_notification_settings.xml
@@ -50,15 +50,23 @@
</Preference>
</PreferenceCategory>
- <PreferenceCategory
+ <Preference
android:key="conversations"
android:title="@string/conversations_category_title"
- android:order="5">
- <Preference
- android:key="manage_conversations"
- android:title="@string/manage_conversations"
- android:fragment="com.android.settings.notification.app.ConversationListSettings"/>
- </PreferenceCategory>
+ settings:allowDividerAbove="true"
+ android:summary="@string/manage_conversations"
+ android:order="6"
+ android:fragment="com.android.settings.notification.app.ConversationListSettings"
+ />
+
+ <Preference
+ android:key="notification_bubbles"
+ android:title="@string/notification_bubbles_title"
+ android:summary="@string/notifications_bubble_setting_on_summary"
+ android:order="7"
+ settings:controller="com.android.settings.notification.BubbleSummaryNotificationPreferenceController"
+ android:fragment="com.android.settings.notification.BubbleNotificationSettings"
+ />
<PreferenceCategory
android:key="configure_notifications_lock"
diff --git a/src/com/android/settings/development/BubbleGlobalPreferenceController.java b/src/com/android/settings/development/BubbleGlobalPreferenceController.java
deleted file mode 100644
index 2f22d09..0000000
--- a/src/com/android/settings/development/BubbleGlobalPreferenceController.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.development;
-
-import android.content.Context;
-import android.provider.Settings;
-
-import androidx.annotation.VisibleForTesting;
-import androidx.preference.Preference;
-import androidx.preference.SwitchPreference;
-
-import com.android.settings.core.PreferenceControllerMixin;
-import com.android.settingslib.development.DeveloperOptionsPreferenceController;
-
-public class BubbleGlobalPreferenceController extends DeveloperOptionsPreferenceController
- implements Preference.OnPreferenceChangeListener, PreferenceControllerMixin {
-
- @VisibleForTesting
- static final int ON = 1;
- @VisibleForTesting
- static final int OFF = 0;
-
- public BubbleGlobalPreferenceController(Context context) {
- super(context);
- }
-
- @Override
- public String getPreferenceKey() {
- return Settings.Global.NOTIFICATION_BUBBLES;
- }
-
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- writeSetting((boolean) newValue);
- return true;
- }
-
- @Override
- public void updateState(Preference preference) {
- ((SwitchPreference) mPreference).setChecked(isEnabled());
- }
-
- @Override
- protected void onDeveloperOptionsSwitchDisabled() {
- super.onDeveloperOptionsSwitchDisabled();
- writeSetting(false /* isEnabled */);
- updateState(mPreference);
- }
-
- private boolean isEnabled() {
- return Settings.Global.getInt(mContext.getContentResolver(),
- Settings.Global.NOTIFICATION_BUBBLES, OFF) == ON;
- }
-
- private void writeSetting(boolean isEnabled) {
- Settings.Global.putInt(mContext.getContentResolver(),
- Settings.Global.NOTIFICATION_BUBBLES, isEnabled ? ON : OFF);
- }
-}
diff --git a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
index 66b93e1..d2d7372 100644
--- a/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
+++ b/src/com/android/settings/development/DevelopmentSettingsDashboardFragment.java
@@ -508,7 +508,6 @@
controllers.add(new DesktopModePreferenceController(context));
controllers.add(new SizeCompatFreeformPreferenceController(context));
controllers.add(new ShortcutManagerThrottlingPreferenceController(context));
- controllers.add(new BubbleGlobalPreferenceController(context));
controllers.add(new EnableGnssRawMeasFullTrackingPreferenceController(context));
controllers.add(new DefaultLaunchPreferenceController(context, "running_apps"));
controllers.add(new DefaultLaunchPreferenceController(context, "demo_mode"));
diff --git a/src/com/android/settings/notification/BubbleNotificationPreferenceController.java b/src/com/android/settings/notification/BubbleNotificationPreferenceController.java
new file mode 100644
index 0000000..0fa480c
--- /dev/null
+++ b/src/com/android/settings/notification/BubbleNotificationPreferenceController.java
@@ -0,0 +1,132 @@
+/*
+ * 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;
+
+import static android.provider.Settings.Global.NOTIFICATION_BUBBLES;
+
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.ContentObserver;
+import android.net.Uri;
+import android.os.Handler;
+import android.provider.Settings;
+
+import androidx.annotation.VisibleForTesting;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
+import com.android.settings.core.PreferenceControllerMixin;
+import com.android.settings.core.TogglePreferenceController;
+import com.android.settingslib.core.lifecycle.LifecycleObserver;
+import com.android.settingslib.core.lifecycle.events.OnPause;
+import com.android.settingslib.core.lifecycle.events.OnResume;
+
+/**
+ * Feature level screen for bubbles, available through notification menu.
+ * Allows user to turn bubbles on or off for the device.
+ */
+public class BubbleNotificationPreferenceController extends TogglePreferenceController
+ implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener,
+ LifecycleObserver, OnResume, OnPause {
+
+ private static final String TAG = "BubbleNotifPrefContr";
+
+ @VisibleForTesting
+ static final int ON = 1;
+ @VisibleForTesting
+ static final int OFF = 0;
+
+ private SettingObserver mSettingObserver;
+
+ public BubbleNotificationPreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ @Override
+ public void displayPreference(PreferenceScreen screen) {
+ super.displayPreference(screen);
+ Preference preference = screen.findPreference(getPreferenceKey());
+ if (preference != null) {
+ mSettingObserver = new SettingObserver(preference);
+ }
+ }
+
+ @Override
+ public void onResume() {
+ if (mSettingObserver != null) {
+ mSettingObserver.register(mContext.getContentResolver(), true /* register */);
+ }
+ }
+
+ @Override
+ public void onPause() {
+ if (mSettingObserver != null) {
+ mSettingObserver.register(mContext.getContentResolver(), false /* register */);
+ }
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+
+ @Override
+ public boolean isChecked() {
+ return Settings.Global.getInt(mContext.getContentResolver(),
+ NOTIFICATION_BUBBLES, ON) == ON;
+ }
+
+ @Override
+ public boolean setChecked(boolean isChecked) {
+ return Settings.Global.putInt(mContext.getContentResolver(),
+ NOTIFICATION_BUBBLES, isChecked ? ON : OFF);
+ }
+
+ @Override
+ public boolean isSliceable() {
+ return false;
+ }
+
+ class SettingObserver extends ContentObserver {
+
+ private final Uri NOTIFICATION_BUBBLES_URI =
+ Settings.Global.getUriFor(NOTIFICATION_BUBBLES);
+
+ private final Preference mPreference;
+
+ SettingObserver(Preference preference) {
+ super(new Handler());
+ mPreference = preference;
+ }
+
+ public void register(ContentResolver cr, boolean register) {
+ if (register) {
+ cr.registerContentObserver(NOTIFICATION_BUBBLES_URI, false, this);
+ } else {
+ cr.unregisterContentObserver(this);
+ }
+ }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ super.onChange(selfChange, uri);
+ if (NOTIFICATION_BUBBLES_URI.equals(uri)) {
+ updateState(mPreference);
+ }
+ }
+ }
+}
diff --git a/src/com/android/settings/notification/BubbleNotificationSettings.java b/src/com/android/settings/notification/BubbleNotificationSettings.java
new file mode 100644
index 0000000..6e04683
--- /dev/null
+++ b/src/com/android/settings/notification/BubbleNotificationSettings.java
@@ -0,0 +1,52 @@
+/*
+ * 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;
+
+import android.app.settings.SettingsEnums;
+
+import com.android.settings.R;
+import com.android.settings.core.OnActivityResultListener;
+import com.android.settings.dashboard.DashboardFragment;
+import com.android.settings.search.BaseSearchIndexProvider;
+import com.android.settingslib.search.SearchIndexable;
+
+@SearchIndexable
+public class BubbleNotificationSettings extends DashboardFragment implements
+ OnActivityResultListener {
+ private static final String TAG = "BubbleNotiSettings";
+
+ @Override
+ public int getMetricsCategory() {
+ return SettingsEnums.BUBBLE_SETTINGS;
+ }
+
+ @Override
+ protected String getLogTag() {
+ return TAG;
+ }
+
+ @Override
+ protected int getPreferenceScreenResId() {
+ return R.xml.bubble_notification_settings;
+ }
+
+ /**
+ * For Search.
+ */
+ public static final BaseSearchIndexProvider SEARCH_INDEX_DATA_PROVIDER =
+ new BaseSearchIndexProvider(R.xml.bubble_notification_settings);
+}
diff --git a/src/com/android/settings/notification/BubbleSummaryNotificationPreferenceController.java b/src/com/android/settings/notification/BubbleSummaryNotificationPreferenceController.java
new file mode 100644
index 0000000..f123c51
--- /dev/null
+++ b/src/com/android/settings/notification/BubbleSummaryNotificationPreferenceController.java
@@ -0,0 +1,58 @@
+/*
+ * 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;
+
+import static android.provider.Settings.Global.NOTIFICATION_BUBBLES;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import androidx.annotation.VisibleForTesting;
+
+import com.android.settings.R;
+import com.android.settings.core.BasePreferenceController;
+
+/**
+ * Summary of the feature setting for bubbles, available through notification menu.
+ */
+public class BubbleSummaryNotificationPreferenceController extends BasePreferenceController {
+
+ @VisibleForTesting
+ static final int ON = 1;
+
+ public BubbleSummaryNotificationPreferenceController(Context context, String preferenceKey) {
+ super(context, preferenceKey);
+ }
+
+ @Override
+ public CharSequence getSummary() {
+ return mContext.getString(
+ areBubblesEnabled()
+ ? R.string.notifications_bubble_setting_on_summary
+ : R.string.switch_off_text);
+ }
+
+ @Override
+ public int getAvailabilityStatus() {
+ return AVAILABLE;
+ }
+
+ private boolean areBubblesEnabled() {
+ return Settings.Global.getInt(mContext.getContentResolver(),
+ NOTIFICATION_BUBBLES, ON) == ON;
+ }
+}
diff --git a/src/com/android/settings/notification/NotificationBackend.java b/src/com/android/settings/notification/NotificationBackend.java
index fb0a438..b172879 100644
--- a/src/com/android/settings/notification/NotificationBackend.java
+++ b/src/com/android/settings/notification/NotificationBackend.java
@@ -24,6 +24,7 @@
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.app.NotificationHistory;
+import android.app.NotificationManager;
import android.app.role.RoleManager;
import android.app.usage.IUsageStatsManager;
import android.app.usage.UsageEvents;
@@ -81,7 +82,7 @@
row.icon = IconDrawableFactory.newInstance(context).getBadgedIcon(app);
row.banned = getNotificationsBanned(row.pkg, row.uid);
row.showBadge = canShowBadge(row.pkg, row.uid);
- row.allowBubbles = canBubble(row.pkg, row.uid);
+ row.bubblePreference = getBubblePreference(row.pkg, row.uid);
row.userId = UserHandle.getUserId(row.uid);
row.blockedChannelCount = getBlockedChannelCount(row.pkg, row.uid);
row.channelCount = getChannelCount(row.pkg, row.uid);
@@ -192,18 +193,18 @@
}
}
- public boolean canBubble(String pkg, int uid) {
+ public int getBubblePreference(String pkg, int uid) {
try {
- return sINM.areBubblesAllowedForPackage(pkg, uid);
+ return sINM.getBubblePreferenceForPackage(pkg, uid);
} catch (Exception e) {
Log.w(TAG, "Error calling NoMan", e);
- return false;
+ return -1;
}
}
- public boolean setAllowBubbles(String pkg, int uid, boolean allow) {
+ public boolean setAllowBubbles(String pkg, int uid, int preference) {
try {
- sINM.setBubblesAllowed(pkg, uid, allow);
+ sINM.setBubblesAllowed(pkg, uid, preference);
return true;
} catch (Exception e) {
Log.w(TAG, "Error calling NoMan", e);
@@ -563,7 +564,7 @@
public boolean systemApp;
public boolean lockedImportance;
public boolean showBadge;
- public boolean allowBubbles;
+ public int bubblePreference = NotificationManager.BUBBLE_PREFERENCE_NONE;
public int userId;
public int blockedChannelCount;
public int channelCount;
diff --git a/src/com/android/settings/notification/app/AppBubbleNotificationSettings.java b/src/com/android/settings/notification/app/AppBubbleNotificationSettings.java
index 0ed1b84..5026a26 100644
--- a/src/com/android/settings/notification/app/AppBubbleNotificationSettings.java
+++ b/src/com/android/settings/notification/app/AppBubbleNotificationSettings.java
@@ -30,6 +30,9 @@
import java.util.ArrayList;
import java.util.List;
+/**
+ * App level settings for bubbles.
+ */
@SearchIndexable
public class AppBubbleNotificationSettings extends NotificationSettings implements
GlobalBubblePermissionObserverMixin.Listener {
diff --git a/src/com/android/settings/notification/app/AppNotificationSettings.java b/src/com/android/settings/notification/app/AppNotificationSettings.java
index d9f4239..a422841 100644
--- a/src/com/android/settings/notification/app/AppNotificationSettings.java
+++ b/src/com/android/settings/notification/app/AppNotificationSettings.java
@@ -22,6 +22,10 @@
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.settingslib.core.AbstractPreferenceController;
@@ -29,10 +33,6 @@
import java.util.ArrayList;
import java.util.List;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceGroup;
-import androidx.preference.PreferenceScreen;
-
/** These settings are per app, so should not be returned in global search results. */
public class AppNotificationSettings extends NotificationSettings {
private static final String TAG = "AppNotificationSettings";
@@ -41,8 +41,7 @@
private static String KEY_ADVANCED_CATEGORY = "app_advanced";
private static String KEY_BADGE = "badge";
private static String KEY_APP_LINK = "app_link";
- private static String KEY_BUBBLE = "bubble_link_pref";
- private static String[] LEGACY_NON_ADVANCED_KEYS = {KEY_BADGE, KEY_APP_LINK, KEY_BUBBLE};
+ private static String[] LEGACY_NON_ADVANCED_KEYS = {KEY_BADGE, KEY_APP_LINK};
@Override
public int getMetricsCategory() {
@@ -121,9 +120,9 @@
mControllers.add(new DescriptionPreferenceController(context));
mControllers.add(new NotificationsOffPreferenceController(context));
mControllers.add(new DeletedChannelsPreferenceController(context, mBackend));
- mControllers.add(new BubbleSummaryPreferenceController(context, mBackend));
mControllers.add(new ChannelListPreferenceController(context, mBackend));
mControllers.add(new AppConversationListPreferenceController(context, mBackend));
+ mControllers.add(new BubbleSummaryPreferenceController(context, mBackend));
return new ArrayList<>(mControllers);
}
}
diff --git a/src/com/android/settings/notification/app/BubblePreference.java b/src/com/android/settings/notification/app/BubblePreference.java
new file mode 100644
index 0000000..679b663
--- /dev/null
+++ b/src/com/android/settings/notification/app/BubblePreference.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.BUBBLE_PREFERENCE_ALL;
+import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
+import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED;
+
+import android.content.Context;
+import android.content.res.ColorStateList;
+import android.graphics.drawable.Drawable;
+import android.util.AttributeSet;
+import android.view.View;
+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;
+import com.android.settingslib.RestrictedLockUtils;
+import com.android.settingslib.RestrictedPreferenceHelper;
+
+/**
+ * A tri-state preference allowing a user to specify what gets to bubble.
+ */
+public class BubblePreference extends Preference implements View.OnClickListener {
+ RestrictedPreferenceHelper mHelper;
+
+ private int mSelectedPreference;
+
+ private Context mContext;
+ private Drawable mSelectedBackground;
+ private Drawable mUnselectedBackground;
+
+ private ButtonViewHolder mBubbleAllButton;
+ private ButtonViewHolder mBubbleSelectedButton;
+ private ButtonViewHolder mBubbleNoneButton;
+
+ public BubblePreference(Context context) {
+ this(context, null);
+ }
+
+ public BubblePreference(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public BubblePreference(Context context, AttributeSet attrs, int defStyleAttr) {
+ this(context, attrs, defStyleAttr, 0);
+ }
+
+ public BubblePreference(Context context, AttributeSet attrs,
+ int defStyleAttr, int defStyleRes) {
+ super(context, attrs, defStyleAttr, defStyleRes);
+ mHelper = new RestrictedPreferenceHelper(context, this, attrs);
+ mHelper.useAdminDisabledSummary(true);
+ mContext = context;
+ mSelectedBackground = mContext.getDrawable(R.drawable.button_border_selected);
+ mUnselectedBackground = mContext.getDrawable(R.drawable.button_border_unselected);
+ setLayoutResource(R.layout.bubble_preference);
+ }
+
+ public void setSelectedPreference(int preference) {
+ mSelectedPreference = preference;
+ }
+
+ public int getSelectedPreference() {
+ return mSelectedPreference;
+ }
+
+ public void setDisabledByAdmin(RestrictedLockUtils.EnforcedAdmin admin) {
+ if (mHelper.setDisabledByAdmin(admin)) {
+ notifyChanged();
+ }
+ }
+
+ @Override
+ public void onBindViewHolder(final PreferenceViewHolder holder) {
+ super.onBindViewHolder(holder);
+
+ final boolean disabledByAdmin = mHelper.isDisabledByAdmin();
+ View summary = holder.findViewById(android.R.id.summary);
+ if (disabledByAdmin) {
+ mHelper.onBindViewHolder(holder);
+ summary.setVisibility(View.VISIBLE);
+ } else {
+ summary.setVisibility(View.GONE);
+ }
+ holder.itemView.setClickable(false);
+
+ View bubbleAll = holder.findViewById(R.id.bubble_all);
+ ImageView bubbleAllImage = (ImageView) holder.findViewById(R.id.bubble_all_icon);
+ TextView bubbleAllText = (TextView) holder.findViewById(R.id.bubble_all_label);
+ mBubbleAllButton = new ButtonViewHolder(bubbleAll, bubbleAllImage, bubbleAllText,
+ BUBBLE_PREFERENCE_ALL);
+ mBubbleAllButton.setSelected(mContext, mSelectedPreference == BUBBLE_PREFERENCE_ALL);
+ bubbleAll.setTag(BUBBLE_PREFERENCE_ALL);
+ bubbleAll.setOnClickListener(this);
+ bubbleAll.setVisibility(disabledByAdmin ? View.GONE : View.VISIBLE);
+
+ View bubbleSelected = holder.findViewById(R.id.bubble_selected);
+ ImageView bubbleSelectedImage = (ImageView) holder.findViewById(R.id.bubble_selected_icon);
+ TextView bubbleSelectedText = (TextView) holder.findViewById(R.id.bubble_selected_label);
+ mBubbleSelectedButton = new ButtonViewHolder(bubbleSelected, bubbleSelectedImage,
+ bubbleSelectedText, BUBBLE_PREFERENCE_SELECTED);
+ mBubbleSelectedButton.setSelected(mContext,
+ mSelectedPreference == BUBBLE_PREFERENCE_SELECTED);
+ bubbleSelected.setTag(BUBBLE_PREFERENCE_SELECTED);
+ bubbleSelected.setOnClickListener(this);
+ bubbleSelected.setVisibility(disabledByAdmin ? View.GONE : View.VISIBLE);
+
+ View bubbleNone = holder.findViewById(R.id.bubble_none);
+ ImageView bubbleNoneImage = (ImageView) holder.findViewById(R.id.bubble_none_icon);
+ TextView bubbleNoneText = (TextView) holder.findViewById(R.id.bubble_none_label);
+ mBubbleNoneButton = new ButtonViewHolder(bubbleNone, bubbleNoneImage, bubbleNoneText,
+ BUBBLE_PREFERENCE_NONE);
+ mBubbleNoneButton.setSelected(mContext, mSelectedPreference == BUBBLE_PREFERENCE_NONE);
+ bubbleNone.setTag(BUBBLE_PREFERENCE_NONE);
+ bubbleNone.setOnClickListener(this);
+ bubbleNone.setVisibility(disabledByAdmin ? View.GONE : View.VISIBLE);
+ }
+
+ @Override
+ public void onClick(View v) {
+ final int selected = (int) v.getTag();
+ callChangeListener(selected);
+
+ mBubbleAllButton.setSelected(mContext, selected == BUBBLE_PREFERENCE_ALL);
+ mBubbleSelectedButton.setSelected(mContext, selected == BUBBLE_PREFERENCE_SELECTED);
+ mBubbleNoneButton.setSelected(mContext, selected == BUBBLE_PREFERENCE_NONE);
+ }
+
+ private class ButtonViewHolder {
+ private View mView;
+ private ImageView mImageView;
+ private TextView mTextView;
+ private int mId;
+
+ ButtonViewHolder(View v, ImageView iv, TextView tv, int identifier) {
+ mView = v;
+ mImageView = iv;
+ mTextView = tv;
+ mId = identifier;
+ }
+
+ void setSelected(Context context, boolean selected) {
+ mView.setBackground(selected ? mSelectedBackground : mUnselectedBackground);
+ mView.setSelected(selected);
+
+ ColorStateList stateList = selected
+ ? Utils.getColorAccent(context)
+ : Utils.getColorAttr(context, android.R.attr.textColorPrimary);
+ mImageView.setImageTintList(stateList);
+ mTextView.setTextColor(stateList);
+ }
+ }
+}
diff --git a/src/com/android/settings/notification/app/BubblePreferenceController.java b/src/com/android/settings/notification/app/BubblePreferenceController.java
index d33ba7e..3255192 100644
--- a/src/com/android/settings/notification/app/BubblePreferenceController.java
+++ b/src/com/android/settings/notification/app/BubblePreferenceController.java
@@ -16,6 +16,7 @@
package com.android.settings.notification.app;
+import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
import static android.provider.Settings.Global.NOTIFICATION_BUBBLES;
import android.annotation.Nullable;
@@ -26,11 +27,14 @@
import androidx.fragment.app.FragmentManager;
import androidx.preference.Preference;
-import com.android.settings.R;
import com.android.settings.core.PreferenceControllerMixin;
import com.android.settings.notification.NotificationBackend;
import com.android.settingslib.RestrictedSwitchPreference;
+/**
+ * Preference controller for Bubbles. This is used as the app-specific page and conversation
+ * settings.
+ */
public class BubblePreferenceController extends NotificationPreferenceController
implements PreferenceControllerMixin, Preference.OnPreferenceChangeListener {
@@ -74,40 +78,49 @@
return true;
}
+ @Override
public void updateState(Preference preference) {
- if (mAppRow != null) {
- RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;
+ if (mIsAppPage && mAppRow != null) {
+ // We're on the app specific bubble page which displays a tri-state
+ int backEndPref = mAppRow.bubblePreference;
+ BubblePreference pref = (BubblePreference) preference;
pref.setDisabledByAdmin(mAdmin);
- if (mChannel != null) {
- pref.setChecked(mChannel.canBubble() && isGloballyEnabled());
- pref.setEnabled(!pref.isDisabledByAdmin());
+ if (!isGloballyEnabled()) {
+ pref.setSelectedPreference(BUBBLE_PREFERENCE_NONE);
} else {
- pref.setChecked(mAppRow.allowBubbles && isGloballyEnabled());
- pref.setSummary(mContext.getString(
- R.string.bubbles_app_toggle_summary, mAppRow.label));
+ pref.setSelectedPreference(backEndPref);
}
+ } else if (mChannel != null) {
+ // We're on the channel specific notification page which displays a toggle.
+ RestrictedSwitchPreference switchpref = (RestrictedSwitchPreference) preference;
+ switchpref.setDisabledByAdmin(mAdmin);
+ switchpref.setChecked(mChannel.canBubble() && isGloballyEnabled());
}
}
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
- final boolean value = (Boolean) newValue && isGloballyEnabled();
if (mChannel != null) {
- mChannel.setAllowBubbles(value);
+ // Channel page is toggle
+ mChannel.setAllowBubbles((boolean) newValue);
saveChannel();
- return true;
- } else if (mAppRow != null && mFragmentManager != null) {
- RestrictedSwitchPreference pref = (RestrictedSwitchPreference) preference;
- // if the global setting is off, toggling app level permission requires extra
- // confirmation
- if (!isGloballyEnabled() && !pref.isChecked()) {
- new BubbleWarningDialogFragment()
- .setPkgInfo(mAppRow.pkg, mAppRow.uid)
- .show(mFragmentManager, "dialog");
- return false;
- } else {
- mAppRow.allowBubbles = value;
- mBackend.setAllowBubbles(mAppRow.pkg, mAppRow.uid, value);
+ } else if (mIsAppPage) {
+ // App page is bubble preference
+ BubblePreference pref = (BubblePreference) preference;
+ if (mAppRow != null && mFragmentManager != null) {
+ final int value = (int) newValue;
+ if (!isGloballyEnabled()
+ && pref.getSelectedPreference() == BUBBLE_PREFERENCE_NONE) {
+ // if the global setting is off, toggling app level permission requires extra
+ // confirmation
+ new BubbleWarningDialogFragment()
+ .setPkgPrefInfo(mAppRow.pkg, mAppRow.uid, value)
+ .show(mFragmentManager, "dialog");
+ return false;
+ } else {
+ mAppRow.bubblePreference = value;
+ mBackend.setAllowBubbles(mAppRow.pkg, mAppRow.uid, value);
+ }
}
}
return true;
@@ -118,21 +131,26 @@
NOTIFICATION_BUBBLES, SYSTEM_WIDE_OFF) == SYSTEM_WIDE_ON;
}
- // Used in app level prompt that confirms the user is ok with turning on bubbles
- // globally. If they aren't, undo what
+ /**
+ * Used in app level prompt that confirms the user is ok with turning on bubbles
+ * globally. If they aren't, undo that.
+ */
public static void revertBubblesApproval(Context mContext, String pkg, int uid) {
NotificationBackend backend = new NotificationBackend();
- backend.setAllowBubbles(pkg, uid, false);
+ backend.setAllowBubbles(pkg, uid, BUBBLE_PREFERENCE_NONE);
+
// changing the global settings will cause the observer on the host page to reload
// correct preference state
Settings.Global.putInt(mContext.getContentResolver(),
NOTIFICATION_BUBBLES, SYSTEM_WIDE_OFF);
}
- // Apply global bubbles approval
- public static void applyBubblesApproval(Context mContext, String pkg, int uid) {
+ /**
+ * Apply global bubbles approval
+ */
+ public static void applyBubblesApproval(Context mContext, String pkg, int uid, int pref) {
NotificationBackend backend = new NotificationBackend();
- backend.setAllowBubbles(pkg, uid, true);
+ backend.setAllowBubbles(pkg, uid, pref);
// changing the global settings will cause the observer on the host page to reload
// correct preference state
Settings.Global.putInt(mContext.getContentResolver(),
diff --git a/src/com/android/settings/notification/app/BubbleSummaryPreferenceController.java b/src/com/android/settings/notification/app/BubbleSummaryPreferenceController.java
index f13613c..06c6f3a 100644
--- a/src/com/android/settings/notification/app/BubbleSummaryPreferenceController.java
+++ b/src/com/android/settings/notification/app/BubbleSummaryPreferenceController.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2019 The Android Open Source Project
+ * 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.
@@ -16,39 +16,35 @@
package com.android.settings.notification.app;
+import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
+import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
import static android.provider.Settings.Global.NOTIFICATION_BUBBLES;
-import android.app.settings.SettingsEnums;
import android.content.Context;
-import android.os.Bundle;
+import android.content.Intent;
+import android.content.res.Resources;
import android.provider.Settings;
-import com.android.settings.R;
-import com.android.settings.applications.AppInfoBase;
-import com.android.settings.core.SubSettingLauncher;
-import com.android.settings.notification.NotificationBackend;
-
import androidx.annotation.VisibleForTesting;
import androidx.preference.Preference;
-public class BubbleSummaryPreferenceController extends NotificationPreferenceController {
+import com.android.settings.R;
+import com.android.settings.notification.NotificationBackend;
- private static final String KEY = "bubble_link_pref";
+/**
+ * Summary of the app setting for bubbles, available through app notification settings.
+ */
+public class BubbleSummaryPreferenceController extends NotificationPreferenceController {
+ private static final String KEY = "bubble_pref_link";
+
@VisibleForTesting
- static final int SYSTEM_WIDE_ON = 1;
- @VisibleForTesting
- static final int SYSTEM_WIDE_OFF = 0;
+ static final int ON = 1;
public BubbleSummaryPreferenceController(Context context, NotificationBackend backend) {
super(context, backend);
}
@Override
- public String getPreferenceKey() {
- return KEY;
- }
-
- @Override
public boolean isAvailable() {
if (!super.isAvailable()) {
return false;
@@ -63,45 +59,47 @@
if (isDefaultChannel()) {
return true;
} else {
- return mAppRow != null && mAppRow.allowBubbles;
+ return mAppRow != null;
}
}
return isGloballyEnabled();
}
@Override
+ public String getPreferenceKey() {
+ return KEY;
+ }
+
+ @Override
public void updateState(Preference preference) {
super.updateState(preference);
if (mAppRow != null) {
- Bundle args = new Bundle();
- args.putString(AppInfoBase.ARG_PACKAGE_NAME, mAppRow.pkg);
- args.putInt(AppInfoBase.ARG_PACKAGE_UID, mAppRow.uid);
-
- preference.setIntent(new SubSettingLauncher(mContext)
- .setDestination(AppBubbleNotificationSettings.class.getName())
- .setArguments(args)
- .setSourceMetricsCategory(
- SettingsEnums.NOTIFICATION_APP_NOTIFICATION)
- .toIntent());
+ final Intent intent = new Intent(Settings.ACTION_APP_NOTIFICATION_BUBBLE_SETTINGS);
+ intent.putExtra(Settings.EXTRA_APP_PACKAGE, mAppRow.pkg);
+ intent.putExtra(Settings.EXTRA_APP_UID, mAppRow.uid);
+ preference.setIntent(intent);
}
}
@Override
public CharSequence getSummary() {
- boolean canBubble = false;
- if (mAppRow != null) {
- if (mChannel != null) {
- canBubble |= mChannel.canBubble() && isGloballyEnabled();
- } else {
- canBubble |= mAppRow.allowBubbles && isGloballyEnabled();
- }
+ if (mAppRow == null) {
+ return null;
}
- return mContext.getString(canBubble ? R.string.switch_on_text : R.string.switch_off_text);
+ int backEndPref = mAppRow.bubblePreference;
+ Resources res = mContext.getResources();
+ if (backEndPref == BUBBLE_PREFERENCE_NONE || !isGloballyEnabled()) {
+ return res.getString(R.string.bubble_app_setting_none);
+ } else if (backEndPref == BUBBLE_PREFERENCE_ALL) {
+ return res.getString(R.string.bubble_app_setting_all);
+ } else {
+ return res.getString(R.string.bubble_app_setting_selected);
+ }
}
private boolean isGloballyEnabled() {
return Settings.Global.getInt(mContext.getContentResolver(),
- NOTIFICATION_BUBBLES, SYSTEM_WIDE_OFF) == SYSTEM_WIDE_ON;
+ NOTIFICATION_BUBBLES, ON) == ON;
}
}
diff --git a/src/com/android/settings/notification/app/BubbleWarningDialogFragment.java b/src/com/android/settings/notification/app/BubbleWarningDialogFragment.java
index d3aa758..7d5b24a 100644
--- a/src/com/android/settings/notification/app/BubbleWarningDialogFragment.java
+++ b/src/com/android/settings/notification/app/BubbleWarningDialogFragment.java
@@ -27,6 +27,7 @@
public class BubbleWarningDialogFragment extends InstrumentedDialogFragment {
static final String KEY_PKG = "p";
static final String KEY_UID = "u";
+ static final String KEY_SELECTED_PREFERENCE = "pref";
@Override
@@ -34,10 +35,11 @@
return SettingsEnums.DIALOG_APP_BUBBLE_SETTINGS;
}
- public BubbleWarningDialogFragment setPkgInfo(String pkg, int uid) {
+ public BubbleWarningDialogFragment setPkgPrefInfo(String pkg, int uid, int preference) {
Bundle args = new Bundle();
args.putString(KEY_PKG, pkg);
args.putInt(KEY_UID, uid);
+ args.putInt(KEY_SELECTED_PREFERENCE, preference);
setArguments(args);
return this;
}
@@ -48,6 +50,7 @@
final Bundle args = getArguments();
final String pkg = args.getString(KEY_PKG);
final int uid = args.getInt(KEY_UID);
+ final int pref = args.getInt(KEY_SELECTED_PREFERENCE);
final String title =
getResources().getString(R.string.bubbles_feature_disabled_dialog_title);
@@ -60,7 +63,7 @@
.setPositiveButton(R.string.bubbles_feature_disabled_button_approve,
(dialog, id) ->
BubblePreferenceController.applyBubblesApproval(
- getContext(), pkg, uid))
+ getContext(), pkg, uid, pref))
.setNegativeButton(R.string.bubbles_feature_disabled_button_cancel,
(dialog, id) ->
BubblePreferenceController.revertBubblesApproval(
diff --git a/tests/robotests/src/com/android/settings/development/BubbleGlobalPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/development/BubbleGlobalPreferenceControllerTest.java
deleted file mode 100644
index 9e52a88..0000000
--- a/tests/robotests/src/com/android/settings/development/BubbleGlobalPreferenceControllerTest.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2019 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.settings.development;
-
-import static android.provider.Settings.Global.NOTIFICATION_BUBBLES;
-
-import static com.android.settings.development.BubbleGlobalPreferenceController.OFF;
-import static com.android.settings.development.BubbleGlobalPreferenceController.ON;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.provider.Settings;
-
-import androidx.preference.PreferenceScreen;
-import androidx.preference.SwitchPreference;
-
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
-import org.mockito.MockitoAnnotations;
-import org.robolectric.RobolectricTestRunner;
-import org.robolectric.RuntimeEnvironment;
-
-@RunWith(RobolectricTestRunner.class)
-public class BubbleGlobalPreferenceControllerTest {
- private Context mContext;
-
- @Mock
- private SwitchPreference mPreference;
- @Mock
- private PreferenceScreen mPreferenceScreen;
-
- private BubbleGlobalPreferenceController mController;
-
- @Before
- public void setUp() {
- MockitoAnnotations.initMocks(this);
- mContext = RuntimeEnvironment.application;
- mController = new BubbleGlobalPreferenceController(mContext);
- when(mPreferenceScreen.findPreference(mController.getPreferenceKey()))
- .thenReturn(mPreference);
- mController.displayPreference(mPreferenceScreen);
- }
-
- @Test
- public void onPreferenceChange_settingEnabled_allowBubbles_shouldBeOn() {
- mController.onPreferenceChange(mPreference, true /* new value */);
-
- assertThat(isSettingEnabled()).isTrue();
- }
-
- @Test
- public void onPreferenceChange_settingDisabled_allowBubbles_shouldBeOff() {
- mController.onPreferenceChange(mPreference, false /* new value */);
-
- assertThat(isSettingEnabled()).isFalse();
- }
-
- @Test
- public void updateState_settingEnabled_preferenceShouldBeChecked() {
- Settings.Global.putInt(mContext.getContentResolver(),
- NOTIFICATION_BUBBLES, 1 /* enabled */);
- mController.updateState(mPreference);
-
- verify(mPreference).setChecked(true);
- }
-
- @Test
- public void updateState_settingReset_defaultDisabled_preferenceShouldNotBeChecked() {
- Settings.Global.putInt(mContext.getContentResolver(),
- NOTIFICATION_BUBBLES, 0 /* enabled */);
- mController.updateState(mPreference);
-
- verify(mPreference).setChecked(false);
- }
-
- @Test
- public void onDeveloperOptionsSwitchDisabled_shouldDisable() {
- mController.onDeveloperOptionsSwitchDisabled();
-
- verify(mPreference).setChecked(false);
- verify(mPreference).setEnabled(false);
-
- assertThat(isSettingEnabled()).isFalse();
- }
-
- private boolean isSettingEnabled() {
- return Settings.Global.getInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES,
- OFF /* default off */) == ON;
- }
-
-}
diff --git a/tests/robotests/src/com/android/settings/notification/BubbleNotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/BubbleNotificationPreferenceControllerTest.java
new file mode 100644
index 0000000..b2cf55b
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/BubbleNotificationPreferenceControllerTest.java
@@ -0,0 +1,138 @@
+/*
+ * 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;
+
+import static android.provider.Settings.Global.NOTIFICATION_BUBBLES;
+
+import static com.android.settings.core.BasePreferenceController.AVAILABLE;
+import static com.android.settings.notification.BadgingNotificationPreferenceController.OFF;
+import static com.android.settings.notification.BadgingNotificationPreferenceController.ON;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+import androidx.preference.TwoStatePreference;
+
+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;
+
+@RunWith(RobolectricTestRunner.class)
+public class BubbleNotificationPreferenceControllerTest {
+
+ private Context mContext;
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private PreferenceScreen mScreen;
+
+ private BubbleNotificationPreferenceController mController;
+ private Preference mPreference;
+
+ private static final String KEY_NOTIFICATION_BUBBLES = "notification_bubbles";
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mContext = RuntimeEnvironment.application;
+ mController = new BubbleNotificationPreferenceController(mContext,
+ KEY_NOTIFICATION_BUBBLES);
+ mPreference = new Preference(RuntimeEnvironment.application);
+ mPreference.setKey(mController.getPreferenceKey());
+ when(mScreen.findPreference(mPreference.getKey())).thenReturn(mPreference);
+ }
+
+ @Test
+ public void getAvilabilityStatus_returnsAvailable() {
+ assertEquals(AVAILABLE, mController.getAvailabilityStatus());
+ }
+
+ @Test
+ public void updateState_settingIsOn_preferenceSetChecked() {
+ final TwoStatePreference preference = mock(TwoStatePreference.class);
+ Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, ON);
+
+ mController.updateState(preference);
+
+ verify(preference).setChecked(true);
+ }
+
+ @Test
+ public void updateState_settingIsOff_preferenceSetUnchecked() {
+ final TwoStatePreference preference = mock(TwoStatePreference.class);
+ Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, OFF);
+ assertThat(Settings.Global.getInt(mContext.getContentResolver(),
+ NOTIFICATION_BUBBLES, ON)).isEqualTo(OFF);
+
+ mController.updateState(preference);
+
+ verify(preference).setChecked(false);
+ }
+
+ @Test
+ public void isChecked_settingIsOff_shouldReturnFalse() {
+ Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, OFF);
+
+ assertThat(mController.isChecked()).isFalse();
+ }
+
+ @Test
+ public void isChecked_settingIsOn_shouldReturnTrue() {
+ Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, ON);
+
+ assertThat(mController.isChecked()).isTrue();
+ }
+
+ @Test
+ public void setChecked_setFalse_disablesSetting() {
+ Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, ON);
+
+ mController.setChecked(false);
+ int updatedValue = Settings.Global.getInt(mContext.getContentResolver(),
+ NOTIFICATION_BUBBLES, -1);
+
+ assertThat(updatedValue).isEqualTo(OFF);
+ }
+
+ @Test
+ public void setChecked_setTrue_enablesSetting() {
+ Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, OFF);
+
+ mController.setChecked(true);
+ int updatedValue = Settings.Global.getInt(mContext.getContentResolver(),
+ NOTIFICATION_BUBBLES, -1);
+
+ assertThat(updatedValue).isEqualTo(ON);
+ }
+
+ @Test
+ public void isSliceable_returnsFalse() {
+ assertThat(mController.isSliceable()).isFalse();
+ }
+}
diff --git a/tests/robotests/src/com/android/settings/notification/BubbleSummaryNotificationPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/BubbleSummaryNotificationPreferenceControllerTest.java
new file mode 100644
index 0000000..b5f505b
--- /dev/null
+++ b/tests/robotests/src/com/android/settings/notification/BubbleSummaryNotificationPreferenceControllerTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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;
+
+import static android.provider.Settings.Global.NOTIFICATION_BUBBLES;
+
+import static com.android.settings.notification.BadgingNotificationPreferenceController.OFF;
+import static com.android.settings.notification.BadgingNotificationPreferenceController.ON;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import android.content.Context;
+import android.provider.Settings;
+
+import androidx.preference.Preference;
+
+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 BubbleSummaryNotificationPreferenceControllerTest {
+
+ private Context mContext;
+
+ private BubbleSummaryNotificationPreferenceController mController;
+ private Preference mPreference;
+
+ private static final String KEY_NOTIFICATION_BUBBLES = "notification_bubbles";
+
+ @Before
+ public void setUp() {
+ mContext = RuntimeEnvironment.application;
+ mController = new BubbleSummaryNotificationPreferenceController(mContext,
+ KEY_NOTIFICATION_BUBBLES);
+ mPreference = new Preference(RuntimeEnvironment.application);
+ }
+
+ @Test
+ public void getSummary_NOTIFICATION_BUBBLESIsOff_returnOffString() {
+ Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, OFF);
+
+ assertThat(mController.getSummary()).isEqualTo("Off");
+ }
+
+ @Test
+ public void getSummary_NOTIFICATION_BUBBLESIsOff_returnOnString() {
+ Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, ON);
+
+ String onString = mContext.getString(R.string.notifications_bubble_setting_on_summary);
+ assertThat(mController.getSummary()).isEqualTo(onString);
+ }
+}
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 c2c45cb..0cf6dc6 100644
--- a/tests/robotests/src/com/android/settings/notification/app/BubblePreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/app/BubblePreferenceControllerTest.java
@@ -17,6 +17,9 @@
package com.android.settings.notification.app;
import static android.app.NotificationChannel.DEFAULT_CHANNEL_ID;
+import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
+import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
+import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED;
import static android.app.NotificationManager.IMPORTANCE_HIGH;
import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_NONE;
@@ -25,8 +28,8 @@
import static com.android.settings.notification.app.BubblePreferenceController.SYSTEM_WIDE_OFF;
import static com.android.settings.notification.app.BubblePreferenceController.SYSTEM_WIDE_ON;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
@@ -44,6 +47,11 @@
import android.os.UserManager;
import android.provider.Settings;
+import androidx.fragment.app.FragmentManager;
+import androidx.fragment.app.FragmentTransaction;
+import androidx.preference.Preference;
+import androidx.preference.PreferenceScreen;
+
import com.android.settings.notification.NotificationBackend;
import com.android.settingslib.RestrictedLockUtils;
import com.android.settingslib.RestrictedSwitchPreference;
@@ -58,11 +66,6 @@
import org.robolectric.RuntimeEnvironment;
import org.robolectric.shadows.ShadowApplication;
-import androidx.fragment.app.FragmentManager;
-import androidx.fragment.app.FragmentTransaction;
-import androidx.preference.Preference;
-import androidx.preference.PreferenceScreen;
-
@RunWith(RobolectricTestRunner.class)
public class BubblePreferenceControllerTest {
@@ -125,7 +128,7 @@
public void testIsAvailable_channel_yesIfAppOff() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- appRow.allowBubbles = false;
+ appRow.bubblePreference = BUBBLE_PREFERENCE_NONE;
NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, null, null, null, null);
@@ -177,7 +180,7 @@
@Test
public void testIsAvailable_defaultChannel() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- appRow.allowBubbles = true;
+ appRow.bubblePreference = BUBBLE_PREFERENCE_ALL;
NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
when(channel.getId()).thenReturn(DEFAULT_CHANNEL_ID);
@@ -190,7 +193,7 @@
@Test
public void testIsAvailable_channel() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- appRow.allowBubbles = true;
+ appRow.bubblePreference = BUBBLE_PREFERENCE_ALL;
NotificationChannel channel = mock(NotificationChannel.class);
when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
mController.onResume(appRow, channel, null, null, null, null);
@@ -213,7 +216,20 @@
}
@Test
- public void testUpdateState_channelNotBlockable() {
+ public void testUpdateState_app_disabledByAdmin() {
+ NotificationChannel channel = mock(NotificationChannel.class);
+ when(channel.getId()).thenReturn("something");
+ mAppPageController.onResume(new NotificationBackend.AppRow(), channel, null,
+ null, null, mock(RestrictedLockUtils.EnforcedAdmin.class));
+
+ BubblePreference pref = new BubblePreference(mContext);
+ mAppPageController.updateState(pref);
+
+ assertFalse(pref.isEnabled());
+ }
+
+ @Test
+ public void testUpdateState_channel_channelNotBlockable() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
NotificationChannel channel = mock(NotificationChannel.class);
@@ -251,21 +267,24 @@
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.label = "App!";
- appRow.allowBubbles = true;
- mController.onResume(appRow, null, null, null, null, null);
+ appRow.bubblePreference = BUBBLE_PREFERENCE_ALL;
+ mAppPageController.onResume(appRow, null, null, null, null, null);
- RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext);
- mController.updateState(pref);
- assertTrue(pref.isChecked());
+ BubblePreference pref = new BubblePreference(mContext);
+ mAppPageController.updateState(pref);
+ assertEquals(BUBBLE_PREFERENCE_ALL, pref.getSelectedPreference());
- appRow.allowBubbles = false;
- mController.onResume(appRow, null, null, null, null, null);
+ appRow.bubblePreference = BUBBLE_PREFERENCE_NONE;
+ mAppPageController.onResume(appRow, null, null, null, null, null);
- mController.updateState(pref);
- assertFalse(pref.isChecked());
+ mAppPageController.updateState(pref);
+ assertEquals(BUBBLE_PREFERENCE_NONE, pref.getSelectedPreference());
- assertNotNull(pref.getSummary());
- assertTrue(pref.getSummary().toString().contains(appRow.label));
+ appRow.bubblePreference = BUBBLE_PREFERENCE_SELECTED;
+ mAppPageController.onResume(appRow, null, null, null, null, null);
+
+ mAppPageController.updateState(pref);
+ assertEquals(BUBBLE_PREFERENCE_SELECTED, pref.getSelectedPreference());
}
@Test
@@ -274,22 +293,21 @@
NOTIFICATION_BUBBLES, SYSTEM_WIDE_OFF);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.label = "App!";
- appRow.allowBubbles = true;
- mController.onResume(appRow, null, null, null, null, null);
+ appRow.bubblePreference = BUBBLE_PREFERENCE_ALL;
+ mAppPageController.onResume(appRow, null, null, null, null, null);
- RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext);
- mController.updateState(pref);
- assertFalse(pref.isChecked());
+ BubblePreference pref = new BubblePreference(mContext);
+ mAppPageController.updateState(pref);
+ assertEquals(BUBBLE_PREFERENCE_NONE, pref.getSelectedPreference());
}
@Test
public void testOnPreferenceChange_on_channel() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- appRow.allowBubbles = true;
+ appRow.bubblePreference = BUBBLE_PREFERENCE_SELECTED;
NotificationChannel channel =
new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_LOW);
- channel.setAllowBubbles(false);
mController.onResume(appRow, channel, null, null, null, null);
RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext);
@@ -306,10 +324,9 @@
public void testOnPreferenceChange_off_channel() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- appRow.allowBubbles = true;
+ appRow.bubblePreference = BUBBLE_PREFERENCE_SELECTED;
NotificationChannel channel =
new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_HIGH);
- channel.setAllowBubbles(true);
mController.onResume(appRow, channel, null, null, null, null);
RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext);
@@ -322,59 +339,78 @@
assertFalse(channel.canBubble());
}
+
@Test
- public void testOnPreferenceChange_on_app() {
+ public void testOnPreferenceChange_app_all() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- appRow.allowBubbles = false;
- mController.onResume(appRow, null, null, null, null, null);
+ appRow.bubblePreference = BUBBLE_PREFERENCE_NONE;
+ mAppPageController.onResume(appRow, null, null, null, null, null);
- RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext);
+ BubblePreference pref = new BubblePreference(mContext);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
- mController.displayPreference(mScreen);
- mController.updateState(pref);
+ mAppPageController.displayPreference(mScreen);
+ mAppPageController.updateState(pref);
- mController.onPreferenceChange(pref, true);
+ mAppPageController.onPreferenceChange(pref, BUBBLE_PREFERENCE_ALL);
- assertTrue(appRow.allowBubbles);
- verify(mBackend, times(1)).setAllowBubbles(any(), anyInt(), eq(true));
+ assertEquals(appRow.bubblePreference, BUBBLE_PREFERENCE_ALL);
+ verify(mBackend, times(1)).setAllowBubbles(any(), anyInt(), eq(BUBBLE_PREFERENCE_ALL));
}
@Test
- public void testOnPreferenceChange_off_app() {
- Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
- NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- appRow.allowBubbles = true;
- mController.onResume(appRow, null, null, null, null, null);
-
- RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext);
- when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
- mController.displayPreference(mScreen);
- mController.updateState(pref);
-
- mController.onPreferenceChange(pref, false);
-
- assertFalse(appRow.allowBubbles);
- verify(mBackend, times(1)).setAllowBubbles(any(), anyInt(), eq(false));
- }
-
- @Test
- public void testOnPreferenceChange_on_app_offGlobally() {
+ public void testOnPreferenceChange_app_all_offGlobally() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES,
SYSTEM_WIDE_OFF);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- appRow.allowBubbles = false;
- mController.onResume(appRow, null, null, null, null, null);
+ appRow.bubblePreference = BUBBLE_PREFERENCE_NONE;
+ mAppPageController.onResume(appRow, null, null, null, null, null);
- RestrictedSwitchPreference pref = new RestrictedSwitchPreference(mContext);
+ BubblePreference pref = new BubblePreference(mContext);
when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
- mController.displayPreference(mScreen);
- mController.updateState(pref);
+ mAppPageController.displayPreference(mScreen);
+ mAppPageController.updateState(pref);
- mController.onPreferenceChange(pref, true);
+ mAppPageController.onPreferenceChange(pref, BUBBLE_PREFERENCE_ALL);
- assertFalse(appRow.allowBubbles);
- verify(mBackend, never()).setAllowBubbles(any(), anyInt(), eq(true));
+ assertEquals(appRow.bubblePreference, BUBBLE_PREFERENCE_NONE);
+ verify(mBackend, never()).setAllowBubbles(any(), anyInt(), eq(BUBBLE_PREFERENCE_ALL));
verify(mFragmentManager, times(1)).beginTransaction();
}
+
+ @Test
+ public void testOnPreferenceChange_app_selected() {
+ Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
+ NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+ appRow.bubblePreference = BUBBLE_PREFERENCE_ALL;
+ mAppPageController.onResume(appRow, null, null, null, null, null);
+
+ BubblePreference pref = new BubblePreference(mContext);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
+ mAppPageController.displayPreference(mScreen);
+ mAppPageController.updateState(pref);
+
+ mAppPageController.onPreferenceChange(pref, BUBBLE_PREFERENCE_NONE);
+
+ assertEquals(BUBBLE_PREFERENCE_NONE, appRow.bubblePreference);
+ verify(mBackend, times(1)).setAllowBubbles(any(), anyInt(), eq(BUBBLE_PREFERENCE_NONE));
+ }
+
+ @Test
+ public void testOnPreferenceChange_app_none() {
+ Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
+ NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+ appRow.bubblePreference = BUBBLE_PREFERENCE_ALL;
+ mAppPageController.onResume(appRow, null, null, null, null, null);
+
+ BubblePreference pref = new BubblePreference(mContext);
+ when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
+ mAppPageController.displayPreference(mScreen);
+ mAppPageController.updateState(pref);
+
+ mAppPageController.onPreferenceChange(pref, BUBBLE_PREFERENCE_NONE);
+
+ assertEquals(BUBBLE_PREFERENCE_NONE, appRow.bubblePreference);
+ verify(mBackend, times(1)).setAllowBubbles(any(), anyInt(), eq(BUBBLE_PREFERENCE_NONE));
+ }
}
diff --git a/tests/robotests/src/com/android/settings/notification/app/BubbleSummaryPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/app/BubbleSummaryPreferenceControllerTest.java
index 80abfbb..9d664ac 100644
--- a/tests/robotests/src/com/android/settings/notification/app/BubbleSummaryPreferenceControllerTest.java
+++ b/tests/robotests/src/com/android/settings/notification/app/BubbleSummaryPreferenceControllerTest.java
@@ -17,28 +17,31 @@
package com.android.settings.notification.app;
import static android.app.NotificationChannel.DEFAULT_CHANNEL_ID;
+import static android.app.NotificationManager.BUBBLE_PREFERENCE_ALL;
+import static android.app.NotificationManager.BUBBLE_PREFERENCE_NONE;
+import static android.app.NotificationManager.BUBBLE_PREFERENCE_SELECTED;
import static android.app.NotificationManager.IMPORTANCE_HIGH;
import static android.provider.Settings.Global.NOTIFICATION_BUBBLES;
-import static com.android.settings.notification.app.BubbleSummaryPreferenceController.SYSTEM_WIDE_OFF;
-import static com.android.settings.notification.app.BubbleSummaryPreferenceController.SYSTEM_WIDE_ON;
+import static com.android.settings.notification.app.BubblePreferenceController.SYSTEM_WIDE_OFF;
+import static com.android.settings.notification.app.BubblePreferenceController.SYSTEM_WIDE_ON;
import static junit.framework.TestCase.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.NotificationChannel;
import android.content.Context;
import android.provider.Settings;
+import androidx.preference.Preference;
+
+import com.android.settings.R;
import com.android.settings.notification.NotificationBackend;
import org.junit.Before;
@@ -50,8 +53,6 @@
import org.robolectric.RuntimeEnvironment;
import org.robolectric.shadows.ShadowApplication;
-import androidx.preference.Preference;
-
@RunWith(RobolectricTestRunner.class)
public class BubbleSummaryPreferenceControllerTest {
@@ -70,13 +71,13 @@
}
@Test
- public void testNoCrashIfNoOnResume() {
+ public void isAvailable_noOnResume_shouldNotCrash() {
mController.isAvailable();
mController.updateState(mock(Preference.class));
}
@Test
- public void testIsAvailable_notIfAppBlocked() {
+ public void isAvailable_appBlocked_shouldReturnFalse() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
appRow.banned = true;
mController.onResume(appRow, mock(NotificationChannel.class), null, null, null, null);
@@ -84,53 +85,52 @@
}
@Test
- public void testIsAvailable_notIfOffGlobally() {
- NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- NotificationChannel channel = mock(NotificationChannel.class);
- when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
- mController.onResume(appRow, channel, null, null, null, null);
- Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES,
- SYSTEM_WIDE_OFF);
-
- assertFalse(mController.isAvailable());
- }
-
- @Test
- public void testIsAvailable_app() {
+ public void isAvailable_nullChannelNOTIFICATION_BUBBLESisOn_shouldReturnTrue() {
+ Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
mController.onResume(appRow, null, null, null, null, null);
- Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
assertTrue(mController.isAvailable());
}
@Test
- public void testIsNotAvailable_app_globalOff() {
- NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- mController.onResume(appRow, null, null, null, null, null);
+ public void isAvailable_nullChannelNOTIFICATION_BUBBLESisOff_shouldReturnFalse() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES,
SYSTEM_WIDE_OFF);
+ NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+ mController.onResume(appRow, null, null, null, null, null);
assertFalse(mController.isAvailable());
}
@Test
- public void testIsAvailable_defaultChannel() {
+ public void isAvailable_nonNullChannelNOTIFICATION_BUBBLESisOff_shouldReturnFalse() {
+ Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES,
+ SYSTEM_WIDE_OFF);
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- appRow.allowBubbles = true;
+ NotificationChannel channel = mock(NotificationChannel.class);
+ when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH);
+ mController.onResume(appRow, channel, null, null, null, null);
+
+ assertFalse(mController.isAvailable());
+ }
+
+ @Test
+ public void isAvailable_defaultChannelNOTIFICATION_BUBBLESisOn_shouldReturnTrue() {
+ Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
+ 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);
- Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
assertTrue(mController.isAvailable());
}
@Test
- public void testUpdateState() {
+ public void updateState_setsIntent() {
NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- appRow.allowBubbles = true;
+ appRow.bubblePreference = BUBBLE_PREFERENCE_ALL;
mController.onResume(appRow, null, null, null, null, null);
Preference pref = new Preference(mContext);
@@ -139,22 +139,53 @@
}
@Test
- public void testGetSummary() {
- Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
- NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
- appRow.allowBubbles = true;
- mController.onResume(appRow, null, null, null, null, null);
-
- assertEquals("On", mController.getSummary());
-
+ public void getSummary_NOTIFICATION_BUBBLESIsOff_returnsNoneString() {
Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES,
SYSTEM_WIDE_OFF);
- assertEquals("Off", mController.getSummary());
- Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON);
- appRow.allowBubbles = false;
+ NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
mController.onResume(appRow, null, null, null, null, null);
- assertEquals("Off", mController.getSummary());
+ String noneString = mContext.getString(R.string.bubble_app_setting_none);
+ assertEquals(noneString, mController.getSummary());
+ }
+
+ @Test
+ public void getSummary_BUBBLE_PREFERENCE_NONEisSelected_returnsNoneString() {
+ Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES,
+ SYSTEM_WIDE_ON);
+
+ NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+ appRow.bubblePreference = BUBBLE_PREFERENCE_NONE;
+ mController.onResume(appRow, null, null, null, null, null);
+
+ String noneString = mContext.getString(R.string.bubble_app_setting_none);
+ assertEquals(noneString, mController.getSummary());
+ }
+
+ @Test
+ public void getSummary_BUBBLE_PREFERENCE_ALLisSelected_returnsAllString() {
+ Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES,
+ SYSTEM_WIDE_ON);
+
+ NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+ appRow.bubblePreference = BUBBLE_PREFERENCE_ALL;
+ mController.onResume(appRow, null, null, null, null, null);
+
+ String allString = mContext.getString(R.string.bubble_app_setting_all);
+ assertEquals(allString, mController.getSummary());
+ }
+
+ @Test
+ public void getSummary_BUBBLE_PREFERENCE_SELECTEDisSelected_returnsSelectedString() {
+ Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES,
+ SYSTEM_WIDE_ON);
+
+ NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
+ appRow.bubblePreference = BUBBLE_PREFERENCE_SELECTED;
+ mController.onResume(appRow, null, null, null, null, null);
+
+ String selectedString = mContext.getString(R.string.bubble_app_setting_selected);
+ assertEquals(selectedString, mController.getSummary());
}
}