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

Commit 3bfa40e2 authored by John Spurlock's avatar John Spurlock Committed by Android Git Automerger
Browse files

am 752dc6e1: New NotificationListenerService listener flags api.

* commit '752dc6e171f3ba503b2a119f3ab5149b920a5161':
  New NotificationListenerService listener flags api.
parents 94d21115 1fa865f3
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -27226,14 +27226,19 @@ package android.service.notification {
    method public final void cancelNotification(java.lang.String);
    method public final void cancelNotifications(java.lang.String[]);
    method public android.service.notification.StatusBarNotification[] getActiveNotifications();
    method public final int getCurrentListenerFlags();
    method public android.service.notification.NotificationListenerService.RankingMap getCurrentRanking();
    method public android.os.IBinder onBind(android.content.Intent);
    method public void onListenerConnected();
    method public void onListenerFlagsChanged(int);
    method public void onNotificationPosted(android.service.notification.StatusBarNotification);
    method public void onNotificationPosted(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
    method public void onNotificationRankingUpdate(android.service.notification.NotificationListenerService.RankingMap);
    method public void onNotificationRemoved(android.service.notification.StatusBarNotification);
    method public void onNotificationRemoved(android.service.notification.StatusBarNotification, android.service.notification.NotificationListenerService.RankingMap);
    method public final void requestListenerFlags(int);
    field public static final int FLAG_DISABLE_HOST_ALERTS = 1; // 0x1
    field public static final int FLAG_NONE = 0; // 0x0
    field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationListenerService";
  }
+2 −0
Original line number Diff line number Diff line
@@ -59,6 +59,8 @@ interface INotificationManager
    void cancelNotificationsFromListener(in INotificationListener token, in String[] keys);

    ParceledListSlice getActiveNotificationsFromListener(in INotificationListener token);
    void requestFlagsFromListener(in INotificationListener token, int flags);
    int getFlagsFromListener(in INotificationListener token);

    ZenModeConfig getZenModeConfig();
    boolean setZenModeConfig(in ZenModeConfig config);
+1 −0
Original line number Diff line number Diff line
@@ -28,4 +28,5 @@ oneway interface INotificationListener
    void onNotificationRemoved(in StatusBarNotification notification,
            in NotificationRankingUpdate update);
    void onNotificationRankingUpdate(in NotificationRankingUpdate update);
    void onListenerFlagsChanged(int flags);
}
 No newline at end of file
