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

Commit 6503162d authored by Julia Reynolds's avatar Julia Reynolds
Browse files

Silence notifications that are manually unsnoozed

Test: atest
Bug: 149486431
Change-Id: I7d11859210f6000120b2c51dc33da3d0928fb22e
parent ccf72664
Loading
Loading
Loading
Loading
+26 −16
Original line number Diff line number Diff line
@@ -2068,20 +2068,17 @@ public class NotificationManagerService extends SystemService {

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

        final File systemDir = new File(Environment.getDataDirectory(), "system");
@@ -3983,7 +3980,7 @@ public class NotificationManagerService extends SystemService {
                synchronized (mNotificationLock) {
                    final ManagedServiceInfo info =
                            mAssistants.checkServiceTokenLocked(token);
                    unsnoozeNotificationInt(key, info);
                    unsnoozeNotificationInt(key, info, false);
                }
            } finally {
                Binder.restoreCallingIdentity(identity);
@@ -4006,7 +4003,7 @@ public class NotificationManagerService extends SystemService {
                    if (!info.isSystem) {
                        throw new SecurityException("Not allowed to unsnooze before deadline");
                    }
                    unsnoozeNotificationInt(key, info);
                    unsnoozeNotificationInt(key, info, true);
                }
            } finally {
                Binder.restoreCallingIdentity(identity);
@@ -5525,6 +5522,13 @@ public class NotificationManagerService extends SystemService {
    void enqueueNotificationInternal(final String pkg, final String opPkg, final int callingUid,
            final int callingPid, final String tag, final int id, final Notification notification,
            int incomingUserId) {
        enqueueNotificationInternal(pkg, opPkg, callingUid, callingPid, tag, id, notification,
        incomingUserId, false);
    }

    void enqueueNotificationInternal(final String pkg, final String opPkg, final int callingUid,
        final int callingPid, final String tag, final int id, final Notification notification,
        int incomingUserId, boolean postSilently) {
        if (DBG) {
            Slog.v(TAG, "enqueueNotificationInternal: pkg=" + pkg + " id=" + id
                    + " notification=" + notification);
@@ -5605,6 +5609,7 @@ public class NotificationManagerService extends SystemService {
                user, null, System.currentTimeMillis());
        final NotificationRecord r = new NotificationRecord(getContext(), n, channel);
        r.setIsAppImportanceLocked(mPreferencesHelper.getIsAppImportanceLocked(pkg, callingUid));
        r.setPostSilently(postSilently);

        if ((notification.flags & Notification.FLAG_FOREGROUND_SERVICE) != 0) {
            final boolean fgServiceShown = channel.isFgServiceShown();
@@ -7040,6 +7045,11 @@ public class NotificationManagerService extends SystemService {
            return true;
        }

        // Suppressed because a user manually unsnoozed something (or similar)
        if (record.shouldPostSilently()) {
            return true;
        }

        // muted by listener
        final String disableEffects = disableNotificationEffects(record);
        if (disableEffects != null) {
@@ -8054,13 +8064,13 @@ public class NotificationManagerService extends SystemService {
        mHandler.post(new SnoozeNotificationRunnable(key, duration, snoozeCriterionId));
    }

    void unsnoozeNotificationInt(String key, ManagedServiceInfo listener) {
    void unsnoozeNotificationInt(String key, ManagedServiceInfo listener, boolean muteOnReturn) {
        String listenerName = listener == null ? null : listener.component.toShortString();
        if (DBG) {
            Slog.d(TAG, String.format("unsnooze event(%s, %s)", key, listenerName));
        }
        mSnoozeHelper.cleanupPersistedContext(key);
        mSnoozeHelper.repost(key);
        mSnoozeHelper.repost(key, muteOnReturn);
        handleSavePolicyFile();
    }

+12 −0
Original line number Diff line number Diff line
@@ -187,6 +187,7 @@ public final class NotificationRecord {
    private boolean mSuggestionsGeneratedByAssistant;
    private boolean mEditChoicesBeforeSending;
    private boolean mHasSeenSmartReplies;
    private boolean mPostSilently;
    /**
     * Whether this notification (and its channels) should be considered user locked. Used in
     * conjunction with user sentiment calculation.
@@ -856,6 +857,17 @@ public final class NotificationRecord {
        return mHidden;
    }

    /**
     * Override of all alerting information on the channel and notification. Used when notifications
     * are reposted in response to direct user action and thus don't need to alert.
     */
    public void setPostSilently(boolean postSilently) {
        mPostSilently = postSilently;
    }

    public boolean shouldPostSilently() {
        return mPostSilently;
    }

    public void setSuppressedVisualEffects(int effects) {
        mSuppressedVisualEffects = effects;
+7 −7
Original line number Diff line number Diff line
@@ -332,14 +332,14 @@ public class SnoozeHelper {
        records.put(record.getKey(), record);
    }

    protected void repost(String key) {
    protected void repost(String key, boolean muteOnReturn) {
        Integer userId = mUsers.get(key);
        if (userId != null) {
            repost(key, userId);
            repost(key, userId, muteOnReturn);
        }
    }

    protected void repost(String key, int userId) {
    protected void repost(String key, int userId, boolean muteOnReturn) {
        final String pkg = mPackages.remove(key);
        ArrayMap<String, NotificationRecord> records =
                mSnoozedNotifications.get(getPkgKey(userId, pkg));
@@ -356,7 +356,7 @@ public class SnoozeHelper {
            MetricsLogger.action(record.getLogMaker()
                    .setCategory(MetricsProto.MetricsEvent.NOTIFICATION_SNOOZED)
                    .setType(MetricsProto.MetricsEvent.TYPE_OPEN));
            mCallback.repost(userId, record);
            mCallback.repost(userId, record, muteOnReturn);
        }
    }

@@ -388,7 +388,7 @@ public class SnoozeHelper {
                MetricsLogger.action(record.getLogMaker()
                        .setCategory(MetricsProto.MetricsEvent.NOTIFICATION_SNOOZED)
                        .setType(MetricsProto.MetricsEvent.TYPE_OPEN));
                mCallback.repost(userId, record);
                mCallback.repost(userId, record, false);
            }
        }
    }
@@ -601,7 +601,7 @@ public class SnoozeHelper {
    }

    protected interface Callback {
        void repost(int userId, NotificationRecord r);
        void repost(int userId, NotificationRecord r, boolean muteOnReturn);
    }

    private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@@ -612,7 +612,7 @@ public class SnoozeHelper {
            }
            if (REPOST_ACTION.equals(intent.getAction())) {
                repost(intent.getStringExtra(EXTRA_KEY), intent.getIntExtra(EXTRA_USER_ID,
                        UserHandle.USER_SYSTEM));
                        UserHandle.USER_SYSTEM), false);
            }
        }
    };
+12 −0
Original line number Diff line number Diff line
@@ -845,6 +845,18 @@ public class BuzzBeepBlinkTest extends UiServiceTestCase {
        assertNotEquals(-1, r.getLastAudiblyAlertedMs());
    }

    @Test
    public void testPostSilently() throws Exception {
        NotificationRecord r = getBuzzyNotification();
        r.setPostSilently(true);

        mService.buzzBeepBlinkLocked(r);

        verifyNeverBeep();
        assertFalse(r.isInterruptive());
        assertEquals(-1, r.getLastAudiblyAlertedMs());
    }

    @Test
    public void testGroupAlertSummarySilenceChild() throws Exception {
        NotificationRecord child = getBeepyNotificationRecord("a", GROUP_ALERT_SUMMARY);
+26 −15
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;

import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Matchers.any;
import static org.mockito.Matchers.anyInt;
@@ -363,8 +364,8 @@ public class SnoozeHelperTest extends UiServiceTestCase {

        mSnoozeHelper.cancel(UserHandle.USER_SYSTEM, r.getSbn().getPackageName(), "one", 1);

        mSnoozeHelper.repost(r.getKey(), UserHandle.USER_SYSTEM);
        verify(mCallback, never()).repost(UserHandle.USER_SYSTEM, r);
        mSnoozeHelper.repost(r.getKey(), UserHandle.USER_SYSTEM, false);
        verify(mCallback, never()).repost(UserHandle.USER_SYSTEM, r, false);
    }

    @Test
@@ -374,8 +375,8 @@ public class SnoozeHelperTest extends UiServiceTestCase {
        NotificationRecord r2 = getNotificationRecord("pkg", 2, "one", UserHandle.ALL);
        mSnoozeHelper.snooze(r2, 1000);
        reset(mAm);
        mSnoozeHelper.repost(r.getKey(), UserHandle.USER_SYSTEM);
        verify(mCallback, times(1)).repost(UserHandle.USER_SYSTEM, r);
        mSnoozeHelper.repost(r.getKey(), UserHandle.USER_SYSTEM, false);
        verify(mCallback, times(1)).repost(UserHandle.USER_SYSTEM, r, false);
        ArgumentCaptor<PendingIntent> captor = ArgumentCaptor.forClass(PendingIntent.class);
        verify(mAm).cancel(captor.capture());
        assertEquals(r.getKey(), captor.getValue().getIntent().getStringExtra(EXTRA_KEY));
@@ -388,8 +389,8 @@ public class SnoozeHelperTest extends UiServiceTestCase {
        NotificationRecord r2 = getNotificationRecord("pkg", 2, "one", UserHandle.ALL);
        mSnoozeHelper.snooze(r2, 1000);
        reset(mAm);
        mSnoozeHelper.repost(r.getKey());
        verify(mCallback, times(1)).repost(UserHandle.USER_SYSTEM, r);
        mSnoozeHelper.repost(r.getKey(), false);
        verify(mCallback, times(1)).repost(UserHandle.USER_SYSTEM, r, false);
        verify(mAm).cancel(any(PendingIntent.class));
    }

@@ -400,10 +401,10 @@ public class SnoozeHelperTest extends UiServiceTestCase {
        r.getNotification().category = "NEW CATEGORY";

        mSnoozeHelper.update(UserHandle.USER_SYSTEM, r);
        verify(mCallback, never()).repost(anyInt(), any(NotificationRecord.class));
        verify(mCallback, never()).repost(anyInt(), any(NotificationRecord.class), anyBoolean());

        mSnoozeHelper.repost(r.getKey(), UserHandle.USER_SYSTEM);
        verify(mCallback, times(1)).repost(UserHandle.USER_SYSTEM, r);
        mSnoozeHelper.repost(r.getKey(), UserHandle.USER_SYSTEM, false);
        verify(mCallback, times(1)).repost(UserHandle.USER_SYSTEM, r, false);
    }

    @Test
@@ -420,12 +421,22 @@ public class SnoozeHelperTest extends UiServiceTestCase {
        mSnoozeHelper.update(UserHandle.USER_SYSTEM, r);

        // verify callback is called when repost (snooze is expired)
        verify(mCallback, never()).repost(anyInt(), any(NotificationRecord.class));
        mSnoozeHelper.repost(r.getKey(), UserHandle.USER_SYSTEM);
        verify(mCallback, times(1)).repost(UserHandle.USER_SYSTEM, r);
        verify(mCallback, never()).repost(anyInt(), any(NotificationRecord.class), anyBoolean());
        mSnoozeHelper.repost(r.getKey(), UserHandle.USER_SYSTEM, false);
        verify(mCallback, times(1)).repost(UserHandle.USER_SYSTEM, r, false);
        assertFalse(r.isCanceled);
    }

    @Test
    public void testReport_passesFlag() throws Exception {
        // snooze a notification
        NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
        mSnoozeHelper.snooze(r , 1000);

        mSnoozeHelper.repost(r.getKey(), UserHandle.USER_SYSTEM, true);
        verify(mCallback, times(1)).repost(UserHandle.USER_SYSTEM, r, true);
    }

    @Test
    public void testGetSnoozedBy() throws Exception {
        NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
@@ -523,7 +534,7 @@ public class SnoozeHelperTest extends UiServiceTestCase {
        mSnoozeHelper.snooze(r2, 1000);
        mSnoozeHelper.repostGroupSummary("pkg", UserHandle.USER_SYSTEM, "group1");

        verify(mCallback, never()).repost(UserHandle.USER_SYSTEM, r);
        verify(mCallback, never()).repost(eq(UserHandle.USER_SYSTEM), eq(r), anyBoolean());
    }

    @Test
@@ -542,8 +553,8 @@ public class SnoozeHelperTest extends UiServiceTestCase {

        mSnoozeHelper.repostGroupSummary("pkg", UserHandle.USER_SYSTEM, r.getGroupKey());

        verify(mCallback, times(1)).repost(UserHandle.USER_SYSTEM, r);
        verify(mCallback, never()).repost(UserHandle.USER_SYSTEM, r2);
        verify(mCallback, times(1)).repost(UserHandle.USER_SYSTEM, r, false);
        verify(mCallback, never()).repost(UserHandle.USER_SYSTEM, r2, false);

        assertEquals(1, mSnoozeHelper.getSnoozed().size());
        assertEquals(1, mSnoozeHelper.getSnoozed(UserHandle.USER_SYSTEM, "pkg").size());