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

Commit b1d846cb authored by Yanting Yang's avatar Yanting Yang
Browse files

Add condition to ignore invalid packages in NotificationChannelSlice

If all displayable notification channels of package are turned off,
stop showing notification channel slice of package.

Bug: 124480122
Test: robotests
Change-Id: I3ce9ebc4cca18dac3b4b6f15c28c697b72df81e3
parent 7bac0033
Loading
Loading
Loading
Loading
+27 −18
Original line number Diff line number Diff line
@@ -176,15 +176,10 @@ public class NotificationChannelSlice implements CustomSliceable {
                .setSubtitle(getSubTitle(mPackageName, mUid))
                .setPrimaryAction(getPrimarySliceAction(icon, title, getIntent())));

        // Get rows by notification channel.
        // Add notification channel rows.
        final List<ListBuilder.RowBuilder> rows = getNotificationChannelRows(packageInfo, icon);

        // Get displayable notification channel count.
        final int channelCount = Math.min(rows.size(), DEFAULT_EXPANDED_ROW_COUNT);

        // According to the displayable channel count to add rows.
        for (int i = 0; i < channelCount; i++) {
            listBuilder.addRow(rows.get(i));
        for (ListBuilder.RowBuilder rowBuilder : rows) {
            listBuilder.addRow(rowBuilder);
        }

        return listBuilder.build();
@@ -279,10 +274,9 @@ public class NotificationChannelSlice implements CustomSliceable {
    private List<ListBuilder.RowBuilder> getNotificationChannelRows(PackageInfo packageInfo,
            IconCompat icon) {
        final List<ListBuilder.RowBuilder> notificationChannelRows = new ArrayList<>();
        final List<NotificationChannel> enabledChannels = getEnabledChannels(mPackageName, mUid,
                mAppRow);
        final List<NotificationChannel> displayableChannels = getDisplayableChannels(mAppRow);

        for (NotificationChannel channel : enabledChannels) {
        for (NotificationChannel channel : displayableChannels) {
            notificationChannelRows.add(new ListBuilder.RowBuilder()
                    .setTitle(channel.getName())
                    .setSubtitle(NotificationBackend.getSentSummary(
@@ -356,10 +350,9 @@ public class NotificationChannelSlice implements CustomSliceable {
                title);
    }

    private List<NotificationChannel> getEnabledChannels(String packageName, int uid,
            NotificationBackend.AppRow appRow) {
    private List<NotificationChannel> getDisplayableChannels(NotificationBackend.AppRow appRow) {
        final List<NotificationChannelGroup> channelGroupList =
                mNotificationBackend.getGroups(packageName, uid).getList();
                mNotificationBackend.getGroups(appRow.pkg, appRow.uid).getList();
        final List<NotificationChannel> channels = channelGroupList.stream()
                .flatMap(group -> group.getChannels().stream().filter(
                        channel -> isChannelEnabled(group, channel, appRow)))
@@ -376,8 +369,11 @@ public class NotificationChannelSlice implements CustomSliceable {
        }

        // Sort the notification channels with notification sent count by descending.
        return channelStates.stream().sorted(CHANNEL_STATE_COMPARATOR).map(
                state -> state.getNotificationChannel()).collect(Collectors.toList());
        return channelStates.stream()
                .sorted(CHANNEL_STATE_COMPARATOR)
                .map(state -> state.getNotificationChannel())
                .limit(DEFAULT_EXPANDED_ROW_COUNT)
                .collect(Collectors.toList());
    }

    private PackageInfo getMaxSentNotificationsPackage(List<PackageInfo> packageInfoList) {
@@ -391,10 +387,14 @@ public class NotificationChannelSlice implements CustomSliceable {
        for (PackageInfo packageInfo : packageInfoList) {
            final NotificationBackend.AppRow appRow = mNotificationBackend.loadAppRow(mContext,
                    mContext.getPackageManager(), packageInfo);
            // Ignore packages which are banned notifications or block all displayable channels.
            if (appRow.banned || isAllChannelsBlocked(getDisplayableChannels(appRow))) {
                continue;
            }

            // Get sent notification count from app.
            final int sentCount = appRow.sentByApp.sentCount;
            if (!appRow.banned && sentCount >= MIN_NOTIFICATION_SENT_COUNT
                    && sentCount > maxSentCount) {
            if (sentCount >= MIN_NOTIFICATION_SENT_COUNT && sentCount > maxSentCount) {
                maxSentCount = sentCount;
                maxSentCountPackage = packageInfo;
                mAppRow = appRow;
@@ -404,6 +404,15 @@ public class NotificationChannelSlice implements CustomSliceable {
        return maxSentCountPackage;
    }

    private boolean isAllChannelsBlocked(List<NotificationChannel> channels) {
        for (NotificationChannel channel : channels) {
            if (channel.getImportance() != IMPORTANCE_NONE) {
                return false;
            }
        }
        return true;
    }

    protected CharSequence getSubTitle(String packageName, int uid) {
        final int channelCount = mNotificationBackend.getChannelCount(packageName, uid);

+47 −16
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.settings.homepage.contextualcards.slices;

import static android.app.NotificationManager.IMPORTANCE_LOW;
import static android.app.NotificationManager.IMPORTANCE_NONE;
import static android.app.slice.Slice.HINT_LIST_ITEM;
import static android.app.slice.SliceItem.FORMAT_SLICE;
@@ -116,7 +117,8 @@ public class NotificationChannelSliceTest {
    public void getSlice_hasSuggestedApp_shouldHaveNotificationChannelTitle() {
        addMockPackageToPackageManager(true /* isRecentlyInstalled */,
                ApplicationInfo.FLAG_INSTALLED);
        mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */);
        mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */,
                false /* isChannelBlocked */);

        final Slice slice = mNotificationChannelSlice.getSlice();

@@ -130,7 +132,8 @@ public class NotificationChannelSliceTest {
    public void getSlice_hasSuggestedApp_shouldSortByNotificationSentCount() {
        addMockPackageToPackageManager(true /* isRecentlyInstalled */,
                ApplicationInfo.FLAG_INSTALLED);
        mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */);
        mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */,
                false /* isChannelBlocked */);

        final Slice slice = mNotificationChannelSlice.getSlice();

@@ -157,7 +160,8 @@ public class NotificationChannelSliceTest {
    public void getSlice_noRecentlyInstalledApp_shouldHaveNoSuggestedAppTitle() {
        addMockPackageToPackageManager(false /* isRecentlyInstalled */,
                ApplicationInfo.FLAG_INSTALLED);
        mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */);
        mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */,
                false /* isChannelBlocked */);

        final Slice slice = mNotificationChannelSlice.getSlice();

@@ -169,7 +173,8 @@ public class NotificationChannelSliceTest {
    public void getSlice_noMultiChannelApp_shouldHaveNoSuggestedAppTitle() {
        addMockPackageToPackageManager(true /* isRecentlyInstalled */,
                ApplicationInfo.FLAG_INSTALLED);
        mockNotificationBackend(1 /* channelCount */, NOTIFICATION_COUNT, false /* banned */);
        mockNotificationBackend(1 /* channelCount */, NOTIFICATION_COUNT, false /* banned */,
                false /* isChannelBlocked */);

        final Slice slice = mNotificationChannelSlice.getSlice();

@@ -178,10 +183,12 @@ public class NotificationChannelSliceTest {
    }

    @Test
    @Config(shadows = ShadowRestrictedLockUtilsInternal.class)
    public void getSlice_insufficientNotificationSentCount_shouldHaveNoSuggestedAppTitle() {
        addMockPackageToPackageManager(true /* isRecentlyInstalled */,
                ApplicationInfo.FLAG_INSTALLED);
        mockNotificationBackend(CHANNEL_COUNT, 1 /* notificationCount */, false /* banned */);
        mockNotificationBackend(CHANNEL_COUNT, 1 /* notificationCount */, false /* banned */,
                false /* isChannelBlocked */);

        final Slice slice = mNotificationChannelSlice.getSlice();

@@ -192,7 +199,8 @@ public class NotificationChannelSliceTest {
    @Test
    public void getSlice_isSystemApp_shouldHaveNoSuggestedAppTitle() {
        addMockPackageToPackageManager(true /* isRecentlyInstalled */, ApplicationInfo.FLAG_SYSTEM);
        mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */);
        mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */,
                false /* isChannelBlocked */);

        final Slice slice = mNotificationChannelSlice.getSlice();

@@ -204,7 +212,8 @@ public class NotificationChannelSliceTest {
    public void getSlice_isNotificationBanned_shouldHaveNoSuggestedAppTitle() {
        addMockPackageToPackageManager(true /* isRecentlyInstalled */,
                ApplicationInfo.FLAG_INSTALLED);
        mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, true /* banned */);
        mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, true /* banned */,
                false /* isChannelBlocked */);

        final Slice slice = mNotificationChannelSlice.getSlice();

@@ -218,7 +227,7 @@ public class NotificationChannelSliceTest {
        addMockPackageToPackageManager(true /* isRecentlyInstalled */,
                ApplicationInfo.FLAG_INSTALLED);
        mockNotificationBackend(NotificationChannelSlice.DEFAULT_EXPANDED_ROW_COUNT * 2,
                NOTIFICATION_COUNT, false /* banned */);
                NOTIFICATION_COUNT, false /* banned */, false /* isChannelBlocked */);

        final Slice slice = mNotificationChannelSlice.getSlice();

@@ -234,7 +243,8 @@ public class NotificationChannelSliceTest {
    public void getSlice_channelCountIsLessThanDefaultRows_subTitleShouldNotHaveTapToManagerAll() {
        addMockPackageToPackageManager(true /* isRecentlyInstalled */,
                ApplicationInfo.FLAG_INSTALLED);
        mockNotificationBackend(CHANNEL_COUNT - 1, NOTIFICATION_COUNT, false /* banned */);
        mockNotificationBackend(CHANNEL_COUNT - 1, NOTIFICATION_COUNT, false /* banned */,
                false /* isChannelBlocked */);

        final Slice slice = mNotificationChannelSlice.getSlice();

@@ -249,7 +259,8 @@ public class NotificationChannelSliceTest {
    public void getSlice_channelCountIsEqualToDefaultRows_subTitleShouldNotHaveTapToManagerAll() {
        addMockPackageToPackageManager(true /* isRecentlyInstalled */,
                ApplicationInfo.FLAG_INSTALLED);
        mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */);
        mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */,
                false /* isChannelBlocked */);

        final Slice slice = mNotificationChannelSlice.getSlice();

@@ -263,7 +274,8 @@ public class NotificationChannelSliceTest {
    public void getSlice_channelCountIsMoreThanDefaultRows_subTitleShouldHaveTapToManagerAll() {
        addMockPackageToPackageManager(true /* isRecentlyInstalled */,
                ApplicationInfo.FLAG_INSTALLED);
        mockNotificationBackend(CHANNEL_COUNT + 1, NOTIFICATION_COUNT, false /* banned */);
        mockNotificationBackend(CHANNEL_COUNT + 1, NOTIFICATION_COUNT, false /* banned */,
                false /* isChannelBlocked */);

        final Slice slice = mNotificationChannelSlice.getSlice();

@@ -273,6 +285,20 @@ public class NotificationChannelSliceTest {
                        CHANNEL_COUNT + 1));
    }

    @Test
    @Config(shadows = ShadowRestrictedLockUtilsInternal.class)
    public void getSlice_isAllDisplayableChannelBlocked_shouldHaveNoSuggestedAppTitle() {
        addMockPackageToPackageManager(true /* isRecentlyInstalled */,
                ApplicationInfo.FLAG_INSTALLED);
        mockNotificationBackend(CHANNEL_COUNT, NOTIFICATION_COUNT, false /* banned */,
                true /* isChannelBlocked */);

        final Slice slice = mNotificationChannelSlice.getSlice();

        final SliceMetadata metadata = SliceMetadata.from(mContext, slice);
        assertThat(metadata.getTitle()).isEqualTo(mContext.getString(R.string.no_suggested_app));
    }

    private void addMockPackageToPackageManager(boolean isRecentlyInstalled, int flags) {
        final ApplicationInfo applicationInfo = new ApplicationInfo();
        applicationInfo.name = APP_LABEL;
@@ -294,8 +320,10 @@ public class NotificationChannelSliceTest {
        return System.currentTimeMillis();
    }

    private void mockNotificationBackend(int channelCount, int notificationCount, boolean banned) {
        final List<NotificationChannel> channels = buildNotificationChannel(channelCount);
    private void mockNotificationBackend(int channelCount, int notificationCount, boolean banned,
            boolean isChannelBlocked) {
        final List<NotificationChannel> channels = buildNotificationChannel(channelCount,
                isChannelBlocked);
        final AppRow appRow = buildAppRow(channelCount, notificationCount, banned);

        doReturn(buildNotificationChannelGroups(channels)).when(mNotificationBackend).getGroups(
@@ -308,6 +336,8 @@ public class NotificationChannelSliceTest {

    private AppRow buildAppRow(int channelCount, int sentCount, boolean banned) {
        final AppRow appRow = new AppRow();
        appRow.pkg = PACKAGE_NAME;
        appRow.uid = UID;
        appRow.banned = banned;
        appRow.channelCount = channelCount;
        appRow.sentByApp = new NotificationsSentState();
@@ -317,11 +347,12 @@ public class NotificationChannelSliceTest {
        return appRow;
    }

    private List<NotificationChannel> buildNotificationChannel(int channelCount) {
    private List<NotificationChannel> buildNotificationChannel(int channelCount,
            boolean isChannelBlock) {
        final List<NotificationChannel> channels = new ArrayList<>();
        for (int i = 0; i < channelCount; i++) {
            channels.add(new NotificationChannel(CHANNEL_NAME_PREFIX + i, CHANNEL_NAME_PREFIX + i,
                    IMPORTANCE_NONE));
                    isChannelBlock ? IMPORTANCE_NONE : IMPORTANCE_LOW));
        }

        return channels;