diff options
author | Danny Baumann <dannybaumann@web.de> | 2016-10-19 13:38:06 +0200 |
---|---|---|
committer | Danny Baumann <dannybaumann@web.de> | 2016-10-20 16:44:25 +0200 |
commit | ac7b58ec1c8b07537960bfafe40e31ddc9a94719 (patch) | |
tree | ee40ffee4e20ddc0cbfa6a64827b445a4d05ff0d | |
parent | e05eda22dd6d2e4834b5ff2b364d4258ad590f3e (diff) | |
download | frameworks_base-ac7b58ec1c8b07537960bfafe40e31ddc9a94719.zip frameworks_base-ac7b58ec1c8b07537960bfafe40e31ddc9a94719.tar.gz frameworks_base-ac7b58ec1c8b07537960bfafe40e31ddc9a94719.tar.bz2 |
Support enforcing a minimum delay between notification sounds of an app.
Useful e.g. for messenger apps.
Change-Id: If8e8cc9e2f02d70537c1f9dc14f22bbd0ec1e9a6
3 files changed, 74 insertions, 1 deletions
diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl index 7c51a83..59ff413 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl @@ -58,6 +58,9 @@ interface INotificationManager void setShowNotificationForPackageOnKeyguard(String pkg, int uid, int status); int getShowNotificationForPackageOnKeyguard(String pkg, int uid); + void setPackageNotificationSoundTimeout(String pkg, int uid, long timeout); + long getPackageNotificationSoundTimeout(String pkg, int uid); + // TODO: Remove this when callers have been migrated to the equivalent // INotificationListener method. StatusBarNotification[] getActiveNotifications(String callingPkg); diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 43efddd..b2b6580 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -76,6 +76,7 @@ import android.os.Looper; import android.os.Message; import android.os.Process; import android.os.RemoteException; +import android.os.SystemClock; import android.os.SystemProperties; import android.os.UserHandle; import android.os.UserManager; @@ -100,6 +101,7 @@ import android.util.Log; import android.util.LruCache; import android.util.Slog; import android.util.SparseIntArray; +import android.util.TimeUtils; import android.util.Xml; import android.view.accessibility.AccessibilityEvent; import android.view.accessibility.AccessibilityManager; @@ -302,6 +304,7 @@ public class NotificationManagerService extends SystemService { new ArrayMap<String, NotificationRecord>(); final ArrayList<ToastRecord> mToastQueue = new ArrayList<ToastRecord>(); final ArrayMap<String, NotificationRecord> mSummaryByGroupKey = new ArrayMap<>(); + final ArrayMap<String, Long> mLastSoundTimestamps = new ArrayMap<>(); final PolicyAccess mPolicyAccess = new PolicyAccess(); // The last key in this list owns the hardware. @@ -1595,6 +1598,19 @@ public class NotificationManagerService extends SystemService { return mRankingHelper.getShowNotificationForPackageOnKeyguard(pkg, uid); } + @Override + public void setPackageNotificationSoundTimeout(String pkg, int uid, long timeout) { + checkCallerIsSystem(); + mRankingHelper.setPackageNotificationSoundTimeout(pkg, uid, timeout); + savePolicyFile(); + } + + @Override + public long getPackageNotificationSoundTimeout(String pkg, int uid) { + checkCallerIsSystem(); + return mRankingHelper.getPackageNotificationSoundTimeout(pkg, uid); + } + /** * System-only API for getting a list of current (i.e. not cleared) notifications. * @@ -2317,6 +2333,14 @@ public class NotificationManagerService extends SystemService { } catch (NameNotFoundException e) { // pass } + + 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"); + } } } @@ -2705,6 +2729,7 @@ public class NotificationManagerService extends SystemService { && (record.getUserId() == UserHandle.USER_ALL || record.getUserId() == currentUser || mUserProfiles.isCurrentProfile(record.getUserId())) + && !isInSoundTimeoutPeriod(record) && mSystemReady && mAudioManager != null; @@ -2835,6 +2860,10 @@ public class NotificationManagerService extends SystemService { } else if (wasShowLights) { updateLightsLocked(); } + if (buzz || beep) { + mLastSoundTimestamps.put(generateLastSoundTimeoutKey(record), + SystemClock.elapsedRealtime()); + } if (buzz || beep || blink) { EventLogTags.writeNotificationAlert(record.getKey(), buzz ? 1 : 0, beep ? 1 : 0, blink ? 1 : 0); @@ -2842,6 +2871,24 @@ public class NotificationManagerService extends SystemService { } } + private boolean isInSoundTimeoutPeriod(NotificationRecord record) { + long timeoutMillis = mRankingHelper.getPackageNotificationSoundTimeout( + 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(); + } + private static AudioAttributes audioAttributesForNotification(Notification n) { if (n.audioAttributes != null && !Notification.AUDIO_ATTRIBUTES_DEFAULT.equals(n.audioAttributes)) { diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java index 5112370..233eb0a 100644 --- a/services/core/java/com/android/server/notification/RankingHelper.java +++ b/services/core/java/com/android/server/notification/RankingHelper.java @@ -52,6 +52,7 @@ public class RankingHelper implements RankingConfig { private static final String ATT_PEEKABLE = "peekable"; private static final String ATT_VISIBILITY = "visibility"; private static final String ATT_KEYGUARD = "keyguard"; + private static final String ATT_SOUND_TIMEOUT = "sound-timeout"; private static final int DEFAULT_PRIORITY = Notification.PRIORITY_DEFAULT; private static final boolean DEFAULT_PEEKABLE = true; @@ -146,6 +147,7 @@ public class RankingHelper implements RankingConfig { int vis = safeInt(parser, ATT_VISIBILITY, DEFAULT_VISIBILITY); int keyguard = safeInt(parser, ATT_KEYGUARD, Notification.SHOW_ALL_NOTI_ON_KEYGUARD); + long soundTimeout = safeInt(parser, ATT_SOUND_TIMEOUT, 0); String name = parser.getAttributeValue(null, ATT_NAME); if (!TextUtils.isEmpty(name)) { @@ -178,6 +180,9 @@ public class RankingHelper implements RankingConfig { if (keyguard != Notification.SHOW_ALL_NOTI_ON_KEYGUARD) { r.keyguard = keyguard; } + if (soundTimeout != 0) { + r.notificationSoundTimeout = soundTimeout; + } } } } @@ -207,7 +212,8 @@ public class RankingHelper implements RankingConfig { final Record r = mRecords.valueAt(i); if (r.priority == DEFAULT_PRIORITY && r.peekable == DEFAULT_PEEKABLE && r.visibility == DEFAULT_VISIBILITY - && r.keyguard == Notification.SHOW_ALL_NOTI_ON_KEYGUARD) { + && r.keyguard == Notification.SHOW_ALL_NOTI_ON_KEYGUARD + && r.notificationSoundTimeout == 0) { mRecords.removeAt(i); } } @@ -237,6 +243,9 @@ public class RankingHelper implements RankingConfig { if (r.keyguard != Notification.SHOW_ALL_NOTI_ON_KEYGUARD) { out.attribute(null, ATT_KEYGUARD, Integer.toBinaryString(r.keyguard)); } + if (r.notificationSoundTimeout != 0) { + out.attribute(null, ATT_SOUND_TIMEOUT, Long.toString(r.notificationSoundTimeout)); + } if (!forBackup) { out.attribute(null, ATT_UID, Integer.toString(r.uid)); } @@ -404,6 +413,19 @@ public class RankingHelper implements RankingConfig { updateConfig(); } + public long getPackageNotificationSoundTimeout(String packageName, int uid) { + final Record r = mRecords.get(recordKey(packageName, uid)); + return r != null ? r.notificationSoundTimeout : 0; + } + + public void setPackageNotificationSoundTimeout(String packageName, int uid, long timeout) { + if (timeout == getPackageNotificationSoundTimeout(packageName, uid)) { + return; + } + getOrCreateRecord(packageName, uid).notificationSoundTimeout = timeout; + removeDefaultRecords(); + } + public void dump(PrintWriter pw, String prefix, NotificationManagerService.DumpFilter filter) { if (filter == null) { final int N = mSignalExtractors.length; @@ -487,6 +509,7 @@ public class RankingHelper implements RankingConfig { boolean peekable = DEFAULT_PEEKABLE; int visibility = DEFAULT_VISIBILITY; int keyguard = Notification.SHOW_ALL_NOTI_ON_KEYGUARD; + long notificationSoundTimeout = 0; } } |