When a profile is stopped, remove pending snoozes
To be consistent with the way that non-snoozed notifications
are canceled.
Also, simplify the data structures in SnoozeHelper.
Test: SnoozeHelperTest
Fixes: 211157091
Change-Id: I0cd8b0f406290a7886f4d60309ef3ba626af3726
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 5787efb..9486a45 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1794,6 +1794,7 @@
if (userHandle >= 0) {
cancelAllNotificationsInt(MY_UID, MY_PID, null, null, 0, 0, true, userHandle,
REASON_PROFILE_TURNED_OFF, null);
+ mSnoozeHelper.clearData(userHandle);
}
} else if (action.equals(Intent.ACTION_USER_PRESENT)) {
// turn off LED when user passes through lock screen
diff --git a/services/core/java/com/android/server/notification/SnoozeHelper.java b/services/core/java/com/android/server/notification/SnoozeHelper.java
index 15d7c1e..61936df 100644
--- a/services/core/java/com/android/server/notification/SnoozeHelper.java
+++ b/services/core/java/com/android/server/notification/SnoozeHelper.java
@@ -16,7 +16,6 @@
package com.android.server.notification;
import android.annotation.NonNull;
-import android.annotation.UserIdInt;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.BroadcastReceiver;
@@ -25,7 +24,6 @@
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Binder;
-import android.os.SystemClock;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.util.ArrayMap;
@@ -38,18 +36,15 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.nano.MetricsProto;
-import com.android.internal.util.XmlUtils;
import com.android.server.pm.PackageManagerService;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;
@@ -59,7 +54,7 @@
/**
* NotificationManagerService helper for handling snoozed notifications.
*/
-public class SnoozeHelper {
+public final class SnoozeHelper {
public static final int XML_SNOOZED_NOTIFICATION_VERSION = 1;
static final int CONCURRENT_SNOOZE_LIMIT = 500;
@@ -68,8 +63,6 @@
private static final String XML_SNOOZED_NOTIFICATION = "notification";
private static final String XML_SNOOZED_NOTIFICATION_CONTEXT = "context";
- private static final String XML_SNOOZED_NOTIFICATION_PKG = "pkg";
- private static final String XML_SNOOZED_NOTIFICATION_USER_ID = "user-id";
private static final String XML_SNOOZED_NOTIFICATION_KEY = "key";
//the time the snoozed notification should be reposted
private static final String XML_SNOOZED_NOTIFICATION_TIME = "time";
@@ -91,24 +84,19 @@
private AlarmManager mAm;
private final ManagedServices.UserProfiles mUserProfiles;
- // User id | package name : notification key : record.
- private ArrayMap<String, ArrayMap<String, NotificationRecord>>
- mSnoozedNotifications = new ArrayMap<>();
- // User id | package name : notification key : time-milliseconds .
+ // notification key : record.
+ private ArrayMap<String, NotificationRecord> mSnoozedNotifications = new ArrayMap<>();
+ // notification key : time-milliseconds .
// This member stores persisted snoozed notification trigger times. it persists through reboots
// It should have the notifications that haven't expired or re-posted yet
- private final ArrayMap<String, ArrayMap<String, Long>>
- mPersistedSnoozedNotifications = new ArrayMap<>();
- // User id | package name : notification key : creation ID .
+ private final ArrayMap<String, Long> mPersistedSnoozedNotifications = new ArrayMap<>();
+ // notification key : creation ID.
// This member stores persisted snoozed notification trigger context for the assistant
// it persists through reboots.
// It should have the notifications that haven't expired or re-posted yet
- private final ArrayMap<String, ArrayMap<String, String>>
+ private final ArrayMap<String, String>
mPersistedSnoozedNotificationsWithContext = new ArrayMap<>();
- // notification key : package.
- private ArrayMap<String, String> mPackages = new ArrayMap<>();
- // key : userId
- private ArrayMap<String, Integer> mUsers = new ArrayMap<>();
+
private Callback mCallback;
private final Object mLock = new Object();
@@ -125,21 +113,9 @@
mUserProfiles = userProfiles;
}
- private String getPkgKey(@UserIdInt int userId, String pkg) {
- return userId + "|" + pkg;
- }
-
- void cleanupPersistedContext(String key){
- synchronized (mLock) {
- int userId = mUsers.get(key);
- String pkg = mPackages.get(key);
- removeRecordLocked(pkg, key, userId, mPersistedSnoozedNotificationsWithContext);
- }
- }
-
protected boolean canSnooze(int numberToSnooze) {
synchronized (mLock) {
- if ((mPackages.size() + numberToSnooze) > CONCURRENT_SNOOZE_LIMIT) {
+ if ((mSnoozedNotifications.size() + numberToSnooze) > CONCURRENT_SNOOZE_LIMIT) {
return false;
}
}
@@ -150,11 +126,7 @@
protected Long getSnoozeTimeForUnpostedNotification(int userId, String pkg, String key) {
Long time = null;
synchronized (mLock) {
- ArrayMap<String, Long> snoozed =
- mPersistedSnoozedNotifications.get(getPkgKey(userId, pkg));
- if (snoozed != null) {
- time = snoozed.get(key);
- }
+ time = mPersistedSnoozedNotifications.get(key);
}
if (time == null) {
time = 0L;
@@ -164,29 +136,26 @@
protected String getSnoozeContextForUnpostedNotification(int userId, String pkg, String key) {
synchronized (mLock) {
- ArrayMap<String, String> snoozed =
- mPersistedSnoozedNotificationsWithContext.get(getPkgKey(userId, pkg));
- if (snoozed != null) {
- return snoozed.get(key);
- }
+ return mPersistedSnoozedNotificationsWithContext.get(key);
}
- return null;
}
protected boolean isSnoozed(int userId, String pkg, String key) {
synchronized (mLock) {
- return mSnoozedNotifications.containsKey(getPkgKey(userId, pkg))
- && mSnoozedNotifications.get(getPkgKey(userId, pkg)).containsKey(key);
+ return mSnoozedNotifications.containsKey(key);
}
}
protected Collection<NotificationRecord> getSnoozed(int userId, String pkg) {
synchronized (mLock) {
- if (mSnoozedNotifications.containsKey(getPkgKey(userId, pkg))) {
- return mSnoozedNotifications.get(getPkgKey(userId, pkg)).values();
+ ArrayList snoozed = new ArrayList();
+ for (NotificationRecord r : mSnoozedNotifications.values()) {
+ if (r.getUserId() == userId && r.getSbn().getPackageName().equals(pkg)) {
+ snoozed.add(r);
+ }
}
+ return snoozed;
}
- return Collections.EMPTY_LIST;
}
@NonNull
@@ -194,15 +163,11 @@
String groupKey, Integer userId) {
ArrayList<NotificationRecord> records = new ArrayList<>();
synchronized (mLock) {
- ArrayMap<String, NotificationRecord> allRecords =
- mSnoozedNotifications.get(getPkgKey(userId, pkg));
- if (allRecords != null) {
- for (int i = 0; i < allRecords.size(); i++) {
- NotificationRecord r = allRecords.valueAt(i);
- String currentGroupKey = r.getSbn().getGroup();
- if (Objects.equals(currentGroupKey, groupKey)) {
- records.add(r);
- }
+ for (int i = 0; i < mSnoozedNotifications.size(); i++) {
+ NotificationRecord r = mSnoozedNotifications.valueAt(i);
+ if (r.getSbn().getPackageName().equals(pkg) && r.getUserId() == userId
+ && Objects.equals(r.getSbn().getGroup(), groupKey)) {
+ records.add(r);
}
}
}
@@ -211,31 +176,16 @@
protected NotificationRecord getNotification(String key) {
synchronized (mLock) {
- if (!mUsers.containsKey(key) || !mPackages.containsKey(key)) {
- Slog.w(TAG, "Snoozed data sets no longer agree for " + key);
- return null;
- }
- int userId = mUsers.get(key);
- String pkg = mPackages.get(key);
- ArrayMap<String, NotificationRecord> snoozed =
- mSnoozedNotifications.get(getPkgKey(userId, pkg));
- if (snoozed == null) {
- return null;
- }
- return snoozed.get(key);
+ return mSnoozedNotifications.get(key);
}
}
protected @NonNull List<NotificationRecord> getSnoozed() {
synchronized (mLock) {
- // caller filters records based on the current user profiles and listener access, so just
- // return everything
+ // caller filters records based on the current user profiles and listener access,
+ // so just return everything
List<NotificationRecord> snoozed = new ArrayList<>();
- for (String userPkgKey : mSnoozedNotifications.keySet()) {
- ArrayMap<String, NotificationRecord> snoozedRecords =
- mSnoozedNotifications.get(userPkgKey);
- snoozed.addAll(snoozedRecords.values());
- }
+ snoozed.addAll(mSnoozedNotifications.values());
return snoozed;
}
}
@@ -244,15 +194,13 @@
* Snoozes a notification and schedules an alarm to repost at that time.
*/
protected void snooze(NotificationRecord record, long duration) {
- String pkg = record.getSbn().getPackageName();
String key = record.getKey();
- int userId = record.getUser().getIdentifier();
snooze(record);
- scheduleRepost(pkg, key, userId, duration);
+ scheduleRepost(key, duration);
Long activateAt = System.currentTimeMillis() + duration;
synchronized (mLock) {
- storeRecordLocked(pkg, key, userId, mPersistedSnoozedNotifications, activateAt);
+ mPersistedSnoozedNotifications.put(key, activateAt);
}
}
@@ -260,66 +208,33 @@
* Records a snoozed notification.
*/
protected void snooze(NotificationRecord record, String contextId) {
- int userId = record.getUser().getIdentifier();
if (contextId != null) {
synchronized (mLock) {
- storeRecordLocked(record.getSbn().getPackageName(), record.getKey(),
- userId, mPersistedSnoozedNotificationsWithContext, contextId);
+ mPersistedSnoozedNotificationsWithContext.put(record.getKey(), contextId);
}
}
snooze(record);
}
private void snooze(NotificationRecord record) {
- int userId = record.getUser().getIdentifier();
if (DEBUG) {
Slog.d(TAG, "Snoozing " + record.getKey());
}
synchronized (mLock) {
- storeRecordLocked(record.getSbn().getPackageName(), record.getKey(),
- userId, mSnoozedNotifications, record);
+ mSnoozedNotifications.put(record.getKey(), record);
}
}
- private <T> void storeRecordLocked(String pkg, String key, Integer userId,
- ArrayMap<String, ArrayMap<String, T>> targets, T object) {
-
- mPackages.put(key, pkg);
- mUsers.put(key, userId);
- ArrayMap<String, T> keyToValue = targets.get(getPkgKey(userId, pkg));
- if (keyToValue == null) {
- keyToValue = new ArrayMap<>();
- }
- keyToValue.put(key, object);
- targets.put(getPkgKey(userId, pkg), keyToValue);
- }
-
- private <T> T removeRecordLocked(String pkg, String key, Integer userId,
- ArrayMap<String, ArrayMap<String, T>> targets) {
- T object = null;
- ArrayMap<String, T> keyToValue = targets.get(getPkgKey(userId, pkg));
- if (keyToValue == null) {
- return null;
- }
- object = keyToValue.remove(key);
- if (keyToValue.size() == 0) {
- targets.remove(getPkgKey(userId, pkg));
- }
- return object;
- }
-
protected boolean cancel(int userId, String pkg, String tag, int id) {
synchronized (mLock) {
- ArrayMap<String, NotificationRecord> recordsForPkg =
- mSnoozedNotifications.get(getPkgKey(userId, pkg));
- if (recordsForPkg != null) {
- final Set<Map.Entry<String, NotificationRecord>> records = recordsForPkg.entrySet();
- for (Map.Entry<String, NotificationRecord> record : records) {
- final StatusBarNotification sbn = record.getValue().getSbn();
- if (Objects.equals(sbn.getTag(), tag) && sbn.getId() == id) {
- record.getValue().isCanceled = true;
- return true;
- }
+ final Set<Map.Entry<String, NotificationRecord>> records =
+ mSnoozedNotifications.entrySet();
+ for (Map.Entry<String, NotificationRecord> record : records) {
+ final StatusBarNotification sbn = record.getValue().getSbn();
+ if (sbn.getPackageName().equals(pkg) && sbn.getUserId() == userId
+ && Objects.equals(sbn.getTag(), tag) && sbn.getId() == id) {
+ record.getValue().isCanceled = true;
+ return true;
}
}
}
@@ -336,11 +251,9 @@
if (includeCurrentProfiles) {
userIds = mUserProfiles.getCurrentProfileIds();
}
- for (ArrayMap<String, NotificationRecord> snoozedRecords : mSnoozedNotifications.values()) {
- for (NotificationRecord r : snoozedRecords.values()) {
- if (userIds.binarySearch(r.getUserId()) >= 0) {
- r.isCanceled = true;
- }
+ for (NotificationRecord r : mSnoozedNotifications.values()) {
+ if (userIds.binarySearch(r.getUserId()) >= 0) {
+ r.isCanceled = true;
}
}
}
@@ -348,14 +261,12 @@
protected boolean cancel(int userId, String pkg) {
synchronized (mLock) {
- ArrayMap<String, NotificationRecord> records =
- mSnoozedNotifications.get(getPkgKey(userId, pkg));
- if (records == null) {
- return false;
- }
- int N = records.size();
- for (int i = 0; i < N; i++) {
- records.valueAt(i).isCanceled = true;
+ int n = mSnoozedNotifications.size();
+ for (int i = 0; i < n; i++) {
+ final NotificationRecord r = mSnoozedNotifications.valueAt(i);
+ if (r.getSbn().getPackageName().equals(pkg) && r.getUserId() == userId) {
+ r.isCanceled = true;
+ }
}
return true;
}
@@ -366,20 +277,17 @@
*/
protected void update(int userId, NotificationRecord record) {
synchronized (mLock) {
- ArrayMap<String, NotificationRecord> records =
- mSnoozedNotifications.get(getPkgKey(userId, record.getSbn().getPackageName()));
- if (records == null) {
- return;
+ if (mSnoozedNotifications.containsKey(record.getKey())) {
+ mSnoozedNotifications.put(record.getKey(), record);
}
- records.put(record.getKey(), record);
}
}
protected void repost(String key, boolean muteOnReturn) {
synchronized (mLock) {
- Integer userId = mUsers.get(key);
- if (userId != null) {
- repost(key, userId, muteOnReturn);
+ final NotificationRecord r = mSnoozedNotifications.get(key);
+ if (r != null) {
+ repost(key, r.getUserId(), muteOnReturn);
}
}
}
@@ -387,43 +295,30 @@
protected void repost(String key, int userId, boolean muteOnReturn) {
NotificationRecord record;
synchronized (mLock) {
- final String pkg = mPackages.remove(key);
- mUsers.remove(key);
- removeRecordLocked(pkg, key, userId, mPersistedSnoozedNotifications);
- removeRecordLocked(pkg, key, userId, mPersistedSnoozedNotificationsWithContext);
- ArrayMap<String, NotificationRecord> records =
- mSnoozedNotifications.get(getPkgKey(userId, pkg));
- if (records == null) {
- return;
- }
- record = records.remove(key);
-
+ mPersistedSnoozedNotifications.remove(key);
+ mPersistedSnoozedNotificationsWithContext.remove(key);
+ record = mSnoozedNotifications.remove(key);
}
if (record != null && !record.isCanceled) {
- final PendingIntent pi = createPendingIntent(
- record.getSbn().getPackageName(), record.getKey(), userId);
+ final PendingIntent pi = createPendingIntent(record.getKey());
mAm.cancel(pi);
MetricsLogger.action(record.getLogMaker()
.setCategory(MetricsProto.MetricsEvent.NOTIFICATION_SNOOZED)
.setType(MetricsProto.MetricsEvent.TYPE_OPEN));
- mCallback.repost(userId, record, muteOnReturn);
+ mCallback.repost(record.getUserId(), record, muteOnReturn);
}
}
protected void repostGroupSummary(String pkg, int userId, String groupKey) {
synchronized (mLock) {
- ArrayMap<String, NotificationRecord> recordsByKey
- = mSnoozedNotifications.get(getPkgKey(userId, pkg));
- if (recordsByKey == null) {
- return;
- }
-
String groupSummaryKey = null;
- int N = recordsByKey.size();
- for (int i = 0; i < N; i++) {
- final NotificationRecord potentialGroupSummary = recordsByKey.valueAt(i);
- if (potentialGroupSummary.getSbn().isGroup()
+ int n = mSnoozedNotifications.size();
+ for (int i = 0; i < n; i++) {
+ final NotificationRecord potentialGroupSummary = mSnoozedNotifications.valueAt(i);
+ if (potentialGroupSummary.getSbn().getPackageName().equals(pkg)
+ && potentialGroupSummary.getUserId() == userId
+ && potentialGroupSummary.getSbn().isGroup()
&& potentialGroupSummary.getNotification().isGroupSummary()
&& groupKey.equals(potentialGroupSummary.getGroupKey())) {
groupSummaryKey = potentialGroupSummary.getKey();
@@ -432,16 +327,14 @@
}
if (groupSummaryKey != null) {
- NotificationRecord record = recordsByKey.remove(groupSummaryKey);
- mPackages.remove(groupSummaryKey);
- mUsers.remove(groupSummaryKey);
+ NotificationRecord record = mSnoozedNotifications.remove(groupSummaryKey);
if (record != null && !record.isCanceled) {
Runnable runnable = () -> {
MetricsLogger.action(record.getLogMaker()
.setCategory(MetricsProto.MetricsEvent.NOTIFICATION_SNOOZED)
.setType(MetricsProto.MetricsEvent.TYPE_OPEN));
- mCallback.repost(userId, record, false);
+ mCallback.repost(record.getUserId(), record, false);
};
runnable.run();
}
@@ -451,20 +344,17 @@
protected void clearData(int userId, String pkg) {
synchronized (mLock) {
- ArrayMap<String, NotificationRecord> records =
- mSnoozedNotifications.get(getPkgKey(userId, pkg));
- if (records == null) {
- return;
- }
- for (int i = records.size() - 1; i >= 0; i--) {
- final NotificationRecord r = records.removeAt(i);
- if (r != null) {
- mPackages.remove(r.getKey());
- mUsers.remove(r.getKey());
+ int n = mSnoozedNotifications.size();
+ for (int i = n - 1; i >= 0; i--) {
+ final NotificationRecord record = mSnoozedNotifications.valueAt(i);
+ if (record.getUserId() == userId && record.getSbn().getPackageName().equals(pkg)) {
+ mSnoozedNotifications.removeAt(i);
+ mPersistedSnoozedNotificationsWithContext.remove(record.getKey());
+ mPersistedSnoozedNotifications.remove(record.getKey());
Runnable runnable = () -> {
- final PendingIntent pi = createPendingIntent(pkg, r.getKey(), userId);
+ final PendingIntent pi = createPendingIntent(record.getKey());
mAm.cancel(pi);
- MetricsLogger.action(r.getLogMaker()
+ MetricsLogger.action(record.getLogMaker()
.setCategory(MetricsProto.MetricsEvent.NOTIFICATION_SNOOZED)
.setType(MetricsProto.MetricsEvent.TYPE_DISMISS));
};
@@ -474,47 +364,61 @@
}
}
- private PendingIntent createPendingIntent(String pkg, String key, int userId) {
+ protected void clearData(int userId) {
+ synchronized (mLock) {
+ int n = mSnoozedNotifications.size();
+ for (int i = n - 1; i >= 0; i--) {
+ final NotificationRecord record = mSnoozedNotifications.valueAt(i);
+ if (record.getUserId() == userId) {
+ mSnoozedNotifications.removeAt(i);
+ mPersistedSnoozedNotificationsWithContext.remove(record.getKey());
+ mPersistedSnoozedNotifications.remove(record.getKey());
+
+ Runnable runnable = () -> {
+ final PendingIntent pi = createPendingIntent(record.getKey());
+ mAm.cancel(pi);
+ MetricsLogger.action(record.getLogMaker()
+ .setCategory(MetricsProto.MetricsEvent.NOTIFICATION_SNOOZED)
+ .setType(MetricsProto.MetricsEvent.TYPE_DISMISS));
+ };
+ runnable.run();
+ }
+ }
+ }
+ }
+
+ private PendingIntent createPendingIntent(String key) {
return PendingIntent.getBroadcast(mContext,
REQUEST_CODE_REPOST,
new Intent(REPOST_ACTION)
.setPackage(PackageManagerService.PLATFORM_PACKAGE_NAME)
.setData(new Uri.Builder().scheme(REPOST_SCHEME).appendPath(key).build())
.addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
- .putExtra(EXTRA_KEY, key)
- .putExtra(EXTRA_USER_ID, userId),
+ .putExtra(EXTRA_KEY, key),
PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE);
}
public void scheduleRepostsForPersistedNotifications(long currentTime) {
synchronized (mLock) {
- for (ArrayMap<String, Long> snoozed : mPersistedSnoozedNotifications.values()) {
- for (int i = 0; i < snoozed.size(); i++) {
- String key = snoozed.keyAt(i);
- Long time = snoozed.valueAt(i);
- String pkg = mPackages.get(key);
- Integer userId = mUsers.get(key);
- if (time == null || pkg == null || userId == null) {
- Slog.w(TAG, "data out of sync: " + time + "|" + pkg + "|" + userId);
- continue;
- }
- if (time != null && time > currentTime) {
- scheduleRepostAtTime(pkg, key, userId, time);
- }
+ for (int i = 0; i < mPersistedSnoozedNotifications.size(); i++) {
+ String key = mPersistedSnoozedNotifications.keyAt(i);
+ Long time = mPersistedSnoozedNotifications.valueAt(i);
+ if (time != null && time > currentTime) {
+ scheduleRepostAtTime(key, time);
}
}
}
}
- private void scheduleRepost(String pkg, String key, int userId, long duration) {
- scheduleRepostAtTime(pkg, key, userId, System.currentTimeMillis() + duration);
+ private void scheduleRepost(String key, long duration) {
+ scheduleRepostAtTime(key, System.currentTimeMillis() + duration);
}
- private void scheduleRepostAtTime(String pkg, String key, int userId, long time) {
+ private void scheduleRepostAtTime(String key, long time) {
Runnable runnable = () -> {
final long identity = Binder.clearCallingIdentity();
try {
- final PendingIntent pi = createPendingIntent(pkg, key, userId);
+ final PendingIntent pi = createPendingIntent(key);
mAm.cancel(pi);
if (DEBUG) Slog.d(TAG, "Scheduling evaluate for " + new Date(time));
mAm.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, time, pi);
@@ -528,37 +432,14 @@
public void dump(PrintWriter pw, NotificationManagerService.DumpFilter filter) {
synchronized (mLock) {
pw.println("\n Snoozed notifications:");
- for (String userPkgKey : mSnoozedNotifications.keySet()) {
+ for (String key : mSnoozedNotifications.keySet()) {
pw.print(INDENT);
- pw.println("key: " + userPkgKey);
- ArrayMap<String, NotificationRecord> snoozedRecords =
- mSnoozedNotifications.get(userPkgKey);
- Set<String> snoozedKeys = snoozedRecords.keySet();
- for (String key : snoozedKeys) {
- pw.print(INDENT);
- pw.print(INDENT);
- pw.print(INDENT);
- pw.println(key);
- }
+ pw.println("key: " + key);
}
pw.println("\n Pending snoozed notifications");
- for (String userPkgKey : mPersistedSnoozedNotifications.keySet()) {
+ for (String key : mPersistedSnoozedNotifications.keySet()) {
pw.print(INDENT);
- pw.println("key: " + userPkgKey);
- ArrayMap<String, Long> snoozedRecords =
- mPersistedSnoozedNotifications.get(userPkgKey);
- if (snoozedRecords == null) {
- continue;
- }
- Set<String> snoozedKeys = snoozedRecords.keySet();
- for (String key : snoozedKeys) {
- pw.print(INDENT);
- pw.print(INDENT);
- pw.print(INDENT);
- pw.print(key);
- pw.print(INDENT);
- pw.println(snoozedRecords.get(key));
- }
+ pw.println("key: " + key + " until: " + mPersistedSnoozedNotifications.get(key));
}
}
}
@@ -589,37 +470,22 @@
void insert(T t) throws IOException;
}
- private <T> void writeXml(TypedXmlSerializer out,
- ArrayMap<String, ArrayMap<String, T>> targets, String tag,
- Inserter<T> attributeInserter)
- throws IOException {
- final int M = targets.size();
- for (int i = 0; i < M; i++) {
+ private <T> void writeXml(TypedXmlSerializer out, ArrayMap<String, T> targets, String tag,
+ Inserter<T> attributeInserter) throws IOException {
+ for (int j = 0; j < targets.size(); j++) {
+ String key = targets.keyAt(j);
// T is a String (snoozed until context) or Long (snoozed until time)
- ArrayMap<String, T> keyToValue = targets.valueAt(i);
- for (int j = 0; j < keyToValue.size(); j++) {
- String key = keyToValue.keyAt(j);
- T value = keyToValue.valueAt(j);
- String pkg = mPackages.get(key);
- Integer userId = mUsers.get(key);
+ T value = targets.valueAt(j);
- if (pkg == null || userId == null) {
- Slog.w(TAG, "pkg " + pkg + " or user " + userId + " missing for " + key);
- continue;
- }
+ out.startTag(null, tag);
- out.startTag(null, tag);
+ attributeInserter.insert(value);
- attributeInserter.insert(value);
+ out.attributeInt(null, XML_SNOOZED_NOTIFICATION_VERSION_LABEL,
+ XML_SNOOZED_NOTIFICATION_VERSION);
+ out.attribute(null, XML_SNOOZED_NOTIFICATION_KEY, key);
- out.attributeInt(null, XML_SNOOZED_NOTIFICATION_VERSION_LABEL,
- XML_SNOOZED_NOTIFICATION_VERSION);
- out.attribute(null, XML_SNOOZED_NOTIFICATION_KEY, key);
- out.attribute(null, XML_SNOOZED_NOTIFICATION_PKG, pkg);
- out.attributeInt(null, XML_SNOOZED_NOTIFICATION_USER_ID, userId);
-
- out.endTag(null, tag);
- }
+ out.endTag(null, tag);
}
}
@@ -639,16 +505,12 @@
== XML_SNOOZED_NOTIFICATION_VERSION) {
try {
final String key = parser.getAttributeValue(null, XML_SNOOZED_NOTIFICATION_KEY);
- final String pkg = parser.getAttributeValue(null, XML_SNOOZED_NOTIFICATION_PKG);
- final int userId = parser.getAttributeInt(
- null, XML_SNOOZED_NOTIFICATION_USER_ID, UserHandle.USER_ALL);
if (tag.equals(XML_SNOOZED_NOTIFICATION)) {
final Long time = parser.getAttributeLong(
null, XML_SNOOZED_NOTIFICATION_TIME, 0);
if (time > currentTime) { //only read new stuff
synchronized (mLock) {
- storeRecordLocked(
- pkg, key, userId, mPersistedSnoozedNotifications, time);
+ mPersistedSnoozedNotifications.put(key, time);
}
}
}
@@ -656,9 +518,7 @@
final String creationId = parser.getAttributeValue(
null, XML_SNOOZED_NOTIFICATION_CONTEXT_ID);
synchronized (mLock) {
- storeRecordLocked(
- pkg, key, userId, mPersistedSnoozedNotificationsWithContext,
- creationId);
+ mPersistedSnoozedNotificationsWithContext.put(key, creationId);
}
}
} catch (Exception e) {
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java b/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java
index 8bead57..7817e81 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java
@@ -20,6 +20,7 @@
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
@@ -39,7 +40,6 @@
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
-import android.os.SystemClock;
import android.os.UserHandle;
import android.service.notification.StatusBarNotification;
import android.test.suitebuilder.annotation.SmallTest;
@@ -50,7 +50,6 @@
import androidx.test.runner.AndroidJUnit4;
-import com.android.internal.util.FastXmlSerializer;
import com.android.server.UiServiceTestCase;
import com.android.server.pm.PackageManagerService;
@@ -60,9 +59,7 @@
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
-import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
-import org.xmlpull.v1.XmlSerializer;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
@@ -198,18 +195,6 @@
}
@Test
- public void testCleanupContextShouldRemovePersistedRecord() {
- NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
- mSnoozeHelper.snooze(r, "context");
- mSnoozeHelper.cleanupPersistedContext(r.getSbn().getKey());
- assertNull(mSnoozeHelper.getSnoozeContextForUnpostedNotification(
- r.getUser().getIdentifier(),
- r.getSbn().getPackageName(),
- r.getSbn().getKey()
- ));
- }
-
- @Test
public void testReadNoneSnoozedNotification() throws XmlPullParserException,
IOException, InterruptedException {
NotificationRecord r = getNotificationRecord(
@@ -219,8 +204,9 @@
assertEquals("should see a zero value for unsnoozed notification",
0L,
mSnoozeHelper.getSnoozeTimeForUnpostedNotification(
- UserHandle.SYSTEM.getIdentifier(),
- "not_my_package", r.getKey()).longValue());
+ UserHandle.SYSTEM.getIdentifier(), "not_my_package",
+ getNotificationRecord("not_my_package", 1, "one",
+ UserHandle.SYSTEM).getKey()).longValue());
}
@Test
@@ -592,7 +578,7 @@
}
@Test
- public void testClearData() {
+ public void testClearData_userPackage() {
// snooze 2 from same package
NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
NotificationRecord r2 = getNotificationRecord("pkg", 2, "two", UserHandle.SYSTEM);
@@ -616,17 +602,72 @@
}
@Test
+ public void testClearData_user() {
+ // snooze 2 from same package
+ NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
+ NotificationRecord r2 = getNotificationRecord("pkg2", 2, "two", UserHandle.SYSTEM);
+ NotificationRecord r3 = getNotificationRecord("pkg2", 3, "three", UserHandle.SYSTEM);
+ NotificationRecord r4 = getNotificationRecord("pkg", 2, "two", UserHandle.ALL);
+ mSnoozeHelper.snooze(r, 1000);
+ mSnoozeHelper.snooze(r2, 1000);
+ mSnoozeHelper.snooze(r3, "until");
+ mSnoozeHelper.snooze(r4, "until");
+
+ assertTrue(mSnoozeHelper.isSnoozed(
+ UserHandle.USER_SYSTEM, r.getSbn().getPackageName(), r.getKey()));
+ assertTrue(mSnoozeHelper.isSnoozed(
+ UserHandle.USER_SYSTEM, r2.getSbn().getPackageName(), r2.getKey()));
+ assertTrue(mSnoozeHelper.isSnoozed(
+ UserHandle.USER_SYSTEM, r3.getSbn().getPackageName(), r3.getKey()));
+ assertTrue(mSnoozeHelper.isSnoozed(
+ UserHandle.USER_ALL, r4.getSbn().getPackageName(), r4.getKey()));
+
+ // clear data
+ mSnoozeHelper.clearData(UserHandle.USER_SYSTEM);
+
+ // nothing in USER_SYSTEM snoozed; alarms canceled
+ assertFalse(mSnoozeHelper.isSnoozed(
+ UserHandle.USER_SYSTEM, r.getSbn().getPackageName(), r.getKey()));
+ assertFalse(mSnoozeHelper.isSnoozed(
+ UserHandle.USER_SYSTEM, r2.getSbn().getPackageName(), r2.getKey()));
+ assertFalse(mSnoozeHelper.isSnoozed(
+ UserHandle.USER_SYSTEM, r3.getSbn().getPackageName(), r3.getKey()));
+ assertTrue(mSnoozeHelper.isSnoozed(
+ UserHandle.USER_SYSTEM, r4.getSbn().getPackageName(), r4.getKey()));
+
+ assertNull(mSnoozeHelper.getSnoozeContextForUnpostedNotification(
+ r3.getUser().getIdentifier(), r3.getSbn().getPackageName(),
+ r3.getSbn().getKey()));
+ assertNotNull(mSnoozeHelper.getSnoozeContextForUnpostedNotification(
+ r4.getUser().getIdentifier(), r4.getSbn().getPackageName(),
+ r4.getSbn().getKey()));
+ assertEquals(0L, mSnoozeHelper.getSnoozeTimeForUnpostedNotification(
+ r.getUser().getIdentifier(), r.getSbn().getPackageName(),
+ r.getSbn().getKey()).longValue());
+ assertEquals(0L, mSnoozeHelper.getSnoozeTimeForUnpostedNotification(
+ r2.getUser().getIdentifier(), r2.getSbn().getPackageName(),
+ r2.getSbn().getKey()).longValue());
+
+ // 2 for initial timed-snoozes, once each for canceling the USER_SYSTEM snoozes
+ verify(mAm, times(5)).cancel(any(PendingIntent.class));
+ }
+
+ @Test
public void testClearData_otherRecordsUntouched() {
// 2 packages, 2 users
NotificationRecord r = getNotificationRecord("pkg", 1, "one", UserHandle.SYSTEM);
+ NotificationRecord rb = getNotificationRecord("pkg", 1, "oneb", UserHandle.SYSTEM);
NotificationRecord r2 = getNotificationRecord("pkg", 2, "two", UserHandle.ALL);
NotificationRecord r3 = getNotificationRecord("pkg2", 3, "three", UserHandle.SYSTEM);
mSnoozeHelper.snooze(r, 1000);
+ mSnoozeHelper.snooze(rb, "until");
mSnoozeHelper.snooze(r2, 1000);
mSnoozeHelper.snooze(r3, 1000);
assertTrue(mSnoozeHelper.isSnoozed(
UserHandle.USER_SYSTEM, r.getSbn().getPackageName(), r.getKey()));
assertTrue(mSnoozeHelper.isSnoozed(
+ UserHandle.USER_SYSTEM, rb.getSbn().getPackageName(), rb.getKey()));
+ assertTrue(mSnoozeHelper.isSnoozed(
UserHandle.USER_ALL, r2.getSbn().getPackageName(), r2.getKey()));
assertTrue(mSnoozeHelper.isSnoozed(
UserHandle.USER_SYSTEM, r3.getSbn().getPackageName(), r3.getKey()));
@@ -636,12 +677,22 @@
assertFalse(mSnoozeHelper.isSnoozed(
UserHandle.USER_SYSTEM, r.getSbn().getPackageName(), r.getKey()));
+ assertFalse(mSnoozeHelper.isSnoozed(
+ UserHandle.USER_SYSTEM, rb.getSbn().getPackageName(), rb.getKey()));
assertTrue(mSnoozeHelper.isSnoozed(
UserHandle.USER_ALL, r2.getSbn().getPackageName(), r2.getKey()));
assertTrue(mSnoozeHelper.isSnoozed(
UserHandle.USER_SYSTEM, r3.getSbn().getPackageName(), r3.getKey()));
+
+ assertNull(mSnoozeHelper.getSnoozeContextForUnpostedNotification(
+ rb.getUser().getIdentifier(), rb.getSbn().getPackageName(),
+ rb.getSbn().getKey()));
+ assertEquals(0L, mSnoozeHelper.getSnoozeTimeForUnpostedNotification(
+ r.getUser().getIdentifier(), r.getSbn().getPackageName(),
+ r.getSbn().getKey()).longValue());
+
// once for each initial snooze, once for canceling one snooze
- verify(mAm, times(4)).cancel(any(PendingIntent.class));
+ verify(mAm, times(5)).cancel(any(PendingIntent.class));
}
private NotificationRecord getNotificationRecord(String pkg, int id, String tag,