Merge "Ignore flaky test" into rvc-dev
diff --git a/apex/media/framework/java/android/media/MediaParser.java b/apex/media/framework/java/android/media/MediaParser.java
index 566f4cd..b721d87 100644
--- a/apex/media/framework/java/android/media/MediaParser.java
+++ b/apex/media/framework/java/android/media/MediaParser.java
@@ -700,30 +700,34 @@
         mDataSource.mInputReader = seekableInputReader;
 
         // TODO: Apply parameters when creating extractor instances.
-        if (mExtractorName != null) {
-            mExtractor = EXTRACTOR_FACTORIES_BY_NAME.get(mExtractorName).createInstance();
-        } else if (mExtractor == null) {
-            for (String parserName : mParserNamesPool) {
-                Extractor extractor = EXTRACTOR_FACTORIES_BY_NAME.get(parserName).createInstance();
-                try {
-                    if (extractor.sniff(mExtractorInput)) {
-                        mExtractorName = parserName;
-                        mExtractor = extractor;
-                        mExtractor.init(new ExtractorOutputAdapter());
-                        break;
+        if (mExtractor == null) {
+            if (mExtractorName != null) {
+                mExtractor = EXTRACTOR_FACTORIES_BY_NAME.get(mExtractorName).createInstance();
+                mExtractor.init(new ExtractorOutputAdapter());
+            } else {
+                for (String parserName : mParserNamesPool) {
+                    Extractor extractor =
+                            EXTRACTOR_FACTORIES_BY_NAME.get(parserName).createInstance();
+                    try {
+                        if (extractor.sniff(mExtractorInput)) {
+                            mExtractorName = parserName;
+                            mExtractor = extractor;
+                            mExtractor.init(new ExtractorOutputAdapter());
+                            break;
+                        }
+                    } catch (EOFException e) {
+                        // Do nothing.
+                    } catch (IOException | InterruptedException e) {
+                        throw new IllegalStateException(e);
+                    } finally {
+                        mExtractorInput.resetPeekPosition();
                     }
-                } catch (EOFException e) {
-                    // Do nothing.
-                } catch (IOException | InterruptedException e) {
-                    throw new IllegalStateException(e);
-                } finally {
-                    mExtractorInput.resetPeekPosition();
                 }
+                if (mExtractor == null) {
+                    throw UnrecognizedInputFormatException.createForExtractors(mParserNamesPool);
+                }
+                return true;
             }
-            if (mExtractor == null) {
-                throw UnrecognizedInputFormatException.createForExtractors(mParserNamesPool);
-            }
-            return true;
         }
 
         if (isPendingSeek()) {
diff --git a/cmds/statsd/src/atoms.proto b/cmds/statsd/src/atoms.proto
index b86dc35..e58e7bc 100644
--- a/cmds/statsd/src/atoms.proto
+++ b/cmds/statsd/src/atoms.proto
@@ -380,8 +380,8 @@
         BootTimeEventErrorCode boot_time_event_error_code_reported = 242 [(module) = "framework"];
         UserspaceRebootReported userspace_reboot_reported = 243 [(module) = "framework"];
         NotificationReported notification_reported = 244 [(module) = "framework"];
-        NotificationPanelReported notification_panel_reported = 245;
-        NotificationChannelModified notification_channel_modified = 246;
+        NotificationPanelReported notification_panel_reported = 245 [(module) = "sysui"];
+        NotificationChannelModified notification_channel_modified = 246 [(module) = "framework"];
         IntegrityCheckResultReported integrity_check_result_reported = 247 [(module) = "framework"];
         IntegrityRulesPushed integrity_rules_pushed = 248 [(module) = "framework"];
         CellBroadcastMessageReported cb_message_reported =
@@ -3637,8 +3637,8 @@
     // The notifying app's uid and package.
     optional int32 uid = 2 [(is_uid) = true];
     optional string package_name = 3;
-    // App-assigned notification channel ID or channel-group ID
-    optional string channel_id = 4;
+    // Hash of app-assigned notification channel ID or channel-group ID
+    optional int32 channel_id_hash = 4;
     // Previous importance setting, if applicable
     optional android.stats.sysui.NotificationImportance old_importance = 5;
     // New importance setting
diff --git a/graphics/java/android/graphics/fonts/Font.java b/graphics/java/android/graphics/fonts/Font.java
index 853165d..b09082e 100644
--- a/graphics/java/android/graphics/fonts/Font.java
+++ b/graphics/java/android/graphics/fonts/Font.java
@@ -19,6 +19,7 @@
 import android.annotation.IntRange;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.content.res.AssetFileDescriptor;
 import android.content.res.AssetManager;
 import android.content.res.Resources;
 import android.os.LocaleList;
@@ -219,6 +220,27 @@
             Preconditions.checkNotNull(am, "assetManager can not be null");
             Preconditions.checkNotNull(path, "path can not be null");
 
+            // Attempt to open as FD, which should work unless the asset is compressed
+            AssetFileDescriptor assetFD;
+            try {
+                if (isAsset) {
+                    assetFD = am.openFd(path);
+                } else if (cookie > 0) {
+                    assetFD = am.openNonAssetFd(cookie, path);
+                } else {
+                    assetFD = am.openNonAssetFd(path);
+                }
+
+                try (FileInputStream fis = assetFD.createInputStream()) {
+                    final FileChannel fc = fis.getChannel();
+                    long startOffset = assetFD.getStartOffset();
+                    long declaredLength = assetFD.getDeclaredLength();
+                    return fc.map(FileChannel.MapMode.READ_ONLY, startOffset, declaredLength);
+                }
+            } catch (IOException e) {
+                // failed to open as FD so now we will attempt to open as an input stream
+            }
+
             try (InputStream assetStream = isAsset ? am.open(path, AssetManager.ACCESS_BUFFER)
                     : am.openNonAsset(cookie, path, AssetManager.ACCESS_BUFFER)) {
 
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index 3afd5dc..7c770f4 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -551,7 +551,7 @@
                 super.onAnimationEnd(animation);
                 mScreenshotView.setScaleX(cornerScale);
                 mScreenshotView.setScaleY(cornerScale);
-                mScreenshotView.setX(finalPos.x - height * cornerScale / 2f);
+                mScreenshotView.setX(finalPos.x - width * cornerScale / 2f);
                 mScreenshotView.setY(finalPos.y - height * cornerScale / 2f);
                 Rect bounds = new Rect();
                 mScreenshotView.getBoundsOnScreen(bounds);
diff --git a/services/core/java/com/android/server/appop/AppOpsService.java b/services/core/java/com/android/server/appop/AppOpsService.java
index 5b8a6d9..c15360b 100644
--- a/services/core/java/com/android/server/appop/AppOpsService.java
+++ b/services/core/java/com/android/server/appop/AppOpsService.java
@@ -4060,9 +4060,11 @@
     private void readOp(XmlPullParser parser, @NonNull UidState uidState,
         @NonNull String pkgName, boolean isPrivileged) throws NumberFormatException,
         XmlPullParserException, IOException {
-        Op op = new Op(uidState, pkgName,
-                Integer.parseInt(parser.getAttributeValue(null, "n")),
-                uidState.uid);
+        int opCode = Integer.parseInt(parser.getAttributeValue(null, "n"));
+        if (isIgnoredAppOp(opCode)) {
+            return;
+        }
+        Op op = new Op(uidState, pkgName, opCode, uidState.uid);
 
         final int mode = XmlUtils.readIntAttribute(parser, "m",
                 AppOpsManager.opToDefaultMode(op.op));
@@ -4096,6 +4098,16 @@
         ops.put(op.op, op);
     }
 
+    //TODO(b/149995538): Remove once this has reached all affected devices
+    private static boolean isIgnoredAppOp(int op) {
+        switch (op) {
+            case AppOpsManager.OP_MANAGE_EXTERNAL_STORAGE:
+                return true;
+            default:
+                return false;
+        }
+    }
+
     void writeState() {
         synchronized (mFile) {
             FileOutputStream stream;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 7a777c1..e6fa610 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -2068,19 +2068,16 @@
 
     @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 @@
                 synchronized (mNotificationLock) {
                     final ManagedServiceInfo info =
                             mAssistants.checkServiceTokenLocked(token);
-                    unsnoozeNotificationInt(key, info);
+                    unsnoozeNotificationInt(key, info, false);
                 }
             } finally {
                 Binder.restoreCallingIdentity(identity);
@@ -4006,7 +4003,7 @@
                     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 @@
     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 @@
                 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 @@
             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,12 @@
         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();
     }
 
diff --git a/services/core/java/com/android/server/notification/NotificationRecord.java b/services/core/java/com/android/server/notification/NotificationRecord.java
index c07107f..3f24b38 100644
--- a/services/core/java/com/android/server/notification/NotificationRecord.java
+++ b/services/core/java/com/android/server/notification/NotificationRecord.java
@@ -187,6 +187,7 @@
     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 @@
         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;
diff --git a/services/core/java/com/android/server/notification/SnoozeHelper.java b/services/core/java/com/android/server/notification/SnoozeHelper.java
index d60c291..9a9e733 100644
--- a/services/core/java/com/android/server/notification/SnoozeHelper.java
+++ b/services/core/java/com/android/server/notification/SnoozeHelper.java
@@ -106,6 +106,8 @@
     private ArrayMap<String, Integer> mUsers = new ArrayMap<>();
     private Callback mCallback;
 
+    private final Object mLock = new Object();
+
     public SnoozeHelper(Context context, Callback callback,
             ManagedServices.UserProfiles userProfiles) {
         mContext = context;
@@ -122,41 +124,52 @@
     }
 
     void cleanupPersistedContext(String key){
-        int userId = mUsers.get(key);
-        String pkg = mPackages.get(key);
-        synchronized (mPersistedSnoozedNotificationsWithContext) {
-            removeRecord(pkg, key, userId, mPersistedSnoozedNotificationsWithContext);
+        synchronized (mLock) {
+            int userId = mUsers.get(key);
+            String pkg = mPackages.get(key);
+            removeRecordLocked(pkg, key, userId, mPersistedSnoozedNotificationsWithContext);
         }
     }
 
-    //This function has a side effect of removing the time from the list of persisted notifications.
-    //IT IS NOT IDEMPOTENT!
     @NonNull
     protected Long getSnoozeTimeForUnpostedNotification(int userId, String pkg, String key) {
-        Long time;
-        synchronized (mPersistedSnoozedNotifications) {
-            time = removeRecord(pkg, key, userId, mPersistedSnoozedNotifications);
+        Long time = null;
+        synchronized (mLock) {
+           ArrayMap<String, Long> snoozed =
+                   mPersistedSnoozedNotifications.get(getPkgKey(userId, pkg));
+           if (snoozed != null) {
+               time = snoozed.get(key);
+           }
         }
         if (time == null) {
-            return 0L;
+            time = 0L;
         }
         return time;
     }
 
     protected String getSnoozeContextForUnpostedNotification(int userId, String pkg, String key) {
-        synchronized (mPersistedSnoozedNotificationsWithContext) {
-            return removeRecord(pkg, key, userId, mPersistedSnoozedNotificationsWithContext);
+        synchronized (mLock) {
+            ArrayMap<String, String> snoozed =
+                    mPersistedSnoozedNotificationsWithContext.get(getPkgKey(userId, pkg));
+            if (snoozed != null) {
+                return snoozed.get(key);
+            }
         }
+        return null;
     }
 
     protected boolean isSnoozed(int userId, String pkg, String key) {
-        return mSnoozedNotifications.containsKey(getPkgKey(userId, pkg))
-                && mSnoozedNotifications.get(getPkgKey(userId, pkg)).containsKey(key);
+        synchronized (mLock) {
+            return mSnoozedNotifications.containsKey(getPkgKey(userId, pkg))
+                    && mSnoozedNotifications.get(getPkgKey(userId, pkg)).containsKey(key);
+        }
     }
 
     protected Collection<NotificationRecord> getSnoozed(int userId, String pkg) {
-        if (mSnoozedNotifications.containsKey(getPkgKey(userId, pkg))) {
-            return mSnoozedNotifications.get(getPkgKey(userId, pkg)).values();
+        synchronized (mLock) {
+            if (mSnoozedNotifications.containsKey(getPkgKey(userId, pkg))) {
+                return mSnoozedNotifications.get(getPkgKey(userId, pkg)).values();
+            }
         }
         return Collections.EMPTY_LIST;
     }
@@ -165,14 +178,16 @@
     ArrayList<NotificationRecord> getNotifications(String pkg,
             String groupKey, Integer userId) {
         ArrayList<NotificationRecord> records =  new ArrayList<>();
-        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);
+        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);
+                    }
                 }
             }
         }
@@ -180,30 +195,34 @@
     }
 
     protected NotificationRecord getNotification(String key) {
-        if (!mUsers.containsKey(key) || !mPackages.containsKey(key)) {
-            Slog.w(TAG, "Snoozed data sets no longer agree for " + key);
-            return null;
+        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);
         }
-        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);
     }
 
     protected @NonNull List<NotificationRecord> getSnoozed() {
-        // 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());
+        synchronized (mLock) {
+            // 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());
+            }
+            return snoozed;
         }
-        return snoozed;
     }
 
     /**
@@ -216,9 +235,9 @@
 
         snooze(record);
         scheduleRepost(pkg, key, userId, duration);
-        Long activateAt = SystemClock.elapsedRealtime() + duration;
-        synchronized (mPersistedSnoozedNotifications) {
-            storeRecord(pkg, key, userId, mPersistedSnoozedNotifications, activateAt);
+        Long activateAt = System.currentTimeMillis() + duration;
+        synchronized (mLock) {
+            storeRecordLocked(pkg, key, userId, mPersistedSnoozedNotifications, activateAt);
         }
     }
 
@@ -228,8 +247,8 @@
     protected void snooze(NotificationRecord record, String contextId) {
         int userId = record.getUser().getIdentifier();
         if (contextId != null) {
-            synchronized (mPersistedSnoozedNotificationsWithContext) {
-                storeRecord(record.getSbn().getPackageName(), record.getKey(),
+            synchronized (mLock) {
+                storeRecordLocked(record.getSbn().getPackageName(), record.getKey(),
                         userId, mPersistedSnoozedNotificationsWithContext, contextId);
             }
         }
@@ -241,25 +260,26 @@
         if (DEBUG) {
             Slog.d(TAG, "Snoozing " + record.getKey());
         }
-        storeRecord(record.getSbn().getPackageName(), record.getKey(),
-                userId, mSnoozedNotifications, record);
+        synchronized (mLock) {
+            storeRecordLocked(record.getSbn().getPackageName(), record.getKey(),
+                    userId, mSnoozedNotifications, record);
+        }
     }
 
-    private <T> void storeRecord(String pkg, String key, Integer userId,
+    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);
-
-        mPackages.put(key, pkg);
-        mUsers.put(key, userId);
     }
 
-    private <T> T removeRecord(String pkg, String key, Integer userId,
+    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));
@@ -274,15 +294,17 @@
     }
 
     protected boolean cancel(int userId, String pkg, String tag, int id) {
-        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;
+        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;
+                    }
                 }
             }
         }
@@ -290,125 +312,149 @@
     }
 
     protected void cancel(int userId, boolean includeCurrentProfiles) {
-        if (mSnoozedNotifications.size() == 0) {
-            return;
-        }
-        IntArray userIds = new IntArray();
-        userIds.add(userId);
-        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;
+        synchronized (mLock) {
+            if (mSnoozedNotifications.size() == 0) {
+                return;
+            }
+            IntArray userIds = new IntArray();
+            userIds.add(userId);
+            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;
+                    }
                 }
             }
         }
     }
 
     protected boolean cancel(int userId, String pkg) {
-        ArrayMap<String, NotificationRecord> records =
-                mSnoozedNotifications.get(getPkgKey(userId, pkg));
-        if (records == null) {
-            return false;
+        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;
+            }
+            return true;
         }
-        int N = records.size();
-        for (int i = 0; i < N; i++) {
-            records.valueAt(i).isCanceled = true;
-        }
-        return true;
     }
 
     /**
      * Updates the notification record so the most up to date information is shown on re-post.
      */
     protected void update(int userId, NotificationRecord record) {
-        ArrayMap<String, NotificationRecord> records =
-                mSnoozedNotifications.get(getPkgKey(userId, record.getSbn().getPackageName()));
-        if (records == null) {
-            return;
-        }
-        records.put(record.getKey(), record);
-    }
-
-    protected void repost(String key) {
-        Integer userId = mUsers.get(key);
-        if (userId != null) {
-            repost(key, userId);
+        synchronized (mLock) {
+            ArrayMap<String, NotificationRecord> records =
+                    mSnoozedNotifications.get(getPkgKey(userId, record.getSbn().getPackageName()));
+            if (records == null) {
+                return;
+            }
+            records.put(record.getKey(), record);
         }
     }
 
-    protected void repost(String key, int userId) {
-        final String pkg = mPackages.remove(key);
-        ArrayMap<String, NotificationRecord> records =
-                mSnoozedNotifications.get(getPkgKey(userId, pkg));
-        if (records == null) {
-            return;
+    protected void repost(String key, boolean muteOnReturn) {
+        synchronized (mLock) {
+            Integer userId = mUsers.get(key);
+            if (userId != null) {
+                repost(key, userId, muteOnReturn);
+            }
         }
-        final NotificationRecord record = records.remove(key);
-        mPackages.remove(key);
-        mUsers.remove(key);
+    }
+
+    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);
+
+        }
 
         if (record != null && !record.isCanceled) {
-            final PendingIntent pi = createPendingIntent(pkg, record.getKey(), userId);
+            final PendingIntent pi = createPendingIntent(
+                    record.getSbn().getPackageName(), record.getKey(), userId);
             mAm.cancel(pi);
             MetricsLogger.action(record.getLogMaker()
                     .setCategory(MetricsProto.MetricsEvent.NOTIFICATION_SNOOZED)
                     .setType(MetricsProto.MetricsEvent.TYPE_OPEN));
-            mCallback.repost(userId, record);
+            mCallback.repost(userId, record, muteOnReturn);
         }
     }
 
     protected void repostGroupSummary(String pkg, int userId, String groupKey) {
-        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()
-                    && potentialGroupSummary.getNotification().isGroupSummary()
-                    && groupKey.equals(potentialGroupSummary.getGroupKey())) {
-                groupSummaryKey = potentialGroupSummary.getKey();
-                break;
+        synchronized (mLock) {
+            ArrayMap<String, NotificationRecord> recordsByKey
+                    = mSnoozedNotifications.get(getPkgKey(userId, pkg));
+            if (recordsByKey == null) {
+                return;
             }
-        }
 
-        if (groupSummaryKey != null) {
-            NotificationRecord record = recordsByKey.remove(groupSummaryKey);
-            mPackages.remove(groupSummaryKey);
-            mUsers.remove(groupSummaryKey);
+            String groupSummaryKey = null;
+            int N = recordsByKey.size();
+            for (int i = 0; i < N; i++) {
+                final NotificationRecord potentialGroupSummary = recordsByKey.valueAt(i);
+                if (potentialGroupSummary.getSbn().isGroup()
+                        && potentialGroupSummary.getNotification().isGroupSummary()
+                        && groupKey.equals(potentialGroupSummary.getGroupKey())) {
+                    groupSummaryKey = potentialGroupSummary.getKey();
+                    break;
+                }
+            }
 
-            if (record != null && !record.isCanceled) {
-                MetricsLogger.action(record.getLogMaker()
-                        .setCategory(MetricsProto.MetricsEvent.NOTIFICATION_SNOOZED)
-                        .setType(MetricsProto.MetricsEvent.TYPE_OPEN));
-                mCallback.repost(userId, record);
+            if (groupSummaryKey != null) {
+                NotificationRecord record = recordsByKey.remove(groupSummaryKey);
+                mPackages.remove(groupSummaryKey);
+                mUsers.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);
+                    };
+                    runnable.run();
+                }
             }
         }
     }
 
     protected void clearData(int userId, String pkg) {
-        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());
-                final PendingIntent pi = createPendingIntent(pkg, r.getKey(), userId);
-                mAm.cancel(pi);
-                MetricsLogger.action(r.getLogMaker()
-                        .setCategory(MetricsProto.MetricsEvent.NOTIFICATION_SNOOZED)
-                        .setType(MetricsProto.MetricsEvent.TYPE_DISMISS));
+        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());
+                    Runnable runnable = () -> {
+                        final PendingIntent pi = createPendingIntent(pkg, r.getKey(), userId);
+                        mAm.cancel(pi);
+                        MetricsLogger.action(r.getLogMaker()
+                                .setCategory(MetricsProto.MetricsEvent.NOTIFICATION_SNOOZED)
+                                .setType(MetricsProto.MetricsEvent.TYPE_DISMISS));
+                    };
+                    runnable.run();
+                }
             }
         }
     }
