am 8a497588: am 8028a5a8: am 752dc6e1: New NotificationListenerService listener flags api.

* commit '8a497588b3df725c87ca4f684e15578ef7b4bfe9':
  New NotificationListenerService listener flags api.
This commit is contained in:
John Spurlock
2014-07-22 14:14:29 +00:00
committed by Android Git Automerger
5 changed files with 165 additions and 2 deletions

View File

@@ -27230,14 +27230,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";
}

View File

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

View File

@@ -28,4 +28,5 @@ oneway interface INotificationListener
void onNotificationRemoved(in StatusBarNotification notification,
in NotificationRankingUpdate update);
void onNotificationRankingUpdate(in NotificationRankingUpdate update);
void onListenerFlagsChanged(int flags);
}

View File

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

View File

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