diff options
6 files changed, 146 insertions, 77 deletions
diff --git a/api/current.txt b/api/current.txt index da1ebae..8514584 100644 --- a/api/current.txt +++ b/api/current.txt @@ -27450,19 +27450,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"; } diff --git a/core/java/android/app/INotificationManager.aidl b/core/java/android/app/INotificationManager.aidl index 113c533..4b65934 100644 --- a/core/java/android/app/INotificationManager.aidl +++ b/core/java/android/app/INotificationManager.aidl @@ -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); diff --git a/core/java/android/service/notification/INotificationListener.aidl b/core/java/android/service/notification/INotificationListener.aidl index 19a8ef5..93b2d3b 100644 --- a/core/java/android/service/notification/INotificationListener.aidl +++ b/core/java/android/service/notification/INotificationListener.aidl @@ -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 diff --git a/core/java/android/service/notification/NotificationListenerService.java b/core/java/android/service/notification/NotificationListenerService.java index f807ad6..119f7f6 100644 --- a/core/java/android/service/notification/NotificationListenerService.java +++ b/core/java/android/service/notification/NotificationListenerService.java @@ -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); } } } diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 743abc8..3eb2b7e 100644 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -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 { @@ -804,6 +805,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")); @@ -846,7 +854,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(); @@ -932,11 +940,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() { @@ -1284,23 +1293,29 @@ 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); + public void requestHintsFromListener(INotificationListener token, int hints) { + final long identity = Binder.clearCallingIdentity(); + try { + synchronized (mNotificationList) { + final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token); + final boolean disableEffects = (hints & HINT_HOST_DISABLE_EFFECTS) != 0; + if (disableEffects) { + mListenersDisablingEffects.add(info); + } else { + 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; } } @@ -1395,8 +1410,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) { @@ -1447,7 +1462,7 @@ public class NotificationManagerService extends SystemService { pw.println(" mNotificationPulseEnabled=" + mNotificationPulseEnabled); 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()); @@ -1483,11 +1498,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); } @@ -1705,7 +1720,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 || @@ -2021,14 +2036,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); } } @@ -2048,8 +2063,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; } } @@ -2570,8 +2585,8 @@ public class NotificationManagerService extends SystemService { @Override protected void onServiceRemovedLocked(ManagedServiceInfo removed) { - if (mListenersDisablingAlerts.remove(removed)) { - updateListenerFlagsLocked(); + if (mListenersDisablingEffects.remove(removed)) { + updateListenerHintsLocked(); } } @@ -2655,7 +2670,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; @@ -2663,7 +2678,7 @@ public class NotificationManagerService extends SystemService { mHandler.post(new Runnable() { @Override public void run() { - notifyListenerFlagsChanged(serviceInfo, flags); + notifyListenerHintsChanged(serviceInfo, hints); } }); } @@ -2702,12 +2717,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); } } } diff --git a/services/core/java/com/android/server/notification/ZenModeHelper.java b/services/core/java/com/android/server/notification/ZenModeHelper.java index 9f97583..9282283 100644 --- a/services/core/java/com/android/server/notification/ZenModeHelper.java +++ b/services/core/java/com/android/server/notification/ZenModeHelper.java @@ -41,6 +41,7 @@ import android.os.IBinder; import android.os.UserHandle; import android.provider.Settings.Global; import android.provider.Settings.Secure; +import android.service.notification.NotificationListenerService; import android.service.notification.ZenModeConfig; import android.telecomm.TelecommManager; import android.util.Slog; @@ -125,6 +126,40 @@ public class ZenModeHelper { mAudioManager = audioManager; } + public int getZenModeListenerHint() { + switch(mZenMode) { + case Global.ZEN_MODE_OFF: + return NotificationListenerService.HINT_HOST_INTERRUPTION_LEVEL_ALL; + case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS: + return NotificationListenerService.HINT_HOST_INTERRUPTION_LEVEL_PRIORITY; + case Global.ZEN_MODE_NO_INTERRUPTIONS: + return NotificationListenerService.HINT_HOST_INTERRUPTION_LEVEL_NONE; + default: + return 0; + } + } + + private static int zenFromListenerHint(int hints, int defValue) { + final int level = hints & NotificationListenerService.HOST_INTERRUPTION_LEVEL_MASK; + switch(level) { + case NotificationListenerService.HINT_HOST_INTERRUPTION_LEVEL_ALL: + return Global.ZEN_MODE_OFF; + case NotificationListenerService.HINT_HOST_INTERRUPTION_LEVEL_PRIORITY: + return Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS; + case NotificationListenerService.HINT_HOST_INTERRUPTION_LEVEL_NONE: + return Global.ZEN_MODE_NO_INTERRUPTIONS; + default: + return defValue; + } + } + + public void requestFromListener(int hints) { + final int newZen = zenFromListenerHint(hints, -1); + if (newZen != -1) { + setZenMode(newZen); + } + } + public boolean shouldIntercept(NotificationRecord record) { if (mZenMode != Global.ZEN_MODE_OFF) { if (isSystem(record)) { |