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

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

New api to sync zen mode state from listeners.

 - Allow connected listeners to request changes
   to the primary device's interruption level.
 - Rename alerts -> effects in the other constant,
   which does not affect interruption level.
 - Rename "flags" -> "hints"
 - Basic NoMan wiring for level hint.

Bug:15888672
Change-Id: I2b07fb2c9d32a143fff7c260b7d2cd4d0cd3a592
parent 2d28d6e1
Loading
Loading
Loading
Loading
+9 −5
Original line number Diff line number Diff line
@@ -27409,19 +27409,23 @@ 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 final int getCurrentListenerHints();
    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 onListenerHintsChanged(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
    method public final void requestListenerHints(int);
    field public static final int HINTS_NONE = 0; // 0x0
    field public static final int HINT_HOST_DISABLE_EFFECTS = 4; // 0x4
    field public static final int HINT_HOST_INTERRUPTION_LEVEL_ALL = 1; // 0x1
    field public static final int HINT_HOST_INTERRUPTION_LEVEL_NONE = 3; // 0x3
    field public static final int HINT_HOST_INTERRUPTION_LEVEL_PRIORITY = 2; // 0x2
    field public static final int HOST_INTERRUPTION_LEVEL_MASK = 3; // 0x3
    field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationListenerService";
  }
+2 −2
Original line number Diff line number Diff line
@@ -59,8 +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);
    void requestHintsFromListener(in INotificationListener token, int hints);
    int getHintsFromListener(in INotificationListener token);

    ZenModeConfig getZenModeConfig();
    boolean setZenModeConfig(in ZenModeConfig config);
+1 −1
Original line number Diff line number Diff line
@@ -28,5 +28,5 @@ oneway interface INotificationListener
    void onNotificationRemoved(in StatusBarNotification notification,
            in NotificationRankingUpdate update);
    void onNotificationRankingUpdate(in NotificationRankingUpdate update);
    void onListenerFlagsChanged(int flags);
    void onListenerHintsChanged(int hints);
}
 No newline at end of file
+38 −23
Original line number Diff line number Diff line
@@ -58,11 +58,26 @@ 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;
    /** {@link #getCurrentListenerHints() Listener hints} constant - default state. */
    public static final int HINTS_NONE = 0;

    /** Bitmask range for {@link #getCurrentListenerHints() Listener hints} host interruption level
     * constants.  */
    public static final int HOST_INTERRUPTION_LEVEL_MASK = 0x3;

    /** {@link #getCurrentListenerHints() Listener hints} constant - Normal interruption level. */
    public static final int HINT_HOST_INTERRUPTION_LEVEL_ALL = 1;

    /** {@link #getCurrentListenerHints() Listener hints} constant - Priority interruption level. */
    public static final int HINT_HOST_INTERRUPTION_LEVEL_PRIORITY = 2;

    /** {@link #getCurrentListenerHints() Listener hints} constant - No interruptions level. */
    public static final int HINT_HOST_INTERRUPTION_LEVEL_NONE = 3;

    /** {@link #getCurrentListenerHints() Listener hints} constant - the primary device UI
     * should disable notification sound, vibrating and other visual or aural effects.
     * This does not change the interruption level, only the effects. **/
    public static final int HINT_HOST_DISABLE_EFFECTS = 1 << 2;

    private INotificationListenerWrapper mWrapper = null;
    private RankingMap mRankingMap;
