diff --git a/api/current.txt b/api/current.txt index faeab39f767b2..190397b5ea125 100644 --- a/api/current.txt +++ b/api/current.txt @@ -24317,8 +24317,12 @@ package android.service.notification { ctor public NotificationListenerService(); method public final void cancelAllNotifications(); method public final void cancelNotification(java.lang.String, java.lang.String, int); + method public final void cancelNotifications(java.lang.String[]); + method public java.lang.String[] getActiveNotificationKeys(); method public android.service.notification.StatusBarNotification[] getActiveNotifications(); + method public android.service.notification.StatusBarNotification[] getActiveNotifications(java.lang.String[]); method public android.os.IBinder onBind(android.content.Intent); + method public void onListenerConnected(java.lang.String[]); method public abstract void onNotificationPosted(android.service.notification.StatusBarNotification); method public abstract void onNotificationRemoved(android.service.notification.StatusBarNotification); field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationListenerService"; @@ -24330,6 +24334,7 @@ package android.service.notification { method public android.service.notification.StatusBarNotification clone(); method public int describeContents(); method public int getId(); + method public java.lang.String getKey(); method public android.app.Notification getNotification(); 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 9f933ca66c21e..99114675ed1da 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl @@ -45,7 +45,8 @@ interface INotificationManager void unregisterListener(in INotificationListener listener, int userid); void cancelNotificationFromListener(in INotificationListener token, String pkg, String tag, int id); - void cancelAllNotificationsFromListener(in INotificationListener token); + void cancelNotificationsFromListener(in INotificationListener token, in String[] keys); - StatusBarNotification[] getActiveNotificationsFromListener(in INotificationListener token); + StatusBarNotification[] getActiveNotificationsFromListener(in INotificationListener token, in String[] keys); + String[] getActiveNotificationKeysFromListener(in INotificationListener token); } \ No newline at end of file diff --git a/core/java/android/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl index 425fdc113a344..d4b29d8e3a4d4 100644 --- a/core/java/android/service/notification/INotificationListener.aidl +++ b/core/java/android/service/notification/INotificationListener.aidl @@ -21,6 +21,7 @@ import android.service.notification.StatusBarNotification; /** @hide */ oneway interface INotificationListener { + void onListenerConnected(in String[] notificationKeys); void onNotificationPosted(in StatusBarNotification notification); void onNotificationRemoved(in StatusBarNotification notification); } \ No newline at end of file diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java index cf862b872aa31..050e1a0e52864 100644 --- a/core/java/android/service/notification/NotificationListenerService.java +++ b/core/java/android/service/notification/NotificationListenerService.java @@ -83,6 +83,17 @@ public abstract class NotificationListenerService extends Service { */ public abstract void onNotificationRemoved(StatusBarNotification sbn); + /** + * Implement this method to learn about when the listener is enabled and connected to + * the notification manager. You are safe to call {@link #getActiveNotifications(String[]) + * at this time. + * + * @param notificationKeys The notification keys for all currently posted notifications. + */ + public void onListenerConnected(String[] notificationKeys) { + // optional + } + private final INotificationManager getNotificationInterface() { if (mNoMan == null) { mNoMan = INotificationManager.Stub.asInterface( @@ -132,9 +143,23 @@ public abstract class NotificationListenerService extends Service { * {@see #cancelNotification(String, String, int)} */ public final void cancelAllNotifications() { + cancelNotifications(null /*all*/); + } + + /** + * Inform the notification manager about dismissal of specific notifications. + *
+ * Use this if your listener has a user interface that allows the user to dismiss
+ * multiple notifications at once.
+ *
+ * @param keys Notifications to dismiss, or {@code null} to dismiss all.
+ *
+ * {@see #cancelNotification(String, String, int)}
+ */
+ public final void cancelNotifications(String[] keys) {
if (!isBound()) return;
try {
- getNotificationInterface().cancelAllNotificationsFromListener(mWrapper);
+ getNotificationInterface().cancelNotificationsFromListener(mWrapper, keys);
} catch (android.os.RemoteException ex) {
Log.v(TAG, "Unable to contact notification manager", ex);
}
@@ -142,14 +167,43 @@ public abstract class NotificationListenerService extends Service {
/**
* Request the list of outstanding notifications (that is, those that are visible to the
- * current user). Useful when starting up and you don't know what's already been posted.
+ * current user). Useful when you don't know what's already been posted.
*
* @return An array of active notifications.
*/
public StatusBarNotification[] getActiveNotifications() {
+ return getActiveNotifications(null /*all*/);
+ }
+
+ /**
+ * Request the list of outstanding notifications (that is, those that are visible to the
+ * current user). Useful when you don't know what's already been posted.
+ *
+ * @param keys A specific list of notification keys, or {@code null} for all.
+ * @return An array of active notifications.
+ */
+ public StatusBarNotification[] getActiveNotifications(String[] keys) {
if (!isBound()) return null;
try {
- return getNotificationInterface().getActiveNotificationsFromListener(mWrapper);
+ return getNotificationInterface().getActiveNotificationsFromListener(mWrapper, keys);
+ } catch (android.os.RemoteException ex) {
+ Log.v(TAG, "Unable to contact notification manager", ex);
+ }
+ return null;
+ }
+
+ /**
+ * Request the list of outstanding notification keys(that is, those that are visible to the
+ * current user). You can use the notification keys for subsequent retrieval via
+ * {@link #getActiveNotifications(String[]) or dismissal via
+ * {@link #cancelNotifications(String[]).
+ *
+ * @return An array of active notification keys.
+ */
+ public String[] getActiveNotificationKeys() {
+ if (!isBound()) return null;
+ try {
+ return getNotificationInterface().getActiveNotificationKeysFromListener(mWrapper);
} catch (android.os.RemoteException ex) {
Log.v(TAG, "Unable to contact notification manager", ex);
}
@@ -189,5 +243,13 @@ public abstract class NotificationListenerService extends Service {
Log.w(TAG, "Error running onNotificationRemoved", t);
}
}
+ @Override
+ public void onListenerConnected(String[] notificationKeys) {
+ try {
+ NotificationListenerService.this.onListenerConnected(notificationKeys);
+ } catch (Throwable t) {
+ Log.w(TAG, "Error running onListenerConnected", t);
+ }
+ }
}
}
diff --git a/core/java/android/service/notification/StatusBarNotification.java b/core/java/android/service/notification/StatusBarNotification.java
index b5b9e14298910..7f15ab85261ac 100644
--- a/core/java/android/service/notification/StatusBarNotification.java
+++ b/core/java/android/service/notification/StatusBarNotification.java
@@ -29,6 +29,7 @@ public class StatusBarNotification implements Parcelable {
private final String pkg;
private final int id;
private final String tag;
+ private final String key;
private final int uid;
private final String basePkg;
@@ -68,8 +69,8 @@ public class StatusBarNotification implements Parcelable {
this.notification = notification;
this.user = user;
this.notification.setUser(user);
-
this.postTime = postTime;
+ this.key = key();
}
public StatusBarNotification(Parcel in) {
@@ -88,6 +89,11 @@ public class StatusBarNotification implements Parcelable {
this.user = UserHandle.readFromParcel(in);
this.notification.setUser(this.user);
this.postTime = in.readLong();
+ this.key = key();
+ }
+
+ private String key() {
+ return pkg + '|' + basePkg + '|' + id + '|' + tag + '|' + uid;
}
public void writeToParcel(Parcel out, int flags) {
@@ -148,9 +154,9 @@ public class StatusBarNotification implements Parcelable {
@Override
public String toString() {
return String.format(
- "StatusBarNotification(pkg=%s user=%s id=%d tag=%s score=%d: %s)",
+ "StatusBarNotification(pkg=%s user=%s id=%d tag=%s score=%d key=%s: %s)",
this.pkg, this.user, this.id, this.tag,
- this.score, this.notification);
+ this.score, this.key, this.notification);
}
/** Convenience method to check the notification's flags for
@@ -230,4 +236,11 @@ public class StatusBarNotification implements Parcelable {
public int getScore() {
return score;
}
+
+ /**
+ * A unique instance key for this notification record.
+ */
+ public String getKey() {
+ return key;
+ }
}
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index e25e42cc2d312..ccd6f602bc857 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -65,8 +65,8 @@ import android.service.notification.NotificationListenerService;
import android.service.notification.StatusBarNotification;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
+import android.util.ArrayMap;
import android.util.AtomicFile;
-import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
@@ -76,7 +76,6 @@ import android.view.accessibility.AccessibilityManager;
import android.widget.Toast;
import com.android.internal.R;
-
import com.android.internal.notification.NotificationScorer;
import com.android.server.EventLogTags;
import com.android.server.statusbar.StatusBarManagerInternal;
@@ -169,7 +168,8 @@ public class NotificationManagerService extends SystemService {
// used as a mutex for access to all active notifications & listeners
final ArrayList