+64 −0
Original line number Diff line number Diff line
@@ -53,6 +53,12 @@ public abstract class NotificationListenerService extends Service {
    private final String TAG = NotificationListenerService.class.getSimpleName()
            + "[" + getClass().getSimpleName() + "]";

    /** {@link #getCurrentListenerFlags() Listener flags} constant - default state. **/
    public static final int FLAG_NONE = 0;
    /** {@link #getCurrentListenerFlags() Listener flags} constant - the primary device UI
     * should disable notification sound, vibrating and other visual or aural effects. **/
    public static final int FLAG_DISABLE_HOST_ALERTS = 1;

    private INotificationListenerWrapper mWrapper = null;
    private RankingMap mRankingMap;

@@ -156,6 +162,16 @@ public abstract class NotificationListenerService extends Service {
        // optional
    }

    /**
     * Implement this method to be notified when the
     * {@link #getCurrentListenerFlags() listener flags} change.
     *
     * @param flags The current {@link #getCurrentListenerFlags() listener flags}.
     */
    public void onListenerFlagsChanged(int flags) {
        // optional
    }

    private final INotificationManager getNotificationInterface() {
        if (mNoMan == null) {
            mNoMan = INotificationManager.Stub.asInterface(
@@ -278,6 +294,46 @@ public abstract class NotificationListenerService extends Service {
        return null;
    }

    /**
     * Gets the set of flags representing current state.
     *
     * <p>
     * The current state may differ from the requested state if the flag represents state
     * shared across all listeners or a feature the notification host does not support or refuses
     * to grant.
     *
     * @return One or more of the FLAG_ constants.
     */
    public final int getCurrentListenerFlags() {
        if (!isBound()) return FLAG_NONE;
        try {
            return getNotificationInterface().getFlagsFromListener(mWrapper);
        } catch (android.os.RemoteException ex) {
            Log.v(TAG, "Unable to contact notification manager", ex);
            return FLAG_NONE;
        }
    }

    /**
     * Sets the desired {@link #getCurrentListenerFlags() listener flags}.
     *
     * <p>
     * This is merely a request, the host may or not choose to take action depending
     * on other listener requests or other global state.
     * <p>
     * Listen for updates using {@link #onListenerFlagsChanged(int)}.
     *
     * @param flags One or more of the FLAG_ constants.
     */
    public final void requestListenerFlags(int flags) {
        if (!isBound()) return;
        try {
            getNotificationInterface().requestFlagsFromListener(mWrapper, flags);
        } catch (android.os.RemoteException ex) {
            Log.v(TAG, "Unable to contact notification manager", ex);
        }
    }

    /**
     * Returns current ranking information.
     *
@@ -402,6 +458,14 @@ public abstract class NotificationListenerService extends Service {
                }
            }
        }
        @Override
        public void onListenerFlagsChanged(int flags) throws RemoteException {
            try {
                NotificationListenerService.this.onListenerFlagsChanged(flags);
            } catch (Throwable t) {
                Log.w(TAG, "Error running onListenerFlagsChanged", t);
            }
        }
    }

    private void applyUpdate(NotificationRankingUpdate update) {
+93 −2
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.server.notification;

import static android.service.notification.NotificationListenerService.FLAG_DISABLE_HOST_ALERTS;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.END_TAG;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
@@ -71,6 +72,7 @@ import android.service.notification.ZenModeConfig;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.Log;
import android.util.Slog;
@@ -121,6 +123,7 @@ public class NotificationManagerService extends SystemService {
    static final int MESSAGE_RECONSIDER_RANKING = 4;
    static final int MESSAGE_RANKING_CONFIG_CHANGE = 5;
    static final int MESSAGE_SEND_RANKING_UPDATE = 6;
    static final int MESSAGE_LISTENER_FLAGS_CHANGED = 7;

    static final int LONG_DELAY = 3500; // 3.5 seconds
    static final int SHORT_DELAY = 2000; // 2 seconds
@@ -169,6 +172,9 @@ public class NotificationManagerService extends SystemService {
    NotificationRecord mSoundNotification;
    NotificationRecord mVibrateNotification;

    private final ArraySet<ManagedServiceInfo> mListenersDisablingAlerts = new ArraySet<>();
    private int mListenerFlags;  // right now, all flags are global

    // for enabling and disabling notification pulse behavior
    private boolean mScreenOn = true;
    private boolean mInCall = false;
@@ -463,7 +469,7 @@ public class NotificationManagerService extends SystemService {
        public void onSetDisabled(int status) {
            synchronized (mNotificationList) {
                mDisableNotificationAlerts = (status & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0;
                if (mDisableNotificationAlerts) {
                if (disableNotificationAlerts()) {
                    // cancel whatever's going on
                    long identity = Binder.clearCallingIdentity();
                    try {
@@ -904,6 +910,13 @@ public class NotificationManagerService extends SystemService {
        }
    }

    private void updateListenerFlagsLocked() {
        final int flags = mListenersDisablingAlerts.isEmpty() ? 0 : FLAG_DISABLE_HOST_ALERTS;
        if (flags == mListenerFlags) return;
        mListenerFlags = flags;
        scheduleListenerFlagsChanged(flags);
    }

    private final IBinder mService = new INotificationManager.Stub() {
        // Toasts
        // ============================================================================
@@ -1248,6 +1261,27 @@ public class NotificationManagerService extends SystemService {
            }
        }

        @Override
        public void requestFlagsFromListener(INotificationListener token, int flags) {
            synchronized (mNotificationList) {
                final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
                final boolean disableAlerts = (flags & FLAG_DISABLE_HOST_ALERTS) != 0;
                if (disableAlerts) {
                    mListenersDisablingAlerts.add(info);
                } else {
                    mListenersDisablingAlerts.remove(info);
                }
                updateListenerFlagsLocked();
            }
        }

        @Override
        public int getFlagsFromListener(INotificationListener token) {
            synchronized (mNotificationList) {
                return mListenerFlags;
            }
        }

        @Override
        public ZenModeConfig getZenModeConfig() {
            enforceSystemOrSystemUI("INotificationManager.getZenModeConfig");
@@ -1339,6 +1373,10 @@ public class NotificationManagerService extends SystemService {
        return keys.toArray(new String[keys.size()]);
    }

    private boolean disableNotificationAlerts() {
        return mDisableNotificationAlerts || (mListenerFlags & FLAG_DISABLE_HOST_ALERTS) != 0;
    }

    void dumpImpl(PrintWriter pw, DumpFilter filter) {
        pw.print("Current Notification Manager state");
        if (filter != null) {
@@ -1422,6 +1460,15 @@ public class NotificationManagerService extends SystemService {

                pw.println("\n  Notification listeners:");
                mListeners.dump(pw, filter);
                pw.print("    mListenerFlags: "); pw.println(mListenerFlags);
                pw.print("    mListenersDisablingAlerts: (");
                N = mListenersDisablingAlerts.size();
                for (int i = 0; i < N; i++) {
                    final ManagedServiceInfo listener = mListenersDisablingAlerts.valueAt(i);
                    if (i > 0) pw.print(',');
                    pw.print(listener.component);
                }
                pw.println(')');
            }

            pw.println("\n  Condition providers:");
@@ -1618,7 +1665,7 @@ public class NotificationManagerService extends SystemService {
        }

        // If we're not supposed to beep, vibrate, etc. then don't.
        if (!mDisableNotificationAlerts
        if (!disableNotificationAlerts()
                && (!(record.isUpdate
                    && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 ))
                && (record.getUserId() == UserHandle.USER_ALL ||
@@ -1920,6 +1967,17 @@ public class NotificationManagerService extends SystemService {
        }
    }

    private void scheduleListenerFlagsChanged(int state) {
        mHandler.removeMessages(MESSAGE_LISTENER_FLAGS_CHANGED);
        mHandler.obtainMessage(MESSAGE_LISTENER_FLAGS_CHANGED, state, 0).sendToTarget();
    }

    private void handleListenerFlagsChanged(int state) {
        synchronized (mNotificationList) {
            mListeners.notifyListenerFlagsChangedLocked(state);
        }
    }

    private final class WorkerHandler extends Handler
    {
        @Override
@@ -1936,6 +1994,9 @@ public class NotificationManagerService extends SystemService {
                case MESSAGE_SEND_RANKING_UPDATE:
                    handleSendRankingUpdate();
                    break;
                case MESSAGE_LISTENER_FLAGS_CHANGED:
                    handleListenerFlagsChanged(msg.arg1);
                    break;
            }
        }

@@ -2445,6 +2506,13 @@ public class NotificationManagerService extends SystemService {
            }
        }

        @Override
        protected void onServiceRemovedLocked(ManagedServiceInfo removed) {
            if (mListenersDisablingAlerts.remove(removed)) {
                updateListenerFlagsLocked();
            }
        }

        /**
         * asynchronously notify all listeners about a new notification
         */
@@ -2509,6 +2577,20 @@ public class NotificationManagerService extends SystemService {
            }
        }

        public void notifyListenerFlagsChangedLocked(final int flags) {
            for (final ManagedServiceInfo serviceInfo : mServices) {
                if (!serviceInfo.isEnabledForCurrentProfiles()) {
                    continue;
                }
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        notifyListenerFlagsChanged(serviceInfo, flags);
                    }
                });
            }
        }

        private void notifyPostedIfUserMatch(final ManagedServiceInfo info,
                final StatusBarNotification sbn, NotificationRankingUpdate rankingUpdate) {
            if (!info.enabledAndUserMatches(sbn.getUserId())) {
@@ -2544,6 +2626,15 @@ public class NotificationManagerService extends SystemService {
                Log.e(TAG, "unable to notify listener (ranking update): " + listener, ex);
            }
        }

        private void notifyListenerFlagsChanged(ManagedServiceInfo info, int state) {
            final INotificationListener listener = (INotificationListener) info.service;
            try {
                listener.onListenerFlagsChanged(state);
            } catch (RemoteException ex) {
                Log.e(TAG, "unable to notify listener (listener flags): " + listener, ex);
            }
        }
    }

    public static final class DumpFilter {