am 6049c4b7: Merge "NoListener: Factor out ZEN mode API" into lmp-dev

* commit '6049c4b7ee264585cb4f7720ea628e9c5d389b8d':
  NoListener: Factor out ZEN mode API
This commit is contained in:
Christoph Studer
2014-08-28 19:07:23 +00:00
committed by Android Git Automerger
6 changed files with 188 additions and 44 deletions

View File

@@ -27104,9 +27104,11 @@ package android.service.notification {
method public final void cancelNotifications(java.lang.String[]);
method public android.service.notification.StatusBarNotification[] getActiveNotifications();
method public android.service.notification.StatusBarNotification[] getActiveNotifications(java.lang.String[]);
method public final int getCurrentInterruptionFilter();
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 onInterruptionFilterChanged(int);
method public void onListenerConnected();
method public void onListenerHintsChanged(int);
method public void onNotificationPosted(android.service.notification.StatusBarNotification);
@@ -27114,13 +27116,12 @@ package android.service.notification {
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 requestInterruptionFilter(int);
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 int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1
field public static final int INTERRUPTION_FILTER_ALL = 1; // 0x1
field public static final int INTERRUPTION_FILTER_NONE = 3; // 0x3
field public static final int INTERRUPTION_FILTER_PRIORITY = 2; // 0x2
field public static final java.lang.String SERVICE_INTERFACE = "android.service.notification.NotificationListenerService";
}

View File

@@ -61,6 +61,8 @@ interface INotificationManager
ParceledListSlice getActiveNotificationsFromListener(in INotificationListener token, in String[] keys);
void requestHintsFromListener(in INotificationListener token, int hints);
int getHintsFromListener(in INotificationListener token);
void requestInterruptionFilterFromListener(in INotificationListener token, int interruptionFilter);
int getInterruptionFilterFromListener(in INotificationListener token);
ComponentName getEffectsSuppressor();

View File

@@ -29,4 +29,5 @@ oneway interface INotificationListener
in NotificationRankingUpdate update);
void onNotificationRankingUpdate(in NotificationRankingUpdate update);
void onListenerHintsChanged(int hints);
}
void onInterruptionFilterChanged(int interruptionFilter);
}

View File

