From a27918494f7b897dc5a2db3616373a7ea4e206a2 Mon Sep 17 00:00:00 2001 From: Mady Mellor Date: Fri, 17 Apr 2020 11:24:50 -0700 Subject: [PATCH] Add list of selected/excluded convos to bubble settings * Some changes to extend AppConversationListPrefController * When a user removes something from the selected or excluded list that resets the channel setting Bug: 148619540 Test: make -j40 RunSettingsRoboTests ROBOTEST_FILTER="Bubble" Change-Id: I7a9ed7b70208dbdefca6c3c09d34d55c65f06408 --- res/drawable/ic_delete_x.xml | 25 +++ .../bubble_conversation_remove_button.xml | 24 +++ res/xml/app_bubble_notification_settings.xml | 8 + .../AppBubbleListPreferenceController.java | 154 ++++++++++++++++ .../app/AppBubbleNotificationSettings.java | 11 +- ...pConversationListPreferenceController.java | 43 ++++- .../app/BubblePreferenceController.java | 8 +- .../app/ConversationNotificationSettings.java | 2 +- ...AppBubbleListPreferenceControllerTest.java | 173 ++++++++++++++++++ .../app/BubblePreferenceControllerTest.java | 59 +++--- 10 files changed, 472 insertions(+), 35 deletions(-) create mode 100644 res/drawable/ic_delete_x.xml create mode 100644 res/layout/bubble_conversation_remove_button.xml create mode 100644 src/com/android/settings/notification/AppBubbleListPreferenceController.java create mode 100644 tests/robotests/src/com/android/settings/notification/app/AppBubbleListPreferenceControllerTest.java diff --git a/res/drawable/ic_delete_x.xml b/res/drawable/ic_delete_x.xml new file mode 100644 index 00000000000..345daf03fe6 --- /dev/null +++ b/res/drawable/ic_delete_x.xml @@ -0,0 +1,25 @@ + + + + + diff --git a/res/layout/bubble_conversation_remove_button.xml b/res/layout/bubble_conversation_remove_button.xml new file mode 100644 index 00000000000..6ec48dcbea8 --- /dev/null +++ b/res/layout/bubble_conversation_remove_button.xml @@ -0,0 +1,24 @@ + + + \ No newline at end of file diff --git a/res/xml/app_bubble_notification_settings.xml b/res/xml/app_bubble_notification_settings.xml index 3f52ad38153..976d9f0c48f 100644 --- a/res/xml/app_bubble_notification_settings.xml +++ b/res/xml/app_bubble_notification_settings.xml @@ -27,4 +27,12 @@ android:title="@string/notification_bubbles_title" settings:allowDividerBelow="false"/> + + + diff --git a/src/com/android/settings/notification/AppBubbleListPreferenceController.java b/src/com/android/settings/notification/AppBubbleListPreferenceController.java new file mode 100644 index 00000000000..457a61ce45b --- /dev/null +++ b/src/com/android/settings/notification/AppBubbleListPreferenceController.java @@ -0,0 +1,154 @@ +/* + * 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.app.NotificationChannel.DEFAULT_ALLOW_BUBBLE; +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.annotation.Nullable; +import android.app.NotificationChannel; +import android.app.NotificationChannelGroup; +import android.content.Context; +import android.content.pm.ShortcutInfo; +import android.graphics.drawable.Drawable; +import android.service.notification.ConversationChannelWrapper; +import android.view.View; +import android.widget.ImageView; + +import androidx.preference.Preference; +import androidx.preference.PreferenceViewHolder; + +import com.android.settings.R; +import com.android.settings.notification.app.AppConversationListPreferenceController; +import com.android.settingslib.RestrictedLockUtils; + +import com.google.common.annotations.VisibleForTesting; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * Displays a list of conversations that have either been selected or excluded from bubbling. + */ +public class AppBubbleListPreferenceController extends AppConversationListPreferenceController { + + private static final String KEY = "bubble_conversations"; + + public AppBubbleListPreferenceController(Context context, NotificationBackend backend) { + super(context, backend); + } + + @Override + public void onResume(NotificationBackend.AppRow appRow, + @Nullable NotificationChannel channel, @Nullable NotificationChannelGroup group, + Drawable conversationDrawable, + ShortcutInfo conversationInfo, + RestrictedLockUtils.EnforcedAdmin admin) { + super.onResume(appRow, channel, group, conversationDrawable, conversationInfo, admin); + // In case something changed in the foreground (e.g. via bubble button on notification) + loadConversationsAndPopulate(); + } + + @Override + public String getPreferenceKey() { + return KEY; + } + + @Override + public boolean isAvailable() { + if (!super.isAvailable()) { + return false; + } + if (mAppRow.bubblePreference == BUBBLE_PREFERENCE_NONE) { + return false; + } + return true; + } + + @VisibleForTesting + @Override + public List filterAndSortConversations( + List conversations) { + return conversations.stream() + .sorted(mConversationComparator) + .filter((c) -> { + if (mAppRow.bubblePreference == BUBBLE_PREFERENCE_SELECTED) { + return c.getNotificationChannel().canBubble(); + } else if (mAppRow.bubblePreference == BUBBLE_PREFERENCE_ALL) { + return c.getNotificationChannel().getAllowBubbles() == 0; + } + return false; + }) + .collect(Collectors.toList()); + } + + @Override + protected int getTitleResId() { + // TODO: possible to left align like mocks? + return mAppRow.bubblePreference == BUBBLE_PREFERENCE_SELECTED + ? R.string.bubble_app_setting_selected_conversation_title + : R.string.bubble_app_setting_excluded_conversation_title; + } + + @VisibleForTesting + @Override + public Preference createConversationPref(final ConversationChannelWrapper conversation) { + final ConversationPreference pref = new ConversationPreference(mContext); + populateConversationPreference(conversation, pref); + pref.setOnClickListener((v) -> { + conversation.getNotificationChannel().setAllowBubbles(DEFAULT_ALLOW_BUBBLE); + mBackend.updateChannel(mAppRow.pkg, mAppRow.uid, conversation.getNotificationChannel()); + mPreference.removePreference(pref); + if (mPreference.getPreferenceCount() == 0) { + mPreference.setVisible(false); + } + }); + return pref; + } + + /** Simple preference with a 'x' button at the end. */ + @VisibleForTesting + public static class ConversationPreference extends Preference implements View.OnClickListener { + + View.OnClickListener mOnClickListener; + + ConversationPreference(Context context) { + super(context); + setWidgetLayoutResource(R.layout.bubble_conversation_remove_button); + } + + @Override + public void onBindViewHolder(final PreferenceViewHolder holder) { + super.onBindViewHolder(holder); + ImageView view = holder.itemView.findViewById(R.id.button); + view.setOnClickListener(mOnClickListener); + } + + public void setOnClickListener(View.OnClickListener listener) { + mOnClickListener = listener; + } + + @Override + public void onClick(View v) { + if (mOnClickListener != null) { + mOnClickListener.onClick(v); + } + } + } +} diff --git a/src/com/android/settings/notification/app/AppBubbleNotificationSettings.java b/src/com/android/settings/notification/app/AppBubbleNotificationSettings.java index 5026a26a52a..b1b126e56c0 100644 --- a/src/com/android/settings/notification/app/AppBubbleNotificationSettings.java +++ b/src/com/android/settings/notification/app/AppBubbleNotificationSettings.java @@ -22,6 +22,7 @@ import android.text.TextUtils; import android.util.Log; import com.android.settings.R; +import com.android.settings.notification.AppBubbleListPreferenceController; import com.android.settings.notification.NotificationBackend; import com.android.settings.search.BaseSearchIndexProvider; import com.android.settingslib.core.AbstractPreferenceController; @@ -56,18 +57,20 @@ public class AppBubbleNotificationSettings extends NotificationSettings implemen @Override protected List createPreferenceControllers(Context context) { - mControllers = getPreferenceControllers(context, this); + mControllers = getPreferenceControllers(context, this, mDependentFieldListener); return new ArrayList<>(mControllers); } protected static List getPreferenceControllers( - Context context, AppBubbleNotificationSettings fragment) { + Context context, AppBubbleNotificationSettings fragment, + DependentFieldListener listener) { List controllers = new ArrayList<>(); controllers.add(new HeaderPreferenceController(context, fragment)); controllers.add(new BubblePreferenceController(context, fragment != null ? fragment.getChildFragmentManager() : null, - new NotificationBackend(), true /* isAppPage */)); + new NotificationBackend(), true /* isAppPage */, listener)); + controllers.add(new AppBubbleListPreferenceController(context, new NotificationBackend())); return controllers; } @@ -114,7 +117,7 @@ public class AppBubbleNotificationSettings extends NotificationSettings implemen public List createPreferenceControllers(Context context) { return new ArrayList<>(AppBubbleNotificationSettings.getPreferenceControllers( - context, null)); + context, null, null)); } }; } diff --git a/src/com/android/settings/notification/app/AppConversationListPreferenceController.java b/src/com/android/settings/notification/app/AppConversationListPreferenceController.java index bea015709c2..2fcd2b2059a 100644 --- a/src/com/android/settings/notification/app/AppConversationListPreferenceController.java +++ b/src/com/android/settings/notification/app/AppConversationListPreferenceController.java @@ -19,6 +19,7 @@ package com.android.settings.notification.app; import android.app.NotificationChannel; import android.app.settings.SettingsEnums; import android.content.Context; +import android.content.pm.ParceledListSlice; import android.content.pm.ShortcutInfo; import android.os.AsyncTask; import android.os.Bundle; @@ -33,6 +34,7 @@ import com.android.settings.applications.AppInfoBase; import com.android.settings.core.SubSettingLauncher; import com.android.settings.notification.NotificationBackend; +import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; @@ -42,8 +44,8 @@ public class AppConversationListPreferenceController extends NotificationPrefere private static final String KEY = "conversations"; public static final String ARG_FROM_SETTINGS = "fromSettings"; - private List mConversations; - private PreferenceCategory mPreference; + protected List mConversations = new ArrayList<>(); + protected PreferenceCategory mPreference; private boolean mHasSentMsg; public AppConversationListPreferenceController(Context context, NotificationBackend backend) { @@ -75,13 +77,23 @@ public class AppConversationListPreferenceController extends NotificationPrefere @Override public void updateState(Preference preference) { mPreference = (PreferenceCategory) preference; + loadConversationsAndPopulate(); + } + + protected void loadConversationsAndPopulate() { + if (mAppRow == null) { + return; + } // Load channel settings new AsyncTask() { @Override protected Void doInBackground(Void... unused) { mHasSentMsg = mBackend.hasSentMessage(mAppRow.pkg, mAppRow.uid); - mConversations = mBackend.getConversations(mAppRow.pkg, mAppRow.uid).getList(); - Collections.sort(mConversations, mConversationComparator); + ParceledListSlice list = + mBackend.getConversations(mAppRow.pkg, mAppRow.uid); + if (list != null) { + mConversations = filterAndSortConversations(list.getList()); + } return null; } @@ -95,11 +107,22 @@ public class AppConversationListPreferenceController extends NotificationPrefere }.execute(); } + protected List filterAndSortConversations( + List conversations) { + Collections.sort(conversations, mConversationComparator); + return conversations; + } + + protected int getTitleResId() { + return R.string.conversations_category_title; + } + private void populateList() { + if (mPreference == null) { + return; + } // TODO: if preference has children, compare with newly loaded list mPreference.removeAll(); - mPreference.setTitle(R.string.conversations_category_title); - if (mConversations.isEmpty()) { if (mHasSentMsg) { mPreference.setVisible(true); @@ -112,6 +135,7 @@ public class AppConversationListPreferenceController extends NotificationPrefere } } else { mPreference.setVisible(true); + mPreference.setTitle(getTitleResId()); populateConversations(); } } @@ -127,6 +151,12 @@ public class AppConversationListPreferenceController extends NotificationPrefere protected Preference createConversationPref(final ConversationChannelWrapper conversation) { Preference pref = new Preference(mContext); + populateConversationPreference(conversation, pref); + return pref; + } + + protected void populateConversationPreference(final ConversationChannelWrapper conversation, + final Preference pref) { ShortcutInfo si = conversation.getShortcutInfo(); pref.setTitle(si != null @@ -157,7 +187,6 @@ public class AppConversationListPreferenceController extends NotificationPrefere .setTitleText(pref.getTitle()) .setSourceMetricsCategory(SettingsEnums.NOTIFICATION_APP_NOTIFICATION) .toIntent()); - return pref; } protected Comparator mConversationComparator = diff --git a/src/com/android/settings/notification/app/BubblePreferenceController.java b/src/com/android/settings/notification/app/BubblePreferenceController.java index 02d6d99e049..0ca2095d6ec 100644 --- a/src/com/android/settings/notification/app/BubblePreferenceController.java +++ b/src/com/android/settings/notification/app/BubblePreferenceController.java @@ -49,12 +49,15 @@ public class BubblePreferenceController extends NotificationPreferenceController private boolean mIsAppPage; private boolean mHasSentInvalidMsg; private int mNumConversations; + private NotificationSettings.DependentFieldListener mListener; public BubblePreferenceController(Context context, @Nullable FragmentManager fragmentManager, - NotificationBackend backend, boolean isAppPage) { + NotificationBackend backend, boolean isAppPage, + @Nullable NotificationSettings.DependentFieldListener listener) { super(context, backend); mFragmentManager = fragmentManager; mIsAppPage = isAppPage; + mListener = listener; } @Override @@ -128,6 +131,9 @@ public class BubblePreferenceController extends NotificationPreferenceController mBackend.setAllowBubbles(mAppRow.pkg, mAppRow.uid, value); } } + if (mListener != null) { + mListener.onFieldValueChanged(); + } } return true; } diff --git a/src/com/android/settings/notification/app/ConversationNotificationSettings.java b/src/com/android/settings/notification/app/ConversationNotificationSettings.java index 9ee4a2cf2e1..902c81c8996 100644 --- a/src/com/android/settings/notification/app/ConversationNotificationSettings.java +++ b/src/com/android/settings/notification/app/ConversationNotificationSettings.java @@ -92,7 +92,7 @@ public class ConversationNotificationSettings extends NotificationSettings { mControllers.add(new BadgePreferenceController(context, mBackend)); mControllers.add(new NotificationsOffPreferenceController(context)); mControllers.add(new BubblePreferenceController(context, getChildFragmentManager(), - mBackend, false /* isAppPage */)); + mBackend, false /* isAppPage */, null /* dependentFieldListener */)); mControllers.add(new ConversationDemotePreferenceController(context, this, mBackend)); mControllers.add(new BubbleCategoryPreferenceController(context)); mControllers.add(new BubbleLinkPreferenceController(context)); diff --git a/tests/robotests/src/com/android/settings/notification/app/AppBubbleListPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/app/AppBubbleListPreferenceControllerTest.java new file mode 100644 index 00000000000..d176827c08b --- /dev/null +++ b/tests/robotests/src/com/android/settings/notification/app/AppBubbleListPreferenceControllerTest.java @@ -0,0 +1,173 @@ +/* + * 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_ALLOW_BUBBLE; +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 com.google.common.truth.Truth.assertThat; + +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.anyString; +import static org.mockito.Mockito.mock; +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.content.pm.ParceledListSlice; +import android.content.pm.ShortcutInfo; +import android.os.UserManager; +import android.service.notification.ConversationChannelWrapper; + +import androidx.preference.PreferenceCategory; + +import com.android.settings.notification.AppBubbleListPreferenceController; +import com.android.settings.notification.NotificationBackend; + +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 java.util.ArrayList; +import java.util.List; + + +@RunWith(RobolectricTestRunner.class) +public class AppBubbleListPreferenceControllerTest { + + private Context mContext; + @Mock + private NotificationBackend mBackend; + @Mock + private NotificationManager mNm; + @Mock + private UserManager mUm; + + private AppBubbleListPreferenceController mController; + private ParceledListSlice mConvoList; + + @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; + + List convoList = new ArrayList<>(); + convoList.add(getConvo(-1, "default")); + convoList.add(getConvo(1, "selected")); + convoList.add(getConvo(0, "excluded")); + mConvoList = new ParceledListSlice<>(convoList); + when(mBackend.getConversations(anyString(), anyInt())).thenReturn(mConvoList); + mController = new AppBubbleListPreferenceController(mContext, mBackend); + } + + ConversationChannelWrapper getConvo(int bubbleChannelPref, String channelId) { + ConversationChannelWrapper ccw = new ConversationChannelWrapper(); + NotificationChannel channel = mock(NotificationChannel.class); + when(channel.getId()).thenReturn(channelId); + when(channel.getAllowBubbles()).thenReturn(bubbleChannelPref); + when(channel.canBubble()).thenReturn(bubbleChannelPref == 1); + ccw.setNotificationChannel(channel); + ccw.setPkg("pkg"); + ccw.setUid(1); + ccw.setShortcutInfo(mock(ShortcutInfo.class)); + return ccw; + } + + @Test + public void isAvailable_BUBBLE_PREFERENCE_NONE_false() { + NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); + appRow.bubblePreference = BUBBLE_PREFERENCE_NONE; + mController.onResume(appRow, null, null, null, null, null); + + assertThat(mController.isAvailable()).isFalse(); + } + + @Test + public void isAvailable_BUBBLE_PREFERENCE_SELECTED_true() { + NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); + appRow.bubblePreference = BUBBLE_PREFERENCE_SELECTED; + mController.onResume(appRow, null, null, null, null, null); + + assertThat(mController.isAvailable()).isTrue(); + } + + @Test + public void isAvailable_BUBBLE_PREFERENCE_ALL_true() { + NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); + appRow.bubblePreference = BUBBLE_PREFERENCE_ALL; + mController.onResume(appRow, null, null, null, null, null); + + assertThat(mController.isAvailable()).isTrue(); + } + + @Test + public void filterAndSortConversations_BUBBLE_PREFERENCE_SELECTED_filtersAllowedBubbles() { + NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); + appRow.bubblePreference = BUBBLE_PREFERENCE_SELECTED; + mController.onResume(appRow, null, null, null, null, null); + + List result = + mController.filterAndSortConversations(mConvoList.getList()); + assertThat(result.size()).isEqualTo(1); + assertThat(result.get(0).getNotificationChannel().getId()) + .isEqualTo("selected"); + } + + @Test + public void filterAndSortConversations_BUBBLE_PREFERENCE_ALL_filtersExcludedBubbles() { + NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); + appRow.bubblePreference = BUBBLE_PREFERENCE_ALL; + mController.onResume(appRow, null, null, null, null, null); + + List result = + mController.filterAndSortConversations(mConvoList.getList()); + assertThat(result.size()).isEqualTo(1); + assertThat(result.get(0).getNotificationChannel().getId()) + .isEqualTo("excluded"); + } + + @Test + public void clickConversationPref_updatesChannel() { + NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); + appRow.bubblePreference = BUBBLE_PREFERENCE_ALL; + appRow.pkg = "PKG"; + mController.onResume(appRow, null, null, null, null, null); + mController.mPreference = new PreferenceCategory(mContext); + + ConversationChannelWrapper ccw = mConvoList.getList().get(0); + AppBubbleListPreferenceController.ConversationPreference pref = + (AppBubbleListPreferenceController.ConversationPreference) + mController.createConversationPref(ccw); + pref.onClick(null); + + verify(ccw.getNotificationChannel()).setAllowBubbles(DEFAULT_ALLOW_BUBBLE); + verify(mBackend).updateChannel(anyString(), anyInt(), any(NotificationChannel.class)); + } +} 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 0cf6dc67829..685bca9b119 100644 --- a/tests/robotests/src/com/android/settings/notification/app/BubblePreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/app/BubblePreferenceControllerTest.java @@ -80,6 +80,8 @@ public class BubblePreferenceControllerTest { private PreferenceScreen mScreen; @Mock private FragmentManager mFragmentManager; + @Mock + private NotificationSettings.DependentFieldListener mListener; private BubblePreferenceController mController; private BubblePreferenceController mAppPageController; @@ -93,9 +95,9 @@ public class BubblePreferenceControllerTest { mContext = RuntimeEnvironment.application; when(mFragmentManager.beginTransaction()).thenReturn(mock(FragmentTransaction.class)); mController = spy(new BubblePreferenceController(mContext, mFragmentManager, mBackend, - false /* isAppPage */)); + false /* isAppPage */, mListener)); mAppPageController = spy(new BubblePreferenceController(mContext, mFragmentManager, - mBackend, true /* isAppPage */)); + mBackend, true /* isAppPage */, mListener)); } @Test @@ -106,7 +108,7 @@ public class BubblePreferenceControllerTest { } @Test - public void testIsAvailable_notIfAppBlocked() { + public void isAvailable_notIfAppBlocked() { Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); appRow.banned = true; @@ -115,7 +117,7 @@ public class BubblePreferenceControllerTest { } @Test - public void testIsAvailable_notIfChannelBlocked() { + public void isAvailable_notIfChannelBlocked() { Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationChannel channel = mock(NotificationChannel.class); @@ -125,7 +127,7 @@ public class BubblePreferenceControllerTest { } @Test - public void testIsAvailable_channel_yesIfAppOff() { + public void isAvailable_channel_yesIfAppOff() { Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); appRow.bubblePreference = BUBBLE_PREFERENCE_NONE; @@ -137,7 +139,7 @@ public class BubblePreferenceControllerTest { } @Test - public void testIsNotAvailable_ifOffGlobally_app() { + public void isNotAvailable_ifOffGlobally_app() { NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); mController.onResume(appRow, null, null, null, null, null); Settings.Global.putInt(mContext.getContentResolver(), @@ -147,7 +149,7 @@ public class BubblePreferenceControllerTest { } @Test - public void testIsAvailable_notIfOffGlobally_channel() { + public void isAvailable_notIfOffGlobally_channel() { NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationChannel channel = mock(NotificationChannel.class); when(channel.getImportance()).thenReturn(IMPORTANCE_HIGH); @@ -159,7 +161,7 @@ public class BubblePreferenceControllerTest { } @Test - public void testIsAvailable_app_evenIfOffGlobally() { + public void isAvailable_app_evenIfOffGlobally() { NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); mAppPageController.onResume(appRow, null, null, null, null, null); Settings.Global.putInt(mContext.getContentResolver(), @@ -169,7 +171,7 @@ public class BubblePreferenceControllerTest { } @Test - public void testIsAvailable_app() { + public void isAvailable_app() { NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); mController.onResume(appRow, null, null, null, null, null); Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON); @@ -178,7 +180,7 @@ public class BubblePreferenceControllerTest { } @Test - public void testIsAvailable_defaultChannel() { + public void isAvailable_defaultChannel() { NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); appRow.bubblePreference = BUBBLE_PREFERENCE_ALL; NotificationChannel channel = mock(NotificationChannel.class); @@ -191,7 +193,7 @@ public class BubblePreferenceControllerTest { } @Test - public void testIsAvailable_channel() { + public void isAvailable_channel() { NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); appRow.bubblePreference = BUBBLE_PREFERENCE_ALL; NotificationChannel channel = mock(NotificationChannel.class); @@ -203,7 +205,7 @@ public class BubblePreferenceControllerTest { } @Test - public void testUpdateState_disabledByAdmin() { + public void updateState_disabledByAdmin() { NotificationChannel channel = mock(NotificationChannel.class); when(channel.getId()).thenReturn("something"); mController.onResume(new NotificationBackend.AppRow(), channel, null, @@ -216,7 +218,7 @@ public class BubblePreferenceControllerTest { } @Test - public void testUpdateState_app_disabledByAdmin() { + public void updateState_app_disabledByAdmin() { NotificationChannel channel = mock(NotificationChannel.class); when(channel.getId()).thenReturn("something"); mAppPageController.onResume(new NotificationBackend.AppRow(), channel, null, @@ -229,7 +231,7 @@ public class BubblePreferenceControllerTest { } @Test - public void testUpdateState_channel_channelNotBlockable() { + public void updateState_channel_channelNotBlockable() { Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationChannel channel = mock(NotificationChannel.class); @@ -243,7 +245,7 @@ public class BubblePreferenceControllerTest { } @Test - public void testUpdateState_channel() { + public void updateState_channel() { Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); NotificationChannel channel = mock(NotificationChannel.class); @@ -263,7 +265,7 @@ public class BubblePreferenceControllerTest { } @Test - public void testUpdateState_app() { + public void updateState_app() { Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); appRow.label = "App!"; @@ -288,7 +290,7 @@ public class BubblePreferenceControllerTest { } @Test - public void testUpdateState_app_offGlobally() { + public void updateState_app_offGlobally() { Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_OFF); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); @@ -302,7 +304,7 @@ public class BubblePreferenceControllerTest { } @Test - public void testOnPreferenceChange_on_channel() { + public void onPreferenceChange_on_channel() { Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); appRow.bubblePreference = BUBBLE_PREFERENCE_SELECTED; @@ -321,7 +323,7 @@ public class BubblePreferenceControllerTest { } @Test - public void testOnPreferenceChange_off_channel() { + public void onPreferenceChange_off_channel() { Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); appRow.bubblePreference = BUBBLE_PREFERENCE_SELECTED; @@ -341,7 +343,7 @@ public class BubblePreferenceControllerTest { @Test - public void testOnPreferenceChange_app_all() { + public void onPreferenceChange_app_all() { Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); appRow.bubblePreference = BUBBLE_PREFERENCE_NONE; @@ -379,7 +381,7 @@ public class BubblePreferenceControllerTest { } @Test - public void testOnPreferenceChange_app_selected() { + public void onPreferenceChange_app_selected() { Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); appRow.bubblePreference = BUBBLE_PREFERENCE_ALL; @@ -397,7 +399,7 @@ public class BubblePreferenceControllerTest { } @Test - public void testOnPreferenceChange_app_none() { + public void onPreferenceChange_app_none() { Settings.Global.putInt(mContext.getContentResolver(), NOTIFICATION_BUBBLES, SYSTEM_WIDE_ON); NotificationBackend.AppRow appRow = new NotificationBackend.AppRow(); appRow.bubblePreference = BUBBLE_PREFERENCE_ALL; @@ -413,4 +415,17 @@ public class BubblePreferenceControllerTest { assertEquals(BUBBLE_PREFERENCE_NONE, appRow.bubblePreference); verify(mBackend, times(1)).setAllowBubbles(any(), anyInt(), eq(BUBBLE_PREFERENCE_NONE)); } + + @Test + public void onPreferenceChange_dependentFieldListenerCalled() { + 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); + mAppPageController.onPreferenceChange(pref, BUBBLE_PREFERENCE_NONE); + + verify(mListener, times(1)).onFieldValueChanged(); + } }