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

Commit c4aee98a authored by John Spurlock's avatar John Spurlock
Browse files

Improve error handling in listener services.

Check explicitly for null listeners in NMS, throwing
IllegalArgumentException (on the small list of exceptions
that survive RPC boundaries) with a message.

Normally this situation is caused by listeners that attempt to
perform NM-related actions before they are bound.  Check for
this case in the base NLS class and avoid the call to NM if we
know it will fail.

Although it's tempting to throw an IllegalStateException on the
client side, preserve the existing semantics for backwards-compatibility
purposes.  That is, silently fail (or return null) - and provide a
log warning.

Bug:12805707
Change-Id: I0d92fd0d460a8592e8a23fd8fd718ae2ba3bd4c7
parent 879592d8
Loading
Loading
Loading
Loading
+11 −0
Original line number Original line Diff line number Diff line
@@ -112,6 +112,7 @@ public abstract class NotificationListenerService extends Service {
     *     {@link android.app.NotificationManager#notify(String, int, android.app.Notification)}.
     *     {@link android.app.NotificationManager#notify(String, int, android.app.Notification)}.
     */
     */
    public final void cancelNotification(String pkg, String tag, int id) {
    public final void cancelNotification(String pkg, String tag, int id) {
        if (!isBound()) return;
        try {
        try {
            getNotificationInterface().cancelNotificationFromListener(mWrapper, pkg, tag, id);
            getNotificationInterface().cancelNotificationFromListener(mWrapper, pkg, tag, id);
        } catch (android.os.RemoteException ex) {
        } catch (android.os.RemoteException ex) {
@@ -131,6 +132,7 @@ public abstract class NotificationListenerService extends Service {
     * {@see #cancelNotification(String, String, int)}
     * {@see #cancelNotification(String, String, int)}
     */
     */
    public final void cancelAllNotifications() {
    public final void cancelAllNotifications() {
        if (!isBound()) return;
        try {
        try {
            getNotificationInterface().cancelAllNotificationsFromListener(mWrapper);
            getNotificationInterface().cancelAllNotificationsFromListener(mWrapper);
        } catch (android.os.RemoteException ex) {
        } catch (android.os.RemoteException ex) {
@@ -145,6 +147,7 @@ public abstract class NotificationListenerService extends Service {
     * @return An array of active notifications.
     * @return An array of active notifications.
     */
     */
    public StatusBarNotification[] getActiveNotifications() {
    public StatusBarNotification[] getActiveNotifications() {
        if (!isBound()) return null;
        try {
        try {
            return getNotificationInterface().getActiveNotificationsFromListener(mWrapper);
            return getNotificationInterface().getActiveNotificationsFromListener(mWrapper);
        } catch (android.os.RemoteException ex) {
        } catch (android.os.RemoteException ex) {
@@ -161,6 +164,14 @@ public abstract class NotificationListenerService extends Service {
        return mWrapper;
        return mWrapper;
    }
    }


    private boolean isBound() {
        if (mWrapper == null) {
            Log.w(TAG, "Notification listener service not yet bound.");
            return false;
        }
        return true;
    }

    private class INotificationListenerWrapper extends INotificationListener.Stub {
    private class INotificationListenerWrapper extends INotificationListener.Stub {
        @Override
        @Override
        public void onNotificationPosted(StatusBarNotification sbn) {
        public void onNotificationPosted(StatusBarNotification sbn) {
+9 −0
Original line number Original line Diff line number Diff line
@@ -725,7 +725,14 @@ public class NotificationManagerService extends SystemService {


    // -- APIs to support listeners clicking/clearing notifications --
    // -- APIs to support listeners clicking/clearing notifications --


    private void checkNullListener(INotificationListener listener) {
        if (listener == null) {
            throw new IllegalArgumentException("Listener must not be null");
        }
    }

    private NotificationListenerInfo checkListenerToken(INotificationListener listener) {
    private NotificationListenerInfo checkListenerToken(INotificationListener listener) {
        checkNullListener(listener);
        final IBinder token = listener.asBinder();
        final IBinder token = listener.asBinder();
        final int N = mListeners.size();
        final int N = mListeners.size();
        for (int i=0; i<N; i++) {
        for (int i=0; i<N; i++) {
@@ -1469,6 +1476,7 @@ public class NotificationManagerService extends SystemService {
        public void registerListener(final INotificationListener listener,
        public void registerListener(final INotificationListener listener,
                final ComponentName component, final int userid) {
                final ComponentName component, final int userid) {
            checkCallerIsSystem();
            checkCallerIsSystem();
            checkNullListener(listener);
            registerListenerImpl(listener, component, userid);
            registerListenerImpl(listener, component, userid);
        }
        }


@@ -1477,6 +1485,7 @@ public class NotificationManagerService extends SystemService {
         */
         */
        @Override
        @Override
        public void unregisterListener(INotificationListener listener, int userid) {
        public void unregisterListener(INotificationListener listener, int userid) {
            checkNullListener(listener);
            // no need to check permissions; if your listener binder is in the list,
            // no need to check permissions; if your listener binder is in the list,
            // that's proof that you had permission to add it in the first place
            // that's proof that you had permission to add it in the first place
            unregisterListenerImpl(listener, userid);
            unregisterListenerImpl(listener, userid);