Loading core/java/android/app/INotificationManager.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,8 @@ interface INotificationManager boolean areNotificationsEnabledForPackage(String pkg, int uid); boolean areNotificationsEnabled(String pkg); int getPackageImportance(String pkg); void setNotificationSoundTimeout(String pkg, int uid, long timeout); long getNotificationSoundTimeout(String pkg, int uid); void createNotificationChannelGroups(String pkg, in ParceledListSlice channelGroupList); void createNotificationChannels(String pkg, in ParceledListSlice channelsList); Loading services/core/java/com/android/server/notification/NotificationManagerService.java +49 −1 Original line number Diff line number Diff line Loading @@ -180,6 +180,7 @@ import android.util.AtomicFile; import android.util.Log; import android.util.Slog; import android.util.SparseArray; import android.util.TimeUtils; import android.util.Xml; import android.util.proto.ProtoOutputStream; import android.view.accessibility.AccessibilityEvent; Loading Loading @@ -239,6 +240,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; import java.util.Set; Loading Loading @@ -375,6 +377,7 @@ public class NotificationManagerService extends SystemService { final ArrayList<ToastRecord> mToastQueue = new ArrayList<>(); final ArrayMap<String, NotificationRecord> mSummaryByGroupKey = new ArrayMap<>(); final ArrayMap<Integer, ArrayList<NotifyingApp>> mRecentApps = new ArrayMap<>(); final ArrayMap<String, Long> mLastSoundTimestamps = new ArrayMap<>(); // The last key in this list owns the hardware. ArrayList<String> mLights = new ArrayList<>(); Loading Loading @@ -2174,6 +2177,19 @@ public class NotificationManagerService extends SystemService { savePolicyFile(); } @Override public void setNotificationSoundTimeout(String pkg, int uid, long timeout) { checkCallerIsSystem(); mRankingHelper.setNotificationSoundTimeout(pkg, uid, timeout); savePolicyFile(); } @Override public long getNotificationSoundTimeout(String pkg, int uid) { checkCallerIsSystem(); return mRankingHelper.getNotificationSoundTimeout(pkg, uid); } /** * Updates the enabled state for notifications for the given package (and uid). * Additionally, this method marks the app importance as locked by the user, which means Loading Loading @@ -3982,6 +3998,14 @@ public class NotificationManagerService extends SystemService { pw.println("\n Usage Stats:"); mUsageStats.dump(pw, " ", filter); } long now = SystemClock.elapsedRealtime(); pw.println("\n Last notification sound timestamps:"); for (Map.Entry<String, Long> entry : mLastSoundTimestamps.entrySet()) { pw.print(" " + entry.getKey() + " -> "); TimeUtils.formatDuration(entry.getValue(), now, pw); pw.println(" ago"); } } } Loading Loading @@ -4831,7 +4855,7 @@ public class NotificationManagerService extends SystemService { if (aboveThreshold && isNotificationForCurrentUser(record)) { if (mSystemReady && mAudioManager != null) { if (!isInSoundTimeoutPeriod(record) && mSystemReady && mAudioManager != null) { Uri soundUri = record.getSound(); hasValidSound = soundUri != null && !Uri.EMPTY.equals(soundUri); long[] vibration = record.getVibration(); Loading Loading @@ -4896,6 +4920,12 @@ public class NotificationManagerService extends SystemService { } else if (wasShowLights) { updateLightsLocked(); } if (buzz || beep) { mLastSoundTimestamps.put(generateLastSoundTimeoutKey(record), SystemClock.elapsedRealtime()); } if (buzz || beep || blink) { // Ignore summary updates because we don't display most of the information. if (record.sbn.isGroup() && record.sbn.getNotification().isGroupSummary()) { Loading @@ -4918,6 +4948,24 @@ public class NotificationManagerService extends SystemService { } } private boolean isInSoundTimeoutPeriod(NotificationRecord record) { long timeoutMillis = mRankingHelper.getNotificationSoundTimeout( record.sbn.getPackageName(), record.sbn.getUid()); if (timeoutMillis == 0) { return false; } Long value = mLastSoundTimestamps.get(generateLastSoundTimeoutKey(record)); if (value == null) { return false; } return SystemClock.elapsedRealtime() - value < timeoutMillis; } private String generateLastSoundTimeoutKey(NotificationRecord record) { return record.sbn.getPackageName() + "|" + record.sbn.getUid(); } @GuardedBy("mNotificationLock") boolean canShowLightsLocked(final NotificationRecord record, boolean aboveThreshold) { // device lacks light Loading services/core/java/com/android/server/notification/RankingHelper.java +26 −0 Original line number Diff line number Diff line Loading @@ -86,6 +86,7 @@ public class RankingHelper implements RankingConfig { private static final String ATT_IMPORTANCE = "importance"; private static final String ATT_SHOW_BADGE = "show_badge"; private static final String ATT_APP_USER_LOCKED_FIELDS = "app_user_locked_fields"; private static final String ATT_SOUND_TIMEOUT = "sound-timeout"; private static final int DEFAULT_PRIORITY = Notification.PRIORITY_DEFAULT; private static final int DEFAULT_VISIBILITY = NotificationManager.VISIBILITY_NO_OVERRIDE; Loading Loading @@ -230,6 +231,8 @@ public class RankingHelper implements RankingConfig { parser, ATT_SHOW_BADGE, DEFAULT_SHOW_BADGE); r.lockedAppFields = XmlUtils.readIntAttribute(parser, ATT_APP_USER_LOCKED_FIELDS, DEFAULT_LOCKED_APP_FIELDS); r.soundTimeout = XmlUtils.readIntAttribute(parser, ATT_SOUND_TIMEOUT, 0); final int innerDepth = parser.getDepth(); while ((type = parser.next()) != XmlPullParser.END_DOCUMENT Loading Loading @@ -406,6 +409,7 @@ public class RankingHelper implements RankingConfig { || r.visibility != DEFAULT_VISIBILITY || r.showBadge != DEFAULT_SHOW_BADGE || r.lockedAppFields != DEFAULT_LOCKED_APP_FIELDS || r.soundTimeout != 0 || r.channels.size() > 0 || r.groups.size() > 0; if (hasNonDefaultSettings) { Loading @@ -420,6 +424,9 @@ public class RankingHelper implements RankingConfig { if (r.visibility != DEFAULT_VISIBILITY) { out.attribute(null, ATT_VISIBILITY, Integer.toString(r.visibility)); } if (r.soundTimeout != 0) { out.attribute(null, ATT_SOUND_TIMEOUT, Long.toString(r.soundTimeout)); } out.attribute(null, ATT_SHOW_BADGE, Boolean.toString(r.showBadge)); out.attribute(null, ATT_APP_USER_LOCKED_FIELDS, Integer.toString(r.lockedAppFields)); Loading Loading @@ -1057,6 +1064,21 @@ public class RankingHelper implements RankingConfig { updateConfig(); } /** * @hide */ public long getNotificationSoundTimeout(String pkgName, int uid) { return getOrCreateRecord(pkgName, uid).soundTimeout; } /** * @hide */ public void setNotificationSoundTimeout(String pkgName, int uid, long timeout) { getOrCreateRecord(pkgName, uid).soundTimeout = timeout; updateConfig(); } @VisibleForTesting void lockFieldsForUpdate(NotificationChannel original, NotificationChannel update) { if (original.canBypassDnd() != update.canBypassDnd()) { Loading Loading @@ -1223,6 +1245,9 @@ public class RankingHelper implements RankingConfig { if (r.showBadge != DEFAULT_SHOW_BADGE) { record.put("showBadge", Boolean.valueOf(r.showBadge)); } if (r.soundTimeout != 0) { record.put("soundTimeout", r.soundTimeout); } JSONArray channels = new JSONArray(); for (NotificationChannel channel : r.channels.values()) { channels.put(channel.toJson()); Loading Loading @@ -1479,6 +1504,7 @@ public class RankingHelper implements RankingConfig { int visibility = DEFAULT_VISIBILITY; boolean showBadge = DEFAULT_SHOW_BADGE; int lockedAppFields = DEFAULT_LOCKED_APP_FIELDS; long soundTimeout = 0; ArrayMap<String, NotificationChannel> channels = new ArrayMap<>(); Map<String, NotificationChannelGroup> groups = new ConcurrentHashMap<>(); Loading Loading
core/java/android/app/INotificationManager.aidl +2 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,8 @@ interface INotificationManager boolean areNotificationsEnabledForPackage(String pkg, int uid); boolean areNotificationsEnabled(String pkg); int getPackageImportance(String pkg); void setNotificationSoundTimeout(String pkg, int uid, long timeout); long getNotificationSoundTimeout(String pkg, int uid); void createNotificationChannelGroups(String pkg, in ParceledListSlice channelGroupList); void createNotificationChannels(String pkg, in ParceledListSlice channelsList); Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +49 −1 Original line number Diff line number Diff line Loading @@ -180,6 +180,7 @@ import android.util.AtomicFile; import android.util.Log; import android.util.Slog; import android.util.SparseArray; import android.util.TimeUtils; import android.util.Xml; import android.util.proto.ProtoOutputStream; import android.view.accessibility.AccessibilityEvent; Loading Loading @@ -239,6 +240,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Objects; import java.util.Set; Loading Loading @@ -375,6 +377,7 @@ public class NotificationManagerService extends SystemService { final ArrayList<ToastRecord> mToastQueue = new ArrayList<>(); final ArrayMap<String, NotificationRecord> mSummaryByGroupKey = new ArrayMap<>(); final ArrayMap<Integer, ArrayList<NotifyingApp>> mRecentApps = new ArrayMap<>(); final ArrayMap<String, Long> mLastSoundTimestamps = new ArrayMap<>(); // The last key in this list owns the hardware. ArrayList<String> mLights = new ArrayList<>(); Loading Loading @@ -2174,6 +2177,19 @@ public class NotificationManagerService extends SystemService { savePolicyFile(); } @Override public void setNotificationSoundTimeout(String pkg, int uid, long timeout) { checkCallerIsSystem(); mRankingHelper.setNotificationSoundTimeout(pkg, uid, timeout); savePolicyFile(); } @Override public long getNotificationSoundTimeout(String pkg, int uid) { checkCallerIsSystem(); return mRankingHelper.getNotificationSoundTimeout(pkg, uid); } /** * Updates the enabled state for notifications for the given package (and uid). * Additionally, this method marks the app importance as locked by the user, which means Loading Loading @@ -3982,6 +3998,14 @@ public class NotificationManagerService extends SystemService { pw.println("\n Usage Stats:"); mUsageStats.dump(pw, " ", filter); } long now = SystemClock.elapsedRealtime(); pw.println("\n Last notification sound timestamps:"); for (Map.Entry<String, Long> entry : mLastSoundTimestamps.entrySet()) { pw.print(" " + entry.getKey() + " -> "); TimeUtils.formatDuration(entry.getValue(), now, pw); pw.println(" ago"); } } } Loading Loading @@ -4831,7 +4855,7 @@ public class NotificationManagerService extends SystemService { if (aboveThreshold && isNotificationForCurrentUser(record)) { if (mSystemReady && mAudioManager != null) { if (!isInSoundTimeoutPeriod(record) && mSystemReady && mAudioManager != null) { Uri soundUri = record.getSound(); hasValidSound = soundUri != null && !Uri.EMPTY.equals(soundUri); long[] vibration = record.getVibration(); Loading Loading @@ -4896,6 +4920,12 @@ public class NotificationManagerService extends SystemService { } else if (wasShowLights) { updateLightsLocked(); } if (buzz || beep) { mLastSoundTimestamps.put(generateLastSoundTimeoutKey(record), SystemClock.elapsedRealtime()); } if (buzz || beep || blink) { // Ignore summary updates because we don't display most of the information. if (record.sbn.isGroup() && record.sbn.getNotification().isGroupSummary()) { Loading @@ -4918,6 +4948,24 @@ public class NotificationManagerService extends SystemService { } } private boolean isInSoundTimeoutPeriod(NotificationRecord record) { long timeoutMillis = mRankingHelper.getNotificationSoundTimeout( record.sbn.getPackageName(), record.sbn.getUid()); if (timeoutMillis == 0) { return false; } Long value = mLastSoundTimestamps.get(generateLastSoundTimeoutKey(record)); if (value == null) { return false; } return SystemClock.elapsedRealtime() - value < timeoutMillis; } private String generateLastSoundTimeoutKey(NotificationRecord record) { return record.sbn.getPackageName() + "|" + record.sbn.getUid(); } @GuardedBy("mNotificationLock") boolean canShowLightsLocked(final NotificationRecord record, boolean aboveThreshold) { // device lacks light Loading
services/core/java/com/android/server/notification/RankingHelper.java +26 −0 Original line number Diff line number Diff line Loading @@ -86,6 +86,7 @@ public class RankingHelper implements RankingConfig { private static final String ATT_IMPORTANCE = "importance"; private static final String ATT_SHOW_BADGE = "show_badge"; private static final String ATT_APP_USER_LOCKED_FIELDS = "app_user_locked_fields"; private static final String ATT_SOUND_TIMEOUT = "sound-timeout"; private static final int DEFAULT_PRIORITY = Notification.PRIORITY_DEFAULT; private static final int DEFAULT_VISIBILITY = NotificationManager.VISIBILITY_NO_OVERRIDE; Loading Loading @@ -230,6 +231,8 @@ public class RankingHelper implements RankingConfig { parser, ATT_SHOW_BADGE, DEFAULT_SHOW_BADGE); r.lockedAppFields = XmlUtils.readIntAttribute(parser, ATT_APP_USER_LOCKED_FIELDS, DEFAULT_LOCKED_APP_FIELDS); r.soundTimeout = XmlUtils.readIntAttribute(parser, ATT_SOUND_TIMEOUT, 0); final int innerDepth = parser.getDepth(); while ((type = parser.next()) != XmlPullParser.END_DOCUMENT Loading Loading @@ -406,6 +409,7 @@ public class RankingHelper implements RankingConfig { || r.visibility != DEFAULT_VISIBILITY || r.showBadge != DEFAULT_SHOW_BADGE || r.lockedAppFields != DEFAULT_LOCKED_APP_FIELDS || r.soundTimeout != 0 || r.channels.size() > 0 || r.groups.size() > 0; if (hasNonDefaultSettings) { Loading @@ -420,6 +424,9 @@ public class RankingHelper implements RankingConfig { if (r.visibility != DEFAULT_VISIBILITY) { out.attribute(null, ATT_VISIBILITY, Integer.toString(r.visibility)); } if (r.soundTimeout != 0) { out.attribute(null, ATT_SOUND_TIMEOUT, Long.toString(r.soundTimeout)); } out.attribute(null, ATT_SHOW_BADGE, Boolean.toString(r.showBadge)); out.attribute(null, ATT_APP_USER_LOCKED_FIELDS, Integer.toString(r.lockedAppFields)); Loading Loading @@ -1057,6 +1064,21 @@ public class RankingHelper implements RankingConfig { updateConfig(); } /** * @hide */ public long getNotificationSoundTimeout(String pkgName, int uid) { return getOrCreateRecord(pkgName, uid).soundTimeout; } /** * @hide */ public void setNotificationSoundTimeout(String pkgName, int uid, long timeout) { getOrCreateRecord(pkgName, uid).soundTimeout = timeout; updateConfig(); } @VisibleForTesting void lockFieldsForUpdate(NotificationChannel original, NotificationChannel update) { if (original.canBypassDnd() != update.canBypassDnd()) { Loading Loading @@ -1223,6 +1245,9 @@ public class RankingHelper implements RankingConfig { if (r.showBadge != DEFAULT_SHOW_BADGE) { record.put("showBadge", Boolean.valueOf(r.showBadge)); } if (r.soundTimeout != 0) { record.put("soundTimeout", r.soundTimeout); } JSONArray channels = new JSONArray(); for (NotificationChannel channel : r.channels.values()) { channels.put(channel.toJson()); Loading Loading @@ -1479,6 +1504,7 @@ public class RankingHelper implements RankingConfig { int visibility = DEFAULT_VISIBILITY; boolean showBadge = DEFAULT_SHOW_BADGE; int lockedAppFields = DEFAULT_LOCKED_APP_FIELDS; long soundTimeout = 0; ArrayMap<String, NotificationChannel> channels = new ArrayMap<>(); Map<String, NotificationChannelGroup> groups = new ConcurrentHashMap<>(); Loading