am fa8faa9b: am 508dc373: Merge "New api to sync zen mode state from listeners." into lmp-dev

* commit 'fa8faa9b47b091be53da695b950c9d803699f1a4':
  New api to sync zen mode state from listeners.
This commit is contained in:
John Spurlock
2014-08-08 20:21:24 +00:00
committed by Android Git Automerger
6 changed files with 146 additions and 77 deletions

View File

@@ -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";
}

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}

View File

@@ -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)) {