@@ -174,11 +189,11 @@ public abstract class NotificationListenerService extends Service {

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

@@ -311,40 +326,40 @@ public abstract class NotificationListenerService extends Service {
    }

    /**
     * Gets the set of flags representing current state.
     * Gets the set of hints representing current state.
     *
     * <p>
     * The current state may differ from the requested state if the flag represents state
     * The current state may differ from the requested state if the hint 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.
     * @return One or more of the HINT_ constants.
     */
    public final int getCurrentListenerFlags() {
        if (!isBound()) return FLAG_NONE;
    public final int getCurrentListenerHints() {
        if (!isBound()) return HINTS_NONE;
        try {
            return getNotificationInterface().getFlagsFromListener(mWrapper);
            return getNotificationInterface().getHintsFromListener(mWrapper);
        } catch (android.os.RemoteException ex) {
            Log.v(TAG, "Unable to contact notification manager", ex);
            return FLAG_NONE;
            return HINTS_NONE;
        }
    }

    /**
     * Sets the desired {@link #getCurrentListenerFlags() listener flags}.
     * Sets the desired {@link #getCurrentListenerHints() listener hints}.
     *
     * <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)}.
     * Listen for updates using {@link #onListenerHintsChanged(int)}.
     *
     * @param flags One or more of the FLAG_ constants.
     * @param hints One or more of the HINT_ constants.
     */
    public final void requestListenerFlags(int flags) {
    public final void requestListenerHints(int hints) {
        if (!isBound()) return;
        try {
            getNotificationInterface().requestFlagsFromListener(mWrapper, flags);
            getNotificationInterface().requestHintsFromListener(mWrapper, hints);
        } catch (android.os.RemoteException ex) {
            Log.v(TAG, "Unable to contact notification manager", ex);
        }
@@ -480,11 +495,11 @@ public abstract class NotificationListenerService extends Service {
            }
        }
        @Override
        public void onListenerFlagsChanged(int flags) throws RemoteException {
        public void onListenerHintsChanged(int hints) throws RemoteException {
            try {
                NotificationListenerService.this.onListenerFlagsChanged(flags);
                NotificationListenerService.this.onListenerHintsChanged(hints);
            } catch (Throwable t) {
                Log.w(TAG, "Error running onListenerFlagsChanged", t);
                Log.w(TAG, "Error running onListenerHintsChanged", t);
            }
        }
    }
+61 −46
Original line number Diff line number Diff line
@@ -16,7 +16,7 @@

package com.android.server.notification;

import static android.service.notification.NotificationListenerService.FLAG_DISABLE_HOST_ALERTS;
import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_EFFECTS;
import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
import static org.xmlpull.v1.XmlPullParser.END_TAG;
import static org.xmlpull.v1.XmlPullParser.START_TAG;
@@ -125,7 +125,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 MESSAGE_LISTENER_HINTS_CHANGED = 7;

    static final int LONG_DELAY = 3500; // 3.5 seconds
    static final int SHORT_DELAY = 2000; // 2 seconds
@@ -170,12 +170,12 @@ public class NotificationManagerService extends SystemService {
    private boolean mUseAttentionLight;
    boolean mSystemReady;

    private boolean mDisableNotificationAlerts;
    private boolean mDisableNotificationEffects;
    NotificationRecord mSoundNotification;
    NotificationRecord mVibrateNotification;

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

    // for enabling and disabling notification pulse behavior
    private boolean mScreenOn = true;
@@ -470,8 +470,9 @@ public class NotificationManagerService extends SystemService {
        @Override
        public void onSetDisabled(int status) {
            synchronized (mNotificationList) {
                mDisableNotificationAlerts = (status & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0;
                if (disableNotificationAlerts()) {
                mDisableNotificationEffects =
                        (status & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0;
                if (disableNotificationEffects()) {
                    // cancel whatever's going on
                    long identity = Binder.clearCallingIdentity();
                    try {
@@ -803,6 +804,13 @@ public class NotificationManagerService extends SystemService {
            public void onConfigChanged() {
                savePolicyFile();
            }

            @Override
            void onZenModeChanged() {
                synchronized(mNotificationList) {
                    updateListenerHintsLocked();
                }
            }
        });
        final File systemDir = new File(Environment.getDataDirectory(), "system");
        mPolicyFile = new AtomicFile(new File(systemDir, "notification_policy.xml"));
@@ -845,7 +853,7 @@ public class NotificationManagerService extends SystemService {
        // flag at least once and we'll go back to 0 after that.
        if (0 == Settings.Global.getInt(getContext().getContentResolver(),
                    Settings.Global.DEVICE_PROVISIONED, 0)) {
            mDisableNotificationAlerts = true;
            mDisableNotificationEffects = true;
        }
        mZenModeHelper.updateZenMode();

@@ -931,11 +939,12 @@ 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 void updateListenerHintsLocked() {
        final int hints = (mListenersDisablingEffects.isEmpty() ? 0 : HINT_HOST_DISABLE_EFFECTS) |
                mZenModeHelper.getZenModeListenerHint();
        if (hints == mListenerHints) return;
        mListenerHints = hints;
        scheduleListenerHintsChanged(hints);
    }

    private final IBinder mService = new INotificationManager.Stub() {
@@ -1283,23 +1292,29 @@ public class NotificationManagerService extends SystemService {
        }

        @Override
        public void requestFlagsFromListener(INotificationListener token, int flags) {
        public void requestHintsFromListener(INotificationListener token, int hints) {
            final long identity = Binder.clearCallingIdentity();
            try {
                synchronized (mNotificationList) {
                    final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
                final boolean disableAlerts = (flags & FLAG_DISABLE_HOST_ALERTS) != 0;
                if (disableAlerts) {
                    mListenersDisablingAlerts.add(info);
                    final boolean disableEffects = (hints & HINT_HOST_DISABLE_EFFECTS) != 0;
                    if (disableEffects) {
                        mListenersDisablingEffects.add(info);
                    } else {
                    mListenersDisablingAlerts.remove(info);
                        mListenersDisablingEffects.remove(info);
                    }
                    mZenModeHelper.requestFromListener(hints);
                    updateListenerHintsLocked();
                }
                updateListenerFlagsLocked();
            } finally {
                Binder.restoreCallingIdentity(identity);
            }
        }

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

@@ -1394,8 +1409,8 @@ public class NotificationManagerService extends SystemService {
        return keys.toArray(new String[keys.size()]);
    }

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

    void dumpImpl(PrintWriter pw, DumpFilter filter) {
@@ -1445,7 +1460,7 @@ public class NotificationManagerService extends SystemService {

                    pw.println("  mSoundNotification=" + mSoundNotification);
                    pw.println("  mVibrateNotification=" + mVibrateNotification);
                    pw.println("  mDisableNotificationAlerts=" + mDisableNotificationAlerts);
                    pw.println("  mDisableNotificationEffects=" + mDisableNotificationEffects);
                    pw.println("  mSystemReady=" + mSystemReady);
                }
                pw.println("  mArchive=" + mArchive.toString());
@@ -1481,11 +1496,11 @@ 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();
                pw.print("    mListenerHints: "); pw.println(mListenerHints);
                pw.print("    mListenersDisablingEffects: (");
                N = mListenersDisablingEffects.size();
                for (int i = 0; i < N; i++) {
                    final ManagedServiceInfo listener = mListenersDisablingAlerts.valueAt(i);
                    final ManagedServiceInfo listener = mListenersDisablingEffects.valueAt(i);
                    if (i > 0) pw.print(',');
                    pw.print(listener.component);
                }
@@ -1687,7 +1702,7 @@ public class NotificationManagerService extends SystemService {
        }

        // If we're not supposed to beep, vibrate, etc. then don't.
        if (!disableNotificationAlerts()
        if (!disableNotificationEffects()
                && (!(record.isUpdate
                    && (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 ))
                && (record.getUserId() == UserHandle.USER_ALL ||
@@ -2003,14 +2018,14 @@ 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 scheduleListenerHintsChanged(int state) {
        mHandler.removeMessages(MESSAGE_LISTENER_HINTS_CHANGED);
        mHandler.obtainMessage(MESSAGE_LISTENER_HINTS_CHANGED, state, 0).sendToTarget();
    }

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

@@ -2030,8 +2045,8 @@ public class NotificationManagerService extends SystemService {
                case MESSAGE_SEND_RANKING_UPDATE:
                    handleSendRankingUpdate();
                    break;
                case MESSAGE_LISTENER_FLAGS_CHANGED:
                    handleListenerFlagsChanged(msg.arg1);
                case MESSAGE_LISTENER_HINTS_CHANGED:
                    handleListenerHintsChanged(msg.arg1);
                    break;
            }
        }
@@ -2553,8 +2568,8 @@ public class NotificationManagerService extends SystemService {

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

@@ -2638,7 +2653,7 @@ public class NotificationManagerService extends SystemService {
            }
        }

        public void notifyListenerFlagsChangedLocked(final int flags) {
        public void notifyListenerHintsChangedLocked(final int hints) {
            for (final ManagedServiceInfo serviceInfo : mServices) {
                if (!serviceInfo.isEnabledForCurrentProfiles()) {
                    continue;
@@ -2646,7 +2661,7 @@ public class NotificationManagerService extends SystemService {
                mHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        notifyListenerFlagsChanged(serviceInfo, flags);
                        notifyListenerHintsChanged(serviceInfo, hints);
                    }
                });
            }
@@ -2685,12 +2700,12 @@ public class NotificationManagerService extends SystemService {
            }
        }

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