@@ -58,26 +58,28 @@ public abstract class NotificationListenerService extends Service {
private final String TAG = NotificationListenerService.class.getSimpleName()
+ "[" + getClass().getSimpleName() + "]";
/** {@link #getCurrentListenerHints() Listener hints} constant - default state. */
public static final int HINTS_NONE = 0;
/**
* {@link #getCurrentInterruptionFilter() Interruption filter} constant -
* Normal interruption filter.
*/
public static final int INTERRUPTION_FILTER_ALL = 1;
/** Bitmask range for {@link #getCurrentListenerHints() Listener hints} host interruption level
* constants. */
public static final int HOST_INTERRUPTION_LEVEL_MASK = 0x3;
/**
* {@link #getCurrentInterruptionFilter() Interruption filter} constant -
* Priority interruption filter.
*/
public static final int INTERRUPTION_FILTER_PRIORITY = 2;
/** {@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 #getCurrentInterruptionFilter() Interruption filter} constant -
* No interruptions filter.
*/
public static final int INTERRUPTION_FILTER_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;
* This does not change the interruption filter, only the effects. **/
public static final int HINT_HOST_DISABLE_EFFECTS = 1;
private INotificationListenerWrapper mWrapper = null;
private RankingMap mRankingMap;
@@ -197,6 +199,17 @@ public abstract class NotificationListenerService extends Service {
// optional
}
/**
* Implement this method to be notified when the
* {@link #getCurrentInterruptionFilter() interruption filter} changed.
*
* @param interruptionFilter The current
* {@link #getCurrentInterruptionFilter() interruption filter}.
*/
public void onInterruptionFilterChanged(int interruptionFilter) {
// optional
}
private final INotificationManager getNotificationInterface() {
if (mNoMan == null) {
mNoMan = INotificationManager.Stub.asInterface(
@@ -345,15 +358,42 @@ public abstract class NotificationListenerService extends Service {
* shared across all listeners or a feature the notification host does not support or refuses
* to grant.
*
* @return One or more of the HINT_ constants.
* @return Zero or more of the HINT_ constants.
*/
public final int getCurrentListenerHints() {
if (!isBound()) return HINTS_NONE;
if (!isBound()) return 0;
try {
return getNotificationInterface().getHintsFromListener(mWrapper);
} catch (android.os.RemoteException ex) {
Log.v(TAG, "Unable to contact notification manager", ex);
return HINTS_NONE;
return 0;
}
}
/**
* Gets the current notification interruption filter active on the host.
*
* <p>
* The interruption filter defines which notifications are allowed to interrupt the user
* (e.g. via sound &amp; vibration) and is applied globally. Listeners can find out whether
* a specific notification matched the interruption filter via
* {@link Ranking#matchesInterruptionFilter()}.
* <p>
* The current filter may differ from the previously requested filter if the notification host
* does not support or refuses to apply the requested filter, or if another component changed
* the filter in the meantime.
* <p>
* Listen for updates using {@link #onInterruptionFilterChanged(int)}.
*
* @return One of the INTERRUPTION_FILTER_ constants, or 0 on errors.
*/
public final int getCurrentInterruptionFilter() {
if (!isBound()) return 0;
try {
return getNotificationInterface().getHintsFromListener(mWrapper);
} catch (android.os.RemoteException ex) {
Log.v(TAG, "Unable to contact notification manager", ex);
return 0;
}
}
@@ -361,7 +401,7 @@ public abstract class NotificationListenerService extends Service {
* Sets the desired {@link #getCurrentListenerHints() listener hints}.
*
* <p>
* This is merely a request, the host may or not choose to take action depending
* This is merely a request, the host may or may not choose to take action depending
* on other listener requests or other global state.
* <p>
* Listen for updates using {@link #onListenerHintsChanged(int)}.
@@ -377,6 +417,27 @@ public abstract class NotificationListenerService extends Service {
}
}
/**
* Sets the desired {@link #getCurrentInterruptionFilter() interruption filter}.
*
* <p>
* This is merely a request, the host may or may not choose to apply the requested
* interruption filter depending on other listener requests or other global state.
* <p>
* Listen for updates using {@link #onInterruptionFilterChanged(int)}.
*
* @param interruptionFilter One of the INTERRUPTION_FILTER_ constants.
*/
public final void requestInterruptionFilter(int interruptionFilter) {
if (!isBound()) return;
try {
getNotificationInterface()
.requestInterruptionFilterFromListener(mWrapper, interruptionFilter);
} catch (android.os.RemoteException ex) {
Log.v(TAG, "Unable to contact notification manager", ex);
}
}
/**
* Returns current ranking information.
*
@@ -514,6 +575,15 @@ public abstract class NotificationListenerService extends Service {
Log.w(TAG, "Error running onListenerHintsChanged", t);
}
}
@Override
public void onInterruptionFilterChanged(int interruptionFilter) throws RemoteException {
try {
NotificationListenerService.this.onInterruptionFilterChanged(interruptionFilter);
} catch (Throwable t) {
Log.w(TAG, "Error running onInterruptionFilterChanged", t);
}
}
}
private void applyUpdate(NotificationRankingUpdate update) {

View File

@@ -57,7 +57,6 @@ import android.os.IBinder;
import android.os.IInterface;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
import android.os.UserHandle;
@@ -127,6 +126,7 @@ public class NotificationManagerService extends SystemService {
static final int MESSAGE_RANKING_CONFIG_CHANGE = 5;
static final int MESSAGE_SEND_RANKING_UPDATE = 6;
static final int MESSAGE_LISTENER_HINTS_CHANGED = 7;
static final int MESSAGE_LISTENER_NOTIFICATION_FILTER_CHANGED = 8;
static final int LONG_DELAY = 3500; // 3.5 seconds
static final int SHORT_DELAY = 2000; // 2 seconds
@@ -178,6 +178,7 @@ public class NotificationManagerService extends SystemService {
private final ArraySet<ManagedServiceInfo> mListenersDisablingEffects = new ArraySet<>();
private ComponentName mEffectsSuppressor;
private int mListenerHints; // right now, all hints are global
private int mInterruptionFilter; // current ZEN mode as communicated to listeners
// for enabling and disabling notification pulse behavior
private boolean mScreenOn = true;
@@ -806,7 +807,7 @@ public class NotificationManagerService extends SystemService {
@Override
void onZenModeChanged() {
synchronized(mNotificationList) {
updateListenerHintsLocked();
updateInterruptionFilterLocked();
}
}
});
@@ -938,8 +939,7 @@ public class NotificationManagerService extends SystemService {
}
private void updateListenerHintsLocked() {
final int hints = (mListenersDisablingEffects.isEmpty() ? 0 : HINT_HOST_DISABLE_EFFECTS) |
mZenModeHelper.getZenModeListenerHint();
final int hints = mListenersDisablingEffects.isEmpty() ? 0 : HINT_HOST_DISABLE_EFFECTS;
if (hints == mListenerHints) return;
mListenerHints = hints;
scheduleListenerHintsChanged(hints);
@@ -954,6 +954,13 @@ public class NotificationManagerService extends SystemService {
.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY));
}
private void updateInterruptionFilterLocked() {
int interruptionFilter = mZenModeHelper.getZenModeListenerInterruptionFilter();
if (interruptionFilter == mInterruptionFilter) return;
mInterruptionFilter = interruptionFilter;
scheduleInterruptionFilterChanged(interruptionFilter);
}
private final IBinder mService = new INotificationManager.Stub() {
// Toasts
// ============================================================================
@@ -1318,7 +1325,6 @@ public class NotificationManagerService extends SystemService {
} else {
mListenersDisablingEffects.remove(info);
}
mZenModeHelper.requestFromListener(hints);
updateListenerHintsLocked();
updateEffectsSuppressorLocked();
}
@@ -1334,6 +1340,29 @@ public class NotificationManagerService extends SystemService {
}
}
@Override
public void requestInterruptionFilterFromListener(INotificationListener token,
int interruptionFilter) throws RemoteException {
final long identity = Binder.clearCallingIdentity();
try {
synchronized (mNotificationList) {
mListeners.checkServiceTokenLocked(token);
mZenModeHelper.requestFromListener(interruptionFilter);
updateInterruptionFilterLocked();
}
} finally {
Binder.restoreCallingIdentity(identity);
}
}
@Override
public int getInterruptionFilterFromListener(INotificationListener token)
throws RemoteException {
synchronized (mNotificationLight) {
return mInterruptionFilter;
}
}
@Override
public ZenModeConfig getZenModeConfig() {
enforceSystemOrSystemUI("INotificationManager.getZenModeConfig");
@@ -2058,12 +2087,26 @@ public class NotificationManagerService extends SystemService {
mHandler.obtainMessage(MESSAGE_LISTENER_HINTS_CHANGED, state, 0).sendToTarget();
}
private void scheduleInterruptionFilterChanged(int listenerInterruptionFilter) {
mHandler.removeMessages(MESSAGE_LISTENER_NOTIFICATION_FILTER_CHANGED);
mHandler.obtainMessage(
MESSAGE_LISTENER_NOTIFICATION_FILTER_CHANGED,
listenerInterruptionFilter,
0).sendToTarget();
}
private void handleListenerHintsChanged(int hints) {
synchronized (mNotificationList) {
mListeners.notifyListenerHintsChangedLocked(hints);
}
}
private void handleListenerInterruptionFilterChanged(int interruptionFilter) {
synchronized (mNotificationList) {
mListeners.notifyInterruptionFilterChanged(interruptionFilter);
}
}
private final class WorkerHandler extends Handler
{
@Override
@@ -2083,6 +2126,9 @@ public class NotificationManagerService extends SystemService {
case MESSAGE_LISTENER_HINTS_CHANGED:
handleListenerHintsChanged(msg.arg1);
break;
case MESSAGE_LISTENER_NOTIFICATION_FILTER_CHANGED:
handleListenerInterruptionFilterChanged(msg.arg1);
break;
}
}
@@ -2701,6 +2747,20 @@ public class NotificationManagerService extends SystemService {
}
}
public void notifyInterruptionFilterChanged(final int interruptionFilter) {
for (final ManagedServiceInfo serviceInfo : mServices) {
if (!serviceInfo.isEnabledForCurrentProfiles()) {
continue;
}
mHandler.post(new Runnable() {
@Override
public void run() {
notifyInterruptionFilterChanged(serviceInfo, interruptionFilter);
}
});
}
}
private void notifyPosted(final ManagedServiceInfo info,
final StatusBarNotification sbn, NotificationRankingUpdate rankingUpdate) {
final INotificationListener listener = (INotificationListener)info.service;
@@ -2743,6 +2803,16 @@ public class NotificationManagerService extends SystemService {
}
}
private void notifyInterruptionFilterChanged(ManagedServiceInfo info,
int interruptionFilter) {
final INotificationListener listener = (INotificationListener) info.service;
try {
listener.onInterruptionFilterChanged(interruptionFilter);
} catch (RemoteException ex) {
Log.e(TAG, "unable to notify listener (interruption filter): " + listener, ex);
}
}
private boolean isListenerPackage(String packageName) {
if (packageName == null) {
return false;

View File

@@ -115,35 +115,35 @@ public class ZenModeHelper {
mAudioManager = audioManager;
}
public int getZenModeListenerHint() {
switch(mZenMode) {
public int getZenModeListenerInterruptionFilter() {
switch (mZenMode) {
case Global.ZEN_MODE_OFF:
return NotificationListenerService.HINT_HOST_INTERRUPTION_LEVEL_ALL;
return NotificationListenerService.INTERRUPTION_FILTER_ALL;
case Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS:
return NotificationListenerService.HINT_HOST_INTERRUPTION_LEVEL_PRIORITY;
return NotificationListenerService.INTERRUPTION_FILTER_PRIORITY;
case Global.ZEN_MODE_NO_INTERRUPTIONS:
return NotificationListenerService.HINT_HOST_INTERRUPTION_LEVEL_NONE;
return NotificationListenerService.INTERRUPTION_FILTER_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:
private static int zenModeFromListenerInterruptionFilter(int listenerInterruptionFilter,
int defValue) {
switch (listenerInterruptionFilter) {
case NotificationListenerService.INTERRUPTION_FILTER_ALL:
return Global.ZEN_MODE_OFF;
case NotificationListenerService.HINT_HOST_INTERRUPTION_LEVEL_PRIORITY:
case NotificationListenerService.INTERRUPTION_FILTER_PRIORITY:
return Global.ZEN_MODE_IMPORTANT_INTERRUPTIONS;
case NotificationListenerService.HINT_HOST_INTERRUPTION_LEVEL_NONE:
case NotificationListenerService.INTERRUPTION_FILTER_NONE:
return Global.ZEN_MODE_NO_INTERRUPTIONS;
default:
return defValue;
}
}
public void requestFromListener(int hints) {
final int newZen = zenFromListenerHint(hints, -1);
public void requestFromListener(int interruptionFilter) {
final int newZen = zenModeFromListenerInterruptionFilter(interruptionFilter, -1);
if (newZen != -1) {
setZenMode(newZen, "listener");
}