Add 'Recent Conversations' to the conversation page

Test: atest
Bug: 171191376
Change-Id: Id7208312dff0cc022c2f16b3872fae1a9dc09ed7
This commit is contained in:
Julia Reynolds
2020-10-19 16:21:23 -04:00
parent 2e49b2e639
commit 0aef57d67e
11 changed files with 711 additions and 12 deletions

View File

@@ -18,7 +18,8 @@
android:viewportWidth="24"
android:viewportHeight="24"
android:width="24dp"
android:height="24dp">
android:height="24dp"
android:tint="?android:attr/colorControlNormal">
<path
android:pathData="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12Z"
android:fillColor="#FFFFFF" />

View File

@@ -0,0 +1,34 @@
<?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:orientation="vertical">
<Button
android:id="@+id/conversation_settings_clear_recents"
style="@style/ActionPrimaryButton"
android:layout_marginStart="@dimen/screen_margin_sides"
android:layout_marginEnd="@dimen/description_margin_sides"
android:layout_marginTop="@dimen/zen_mode_settings_button_margin_vertical"
android:layout_marginBottom="@dimen/zen_mode_settings_button_margin_vertical"
android:text="@string/conversation_settings_clear_recents"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</LinearLayout>

View File

@@ -0,0 +1,30 @@
<?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.
-->
<!-- Settings button -->
<ImageView
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/clear_button"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:paddingStart="?android:attr/listPreferredItemPaddingEnd"
android:paddingEnd="?android:attr/listPreferredItemPaddingEnd"
android:background="?android:attr/selectableItemBackground"
android:scaleType="center"
android:src="@drawable/ic_clear"
android:contentDescription="@string/clear" />

View File

@@ -8497,11 +8497,20 @@
<string name="important_conversations_summary">Show at top of conversation section</string>
<!-- [CHAR LIMIT=100] preference category title -->
<string name="other_conversations">Other conversations</string>
<string name="other_conversations">Non-priority conversations</string>
<!-- summary for other conversations list -->
<string name="other_conversations_summary">Conversations you\u2019ve made changes to</string>
<!-- [CHAR LIMIT=100] preference category title -->
<string name="recent_conversations">Recent conversations</string>
<!-- [CHAR LIMIT=20] button title -->
<string name="conversation_settings_clear_recents">Clear recents</string>
<!-- a11y string -->
<string name="clear">Clear</string>
<!-- [CHAR LIMIT=100] Setting to automatically bubble all notifications from favorite conversations -->
<string name="important_bubble">Bubble priority conversations</string>

View File

@@ -43,12 +43,18 @@
</PreferenceCategory>
</PreferenceCategory>
<!--Other conversations added here -->
<!-- Non-priority modified conversations added here -->
<PreferenceCategory
android:title="@string/other_conversations"
android:key="other_conversations"
settings:allowDividerAbove="true"
settings:allowDividerBelow="false" />
<!-- Recent conversations added here -->
<PreferenceCategory
android:title="@string/recent_conversations"
android:key="recent_conversations"
settings:allowDividerAbove="true"
settings:allowDividerBelow="false" />
</PreferenceScreen>

View File

