From 924eed1ca6d3fec5dae7eb0f9c11b8f23f628697 Mon Sep 17 00:00:00 2001 From: Julia Reynolds Date: Thu, 19 Jan 2017 09:52:07 -0500 Subject: [PATCH] Add updatable fields to Ranking - NotificationChannel - Badging Test: runtest systemuinotification & cts Change-Id: I7fd1f2dc06148927e9a4bd5b760d436e2c5e8a98 --- api/current.txt | 2 +- api/system-current.txt | 2 +- api/test-current.txt | 2 +- .../android/app/INotificationManager.aidl | 2 + .../java/android/app/NotificationChannel.java | 5 +- .../NotificationListenerService.java | 73 ++++++--- .../NotificationRankingUpdate.java | 23 ++- .../notification/StatusBarNotification.java | 19 +-- core/res/res/values/config.xml | 1 + .../systemui/statusbar/BaseStatusBar.java | 6 +- .../systemui/statusbar/NotificationData.java | 11 ++ .../systemui/statusbar/NotificationGuts.java | 16 +- .../statusbar/phone/PhoneStatusBar.java | 2 +- .../statusbar/NotificationGutsTest.java | 41 ++--- .../server/notification/BadgeExtractor.java | 59 +++++++ .../NotificationManagerService.java | 89 +++++++---- .../notification/NotificationRecord.java | 29 ++-- .../server/notification/RankingConfig.java | 2 + .../server/notification/RankingHelper.java | 41 ++++- .../notification/BadgeExtractorTest.java | 151 ++++++++++++++++++ .../notification/BuzzBeepBlinkTest.java | 4 +- .../server/notification/GroupHelperTest.java | 4 +- .../notification/ImportanceExtractorTest.java | 4 +- .../NotificationComparatorTest.java | 40 ++--- .../NotificationListenerServiceTest.java | 13 +- .../NotificationManagerServiceTest.java | 4 +- .../notification/NotificationRecordTest.java | 30 ++-- .../notification/RankingHelperTest.java | 33 ++-- .../server/notification/SnoozeHelperTest.java | 4 +- 29 files changed, 531 insertions(+), 181 deletions(-) create mode 100644 services/core/java/com/android/server/notification/BadgeExtractor.java create mode 100644 services/tests/notification/src/com/android/server/notification/BadgeExtractorTest.java diff --git a/api/current.txt b/api/current.txt index cd66ed67da02b..0fce726e7c2c3 100644 --- a/api/current.txt +++ b/api/current.txt @@ -35788,6 +35788,7 @@ package android.service.notification { public static class NotificationListenerService.Ranking { ctor public NotificationListenerService.Ranking(); + method public boolean canShowBadge(); method public java.util.List getAdditionalPeople(); method public android.app.NotificationChannel getChannel(); method public int getImportance(); @@ -35829,7 +35830,6 @@ package android.service.notification { method public int getId(); method public java.lang.String getKey(); method public android.app.Notification getNotification(); - method public android.app.NotificationChannel getNotificationChannel(); method public java.lang.String getOverrideGroupKey(); method public java.lang.String getPackageName(); method public long getPostTime(); diff --git a/api/system-current.txt b/api/system-current.txt index a3deab04eb284..e41a845cda091 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -38733,6 +38733,7 @@ package android.service.notification { public static class NotificationListenerService.Ranking { ctor public NotificationListenerService.Ranking(); + method public boolean canShowBadge(); method public java.util.List getAdditionalPeople(); method public android.app.NotificationChannel getChannel(); method public int getImportance(); @@ -38774,7 +38775,6 @@ package android.service.notification { method public int getId(); method public java.lang.String getKey(); method public android.app.Notification getNotification(); - method public android.app.NotificationChannel getNotificationChannel(); method public java.lang.String getOverrideGroupKey(); method public java.lang.String getPackageName(); method public long getPostTime(); diff --git a/api/test-current.txt b/api/test-current.txt index f07f3b4791118..a152e493cabba 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -35909,6 +35909,7 @@ package android.service.notification { public static class NotificationListenerService.Ranking { ctor public NotificationListenerService.Ranking(); + method public boolean canShowBadge(); method public java.util.List getAdditionalPeople(); method public android.app.NotificationChannel getChannel(); method public int getImportance(); @@ -35950,7 +35951,6 @@ package android.service.notification { method public int getId(); method public java.lang.String getKey(); method public android.app.Notification getNotification(); - method public android.app.NotificationChannel getNotificationChannel(); method public java.lang.String getOverrideGroupKey(); method public java.lang.String getPackageName(); method public long getPostTime(); diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl index f909af0692248..d674bfe232315 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl @@ -47,6 +47,8 @@ interface INotificationManager in Notification notification, inout int[] idReceived, int userId); void cancelNotificationWithTag(String pkg, String tag, int id, int userId); + void setShowBadge(String pkg, int uid, boolean showBadge); + boolean canShowBadge(String pkg, int uid); void setNotificationsEnabledForPackage(String pkg, int uid, boolean enabled); boolean areNotificationsEnabledForPackage(String pkg, int uid); boolean areNotificationsEnabled(String pkg); diff --git a/core/java/android/app/NotificationChannel.java b/core/java/android/app/NotificationChannel.java index 56ef791d365a7..be5f80a82b1ba 100644 --- a/core/java/android/app/NotificationChannel.java +++ b/core/java/android/app/NotificationChannel.java @@ -122,6 +122,7 @@ public final class NotificationChannel implements Parcelable { private static final int DEFAULT_IMPORTANCE = NotificationManager.IMPORTANCE_UNSPECIFIED; private static final boolean DEFAULT_DELETED = false; + private static final boolean DEFAULT_SHOW_BADGE = true; private final String mId; private CharSequence mName; @@ -133,7 +134,7 @@ public final class NotificationChannel implements Parcelable { private long[] mVibration; private int mUserLockedFields; private boolean mVibrationEnabled; - private boolean mShowBadge; + private boolean mShowBadge = DEFAULT_SHOW_BADGE; private boolean mDeleted = DEFAULT_DELETED; /** @@ -368,6 +369,8 @@ public final class NotificationChannel implements Parcelable { /** * Returns whether notifications posted to this channel can appear as badges in a Launcher * application. + * + * Note that badging may be disabled for other reasons. */ public boolean canShowBadge() { return mShowBadge; diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java index 694837e53c733..d9306897d8767 100644 --- a/core/java/android/service/notification/NotificationListenerService.java +++ b/core/java/android/service/notification/NotificationListenerService.java @@ -1166,11 +1166,12 @@ public abstract class NotificationListenerService extends Service { // System specified group key. private String mOverrideGroupKey; // Notification assistant channel override. - private NotificationChannel mOverrideChannel; + private NotificationChannel mChannel; // Notification assistant people override. private ArrayList mOverridePeople; // Notification assistant snooze criteria. private ArrayList mSnoozeCriteria; + private boolean mShowBadge; public Ranking() {} @@ -1200,7 +1201,7 @@ public abstract class NotificationListenerService extends Service { } /** - * Returns the user specificed visibility for the package that posted + * Returns the user specified visibility for the package that posted * this notification, or * {@link NotificationListenerService.Ranking#VISIBILITY_NO_OVERRIDE} if * no such preference has been expressed. @@ -1233,7 +1234,7 @@ public abstract class NotificationListenerService extends Service { * Returns the importance of the notification, which dictates its * modes of presentation, see: {@link NotificationManager#IMPORTANCE_DEFAULT}, etc. * - * @return the rank of the notification + * @return the importance of the notification */ public @NotificationManager.Importance int getImportance() { return mImportance; @@ -1258,12 +1259,11 @@ public abstract class NotificationListenerService extends Service { } /** - * If the {@link NotificationAssistantService} has overridden the channel this notification - * was posted to, then this will not match the channel provided by the posting application - * and this should be used to determine the interruptiveness of the notification instead. + * Returns the notification channel this notification was posted to, which dictates + * notification behavior and presentation. */ public NotificationChannel getChannel() { - return mOverrideChannel; + return mChannel; } /** @@ -1283,11 +1283,20 @@ public abstract class NotificationListenerService extends Service { return mSnoozeCriteria; } + /** + * Returns whether this notification can be displayed as a badge. + * + * @return true if the notification can be displayed as a badge, false otherwise. + */ + public boolean canShowBadge() { + return mShowBadge; + } + private void populate(String key, int rank, boolean matchesInterruptionFilter, int visibilityOverride, int suppressedVisualEffects, int importance, CharSequence explanation, String overrideGroupKey, - NotificationChannel overrideChannel, ArrayList overridePeople, - ArrayList snoozeCriteria) { + NotificationChannel channel, ArrayList overridePeople, + ArrayList snoozeCriteria, boolean showBadge) { mKey = key; mRank = rank; mIsAmbient = importance < NotificationManager.IMPORTANCE_LOW; @@ -1297,9 +1306,10 @@ public abstract class NotificationListenerService extends Service { mImportance = importance; mImportanceExplanation = explanation; mOverrideGroupKey = overrideGroupKey; - mOverrideChannel = overrideChannel; + mChannel = channel; mOverridePeople = overridePeople; mSnoozeCriteria = snoozeCriteria; + mShowBadge = showBadge; } /** @@ -1343,9 +1353,10 @@ public abstract class NotificationListenerService extends Service { private ArrayMap mImportance; private ArrayMap mImportanceExplanation; private ArrayMap mOverrideGroupKeys; - private ArrayMap mOverrideChannels; + private ArrayMap mChannels; private ArrayMap> mOverridePeople; private ArrayMap> mSnoozeCriteria; + private ArrayMap mShowBadge; private RankingMap(NotificationRankingUpdate rankingUpdate) { mRankingUpdate = rankingUpdate; @@ -1373,7 +1384,8 @@ public abstract class NotificationListenerService extends Service { outRanking.populate(key, rank, !isIntercepted(key), getVisibilityOverride(key), getSuppressedVisualEffects(key), getImportance(key), getImportanceExplanation(key), getOverrideGroupKey(key), - getOverrideChannel(key), getOverridePeople(key), getSnoozeCriteria(key)); + getChannel(key), getOverridePeople(key), getSnoozeCriteria(key), + getShowBadge(key)); return rank >= 0; } @@ -1453,13 +1465,13 @@ public abstract class NotificationListenerService extends Service { return mOverrideGroupKeys.get(key); } - private NotificationChannel getOverrideChannel(String key) { + private NotificationChannel getChannel(String key) { synchronized (this) { - if (mOverrideChannels == null) { - buildOverrideChannelsLocked(); + if (mChannels == null) { + buildChannelsLocked(); } } - return mOverrideChannels.get(key); + return mChannels.get(key); } private ArrayList getOverridePeople(String key) { @@ -1480,6 +1492,16 @@ public abstract class NotificationListenerService extends Service { return mSnoozeCriteria.get(key); } + private boolean getShowBadge(String key) { + synchronized (this) { + if (mShowBadge == null) { + buildShowBadgeLocked(); + } + } + Boolean showBadge = mShowBadge.get(key); + return showBadge == null ? false : showBadge.booleanValue(); + } + // Locked by 'this' private void buildRanksLocked() { String[] orderedKeys = mRankingUpdate.getOrderedKeys(); @@ -1544,11 +1566,11 @@ public abstract class NotificationListenerService extends Service { } // Locked by 'this' - private void buildOverrideChannelsLocked() { - Bundle overrideChannels = mRankingUpdate.getOverrideChannels(); - mOverrideChannels = new ArrayMap<>(overrideChannels.size()); - for (String key : overrideChannels.keySet()) { - mOverrideChannels.put(key, overrideChannels.getParcelable(key)); + private void buildChannelsLocked() { + Bundle channels = mRankingUpdate.getChannels(); + mChannels = new ArrayMap<>(channels.size()); + for (String key : channels.keySet()) { + mChannels.put(key, channels.getParcelable(key)); } } @@ -1570,6 +1592,15 @@ public abstract class NotificationListenerService extends Service { } } + // Locked by 'this' + private void buildShowBadgeLocked() { + Bundle showBadge = mRankingUpdate.getShowBadge(); + mShowBadge = new ArrayMap<>(showBadge.size()); + for (String key : showBadge.keySet()) { + mShowBadge.put(key, showBadge.getBoolean(key)); + } + } + // ----------- Parcelable @Override diff --git a/core/java/android/service/notification/NotificationRankingUpdate.java b/core/java/android/service/notification/NotificationRankingUpdate.java index a2cdeffef2b16..326b212a94175 100644 --- a/core/java/android/service/notification/NotificationRankingUpdate.java +++ b/core/java/android/service/notification/NotificationRankingUpdate.java @@ -31,14 +31,16 @@ public class NotificationRankingUpdate implements Parcelable { private final int[] mImportance; private final Bundle mImportanceExplanation; private final Bundle mOverrideGroupKeys; - private final Bundle mOverrideChannels; + private final Bundle mChannels; private final Bundle mOverridePeople; private final Bundle mSnoozeCriteria; + private final Bundle mShowBadge; public NotificationRankingUpdate(String[] keys, String[] interceptedKeys, Bundle visibilityOverrides, Bundle suppressedVisualEffects, int[] importance, Bundle explanation, Bundle overrideGroupKeys, - Bundle overrideChannels, Bundle overridePeople, Bundle snoozeCriteria) { + Bundle channels, Bundle overridePeople, Bundle snoozeCriteria, + Bundle showBadge) { mKeys = keys; mInterceptedKeys = interceptedKeys; mVisibilityOverrides = visibilityOverrides; @@ -46,9 +48,10 @@ public class NotificationRankingUpdate implements Parcelable { mImportance = importance; mImportanceExplanation = explanation; mOverrideGroupKeys = overrideGroupKeys; - mOverrideChannels = overrideChannels; + mChannels = channels; mOverridePeople = overridePeople; mSnoozeCriteria = snoozeCriteria; + mShowBadge = showBadge; } public NotificationRankingUpdate(Parcel in) { @@ -60,9 +63,10 @@ public class NotificationRankingUpdate implements Parcelable { in.readIntArray(mImportance); mImportanceExplanation = in.readBundle(); mOverrideGroupKeys = in.readBundle(); - mOverrideChannels = in.readBundle(); + mChannels = in.readBundle(); mOverridePeople = in.readBundle(); mSnoozeCriteria = in.readBundle(); + mShowBadge = in.readBundle(); } @Override @@ -79,9 +83,10 @@ public class NotificationRankingUpdate implements Parcelable { out.writeIntArray(mImportance); out.writeBundle(mImportanceExplanation); out.writeBundle(mOverrideGroupKeys); - out.writeBundle(mOverrideChannels); + out.writeBundle(mChannels); out.writeBundle(mOverridePeople); out.writeBundle(mSnoozeCriteria); + out.writeBundle(mShowBadge); } public static final Parcelable.Creator CREATOR @@ -123,8 +128,8 @@ public class NotificationRankingUpdate implements Parcelable { return mOverrideGroupKeys; } - public Bundle getOverrideChannels() { - return mOverrideChannels; + public Bundle getChannels() { + return mChannels; } public Bundle getOverridePeople() { @@ -134,4 +139,8 @@ public class NotificationRankingUpdate implements Parcelable { public Bundle getSnoozeCriteria() { return mSnoozeCriteria; } + + public Bundle getShowBadge() { + return mShowBadge; + } } diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java index 6276af398c434..85baf4edaeca9 100644 --- a/core/java/android/service/notification/StatusBarNotification.java +++ b/core/java/android/service/notification/StatusBarNotification.java @@ -43,21 +43,18 @@ public class StatusBarNotification implements Parcelable { private final Notification notification; private final UserHandle user; private final long postTime; - private final NotificationChannel channel; private Context mContext; // used for inflation & icon expansion /** @hide */ - public StatusBarNotification(String pkg, String opPkg, NotificationChannel channel, int id, + public StatusBarNotification(String pkg, String opPkg, int id, String tag, int uid, int initialPid, Notification notification, UserHandle user, String overrideGroupKey, long postTime) { if (pkg == null) throw new NullPointerException(); if (notification == null) throw new NullPointerException(); - if (channel == null) throw new IllegalArgumentException(); this.pkg = pkg; this.opPkg = opPkg; - this.channel = channel; this.id = id; this.tag = tag; this.uid = uid; @@ -88,7 +85,6 @@ public class StatusBarNotification implements Parcelable { this.postTime = postTime; this.key = key(); this.groupKey = groupKey(); - this.channel = null; } public StatusBarNotification(Parcel in) { @@ -112,7 +108,6 @@ public class StatusBarNotification implements Parcelable { } this.key = key(); this.groupKey = groupKey(); - this.channel = NotificationChannel.CREATOR.createFromParcel(in); } private String key() { @@ -182,7 +177,6 @@ public class StatusBarNotification implements Parcelable { } else { out.writeInt(0); } - this.channel.writeToParcel(out, flags); } public int describeContents() { @@ -209,14 +203,14 @@ public class StatusBarNotification implements Parcelable { public StatusBarNotification cloneLight() { final Notification no = new Notification(); this.notification.cloneInto(no, false); // light copy - return new StatusBarNotification(this.pkg, this.opPkg, this.channel, + return new StatusBarNotification(this.pkg, this.opPkg, this.id, this.tag, this.uid, this.initialPid, no, this.user, this.overrideGroupKey, this.postTime); } @Override public StatusBarNotification clone() { - return new StatusBarNotification(this.pkg, this.opPkg, this.channel, + return new StatusBarNotification(this.pkg, this.opPkg, this.id, this.tag, this.uid, this.initialPid, this.notification.clone(), this.user, this.overrideGroupKey, this.postTime); } @@ -335,13 +329,6 @@ public class StatusBarNotification implements Parcelable { return overrideGroupKey; } - /** - * Returns the channel this notification was posted to. - */ - public NotificationChannel getNotificationChannel() { - return channel; - } - /** * @hide */ diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 7de48d3305bb0..c36279c28fdbe 100644 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -2090,6 +2090,7 @@ com.android.server.notification.ImportanceExtractor com.android.server.notification.NotificationIntrusivenessExtractor com.android.server.notification.VisibilityExtractor + com.android.server.notification.BadgeExtractor