@@ -425,93 +471,102 @@
     }
 
     public void scheduleRepostsForPersistedNotifications(long currentTime) {
-        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);
+        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);
+                    }
                 }
             }
-
         }
     }
 
     private void scheduleRepost(String pkg, String key, int userId, long duration) {
-        scheduleRepostAtTime(pkg, key, userId, SystemClock.elapsedRealtime() + duration);
+        scheduleRepostAtTime(pkg, key, userId, System.currentTimeMillis() + duration);
     }
 
     private void scheduleRepostAtTime(String pkg, String key, int userId, long time) {
-        long identity = Binder.clearCallingIdentity();
-        try {
-            final PendingIntent pi = createPendingIntent(pkg, key, userId);
-            mAm.cancel(pi);
-            if (DEBUG) Slog.d(TAG, "Scheduling evaluate for " + new Date(time));
-            mAm.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, time, pi);
-        } finally {
-            Binder.restoreCallingIdentity(identity);
-        }
+        Runnable runnable = () -> {
+            long identity = Binder.clearCallingIdentity();
+            try {
+                final PendingIntent pi = createPendingIntent(pkg, key, userId);
+                mAm.cancel(pi);
+                if (DEBUG) Slog.d(TAG, "Scheduling evaluate for " + new Date(time));
+                mAm.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, time, pi);
+            } finally {
+                Binder.restoreCallingIdentity(identity);
+            }
+        };
+        runnable.run();
     }
 
     public void dump(PrintWriter pw, NotificationManagerService.DumpFilter filter) {
-        pw.println("\n  Snoozed notifications:");
-        for (String userPkgKey : 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) {
+        synchronized (mLock) {
+            pw.println("\n  Snoozed notifications:");
+            for (String userPkgKey : mSnoozedNotifications.keySet()) {
                 pw.print(INDENT);
-                pw.print(INDENT);
-                pw.print(INDENT);
-                pw.println(key);
+                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("\n Pending snoozed notifications");
-        for (String userPkgKey : 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.println("\n Pending snoozed notifications");
+            for (String userPkgKey : mPersistedSnoozedNotifications.keySet()) {
                 pw.print(INDENT);
-                pw.print(INDENT);
-                pw.print(INDENT);
-                pw.print(key);
-                pw.print(INDENT);
-                pw.println(snoozedRecords.get(key));
+                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));
+                }
             }
         }
     }
 
     protected void writeXml(XmlSerializer out) throws IOException {
-        final long currentTime = System.currentTimeMillis();
-        out.startTag(null, XML_TAG_NAME);
-        writeXml(out, mPersistedSnoozedNotifications, XML_SNOOZED_NOTIFICATION,
-                value -> {
-                    if (value < currentTime) {
-                        return;
-                    }
-                    out.attribute(null, XML_SNOOZED_NOTIFICATION_TIME,
-                            value.toString());
-                });
-        writeXml(out, mPersistedSnoozedNotificationsWithContext, XML_SNOOZED_NOTIFICATION_CONTEXT,
-                value -> {
-                    out.attribute(null, XML_SNOOZED_NOTIFICATION_CONTEXT_ID,
-                            value);
-                });
-        out.endTag(null, XML_TAG_NAME);
+        synchronized (mLock) {
+            final long currentTime = System.currentTimeMillis();
+            out.startTag(null, XML_TAG_NAME);
+            writeXml(out, mPersistedSnoozedNotifications, XML_SNOOZED_NOTIFICATION,
+                    value -> {
+                        if (value < currentTime) {
+                            return;
+                        }
+                        out.attribute(null, XML_SNOOZED_NOTIFICATION_TIME,
+                                value.toString());
+                    });
+            writeXml(out, mPersistedSnoozedNotificationsWithContext,
+                    XML_SNOOZED_NOTIFICATION_CONTEXT,
+                    value -> {
+                        out.attribute(null, XML_SNOOZED_NOTIFICATION_CONTEXT_ID,
+                                value);
+                    });
+            out.endTag(null, XML_TAG_NAME);
+        }
     }
 
     private interface Inserter<T> {
@@ -522,32 +577,35 @@
             ArrayMap<String, ArrayMap<String, T>> targets, String tag,
             Inserter<T> attributeInserter)
             throws IOException {
-        synchronized (targets) {
-            final int M = targets.size();
-            for (int i = 0; i < M; i++) {
-                // 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);
+        final int M = targets.size();
+        for (int i = 0; i < M; i++) {
+            // 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);
 
-                    out.startTag(null, tag);
-
-                    attributeInserter.insert(value);
-
-                    out.attribute(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.attribute(null, XML_SNOOZED_NOTIFICATION_USER_ID,
-                            String.valueOf(userId));
-
-                    out.endTag(null, tag);
+                if (pkg == null || userId == null) {
+                    Slog.w(TAG, "pkg " + pkg + " or user " + userId + " missing for " + key);
+                    continue;
                 }
+
+                out.startTag(null, tag);
+
+                attributeInserter.insert(value);
+
+                out.attribute(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.attribute(null, XML_SNOOZED_NOTIFICATION_USER_ID,
+                        String.valueOf(userId));
+
+                out.endTag(null, tag);
             }
         }
     }
@@ -575,16 +633,18 @@
                         final Long time = XmlUtils.readLongAttribute(
                                 parser, XML_SNOOZED_NOTIFICATION_TIME, 0);
                         if (time > currentTime) { //only read new stuff
-                            synchronized (mPersistedSnoozedNotifications) {
-                                storeRecord(pkg, key, userId, mPersistedSnoozedNotifications, time);
+                            synchronized (mLock) {
+                                storeRecordLocked(
+                                        pkg, key, userId, mPersistedSnoozedNotifications, time);
                             }
                         }
                     }
                     if (tag.equals(XML_SNOOZED_NOTIFICATION_CONTEXT)) {
                         final String creationId = parser.getAttributeValue(
                                 null, XML_SNOOZED_NOTIFICATION_CONTEXT_ID);
-                        synchronized (mPersistedSnoozedNotificationsWithContext) {
-                            storeRecord(pkg, key, userId, mPersistedSnoozedNotificationsWithContext,
+                        synchronized (mLock) {
+                            storeRecordLocked(
+                                    pkg, key, userId, mPersistedSnoozedNotificationsWithContext,
                                     creationId);
                         }
                     }
@@ -601,7 +661,7 @@
     }
 
     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 +672,7 @@
             }
             if (REPOST_ACTION.equals(intent.getAction())) {
                 repost(intent.getStringExtra(EXTRA_KEY), intent.getIntExtra(EXTRA_USER_ID,
-                        UserHandle.USER_SYSTEM));
+                        UserHandle.USER_SYSTEM), false);
             }
         }
     };
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 440b779..36c0659 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -4674,22 +4674,24 @@
             return getUserDataUnchecked(userHandle).mAdminList;
         }
         ArrayList<ActiveAdmin> admins = new ArrayList<>();
