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

Commit ad9412cf authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Change snoozing behavior for notifications in groups" into oc-dev

parents 9a4b756c a78cdffd
Loading
Loading
Loading
Loading
+130 −44
Original line number Original line Diff line number Diff line
@@ -56,6 +56,7 @@ import static android.view.WindowManager.LayoutParams.TYPE_TOAST;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;


import android.Manifest;
import android.Manifest;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.ActivityManagerInternal;
@@ -980,6 +981,14 @@ public class NotificationManagerService extends SystemService {
    void addNotification(NotificationRecord r) {
    void addNotification(NotificationRecord r) {
        mNotificationList.add(r);
        mNotificationList.add(r);
        mNotificationsByKey.put(r.sbn.getKey(), r);
        mNotificationsByKey.put(r.sbn.getKey(), r);
        if (r.sbn.isGroup()) {
            mSummaryByGroupKey.put(r.getGroupKey(), r);
        }
    }

    @VisibleForTesting
    void addEnqueuedNotification(NotificationRecord r) {
        mEnqueuedNotifications.add(r);
    }
    }


    @VisibleForTesting
    @VisibleForTesting
@@ -1016,7 +1025,7 @@ public class NotificationManagerService extends SystemService {
    @VisibleForTesting
    @VisibleForTesting
    void init(Looper looper, IPackageManager packageManager, PackageManager packageManagerClient,
    void init(Looper looper, IPackageManager packageManager, PackageManager packageManagerClient,
            LightsManager lightsManager, NotificationListeners notificationListeners,
            LightsManager lightsManager, NotificationListeners notificationListeners,
            ICompanionDeviceManager companionManager) {
            ICompanionDeviceManager companionManager, SnoozeHelper snoozeHelper) {
        Resources resources = getContext().getResources();
        Resources resources = getContext().getResources();
        mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(),
        mMaxPackageEnqueueRate = Settings.Global.getFloat(getContext().getContentResolver(),
                Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE,
                Settings.Global.MAX_NOTIFICATION_ENQUEUE_RATE,
@@ -1071,21 +1080,7 @@ public class NotificationManagerService extends SystemService {
                sendRegisteredOnlyBroadcast(NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED);
                sendRegisteredOnlyBroadcast(NotificationManager.ACTION_NOTIFICATION_POLICY_CHANGED);
            }
            }
        });
        });
        mSnoozeHelper = new SnoozeHelper(getContext(), new SnoozeHelper.Callback() {
        mSnoozeHelper = snoozeHelper;
            @Override
            public void repost(int userId, NotificationRecord r) {
                try {
                    if (DBG) {
                        Slog.d(TAG, "Reposting " + r.getKey());
                    }
                    enqueueNotificationInternal(r.sbn.getPackageName(), r.sbn.getOpPkg(),
                            r.sbn.getUid(), r.sbn.getInitialPid(), r.sbn.getTag(), r.sbn.getId(),
                            r.sbn.getNotification(), userId);
                } catch (Exception e) {
                    Slog.e(TAG, "Cannot un-snooze notification", e);
                }
            }
        }, mUserProfiles);
        mGroupHelper = new GroupHelper(new GroupHelper.Callback() {
        mGroupHelper = new GroupHelper(new GroupHelper.Callback() {
            @Override
            @Override
            public void addAutoGroup(String key) {
            public void addAutoGroup(String key) {
@@ -1204,9 +1199,25 @@ public class NotificationManagerService extends SystemService {


    @Override
    @Override
    public void onStart() {
    public void onStart() {
        SnoozeHelper snoozeHelper = new SnoozeHelper(getContext(), new SnoozeHelper.Callback() {
            @Override
            public void repost(int userId, NotificationRecord r) {
                try {
                    if (DBG) {
                        Slog.d(TAG, "Reposting " + r.getKey());
                    }
                    enqueueNotificationInternal(r.sbn.getPackageName(), r.sbn.getOpPkg(),
                            r.sbn.getUid(), r.sbn.getInitialPid(), r.sbn.getTag(), r.sbn.getId(),
                            r.sbn.getNotification(), userId);
                } catch (Exception e) {
                    Slog.e(TAG, "Cannot un-snooze notification", e);
                }
            }
        }, mUserProfiles);

        init(Looper.myLooper(), AppGlobals.getPackageManager(), getContext().getPackageManager(),
        init(Looper.myLooper(), AppGlobals.getPackageManager(), getContext().getPackageManager(),
                getLocalService(LightsManager.class), new NotificationListeners(),
                getLocalService(LightsManager.class), new NotificationListeners(),
                null);
                null, snoozeHelper);
        publishBinderService(Context.NOTIFICATION_SERVICE, mService);
        publishBinderService(Context.NOTIFICATION_SERVICE, mService);
        publishLocalService(NotificationManagerInternal.class, mInternalService);
        publishLocalService(NotificationManagerInternal.class, mInternalService);
    }
    }
@@ -3304,7 +3315,7 @@ public class NotificationManagerService extends SystemService {
                        return false;
                        return false;
                    }
                    }
                } else if (isCallerInstantApp(pkg)) {
                } else if (isCallerInstantApp(pkg)) {
                    // Ephemeral apps have some special contraints for notifications.
                    // Ephemeral apps have some special constraints for notifications.
                    // They are not allowed to create new notifications however they are allowed to
                    // They are not allowed to create new notifications however they are allowed to
                    // update notifications created by the system (e.g. a foreground service
                    // update notifications created by the system (e.g. a foreground service
                    // notification).
                    // notification).
@@ -3378,6 +3389,76 @@ public class NotificationManagerService extends SystemService {
        return isBlocked;
        return isBlocked;
    }
    }


    protected class SnoozeNotificationRunnable implements Runnable {
        private final String mKey;
        private final long mDuration;
        private final String mSnoozeCriterionId;

        SnoozeNotificationRunnable(String key, long duration, String snoozeCriterionId) {
            mKey = key;
            mDuration = duration;
            mSnoozeCriterionId = snoozeCriterionId;
        }

        @Override
        public void run() {
            synchronized (mNotificationLock) {
                final NotificationRecord r = findNotificationByKeyLocked(mKey);
                if (r != null) {
                    snoozeLocked(r);
                }
            }
        }

        void snoozeLocked(NotificationRecord r) {
            if (r.sbn.isGroup()) {
                final List<NotificationRecord> groupNotifications = findGroupNotificationsLocked(
                        r.sbn.getPackageName(), r.sbn.getGroupKey(), r.sbn.getUserId());
                if (r.getNotification().isGroupSummary()) {
                    // snooze summary and all children
                    for (int i = 0; i < groupNotifications.size(); i++) {
                        snoozeNotificationLocked(groupNotifications.get(i));
                    }
                } else {
                    // if there is a valid summary for this group, and we are snoozing the only
                    // child, also snooze the summary
                    if (mSummaryByGroupKey.containsKey(r.sbn.getGroupKey())) {
                        if (groupNotifications.size() != 2) {
                            snoozeNotificationLocked(r);
                        } else {
                            // snooze summary and the one child
                            for (int i = 0; i < groupNotifications.size(); i++) {
                                snoozeNotificationLocked(groupNotifications.get(i));
                            }
                        }
                    } else {
                        snoozeNotificationLocked(r);
                    }
                }
            } else {
                // just snooze the one notification
                snoozeNotificationLocked(r);
            }
        }

        void snoozeNotificationLocked(NotificationRecord r) {
            MetricsLogger.action(r.getLogMaker()
                    .setCategory(MetricsEvent.NOTIFICATION_SNOOZED)
                    .setType(MetricsEvent.TYPE_CLOSE)
                    .addTaggedData(MetricsEvent.NOTIFICATION_SNOOZED_CRITERIA,
                            mSnoozeCriterionId == null ? 0 : 1));
            cancelNotificationLocked(r, false, REASON_SNOOZED);
            updateLightsLocked();
            if (mSnoozeCriterionId != null) {
                mNotificationAssistants.notifyAssistantSnoozedLocked(r.sbn, mSnoozeCriterionId);
                mSnoozeHelper.snooze(r);
            } else {
                mSnoozeHelper.snooze(r, mDuration);
            }
            savePolicyFile();
        }
    }

    protected class EnqueueNotificationRunnable implements Runnable {
    protected class EnqueueNotificationRunnable implements Runnable {
        private final NotificationRecord r;
        private final NotificationRecord r;
        private final int userId;
        private final int userId;
@@ -3412,6 +3493,11 @@ public class NotificationManagerService extends SystemService {
                // can to avoid extracting signals.
                // can to avoid extracting signals.
                handleGroupedNotificationLocked(r, old, callingUid, callingPid);
                handleGroupedNotificationLocked(r, old, callingUid, callingPid);


                // if this is a group child, unsnooze parent summary
                if (n.isGroup() && notification.isGroupChild()) {
                    mSnoozeHelper.repostGroupSummary(pkg, r.getUserId(), n.getGroupKey());
                }

                // This conditional is a dirty hack to limit the logging done on
                // This conditional is a dirty hack to limit the logging done on
                //     behalf of the download manager without affecting other apps.
                //     behalf of the download manager without affecting other apps.
                if (!pkg.equals("com.android.providers.downloads")
                if (!pkg.equals("com.android.providers.downloads")
@@ -4394,31 +4480,7 @@ public class NotificationManagerService extends SystemService {
                    snoozeCriterionId, listenerName));
                    snoozeCriterionId, listenerName));
        }
        }
        // Needs to post so that it can cancel notifications not yet enqueued.
        // Needs to post so that it can cancel notifications not yet enqueued.
        mHandler.post(new Runnable() {
        mHandler.post(new SnoozeNotificationRunnable(key, duration, snoozeCriterionId));
            @Override
            public void run() {
                synchronized (mNotificationLock) {
                    final NotificationRecord r = findNotificationByKeyLocked(key);
                    if (r != null) {
                        MetricsLogger.action(r.getLogMaker()
                                .setCategory(MetricsEvent.NOTIFICATION_SNOOZED)
                                .setType(MetricsEvent.TYPE_CLOSE)
                                .addTaggedData(MetricsEvent.NOTIFICATION_SNOOZED_CRITERIA,
                                        snoozeCriterionId == null ? 0 : 1));
                        cancelNotificationLocked(r, false, REASON_SNOOZED);
                        updateLightsLocked();
                        if (snoozeCriterionId != null) {
                            mNotificationAssistants.notifyAssistantSnoozedLocked(r.sbn,
                                    snoozeCriterionId);
                            mSnoozeHelper.snooze(r);
                        } else {
                            mSnoozeHelper.snooze(r, duration);
                        }
                        savePolicyFile();
                    }
                }
            }
        });
    }
    }


    void unsnoozeNotificationInt(String key, ManagedServiceInfo listener) {
    void unsnoozeNotificationInt(String key, ManagedServiceInfo listener) {
@@ -4531,6 +4593,30 @@ public class NotificationManagerService extends SystemService {
        }
        }
    }
    }


    @NonNull List<NotificationRecord> findGroupNotificationsLocked(String pkg,
            String groupKey, int userId) {
        List<NotificationRecord> records = new ArrayList<>();
        records.addAll(findGroupNotificationByListLocked(mNotificationList, pkg, groupKey, userId));
        records.addAll(
                findGroupNotificationByListLocked(mEnqueuedNotifications, pkg, groupKey, userId));
        return records;
    }


    private @NonNull List<NotificationRecord> findGroupNotificationByListLocked(
            ArrayList<NotificationRecord> list, String pkg, String groupKey, int userId) {
        List<NotificationRecord> records = new ArrayList<>();
        final int len = list.size();
        for (int i = 0; i < len; i++) {
            NotificationRecord r = list.get(i);
            if (notificationMatchesUserId(r, userId) && r.getGroupKey().equals(groupKey)
                    && r.sbn.getPackageName().equals(pkg)) {
                records.add(r);
            }
        }
        return records;
    }

    // Searches both enqueued and posted notifications by key.
    // Searches both enqueued and posted notifications by key.
    // TODO: need to combine a bunch of these getters with slightly different behavior.
    // TODO: need to combine a bunch of these getters with slightly different behavior.
    // TODO: Should enqueuing just add to mNotificationsByKey instead?
    // TODO: Should enqueuing just add to mNotificationsByKey instead?
@@ -4545,7 +4631,7 @@ public class NotificationManagerService extends SystemService {
        return null;
        return null;
    }
    }


    private NotificationRecord findNotificationLocked(String pkg, String tag, int id, int userId) {
    NotificationRecord findNotificationLocked(String pkg, String tag, int id, int userId) {
        NotificationRecord r;
        NotificationRecord r;
        if ((r = findNotificationByListLocked(mNotificationList, pkg, tag, id, userId)) != null) {
        if ((r = findNotificationByListLocked(mNotificationList, pkg, tag, id, userId)) != null) {
            return r;
            return r;
+50 −12
Original line number Original line Diff line number Diff line
@@ -25,6 +25,7 @@ import org.xmlpull.v1.XmlSerializer;


import android.annotation.NonNull;
import android.annotation.NonNull;
import android.app.AlarmManager;
import android.app.AlarmManager;
import android.app.Notification;
import android.app.PendingIntent;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Context;
@@ -61,7 +62,6 @@ public class SnoozeHelper {
    private static final String REPOST_ACTION = SnoozeHelper.class.getSimpleName() + ".EVALUATE";
    private static final String REPOST_ACTION = SnoozeHelper.class.getSimpleName() + ".EVALUATE";
    private static final int REQUEST_CODE_REPOST = 1;
    private static final int REQUEST_CODE_REPOST = 1;
    private static final String REPOST_SCHEME = "repost";
    private static final String REPOST_SCHEME = "repost";
    private static final String EXTRA_PKG = "pkg";
    private static final String EXTRA_KEY = "key";
    private static final String EXTRA_KEY = "key";
    private static final String EXTRA_USER_ID = "userId";
    private static final String EXTRA_USER_ID = "userId";


@@ -98,7 +98,7 @@ public class SnoozeHelper {
    protected Collection<NotificationRecord> getSnoozed(int userId, String pkg) {
    protected Collection<NotificationRecord> getSnoozed(int userId, String pkg) {
        if (mSnoozedNotifications.containsKey(userId)
        if (mSnoozedNotifications.containsKey(userId)
                && mSnoozedNotifications.get(userId).containsKey(pkg)) {
                && mSnoozedNotifications.get(userId).containsKey(pkg)) {
            mSnoozedNotifications.get(userId).get(pkg).values();
            return mSnoozedNotifications.get(userId).get(pkg).values();
        }
        }
        return Collections.EMPTY_LIST;
        return Collections.EMPTY_LIST;
    }
    }
@@ -106,6 +106,7 @@ public class SnoozeHelper {
    protected @NonNull List<NotificationRecord> getSnoozed() {
    protected @NonNull List<NotificationRecord> getSnoozed() {
        List<NotificationRecord> snoozedForUser = new ArrayList<>();
        List<NotificationRecord> snoozedForUser = new ArrayList<>();
        int[] userIds = mUserProfiles.getCurrentProfileIds();
        int[] userIds = mUserProfiles.getCurrentProfileIds();
        if (userIds != null) {
            final int N = userIds.length;
            final int N = userIds.length;
            for (int i = 0; i < N; i++) {
            for (int i = 0; i < N; i++) {
                final ArrayMap<String, ArrayMap<String, NotificationRecord>> snoozedPkgs =
                final ArrayMap<String, ArrayMap<String, NotificationRecord>> snoozedPkgs =
@@ -120,6 +121,7 @@ public class SnoozeHelper {
                    }
                    }
                }
                }
            }
            }
        }
        return snoozedForUser;
        return snoozedForUser;
    }
    }


@@ -281,6 +283,42 @@ public class SnoozeHelper {
        }
        }
    }
    }


    protected void repostGroupSummary(String pkg, int userId, String groupKey) {
        if (mSnoozedNotifications.containsKey(userId)) {
            ArrayMap<String, ArrayMap<String, NotificationRecord>> keysByPackage
                    = mSnoozedNotifications.get(userId);

            if (keysByPackage != null && keysByPackage.containsKey(pkg)) {
                ArrayMap<String, NotificationRecord> recordsByKey = keysByPackage.get(pkg);

                if (recordsByKey != null) {
                    String groupSummaryKey = null;
                    int N = recordsByKey.size();
                    for (int i = 0; i < N; i++) {
                        final NotificationRecord potentialGroupSummary = recordsByKey.valueAt(i);
                        if (potentialGroupSummary.sbn.isGroup()
                                && potentialGroupSummary.getNotification().isGroupSummary()
                                && groupKey.equals(potentialGroupSummary.getGroupKey())) {
                            groupSummaryKey = potentialGroupSummary.getKey();
                            break;
                        }
                    }

                    if (groupSummaryKey != null) {
                        NotificationRecord record = recordsByKey.remove(groupSummaryKey);
                        mPackages.remove(groupSummaryKey);
                        mUsers.remove(groupSummaryKey);

                        MetricsLogger.action(record.getLogMaker()
                                .setCategory(MetricsProto.MetricsEvent.NOTIFICATION_SNOOZED)
                                .setType(MetricsProto.MetricsEvent.TYPE_OPEN));
                        mCallback.repost(userId, record);
                    }
                }
            }
        }
    }

    private PendingIntent createPendingIntent(String pkg, String key, int userId) {
    private PendingIntent createPendingIntent(String pkg, String key, int userId) {
        return PendingIntent.getBroadcast(mContext,
        return PendingIntent.getBroadcast(mContext,
                REQUEST_CODE_REPOST,
                REQUEST_CODE_REPOST,
+186 −1
Original line number Original line Diff line number Diff line
@@ -24,6 +24,7 @@ import static junit.framework.Assert.assertTrue;
import static junit.framework.Assert.fail;
import static junit.framework.Assert.fail;


import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyBoolean;
import static org.mockito.Matchers.anyLong;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.any;
@@ -96,6 +97,7 @@ public class NotificationManagerServiceTest {
    private NotificationManagerService.NotificationListeners mNotificationListeners;
    private NotificationManagerService.NotificationListeners mNotificationListeners;
    private ManagedServices.ManagedServiceInfo mListener;
    private ManagedServices.ManagedServiceInfo mListener;
    @Mock private ICompanionDeviceManager mCompanionMgr;
    @Mock private ICompanionDeviceManager mCompanionMgr;
    @Mock SnoozeHelper mSnoozeHelper;


    // Use a Testable subclass so we can simulate calls from the system without failing.
    // Use a Testable subclass so we can simulate calls from the system without failing.
    private static class TestableNotificationManagerService extends NotificationManagerService {
    private static class TestableNotificationManagerService extends NotificationManagerService {
@@ -133,7 +135,8 @@ public class NotificationManagerServiceTest {
                null, new ComponentName(PKG, "test_class"), uid, true, null, 0);
                null, new ComponentName(PKG, "test_class"), uid, true, null, 0);
        when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
        when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
        mNotificationManagerService.init(mTestableLooper.getLooper(), mPackageManager,
        mNotificationManagerService.init(mTestableLooper.getLooper(), mPackageManager,
                mPackageManagerClient, mockLightsManager, mNotificationListeners, mCompanionMgr);
                mPackageManagerClient, mockLightsManager, mNotificationListeners, mCompanionMgr,
                mSnoozeHelper);


        // Tests call directly into the Binder.
        // Tests call directly into the Binder.
        mBinderService = mNotificationManagerService.getBinderService();
        mBinderService = mNotificationManagerService.getBinderService();
@@ -147,6 +150,18 @@ public class NotificationManagerServiceTest {
        mTestableLooper.processAllMessages();
        mTestableLooper.processAllMessages();
    }
    }


    private NotificationRecord generateNotificationRecord(NotificationChannel channel, int id,
            String groupKey, boolean isSummary) {
        Notification.Builder nb = new Notification.Builder(mContext, channel.getId())
                .setContentTitle("foo")
                .setSmallIcon(android.R.drawable.sym_def_app_icon)
                .setGroup(groupKey)
                .setGroupSummary(isSummary);

        StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, "tag", uid, 0,
                nb.build(), new UserHandle(uid), null, 0);
        return new NotificationRecord(mContext, sbn, channel);
    }
    private NotificationRecord generateNotificationRecord(NotificationChannel channel) {
    private NotificationRecord generateNotificationRecord(NotificationChannel channel) {
        return generateNotificationRecord(channel, null);
        return generateNotificationRecord(channel, null);
    }
    }
@@ -395,6 +410,46 @@ public class NotificationManagerServiceTest {
        assertEquals(0, notifs[0].getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE);
        assertEquals(0, notifs[0].getNotification().flags & Notification.FLAG_FOREGROUND_SERVICE);
    }
    }


    @Test
    public void testFindGroupNotificationsLocked() throws Exception {
        // make sure the same notification can be found in both lists and returned
        final NotificationRecord group1 = generateNotificationRecord(
                mTestNotificationChannel, 1, "group1", true);
        mNotificationManagerService.addEnqueuedNotification(group1);
        mNotificationManagerService.addNotification(group1);

        // should not be returned
        final NotificationRecord group2 = generateNotificationRecord(
                mTestNotificationChannel, 2, "group2", true);
        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null,
                group2.sbn.getId(), group2.sbn.getNotification(), group2.sbn.getUserId());
        waitForIdle();

        // should not be returned
        final NotificationRecord nonGroup = generateNotificationRecord(
                mTestNotificationChannel, 3, null, false);
        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null,
                nonGroup.sbn.getId(), nonGroup.sbn.getNotification(), nonGroup.sbn.getUserId());
        waitForIdle();

        // same group, child, should be returned
        final NotificationRecord group1Child = generateNotificationRecord(
                mTestNotificationChannel, 4, "group1", false);
        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null, group1Child.sbn.getId(),
                group1Child.sbn.getNotification(), group1Child.sbn.getUserId());
        waitForIdle();

        List<NotificationRecord> inGroup1 =
                mNotificationManagerService.findGroupNotificationsLocked(PKG, group1.getGroupKey(),
                        group1.sbn.getUserId());
        assertEquals(3, inGroup1.size());
        for (NotificationRecord record : inGroup1) {
            assertTrue(record.getGroupKey().equals(group1.getGroupKey()));
            assertTrue(record.sbn.getId() == 1 || record.sbn.getId() == 4);
        }
    }


    @Test
    @Test
    public void testTvExtenderChannelOverride_onTv() throws Exception {
    public void testTvExtenderChannelOverride_onTv() throws Exception {
        mNotificationManagerService.setIsTelevision(true);
        mNotificationManagerService.setIsTelevision(true);
@@ -701,4 +756,134 @@ public class NotificationManagerServiceTest {
        assertFalse(mNotificationManagerService.hasCompanionDevice(mListener));
        assertFalse(mNotificationManagerService.hasCompanionDevice(mListener));
    }
    }


    @Test
    public void testSnoozeRunnable_snoozeNonGrouped() throws Exception {
        final NotificationRecord nonGrouped = generateNotificationRecord(
                mTestNotificationChannel, 1, null, false);
        final NotificationRecord grouped = generateNotificationRecord(
                mTestNotificationChannel, 2, "group", false);
        mNotificationManagerService.addNotification(grouped);
        mNotificationManagerService.addNotification(nonGrouped);

        NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
                mNotificationManagerService.new SnoozeNotificationRunnable(
                        nonGrouped.getKey(), 100, null);
        snoozeNotificationRunnable.run();

        // only snooze the one notification
        verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
    }

    @Test
    public void testSnoozeRunnable_snoozeSummary_withChildren() throws Exception {
        final NotificationRecord parent = generateNotificationRecord(
                mTestNotificationChannel, 1, "group", true);
        final NotificationRecord child = generateNotificationRecord(
                mTestNotificationChannel, 2, "group", false);
        final NotificationRecord child2 = generateNotificationRecord(
                mTestNotificationChannel, 3, "group", false);
        mNotificationManagerService.addNotification(parent);
        mNotificationManagerService.addNotification(child);
        mNotificationManagerService.addNotification(child2);

        NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
                mNotificationManagerService.new SnoozeNotificationRunnable(
                        parent.getKey(), 100, null);
        snoozeNotificationRunnable.run();

        // snooze parent and children
        verify(mSnoozeHelper, times(3)).snooze(any(NotificationRecord.class), anyLong());
    }

    @Test
    public void testSnoozeRunnable_snoozeGroupChild_fellowChildren() throws Exception {
        final NotificationRecord parent = generateNotificationRecord(
                mTestNotificationChannel, 1, "group", true);
        final NotificationRecord child = generateNotificationRecord(
                mTestNotificationChannel, 2, "group", false);
        final NotificationRecord child2 = generateNotificationRecord(
                mTestNotificationChannel, 3, "group", false);
        mNotificationManagerService.addNotification(parent);
        mNotificationManagerService.addNotification(child);
        mNotificationManagerService.addNotification(child2);

        NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
                mNotificationManagerService.new SnoozeNotificationRunnable(
                        child2.getKey(), 100, null);
        snoozeNotificationRunnable.run();

        // only snooze the one child
        verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
    }

    @Test
    public void testSnoozeRunnable_snoozeGroupChild_onlyChildOfSummary() throws Exception {
        final NotificationRecord parent = generateNotificationRecord(
                mTestNotificationChannel, 1, "group", true);
        assertTrue(parent.sbn.getNotification().isGroupSummary());
        final NotificationRecord child = generateNotificationRecord(
                mTestNotificationChannel, 2, "group", false);
        mNotificationManagerService.addNotification(parent);
        mNotificationManagerService.addNotification(child);

        NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
                mNotificationManagerService.new SnoozeNotificationRunnable(
                        child.getKey(), 100, null);
        snoozeNotificationRunnable.run();

        // snooze child and summary
        verify(mSnoozeHelper, times(2)).snooze(any(NotificationRecord.class), anyLong());
    }

    @Test
    public void testSnoozeRunnable_snoozeGroupChild_noOthersInGroup() throws Exception {
        final NotificationRecord child = generateNotificationRecord(
                mTestNotificationChannel, 2, "group", false);
        mNotificationManagerService.addNotification(child);

        NotificationManagerService.SnoozeNotificationRunnable snoozeNotificationRunnable =
                mNotificationManagerService.new SnoozeNotificationRunnable(
                        child.getKey(), 100, null);
        snoozeNotificationRunnable.run();

        // snooze child only
        verify(mSnoozeHelper, times(1)).snooze(any(NotificationRecord.class), anyLong());
    }

    @Test
    public void testPostGroupChild_unsnoozeParent() throws Exception {
        final NotificationRecord child = generateNotificationRecord(
                mTestNotificationChannel, 2, "group", false);

        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null,
                child.sbn.getId(), child.sbn.getNotification(), child.sbn.getUserId());
        waitForIdle();

        verify(mSnoozeHelper, times(1)).repostGroupSummary(
                anyString(), anyInt(), eq(child.getGroupKey()));
    }

    @Test
    public void testPostNonGroup_noUnsnoozing() throws Exception {
        final NotificationRecord record = generateNotificationRecord(
                mTestNotificationChannel, 2, null, false);

        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null,
                record.sbn.getId(), record.sbn.getNotification(), record.sbn.getUserId());
        waitForIdle();

        verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
    }

    @Test
    public void testPostGroupSummary_noUnsnoozing() throws Exception {
        final NotificationRecord parent = generateNotificationRecord(
                mTestNotificationChannel, 2, "group", true);

        mBinderService.enqueueNotificationWithTag(PKG, "opPkg", null,
                parent.sbn.getId(), parent.sbn.getNotification(), parent.sbn.getUserId());
        waitForIdle();

        verify(mSnoozeHelper, never()).repostGroupSummary(anyString(), anyInt(), anyString());
    }
}
}
+44 −1

File changed.

Preview size limit exceeded, changes collapsed.