Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a55909f8 authored by Yanting Yang's avatar Yanting Yang Committed by Android (Google) Code Review
Browse files

Merge "Sort notification channel in NotificationChannelSlice"

parents 79d5428c 81410323
Loading
Loading
Loading
Loading
+61 −13
Original line number Diff line number Diff line
@@ -57,6 +57,7 @@ import com.android.settings.core.SubSettingLauncher;
import com.android.settings.notification.AppNotificationSettings;
import com.android.settings.notification.ChannelNotificationSettings;
import com.android.settings.notification.NotificationBackend;
import com.android.settings.notification.NotificationBackend.NotificationsSentState;
import com.android.settings.slices.CustomSliceRegistry;
import com.android.settings.slices.CustomSliceable;
import com.android.settings.slices.SliceBroadcastReceiver;
@@ -66,7 +67,6 @@ import com.android.settingslib.RestrictedLockUtilsInternal;
import com.android.settingslib.applications.ApplicationsState;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -103,21 +103,32 @@ public class NotificationChannelSlice implements CustomSliceable {
    private static final String CHANNEL_ID = "channel_id";

    /**
     * TODO(b/119831690): Change to notification count sorting.
     * This is the default sorting from NotificationSettingsBase, will be replaced with notification
     * count sorting mechanism.
     * Sort notification channel with weekly average sent count by descending.
     *
     * 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) -> {
                if (TextUtils.equals(left.getId(), NotificationChannel.DEFAULT_CHANNEL_ID)) {
                    // Uncategorized/miscellaneous legacy channel goes last
                final NotificationsSentState leftState = left.getNotificationsSentState();
                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;
                } else if (TextUtils.equals(right.getId(),
                } else if (TextUtils.equals(rightChannel.getId(),
                        NotificationChannel.DEFAULT_CHANNEL_ID)) {
                    return -1;
                }

                return left.getId().compareTo(right.getId());
                return leftChannel.getId().compareTo(rightChannel.getId());
            };

    private final Context mContext;
@@ -380,9 +391,19 @@ public class NotificationChannelSlice implements CustomSliceable {
                        channel -> isChannelEnabled(group, channel, appRow)))
                .collect(Collectors.toList());

        // TODO(b/119831690): Sort the channels by notification count.
        Collections.sort(channels, mChannelComparator);
        return channels;
        // Pack the notification channel with notification sent state for sorting.
        final List<NotificationChannelState> channelStates = new ArrayList<>();
        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) {
@@ -471,4 +492,31 @@ public class NotificationChannelSlice implements CustomSliceable {

        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;
        }
    }
}
+50 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@ import android.util.ArrayMap;

import androidx.core.graphics.drawable.IconCompat;
import androidx.slice.Slice;
import androidx.slice.SliceItem;
import androidx.slice.SliceMetadata;
import androidx.slice.SliceProvider;
import androidx.slice.core.SliceQuery;
@@ -124,6 +125,34 @@ public class NotificationChannelSliceTest {
                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
    public void getSlice_noRecentlyInstalledApp_shouldHaveNoSuggestedAppTitle() {
        addMockPackageToPackageManager(false /* isRecentlyInstalled */,
@@ -269,10 +298,31 @@ public class NotificationChannelSliceTest {
        final Map<String, NotificationBackend.NotificationsSentState> states = new ArrayMap<>();
        for (int i = 0; i < channelCount; i++) {
            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;
            states.put(CHANNEL_NAME_PREFIX + i, state);
        }

        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();
    }
}
 No newline at end of file