-        for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) {
-            DevicePolicyData policy = getUserDataUnchecked(userInfo.id);
-            if (userInfo.id == userHandle) {
-                admins.addAll(policy.mAdminList);
-            } else if (userInfo.isManagedProfile()) {
-                // For managed profiles, policies set on the parent profile will be included
-                for (int i = 0; i < policy.mAdminList.size(); i++) {
-                    ActiveAdmin admin = policy.mAdminList.get(i);
-                    if (admin.hasParentActiveAdmin()) {
-                        admins.add(admin.getParentActiveAdmin());
+        mInjector.binderWithCleanCallingIdentity(() -> {
+            for (UserInfo userInfo : mUserManager.getProfiles(userHandle)) {
+                DevicePolicyData policy = getUserDataUnchecked(userInfo.id);
+                if (userInfo.id == userHandle) {
+                    admins.addAll(policy.mAdminList);
+                } else if (userInfo.isManagedProfile()) {
+                    // For managed profiles, policies set on the parent profile will be included
+                    for (int i = 0; i < policy.mAdminList.size(); i++) {
+                        ActiveAdmin admin = policy.mAdminList.get(i);
+                        if (admin.hasParentActiveAdmin()) {
+                            admins.add(admin.getParentActiveAdmin());
+                        }
                     }
+                } else {
+                    Slog.w(LOG_TAG, "Unknown user type: " + userInfo);
                 }
-            } else {
-                Slog.w(LOG_TAG, "Unknown user type: " + userInfo);
             }
-        }
+        });
         return admins;
     }
 
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
index f029bc8..afd10dd 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -846,6 +846,18 @@
     }
 
     @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);
 
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 816e8e5..3deeea2 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/SnoozeHelperTest.java
@@ -22,6 +22,7 @@
 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;
@@ -249,7 +250,7 @@
         ArgumentCaptor<Long> captor = ArgumentCaptor.forClass(Long.class);
         verify(mAm, times(1)).setExactAndAllowWhileIdle(
                 anyInt(), captor.capture(), any(PendingIntent.class));
-        long actualSnoozedUntilDuration = captor.getValue() - SystemClock.elapsedRealtime();
+        long actualSnoozedUntilDuration = captor.getValue() - System.currentTimeMillis();
         assertTrue(Math.abs(actualSnoozedUntilDuration - 1000) < 250);
         assertTrue(mSnoozeHelper.isSnoozed(
                 UserHandle.USER_SYSTEM, r.getSbn().getPackageName(), r.getKey()));
@@ -363,8 +364,8 @@
 
         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 @@
         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 @@
         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 @@
         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,13 +421,23 @@
         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);
         NotificationRecord r2 = getNotificationRecord("pkg", 2, "two", UserHandle.SYSTEM);
@@ -523,7 +534,7 @@
         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 @@
 
         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());