diff options
author | Daniel Sandler <dsandler@android.com> | 2013-02-14 10:24:17 -0500 |
---|---|---|
committer | Daniel Sandler <dsandler@android.com> | 2013-02-19 15:26:37 -0500 |
commit | 09a247e9a86df068422cbe8b60430fb6583c028c (patch) | |
tree | d6f63d7f593bb9d062ff47ed655e0c73a1ba5893 | |
parent | 5acb33af357b56fffb055997718b1e4aa97f53fc (diff) | |
download | frameworks_base-09a247e9a86df068422cbe8b60430fb6583c028c.zip frameworks_base-09a247e9a86df068422cbe8b60430fb6583c028c.tar.gz frameworks_base-09a247e9a86df068422cbe8b60430fb6583c028c.tar.bz2 |
New INotificationListener interface.
Use with INotificationManager.registerListener(). Limited to
system only right now.
Change-Id: I65b6a8778267022cdc5e58eb75ae607a54b1cc52
-rw-r--r-- | Android.mk | 1 | ||||
-rw-r--r-- | core/java/android/app/INotificationListener.aidl | 26 | ||||
-rw-r--r-- | core/java/android/app/INotificationManager.aidl | 4 | ||||
-rw-r--r-- | core/java/com/android/internal/statusbar/INotificationListener.java | 0 | ||||
-rw-r--r-- | services/java/com/android/server/NotificationManagerService.java | 91 |
5 files changed, 122 insertions, 0 deletions
@@ -69,6 +69,7 @@ LOCAL_SRC_FILES += \ core/java/android/app/IAlarmManager.aidl \ core/java/android/app/IBackupAgent.aidl \ core/java/android/app/IInstrumentationWatcher.aidl \ + core/java/android/app/INotificationListener.aidl \ core/java/android/app/INotificationManager.aidl \ core/java/android/app/IProcessObserver.aidl \ core/java/android/app/ISearchManager.aidl \ diff --git a/core/java/android/app/INotificationListener.aidl b/core/java/android/app/INotificationListener.aidl new file mode 100644 index 0000000..f010a2a --- /dev/null +++ b/core/java/android/app/INotificationListener.aidl @@ -0,0 +1,26 @@ +/** + * Copyright (c) 2013, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.app; + +import com.android.internal.statusbar.StatusBarNotification; + +/** @hide */ +oneway interface INotificationListener +{ + void onNotificationPosted(in StatusBarNotification notification); + void onNotificationRemoved(in StatusBarNotification notification); +}
\ No newline at end of file diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl index 1f4c81d..14bcc0d 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl @@ -17,6 +17,7 @@ package android.app; +import android.app.INotificationListener; import android.app.ITransientNotification; import android.app.Notification; import android.content.Intent; @@ -39,5 +40,8 @@ interface INotificationManager StatusBarNotification[] getActiveNotifications(String callingPkg); StatusBarNotification[] getHistoricalNotifications(String callingPkg, int count); + + void registerListener(in INotificationListener listener, int userid); + void unregisterListener(in INotificationListener listener, int userid); } diff --git a/core/java/com/android/internal/statusbar/INotificationListener.java b/core/java/com/android/internal/statusbar/INotificationListener.java new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/core/java/com/android/internal/statusbar/INotificationListener.java diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java index 13bf39f..9f2685b 100644 --- a/services/java/com/android/server/NotificationManagerService.java +++ b/services/java/com/android/server/NotificationManagerService.java @@ -26,6 +26,7 @@ import android.app.AppGlobals; import android.app.AppOpsManager; import android.app.IActivityManager; import android.app.INotificationManager; +import android.app.INotificationListener; import android.app.ITransientNotification; import android.app.Notification; import android.app.PendingIntent; @@ -151,6 +152,7 @@ public class NotificationManagerService extends INotificationManager.Stub private boolean mInCall = false; private boolean mNotificationPulseEnabled; + // used as a mutex for access to all active notifications & listeners private final ArrayList<NotificationRecord> mNotificationList = new ArrayList<NotificationRecord>(); @@ -161,6 +163,8 @@ public class NotificationManagerService extends INotificationManager.Stub private final AppOpsManager mAppOps; + private ArrayList<NotificationListenerInfo> mListeners = new ArrayList<NotificationListenerInfo>(); + // Notification control database. For now just contains disabled packages. private AtomicFile mPolicyFile; private HashSet<String> mBlockedPackages = new HashSet<String>(); @@ -174,6 +178,38 @@ public class NotificationManagerService extends INotificationManager.Stub private static final String TAG_PACKAGE = "package"; private static final String ATTR_NAME = "name"; + private class NotificationListenerInfo implements DeathRecipient { + INotificationListener listener; + int userid; + public NotificationListenerInfo(INotificationListener listener, int userid) { + this.listener = listener; + this.userid = userid; + } + + public void notifyPostedIfUserMatch(StatusBarNotification sbn) { + if (this.userid != sbn.getUserId()) return; + try { + listener.onNotificationPosted(sbn); + } catch (RemoteException ex) { + // not there? + } + } + + public void notifyRemovedIfUserMatch(StatusBarNotification sbn) { + if (this.userid != sbn.getUserId()) return; + try { + listener.onNotificationRemoved(sbn); + } catch (RemoteException ex) { + // not there? + } + } + + @Override + public void binderDied() { + unregisterListener(this.listener, this.userid); + } + } + private static class Archive { static final int BUFFER_SIZE = 1000; ArrayDeque<StatusBarNotification> mBuffer = new ArrayDeque<StatusBarNotification>(BUFFER_SIZE); @@ -406,6 +442,56 @@ public class NotificationManagerService extends INotificationManager.Stub return tmp; } + @Override + public void registerListener(final INotificationListener listener, final int userid) { + checkCallerIsSystem(); + synchronized (mNotificationList) { + try { + NotificationListenerInfo info = new NotificationListenerInfo(listener, userid); + listener.asBinder().linkToDeath(info, 0); + mListeners.add(info); + } catch (RemoteException e) { + // already dead + } + } + } + + @Override + public void unregisterListener(INotificationListener listener, int userid) { + checkCallerIsSystem(); + synchronized (mNotificationList) { + final int N = mListeners.size(); + for (int i=N-1; i>=0; i--) { + final NotificationListenerInfo info = mListeners.get(i); + if (info.listener == listener && info.userid == userid) { + mListeners.remove(listener); + } + } + } + } + + private void notifyPostedLocked(NotificationRecord n) { + final StatusBarNotification sbn = n.sbn; + for (final NotificationListenerInfo info : mListeners) { + mHandler.post(new Runnable() { + @Override + public void run() { + info.notifyPostedIfUserMatch(sbn); + }}); + } + } + + private void notifyRemovedLocked(NotificationRecord n) { + final StatusBarNotification sbn = n.sbn; + for (final NotificationListenerInfo info : mListeners) { + mHandler.post(new Runnable() { + @Override + public void run() { + info.notifyRemovedIfUserMatch(sbn); + }}); + } + } + public static final class NotificationRecord { final StatusBarNotification sbn; @@ -1165,6 +1251,8 @@ public class NotificationManagerService extends INotificationManager.Stub // finally, keep some of this information around for later use mArchive.record(n); + + notifyPostedLocked(r); } else { Slog.e(TAG, "Ignoring notification with icon==0: " + notification); if (old != null && old.statusBarKey != null) { @@ -1175,6 +1263,8 @@ public class NotificationManagerService extends INotificationManager.Stub finally { Binder.restoreCallingIdentity(identity); } + + notifyRemovedLocked(r); } return; // do not play sounds, show lights, etc. for invalid notifications } @@ -1341,6 +1431,7 @@ public class NotificationManagerService extends INotificationManager.Stub Binder.restoreCallingIdentity(identity); } r.statusBarKey = null; + notifyRemovedLocked(r); } // sound |