@@ -541,6 +541,15 @@ public class NotificationBackend {
}
}
public void createConversationNotificationChannel(String pkg, int uid,
NotificationChannel parent, String conversationId) {
try {
sINM.createConversationNotificationChannelForPackage(pkg, uid, parent, conversationId);
} catch (Exception e) {
Log.w(TAG, "Error calling NoMan", e);
}
}
public ShortcutInfo getConversationInfo(Context context, String pkg, int uid, String id) {
LauncherApps la = context.getSystemService(LauncherApps.class);

View File

@@ -16,8 +16,10 @@
package com.android.settings.notification.app;
import android.app.people.IPeopleManager;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.os.ServiceManager;
import android.util.Log;
import com.android.settings.R;
@@ -33,8 +35,15 @@ public class ConversationListSettings extends DashboardFragment {
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
NotificationBackend mBackend = new NotificationBackend();
IPeopleManager mPs;
protected List<AbstractPreferenceController> mControllers = new ArrayList<>();
public ConversationListSettings() {
mPs = IPeopleManager.Stub.asInterface(
ServiceManager.getService(Context.PEOPLE_SERVICE));
}
@Override
public int getMetricsCategory() {
return SettingsEnums.NOTIFICATION_CONVERSATION_LIST_SETTINGS;
@@ -53,9 +62,10 @@ public class ConversationListSettings extends DashboardFragment {
@Override
protected List<AbstractPreferenceController> createPreferenceControllers(Context context) {
mControllers = new ArrayList<>();
mControllers.add(new NoConversationsPreferenceController(context, mBackend));
mControllers.add(new NoConversationsPreferenceController(context, mBackend, mPs));
mControllers.add(new PriorityConversationsPreferenceController(context, mBackend));
mControllers.add(new AllConversationsPreferenceController(context, mBackend));
mControllers.add(new RecentConversationsPreferenceController(context, mBackend, mPs));
return new ArrayList<>(mControllers);
}
}

View File

@@ -16,9 +16,12 @@
package com.android.settings.notification.app;
import android.app.people.IPeopleManager;
import android.content.Context;
import android.os.AsyncTask;
import android.os.RemoteException;
import android.service.notification.ConversationChannelWrapper;
import android.util.Log;
import android.view.View;
import androidx.preference.Preference;
@@ -27,17 +30,18 @@ import com.android.settings.R;
import com.android.settings.notification.NotificationBackend;
import com.android.settingslib.widget.LayoutPreference;
import java.util.List;
public class NoConversationsPreferenceController extends ConversationListPreferenceController {
private static String TAG = "NoConversationsPC";
private static final String KEY = "no_conversations";
private List<ConversationChannelWrapper> mConversations;
private IPeopleManager mPs;
private int mConversationCount = 0;
public NoConversationsPreferenceController(Context context,
NotificationBackend backend) {
NotificationBackend backend, IPeopleManager ps) {
super(context, backend);
mPs = ps;
}
@Override
@@ -67,7 +71,12 @@ public class NoConversationsPreferenceController extends ConversationListPrefere
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... unused) {
mConversations = mBackend.getConversations(false).getList();
mConversationCount = mBackend.getConversations(false).getList().size();
try {
mConversationCount += mPs.getRecentConversations().getList().size();
} catch (RemoteException e) {
Log.w(TAG, "Error calling PS", e);
}
return null;
}
@@ -76,9 +85,9 @@ public class NoConversationsPreferenceController extends ConversationListPrefere
if (mContext == null) {
return;
}
pref.findViewById(R.id.onboarding).setVisibility(mConversations.size() == 0
pref.findViewById(R.id.onboarding).setVisibility(mConversationCount == 0
? View.VISIBLE : View.GONE);
preference.setVisible(mConversations.size() == 0);
preference.setVisible(mConversationCount == 0);
}
}.execute();
}

View File

@@ -0,0 +1,80 @@
/*
* 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 android.content.Context;
import android.view.View;
import androidx.preference.PreferenceViewHolder;
import com.android.settings.R;
import com.android.settingslib.TwoTargetPreference;
import com.google.common.annotations.VisibleForTesting;
public class RecentConversationPreference extends TwoTargetPreference {
private OnClearClickListener mOnClearClickListener;
private View mClearView;
public interface OnClearClickListener {
void onClear();
}
public RecentConversationPreference(Context context) {
super(context);
}
public void setOnClearClickListener(
OnClearClickListener onClearClickListener) {
mOnClearClickListener = onClearClickListener;
}
@VisibleForTesting
View getClearView() {
return mClearView;
}
@Override
protected int getSecondTargetResId() {
return R.layout.preference_widget_clear;
}
@VisibleForTesting
int getClearId() {
return R.id.clear_button;
}
@VisibleForTesting
boolean hasClearListener() {
return mOnClearClickListener != null;
}
@Override
public void onBindViewHolder(PreferenceViewHolder view) {
super.onBindViewHolder(view);
final View widgetFrame = view.findViewById(android.R.id.widget_frame);
widgetFrame.setVisibility(mOnClearClickListener != null ? View.VISIBLE : View.GONE);
mClearView = view.findViewById(getClearId());
mClearView.setOnClickListener(v -> {
if (mOnClearClickListener != null) {
mOnClearClickListener.onClear();
}
});
}
}

View File

@@ -0,0 +1,236 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.notification.app;
import static android.app.NotificationManager.IMPORTANCE_NONE;
import android.app.people.ConversationChannel;
import android.app.people.IPeopleManager;
import android.app.settings.SettingsEnums;
import android.content.Context;
import android.content.pm.ShortcutInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.RemoteException;
import android.os.UserHandle;
import android.provider.Settings;
import android.util.Slog;
import android.widget.Button;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceGroup;
import com.android.settings.R;
import com.android.settings.applications.AppInfoBase;
import com.android.settings.core.SubSettingLauncher;
import com.android.settings.notification.NotificationBackend;
import com.android.settingslib.core.AbstractPreferenceController;
import com.android.settingslib.widget.LayoutPreference;
import java.text.Collator;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
public class RecentConversationsPreferenceController extends AbstractPreferenceController {
private static final String TAG = "RecentConversationsPC";
private static final String KEY = "recent_conversations";
private List<ConversationChannel> mConversations;
private final IPeopleManager mPs;
private final NotificationBackend mBackend;
public RecentConversationsPreferenceController(Context context, NotificationBackend backend,
IPeopleManager ps) {
super(context);
mBackend = backend;
mPs = ps;
}
@Override
public String getPreferenceKey() {
return KEY;
}
@Override
public boolean isAvailable() {
return true;
}
Preference getClearAll(PreferenceGroup parent) {
LayoutPreference pref = new LayoutPreference(
mContext, R.layout.conversations_clear_recents);
pref.setOrder(1);
Button button = pref.findViewById(R.id.conversation_settings_clear_recents);
button.setOnClickListener(v -> {
try {
mPs.removeAllRecentConversations();
} catch (RemoteException e) {
Slog.w(TAG, "Could not clear recents", e);
}
updateState(parent);
});
return pref;
}
@Override
public void updateState(Preference preference) {
PreferenceCategory pref = (PreferenceCategory) preference;
// Load conversations
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... unused) {
try {
mConversations = mPs.getRecentConversations().getList();
} catch (RemoteException e) {
Slog.w(TAG, "Could get recents", e);
}
Collections.sort(mConversations, mConversationComparator);
return null;
}
@Override
protected void onPostExecute(Void unused) {
if (mContext == null) {
return;
}
populateList(mConversations, pref);
}
}.execute();
}
protected void populateList(List<ConversationChannel> conversations,
PreferenceGroup containerGroup) {
containerGroup.removeAll();
if (conversations != null) {
populateConversations(conversations, containerGroup);
}
if (containerGroup.getPreferenceCount() == 0) {
containerGroup.setVisible(false);
} else {
containerGroup.setVisible(true);
Preference clearAll = getClearAll(containerGroup);
if (clearAll != null) {
containerGroup.addPreference(clearAll);
}
}
}
protected void populateConversations(List<ConversationChannel> conversations,
PreferenceGroup containerGroup) {
int order = 100;
for (ConversationChannel conversation : conversations) {
if (conversation.getParentNotificationChannel().getImportance() == IMPORTANCE_NONE
|| (conversation.getParentNotificationChannelGroup() != null
&& conversation.getParentNotificationChannelGroup().isBlocked())) {
continue;
}
containerGroup.addPreference(
createConversationPref(containerGroup, conversation, order++));
}
}
protected Preference createConversationPref(PreferenceGroup parent,
final ConversationChannel conversation, int order) {
final String pkg = conversation.getShortcutInfo().getPackage();
final int uid = conversation.getUid();
final String conversationId = conversation.getShortcutInfo().getId();
RecentConversationPreference pref = new RecentConversationPreference(mContext);
if (!conversation.hasActiveNotifications()) {
pref.setOnClearClickListener(() -> {
try {
mPs.removeRecentConversation(pkg, UserHandle.getUserId(uid), conversationId);
parent.removePreference(pref);
} catch (RemoteException e) {
Slog.w(TAG, "Could not clear recent", e);
}
});
}
pref.setOrder(order);
pref.setTitle(getTitle(conversation));
pref.setSummary(getSummary(conversation));
pref.setIcon(mBackend.getConversationDrawable(mContext, conversation.getShortcutInfo(),
pkg, uid, false));
pref.setKey(conversation.getParentNotificationChannel().getId()
+ ":" + conversationId);
pref.setOnPreferenceClickListener(preference -> {
mBackend.createConversationNotificationChannel(
pkg, uid,
conversation.getParentNotificationChannel(),
conversationId);
getSubSettingLauncher(conversation, pref.getTitle()).launch();
return true;
});
return pref;
}
CharSequence getSummary(ConversationChannel conversation) {
return conversation.getParentNotificationChannelGroup() == null
? conversation.getParentNotificationChannel().getName()
: mContext.getString(R.string.notification_conversation_summary,
conversation.getParentNotificationChannel().getName(),
conversation.getParentNotificationChannelGroup().getName());
}
CharSequence getTitle(ConversationChannel conversation) {
ShortcutInfo si = conversation.getShortcutInfo();
return si.getLabel();
}
SubSettingLauncher getSubSettingLauncher(ConversationChannel conversation,
CharSequence title) {
Bundle channelArgs = new Bundle();
channelArgs.putInt(AppInfoBase.ARG_PACKAGE_UID, conversation.getUid());
channelArgs.putString(AppInfoBase.ARG_PACKAGE_NAME,
conversation.getShortcutInfo().getPackage());
channelArgs.putString(Settings.EXTRA_CHANNEL_ID,
conversation.getParentNotificationChannel().getId());
channelArgs.putString(Settings.EXTRA_CONVERSATION_ID,
conversation.getShortcutInfo().getId());
return new SubSettingLauncher(mContext)
.setDestination(ChannelNotificationSettings.class.getName())
.setArguments(channelArgs)
.setExtras(channelArgs)
.setUserHandle(UserHandle.getUserHandleForUid(conversation.getUid()))
.setTitleText(title)
.setSourceMetricsCategory(SettingsEnums.NOTIFICATION_CONVERSATION_LIST_SETTINGS);
}
protected Comparator<ConversationChannel> mConversationComparator =
new Comparator<ConversationChannel>() {
private final Collator sCollator = Collator.getInstance();
@Override
public int compare(ConversationChannel o1, ConversationChannel o2) {
int labelComparison = sCollator.compare(o1.getShortcutInfo().getLabel(),
o2.getShortcutInfo().getLabel());
if (labelComparison == 0) {
return o1.getParentNotificationChannel().getId().compareTo(
o2.getParentNotificationChannel().getId());
}
return labelComparison;
}
};
}

View File

@@ -0,0 +1,275 @@
/*
* 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 com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.app.people.ConversationChannel;
import android.app.people.IPeopleManager;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ShortcutInfo;
import android.os.Bundle;
import android.os.UserHandle;
import android.provider.Settings;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.LinearLayout;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceGroup;
import androidx.preference.PreferenceManager;
import androidx.preference.PreferenceScreen;
import androidx.preference.PreferenceViewHolder;
import com.android.settings.applications.AppInfoBase;
import com.android.settings.notification.NotificationBackend;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import org.robolectric.shadows.ShadowApplication;
import java.util.ArrayList;
@RunWith(RobolectricTestRunner.class)
public class RecentConversationsPreferenceControllerTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mContext;
@Mock
private NotificationBackend mBackend;
@Mock
private IPeopleManager mPs;
private RecentConversationsPreferenceController mController;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
ShadowApplication shadowApplication = ShadowApplication.getInstance();
mContext = RuntimeEnvironment.application;
mController = new RecentConversationsPreferenceController(mContext, mBackend, mPs);
}
@Test
public void isAvailable() {
assertThat(mController.isAvailable()).isTrue();
}
@Test
public void testPopulateList_hideIfNoConversations() {
PreferenceCategory outerContainer = mock(PreferenceCategory.class);
mController.populateList(new ArrayList<>(), outerContainer);
verify(outerContainer).setVisible(false);
verify(outerContainer, never()).addPreference(any());
}
@Test
public void testPopulateList_validConversations() {
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);
ArrayList<ConversationChannel> list = new ArrayList<>();
list.add(ccw);
mController.populateList(list, outerContainer);
// one for the preference, one for the button ro clear all
verify(outerContainer, times(2)).addPreference(any());
}
@Test
public void populateConversations_blocked() {
PreferenceCategory container = mock(PreferenceCategory.class);
ConversationChannel ccw = new ConversationChannel(mock(ShortcutInfo.class), 6,
new NotificationChannel("hi", "hi", 4),
new NotificationChannelGroup("hi", "hi"), 7,
true);
ConversationChannel ccw2 = new ConversationChannel(mock(ShortcutInfo.class), 6,
new NotificationChannel("hi", "hi", 0),
new NotificationChannelGroup("hi", "hi"), 7,
true);
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);
ArrayList<ConversationChannel> list = new ArrayList<>();
list.add(ccw);
list.add(ccw2);
list.add(ccw3);
mController.populateConversations(list, container);
verify(container, times(1)).addPreference(any());
}
@Test
public void getSummary_withGroup() {
ShortcutInfo si = mock(ShortcutInfo.class);
when(si.getLabel()).thenReturn("person");
ConversationChannel ccw = new ConversationChannel(mock(ShortcutInfo.class), 6,
new NotificationChannel("hi", "channel", 4),
new NotificationChannelGroup("hi", "group"), 7,
true);
assertThat(mController.getSummary(ccw).toString()).contains(
ccw.getParentNotificationChannelGroup().getName());
assertThat(mController.getSummary(ccw).toString()).contains(
ccw.getParentNotificationChannel().getName());
}
@Test
public void getSummary_noGroup() {
ShortcutInfo si = mock(ShortcutInfo.class);
when(si.getLabel()).thenReturn("person");
ConversationChannel ccw = new ConversationChannel(mock(ShortcutInfo.class), 6,
new NotificationChannel("hi", "channel", 4),
null, 7,
true);
assertThat(mController.getSummary(ccw).toString()).isEqualTo(
ccw.getParentNotificationChannel().getName());
}
@Test
public void getTitle_withShortcut() {
ShortcutInfo si = mock(ShortcutInfo.class);
when(si.getLabel()).thenReturn("person");
ConversationChannel ccw = new ConversationChannel(si, 6,
new NotificationChannel("hi", "channel", 4),
new NotificationChannelGroup("hi", "group"), 7,
true);
assertThat(mController.getTitle(ccw).toString()).isEqualTo(si.getLabel());
}
@Test
public void testGetSubSettingLauncher() {
ShortcutInfo si = mock(ShortcutInfo.class);
when(si.getId()).thenReturn("person");
when(si.getPackage()).thenReturn("pkg");
ConversationChannel ccw = new ConversationChannel(si, 6,
new NotificationChannel("hi", "channel", 4),
new NotificationChannelGroup("hi", "group"), 7,
true);
Intent intent = mController.getSubSettingLauncher(ccw, "title").toIntent();
Bundle extras = intent.getExtras();
assertThat(extras.getString(AppInfoBase.ARG_PACKAGE_NAME)).isEqualTo(
ccw.getShortcutInfo().getPackage());
assertThat(extras.getInt(AppInfoBase.ARG_PACKAGE_UID)).isEqualTo(ccw.getUid());
assertThat(extras.getString(Settings.EXTRA_CHANNEL_ID)).isEqualTo(
ccw.getParentNotificationChannel().getId());
assertThat(extras.getString(Settings.EXTRA_CONVERSATION_ID)).isEqualTo(
ccw.getShortcutInfo().getId());
}
@Test
public void testCreatesChannel() {
ShortcutInfo si = mock(ShortcutInfo.class);
when(si.getId()).thenReturn("person");
when(si.getPackage()).thenReturn("pkg");
ConversationChannel ccw = new ConversationChannel(si, 6,
new NotificationChannel("hi", "channel", 4),
new NotificationChannelGroup("hi", "group"), 7,
true);
Preference pref = mController.createConversationPref(new PreferenceCategory(mContext),
ccw, 100);
try {
pref.performClick();
} catch (RuntimeException e) {
// expected since it tries to launch an activity
}
verify(mBackend).createConversationNotificationChannel(
si.getPackage(), ccw.getUid(), ccw.getParentNotificationChannel(), si.getId());
}
@Test
public void testRemoveConversation() 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", "channel", 4),
new NotificationChannelGroup("hi", "group"), 7,
false);
RecentConversationPreference pref =
(RecentConversationPreference) 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);
pref.onBindViewHolder(holder);
pref.getClearView().performClick();
verify(mPs).removeRecentConversation(
si.getPackage(), UserHandle.getUserId(ccw.getUid()), si.getId());
}
@Test
public void testNonremoveableConversation() 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", "channel", 4),
new NotificationChannelGroup("hi", "group"), 7,
true);
RecentConversationPreference pref =
(RecentConversationPreference) mController.createConversationPref(
new PreferenceCategory(mContext), ccw, 100);
assertThat(pref.hasClearListener()).isFalse();
}
}