Silence notifications that are manually unsnoozed

Test: atest
Bug: 149486431
Change-Id: I7d11859210f6000120b2c51dc33da3d0928fb22e
This commit is contained in:
Julia Reynolds
2020-02-27 09:11:25 -05:00
parent ccf72664db
commit 6503162db1
5 changed files with 83 additions and 38 deletions

View File

@@ -2068,19 +2068,16 @@ 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) {
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);
} catch (Exception e) {
Slog.e(TAG, "Cannot un-snooze notification", e);
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, true);
} catch (Exception e) {
Slog.e(TAG, "Cannot un-snooze notification", e);
}
}, mUserProfiles);
@@ -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();
}

View File

@@ -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;

View File

@@ -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);
}
}
};

View File

@@ -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);

View File

@@ -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());