Sort notification channel in NotificationChannelSlice
According request to sort the notification channel by average weekly sent count in descending. Bug: 119831690 Test: visual, robotests Change-Id: I96786b077a37dcbc53606f8d98998e01e15b674d
This commit is contained in:
@@ -57,6 +57,7 @@ import com.android.settings.core.SubSettingLauncher;
|
|||||||
import com.android.settings.notification.AppNotificationSettings;
|
import com.android.settings.notification.AppNotificationSettings;
|
||||||
import com.android.settings.notification.ChannelNotificationSettings;
|
import com.android.settings.notification.ChannelNotificationSettings;
|
||||||
import com.android.settings.notification.NotificationBackend;
|
import com.android.settings.notification.NotificationBackend;
|
||||||
|
import com.android.settings.notification.NotificationBackend.NotificationsSentState;
|
||||||
import com.android.settings.slices.CustomSliceRegistry;
|
import com.android.settings.slices.CustomSliceRegistry;
|
||||||
import com.android.settings.slices.CustomSliceable;
|
import com.android.settings.slices.CustomSliceable;
|
||||||
import com.android.settings.slices.SliceBroadcastReceiver;
|
import com.android.settings.slices.SliceBroadcastReceiver;
|
||||||
@@ -66,7 +67,6 @@ import com.android.settingslib.RestrictedLockUtilsInternal;
|
|||||||
import com.android.settingslib.applications.ApplicationsState;
|
import com.android.settingslib.applications.ApplicationsState;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
@@ -103,21 +103,32 @@ public class NotificationChannelSlice implements CustomSliceable {
|
|||||||
private static final String CHANNEL_ID = "channel_id";
|
private static final String CHANNEL_ID = "channel_id";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO(b/119831690): Change to notification count sorting.
|
* Sort notification channel with weekly average sent count by descending.
|
||||||
* This is the default sorting from NotificationSettingsBase, will be replaced with notification
|
*
|
||||||
* count sorting mechanism.
|
* Note:
|
||||||
|
* When the sent count of notification channels is the same, follow the sorting mechanism from
|
||||||
|
* {@link com.android.settings.notification.NotificationSettingsBase#mChannelComparator}.
|
||||||
|
* Since slice view only shows displayable notification channels, so those deleted ones are
|
||||||
|
* excluded from the comparison here.
|
||||||
*/
|
*/
|
||||||
private static final Comparator<NotificationChannel> mChannelComparator =
|
private static final Comparator<NotificationChannelState> CHANNEL_STATE_COMPARATOR =
|
||||||
(left, right) -> {
|
(left, right) -> {
|
||||||
if (TextUtils.equals(left.getId(), NotificationChannel.DEFAULT_CHANNEL_ID)) {
|
final NotificationsSentState leftState = left.getNotificationsSentState();
|
||||||
// Uncategorized/miscellaneous legacy channel goes last
|
final NotificationsSentState rightState = right.getNotificationsSentState();
|
||||||
|
if (rightState.avgSentWeekly != leftState.avgSentWeekly) {
|
||||||
|
return rightState.avgSentWeekly - leftState.avgSentWeekly;
|
||||||
|
}
|
||||||
|
|
||||||
|
final NotificationChannel leftChannel = left.getNotificationChannel();
|
||||||
|
final NotificationChannel rightChannel = right.getNotificationChannel();
|
||||||
|
if (TextUtils.equals(leftChannel.getId(), NotificationChannel.DEFAULT_CHANNEL_ID)) {
|
||||||
return 1;
|
return 1;
|
||||||
} else if (TextUtils.equals(right.getId(),
|
} else if (TextUtils.equals(rightChannel.getId(),
|
||||||
NotificationChannel.DEFAULT_CHANNEL_ID)) {
|
NotificationChannel.DEFAULT_CHANNEL_ID)) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return left.getId().compareTo(right.getId());
|
return leftChannel.getId().compareTo(rightChannel.getId());
|
||||||
};
|
};
|
||||||
|
|
||||||
private final Context mContext;
|
private final Context mContext;
|
||||||
@@ -380,9 +391,19 @@ public class NotificationChannelSlice implements CustomSliceable {
|
|||||||
channel -> isChannelEnabled(group, channel, appRow)))
|
channel -> isChannelEnabled(group, channel, appRow)))
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
// TODO(b/119831690): Sort the channels by notification count.
|
// Pack the notification channel with notification sent state for sorting.
|
||||||
Collections.sort(channels, mChannelComparator);
|
final List<NotificationChannelState> channelStates = new ArrayList<>();
|
||||||
return channels;
|
for (NotificationChannel channel : channels) {
|
||||||
|
NotificationsSentState sentState = appRow.sentByChannel.get(channel.getId());
|
||||||
|
if (sentState == null) {
|
||||||
|
sentState = new NotificationsSentState();
|
||||||
|
}
|
||||||
|
channelStates.add(new NotificationChannelState(sentState, channel));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort the notification channels with notification sent count by descending.
|
||||||
|
return channelStates.stream().sorted(CHANNEL_STATE_COMPARATOR).map(
|
||||||
|
state -> state.getNotificationChannel()).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private PackageInfo getMaxSentNotificationsPackage(List<PackageInfo> packageInfoList) {
|
private PackageInfo getMaxSentNotificationsPackage(List<PackageInfo> packageInfoList) {
|
||||||
@@ -471,4 +492,31 @@ public class NotificationChannelSlice implements CustomSliceable {
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/**
|
||||||
|
* This class is used to sort notification channels according to notification sent count and
|
||||||
|
* notification id in {@link NotificationChannelSlice#CHANNEL_STATE_COMPARATOR}.
|
||||||
|
*
|
||||||
|
* Include {@link NotificationsSentState#avgSentWeekly} and {@link NotificationChannel#getId()}
|
||||||
|
* to get the number of notifications being sent and notification id.
|
||||||
|
*/
|
||||||
|
private static class NotificationChannelState {
|
||||||
|
|
||||||
|
final private NotificationsSentState mNotificationsSentState;
|
||||||
|
final private NotificationChannel mNotificationChannel;
|
||||||
|
|
||||||
|
public NotificationChannelState(NotificationsSentState notificationsSentState,
|
||||||
|
NotificationChannel notificationChannel) {
|
||||||
|
mNotificationsSentState = notificationsSentState;
|
||||||
|
mNotificationChannel = notificationChannel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NotificationChannel getNotificationChannel() {
|
||||||
|
return mNotificationChannel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public NotificationsSentState getNotificationsSentState() {
|
||||||
|
return mNotificationsSentState;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -39,6 +39,7 @@ import android.util.ArrayMap;
|
|||||||
|
|
||||||
import androidx.core.graphics.drawable.IconCompat;
|
import androidx.core.graphics.drawable.IconCompat;
|
||||||
import androidx.slice.Slice;
|
import androidx.slice.Slice;
|
||||||
|
import androidx.slice.SliceItem;
|
||||||
import androidx.slice.SliceMetadata;
|
import androidx.slice.SliceMetadata;
|
||||||
import androidx.slice.SliceProvider;
|
import androidx.slice.SliceProvider;
|
||||||
import androidx.slice.core.SliceQuery;
|
import androidx.slice.core.SliceQuery;
|
||||||
@@ -124,6 +125,34 @@ public class NotificationChannelSliceTest {
|
|||||||
mContext.getString(R.string.manage_app_notification, APP_LABEL));
|
mContext.getString(R.string.manage_app_notification, APP_LABEL));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Config(shadows = ShadowRestrictedLockUtilsInternal.class)
|
||||||
|
public void getSlice_hasSuggestedApp_shouldSortByNotificationSentCount() {
|
||||||
|
addMockPackageToPackageManager(true /* isRecentlyInstalled */,
|
||||||
|
ApplicationInfo.FLAG_INSTALLED);
|
||||||
|
mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */);
|
||||||
|
|
||||||
|
final Slice slice = mNotificationChannelSlice.getSlice();
|
||||||
|
|
||||||
|
// Get all RowBuilders from Slice.
|
||||||
|
final List<SliceItem> rowItems = SliceQuery.findAll(slice, FORMAT_SLICE, HINT_LIST_ITEM,
|
||||||
|
null /* nonHints */);
|
||||||
|
|
||||||
|
// Ensure the total size of rows is equal to the notification channel count with header.
|
||||||
|
assertThat(rowItems).isNotNull();
|
||||||
|
assertThat(rowItems.size()).isEqualTo(CHANNEL_COUNT + 1);
|
||||||
|
|
||||||
|
// Remove the header of slice.
|
||||||
|
rowItems.remove(0);
|
||||||
|
|
||||||
|
// Test the rows of slice are sorted with notification sent count by descending.
|
||||||
|
for (int i = 0; i < rowItems.size(); i++) {
|
||||||
|
// Assert the summary text is the same as expectation.
|
||||||
|
assertThat(getSummaryFromSliceItem(rowItems.get(i))).isEqualTo(
|
||||||
|
mContext.getString(R.string.notifications_sent_weekly, CHANNEL_COUNT - i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getSlice_noRecentlyInstalledApp_shouldHaveNoSuggestedAppTitle() {
|
public void getSlice_noRecentlyInstalledApp_shouldHaveNoSuggestedAppTitle() {
|
||||||
addMockPackageToPackageManager(false /* isRecentlyInstalled */,
|
addMockPackageToPackageManager(false /* isRecentlyInstalled */,
|
||||||
@@ -269,10 +298,31 @@ public class NotificationChannelSliceTest {
|
|||||||
final Map<String, NotificationBackend.NotificationsSentState> states = new ArrayMap<>();
|
final Map<String, NotificationBackend.NotificationsSentState> states = new ArrayMap<>();
|
||||||
for (int i = 0; i < channelCount; i++) {
|
for (int i = 0; i < channelCount; i++) {
|
||||||
final NotificationsSentState state = new NotificationsSentState();
|
final NotificationsSentState state = new NotificationsSentState();
|
||||||
|
// Set the avgSentWeekly for each channel: channel0 is 1, channel1: 2, channel2: 3.
|
||||||
|
state.avgSentWeekly = i + 1;
|
||||||
state.sentCount = sentCount;
|
state.sentCount = sentCount;
|
||||||
states.put(CHANNEL_NAME_PREFIX + i, state);
|
states.put(CHANNEL_NAME_PREFIX + i, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
return states;
|
return states;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private CharSequence getSummaryFromSliceItem(SliceItem rowItem) {
|
||||||
|
if (rowItem == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final Slice rowSlice = rowItem.getSlice();
|
||||||
|
if (rowSlice == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<SliceItem> rowSliceItems = rowSlice.getItems();
|
||||||
|
if (rowSliceItems == null || rowSliceItems.size() < 2) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Index 0: title; Index 1: summary.
|
||||||
|
return rowSliceItems.get(1).getText();
|
||||||
|
}
|
||||||
}
|
}
|
Reference in New Issue
Block a user