diff --git a/src/com/android/settings/notification/app/RecentConversationsPreferenceController.java b/src/com/android/settings/notification/app/RecentConversationsPreferenceController.java index 8be6016cc43..d4ad9944765 100644 --- a/src/com/android/settings/notification/app/RecentConversationsPreferenceController.java +++ b/src/com/android/settings/notification/app/RecentConversationsPreferenceController.java @@ -72,7 +72,7 @@ public class RecentConversationsPreferenceController extends AbstractPreferenceC return true; } - Preference getClearAll(PreferenceGroup parent) { + LayoutPreference getClearAll(PreferenceGroup parent) { LayoutPreference pref = new LayoutPreference( mContext, R.layout.conversations_clear_recents); pref.setOrder(1); @@ -80,10 +80,21 @@ public class RecentConversationsPreferenceController extends AbstractPreferenceC button.setOnClickListener(v -> { try { mPs.removeAllRecentConversations(); + // Removing recents is asynchronous, so we can't immediately reload the list from + // the backend. Instead, proactively remove all of items that were marked as + // clearable, so long as we didn't get an error + + for (int i = parent.getPreferenceCount() - 1; i >= 0; i--) { + Preference p = parent.getPreference(i); + if (p instanceof RecentConversationPreference) { + if (((RecentConversationPreference) p).hasClearListener()) { + parent.removePreference(p); + } + } + } } catch (RemoteException e) { Slog.w(TAG, "Could not clear recents", e); } - updateState(parent); }); return pref; } @@ -118,36 +129,45 @@ public class RecentConversationsPreferenceController extends AbstractPreferenceC protected void populateList(List conversations, PreferenceGroup containerGroup) { containerGroup.removeAll(); + boolean hasClearable = false; if (conversations != null) { - populateConversations(conversations, containerGroup); + hasClearable = populateConversations(conversations, containerGroup); } if (containerGroup.getPreferenceCount() == 0) { containerGroup.setVisible(false); } else { containerGroup.setVisible(true); - Preference clearAll = getClearAll(containerGroup); - if (clearAll != null) { - containerGroup.addPreference(clearAll); + if (hasClearable) { + Preference clearAll = getClearAll(containerGroup); + if (clearAll != null) { + containerGroup.addPreference(clearAll); + } } } } - protected void populateConversations(List conversations, + protected boolean populateConversations(List conversations, PreferenceGroup containerGroup) { int order = 100; + boolean hasClearable = false; for (ConversationChannel conversation : conversations) { if (conversation.getParentNotificationChannel().getImportance() == IMPORTANCE_NONE || (conversation.getParentNotificationChannelGroup() != null && conversation.getParentNotificationChannelGroup().isBlocked())) { continue; } - containerGroup.addPreference( - createConversationPref(containerGroup, conversation, order++)); + RecentConversationPreference pref = + createConversationPref(containerGroup, conversation, order++); + containerGroup.addPreference(pref); + if (pref.hasClearListener()) { + hasClearable = true; + } } + return hasClearable; } - protected Preference createConversationPref(PreferenceGroup parent, + protected RecentConversationPreference createConversationPref(PreferenceGroup parent, final ConversationChannel conversation, int order) { final String pkg = conversation.getShortcutInfo().getPackage(); final int uid = conversation.getUid(); diff --git a/tests/robotests/src/com/android/settings/notification/app/RecentConversationsPreferenceControllerTest.java b/tests/robotests/src/com/android/settings/notification/app/RecentConversationsPreferenceControllerTest.java index 660b4e1ed57..15bc5989e60 100644 --- a/tests/robotests/src/com/android/settings/notification/app/RecentConversationsPreferenceControllerTest.java +++ b/tests/robotests/src/com/android/settings/notification/app/RecentConversationsPreferenceControllerTest.java @@ -47,8 +47,10 @@ import androidx.preference.PreferenceManager; import androidx.preference.PreferenceScreen; import androidx.preference.PreferenceViewHolder; +import com.android.settings.R; import com.android.settings.applications.AppInfoBase; import com.android.settings.notification.NotificationBackend; +import com.android.settingslib.widget.LayoutPreference; import org.junit.Before; import org.junit.Test; @@ -105,9 +107,9 @@ public class RecentConversationsPreferenceControllerTest { ps.addPreference(outerContainer); ConversationChannel ccw = new ConversationChannel(mock(ShortcutInfo.class), 6, - new NotificationChannel("hi", "hi", 4), - new NotificationChannelGroup("hi", "hi"), 7, - true); + new NotificationChannel("hi", "hi", 4), + new NotificationChannelGroup("hi", "hi"), 7, + false); ArrayList list = new ArrayList<>(); list.add(ccw); @@ -124,19 +126,19 @@ public class RecentConversationsPreferenceControllerTest { ConversationChannel ccw = new ConversationChannel(mock(ShortcutInfo.class), 6, new NotificationChannel("hi", "hi", 4), new NotificationChannelGroup("hi", "hi"), 7, - true); + false); ConversationChannel ccw2 = new ConversationChannel(mock(ShortcutInfo.class), 6, new NotificationChannel("hi", "hi", 0), new NotificationChannelGroup("hi", "hi"), 7, - true); + false); NotificationChannelGroup blockedGroup = new NotificationChannelGroup("hi", "hi"); blockedGroup.setBlocked(true); ConversationChannel ccw3 = new ConversationChannel(mock(ShortcutInfo.class), 6, new NotificationChannel("hi", "hi", 4), blockedGroup, 7, - true); + false); ArrayList list = new ArrayList<>(); list.add(ccw); @@ -198,7 +200,6 @@ public class RecentConversationsPreferenceControllerTest { new NotificationChannelGroup("hi", "group"), 7, true); - Intent intent = mController.getSubSettingLauncher(ccw, "title").toIntent(); Bundle extras = intent.getExtras(); @@ -257,6 +258,51 @@ public class RecentConversationsPreferenceControllerTest { si.getPackage(), UserHandle.getUserId(ccw.getUid()), si.getId()); } + @Test + public void testRemoveConversations() throws Exception { + ShortcutInfo si = mock(ShortcutInfo.class); + when(si.getId()).thenReturn("person"); + when(si.getPackage()).thenReturn("pkg"); + ConversationChannel ccw = new ConversationChannel(si, 6, + new NotificationChannel("hi", "hi", 4), + new NotificationChannelGroup("hi", "group"), 7, + false); + + ConversationChannel ccw2 = new ConversationChannel(si, 6, + new NotificationChannel("bye", "bye", 4), + new NotificationChannelGroup("hi", "group"), 7, + true); + + PreferenceCategory group = new PreferenceCategory(mContext); + PreferenceScreen screen = new PreferenceManager(mContext).createPreferenceScreen(mContext); + screen.addPreference(group); + + RecentConversationPreference pref = mController.createConversationPref( + new PreferenceCategory(mContext), ccw, 100); + final View view = View.inflate(mContext, pref.getLayoutResource(), null); + PreferenceViewHolder holder = spy(PreferenceViewHolder.createInstanceForTests(view)); + View delete = View.inflate(mContext, pref.getSecondTargetResId(), null); + when(holder.findViewById(pref.getClearId())).thenReturn(delete); + group.addPreference(pref); + + RecentConversationPreference pref2 = mController.createConversationPref( + new PreferenceCategory(mContext), ccw2, 100); + final View view2 = View.inflate(mContext, pref2.getLayoutResource(), null); + PreferenceViewHolder holder2 = spy(PreferenceViewHolder.createInstanceForTests(view2)); + View delete2 = View.inflate(mContext, pref2.getSecondTargetResId(), null); + when(holder2.findViewById(pref.getClearId())).thenReturn(delete2); + group.addPreference(pref2); + + LayoutPreference clearAll = mController.getClearAll(group); + group.addPreference(clearAll); + + clearAll.findViewById(R.id.conversation_settings_clear_recents).performClick(); + + verify(mPs).removeAllRecentConversations(); + assertThat((Preference) group.findPreference("hi:person")).isNull(); + assertThat((Preference) group.findPreference("bye:person")).isNotNull(); + } + @Test public void testNonremoveableConversation() throws Exception { ShortcutInfo si = mock(ShortcutInfo.class); @@ -272,4 +318,24 @@ public class RecentConversationsPreferenceControllerTest { new PreferenceCategory(mContext), ccw, 100); assertThat(pref.hasClearListener()).isFalse(); } + + @Test + public void testPopulateList_onlyNonremoveableConversations() { + final PreferenceManager preferenceManager = new PreferenceManager(mContext); + PreferenceScreen ps = preferenceManager.createPreferenceScreen(mContext); + PreferenceCategory outerContainer = spy(new PreferenceCategory(mContext)); + ps.addPreference(outerContainer); + + ConversationChannel ccw = new ConversationChannel(mock(ShortcutInfo.class), 6, + new NotificationChannel("hi", "hi", 4), + new NotificationChannelGroup("hi", "hi"), 7, + true /* hasactivenotifs */); + + ArrayList list = new ArrayList<>(); + list.add(ccw); + + mController.populateList(list, outerContainer); + // one for the preference, none for 'clear all' + verify(outerContainer, times(1)).addPreference(any()); + } }