Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 09a247e9 authored by Daniel Sandler's avatar Daniel Sandler
Browse files

New INotificationListener interface.

Use with INotificationManager.registerListener(). Limited to
system only right now.

Change-Id: I65b6a8778267022cdc5e58eb75ae607a54b1cc52
parent 5acb33af
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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 \
+26 −0
Original line number Diff line number Diff line
/**
 * 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
+4 −0
Original line number Diff line number Diff line
@@ -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);
}
+0 −0

Empty file added.

+91 −0
Original line number Diff line number Diff line
@@ -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