Merge "Add granular control over disabled effects." into nyc-dev

am: 196a057

* commit '196a05724d73832571c6e4ad5372b05840ec041f':
  Add granular control over disabled effects.

Change-Id: I453928754c89113f321df08a4ca8612660b1012c
This commit is contained in:
Bryce Lee
2016-04-09 00:42:38 +00:00
committed by android-build-merger
7 changed files with 178 additions and 29 deletions

View File

@@ -34725,7 +34725,9 @@ package android.service.notification {
method public static void requestRebind(android.content.ComponentName) throws android.os.RemoteException;
method public final void requestUnbind() throws android.os.RemoteException;
method public final void setNotificationsShown(java.lang.String[]);
field public static final int HINT_HOST_DISABLE_CALL_EFFECTS = 4; // 0x4
field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1
field public static final int HINT_HOST_DISABLE_NOTIFICATION_EFFECTS = 2; // 0x2
field public static final int INTERRUPTION_FILTER_ALARMS = 4; // 0x4
field public static final int INTERRUPTION_FILTER_ALL = 1; // 0x1
field public static final int INTERRUPTION_FILTER_NONE = 3; // 0x3

View File

@@ -37211,7 +37211,9 @@ package android.service.notification {
method public final void setNotificationsShown(java.lang.String[]);
method public final void setOnNotificationPostedTrim(int);
method public void unregisterAsSystemService() throws android.os.RemoteException;
field public static final int HINT_HOST_DISABLE_CALL_EFFECTS = 4; // 0x4
field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1
field public static final int HINT_HOST_DISABLE_NOTIFICATION_EFFECTS = 2; // 0x2
field public static final int INTERRUPTION_FILTER_ALARMS = 4; // 0x4
field public static final int INTERRUPTION_FILTER_ALL = 1; // 0x1
field public static final int INTERRUPTION_FILTER_NONE = 3; // 0x3

View File

@@ -34798,7 +34798,9 @@ package android.service.notification {
method public static void requestRebind(android.content.ComponentName) throws android.os.RemoteException;
method public final void requestUnbind() throws android.os.RemoteException;
method public final void setNotificationsShown(java.lang.String[]);
field public static final int HINT_HOST_DISABLE_CALL_EFFECTS = 4; // 0x4
field public static final int HINT_HOST_DISABLE_EFFECTS = 1; // 0x1
field public static final int HINT_HOST_DISABLE_NOTIFICATION_EFFECTS = 2; // 0x2
field public static final int INTERRUPTION_FILTER_ALARMS = 4; // 0x4
field public static final int INTERRUPTION_FILTER_ALL = 1; // 0x1
field public static final int INTERRUPTION_FILTER_NONE = 3; // 0x3

View File

@@ -123,6 +123,16 @@ public abstract class NotificationListenerService extends Service {
* This does not change the interruption filter, only the effects. **/
public static final int HINT_HOST_DISABLE_EFFECTS = 1;
/** {@link #getCurrentListenerHints() Listener hints} constant - the primary device UI
* should disable notification sound, but not phone calls.
* This does not change the interruption filter, only the effects. **/
public static final int HINT_HOST_DISABLE_NOTIFICATION_EFFECTS = 1 << 1;
/** {@link #getCurrentListenerHints() Listener hints} constant - the primary device UI
* should disable phone call sounds, buyt not notification sound.
* This does not change the interruption filter, only the effects. **/
public static final int HINT_HOST_DISABLE_CALL_EFFECTS = 1 << 2;
/**
* Whether notification suppressed by DND should not interruption visually when the screen is
* off.

View File

@@ -33,6 +33,8 @@ import static android.service.notification.NotificationRankerService.REASON_PROF
import static android.service.notification.NotificationRankerService.REASON_UNAUTOBUNDLED;
import static android.service.notification.NotificationRankerService.REASON_USER_STOPPED;
import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_EFFECTS;
import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_NOTIFICATION_EFFECTS;
import static android.service.notification.NotificationListenerService.HINT_HOST_DISABLE_CALL_EFFECTS;
import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_OFF;
import static android.service.notification.NotificationListenerService.SUPPRESSED_EFFECT_SCREEN_ON;
import static android.service.notification.NotificationListenerService.TRIM_FULL;
@@ -114,6 +116,7 @@ import android.util.ArraySet;
import android.util.AtomicFile;
import android.util.Log;
import android.util.Slog;
import android.util.SparseArray;
import android.util.Xml;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
@@ -246,8 +249,9 @@ public class NotificationManagerService extends SystemService {
private String mSoundNotificationKey;
private String mVibrateNotificationKey;
private final ArraySet<ManagedServiceInfo> mListenersDisablingEffects = new ArraySet<>();
private ComponentName mEffectsSuppressor;
private final SparseArray<ArraySet<ManagedServiceInfo>> mListenersDisablingEffects =
new SparseArray<ArraySet<ManagedServiceInfo>>();
private List<ComponentName> mEffectsSuppressors = new ArrayList<ComponentName>();
private int mListenerHints; // right now, all hints are global
private int mInterruptionFilter = NotificationListenerService.INTERRUPTION_FILTER_UNKNOWN;
@@ -1112,23 +1116,112 @@ public class NotificationManagerService extends SystemService {
}
private void updateListenerHintsLocked() {
final int hints = mListenersDisablingEffects.isEmpty() ? 0 : HINT_HOST_DISABLE_EFFECTS;
final int hints = calculateHints();
if (hints == mListenerHints) return;
ZenLog.traceListenerHintsChanged(mListenerHints, hints, mListenersDisablingEffects.size());
ZenLog.traceListenerHintsChanged(mListenerHints, hints, mEffectsSuppressors.size());
mListenerHints = hints;
scheduleListenerHintsChanged(hints);
}
private void updateEffectsSuppressorLocked() {
final ComponentName suppressor = !mListenersDisablingEffects.isEmpty()
? mListenersDisablingEffects.valueAt(0).component : null;
if (Objects.equals(suppressor, mEffectsSuppressor)) return;
ZenLog.traceEffectsSuppressorChanged(mEffectsSuppressor, suppressor);
mEffectsSuppressor = suppressor;
mZenModeHelper.setEffectsSuppressed(suppressor != null);
final long updatedSuppressedEffects = calculateSuppressedEffects();
if (updatedSuppressedEffects == mZenModeHelper.getSuppressedEffects()) return;
final List<ComponentName> suppressors = getSuppressors();
ZenLog.traceEffectsSuppressorChanged(mEffectsSuppressors, suppressors, updatedSuppressedEffects);
mEffectsSuppressors = suppressors;
mZenModeHelper.setSuppressedEffects(updatedSuppressedEffects);
sendRegisteredOnlyBroadcast(NotificationManager.ACTION_EFFECTS_SUPPRESSOR_CHANGED);
}
private ArrayList<ComponentName> getSuppressors() {
ArrayList<ComponentName> names = new ArrayList<ComponentName>();
for (int i = mListenersDisablingEffects.size() - 1; i >= 0; --i) {
ArraySet<ManagedServiceInfo> serviceInfoList = mListenersDisablingEffects.valueAt(i);
for (ManagedServiceInfo info : serviceInfoList) {
names.add(info.component);
}
}
return names;
}
private boolean removeDisabledHints(ManagedServiceInfo info) {
return removeDisabledHints(info, 0);
}
private boolean removeDisabledHints(ManagedServiceInfo info, int hints) {
boolean removed = false;
for (int i = mListenersDisablingEffects.size() - 1; i >= 0; --i) {
final int hint = mListenersDisablingEffects.keyAt(i);
final ArraySet<ManagedServiceInfo> listeners =
mListenersDisablingEffects.valueAt(i);
if (hints == 0 || (hint & hints) == hint) {
removed = removed || listeners.remove(info);
}
}
return removed;
}
private void addDisabledHints(ManagedServiceInfo info, int hints) {
if ((hints & HINT_HOST_DISABLE_EFFECTS) != 0) {
addDisabledHint(info, HINT_HOST_DISABLE_EFFECTS);
}
if ((hints & HINT_HOST_DISABLE_NOTIFICATION_EFFECTS) != 0) {
addDisabledHint(info, HINT_HOST_DISABLE_NOTIFICATION_EFFECTS);
}
if ((hints & HINT_HOST_DISABLE_CALL_EFFECTS) != 0) {
addDisabledHint(info, HINT_HOST_DISABLE_CALL_EFFECTS);
}
}
private void addDisabledHint(ManagedServiceInfo info, int hint) {
if (mListenersDisablingEffects.indexOfKey(hint) < 0) {
mListenersDisablingEffects.put(hint, new ArraySet<ManagedServiceInfo>());
}
ArraySet<ManagedServiceInfo> hintListeners = mListenersDisablingEffects.get(hint);
hintListeners.add(info);
}
private int calculateHints() {
int hints = 0;
for (int i = mListenersDisablingEffects.size() - 1; i >= 0; --i) {
int hint = mListenersDisablingEffects.keyAt(i);
ArraySet<ManagedServiceInfo> serviceInfoList = mListenersDisablingEffects.valueAt(i);
if (!serviceInfoList.isEmpty()) {
hints |= hint;
}
}
return hints;
}
private long calculateSuppressedEffects() {
int hints = calculateHints();
long suppressedEffects = 0;
if ((hints & HINT_HOST_DISABLE_EFFECTS) != 0) {
suppressedEffects |= ZenModeHelper.SUPPRESSED_EFFECT_ALL;
}
if ((hints & HINT_HOST_DISABLE_NOTIFICATION_EFFECTS) != 0) {
suppressedEffects |= ZenModeHelper.SUPPRESSED_EFFECT_NOTIFICATIONS;
}
if ((hints & HINT_HOST_DISABLE_CALL_EFFECTS) != 0) {
suppressedEffects |= ZenModeHelper.SUPPRESSED_EFFECT_CALLS;
}
return suppressedEffects;
}
private void updateInterruptionFilterLocked() {
int interruptionFilter = mZenModeHelper.getZenModeListenerInterruptionFilter();
if (interruptionFilter == mInterruptionFilter) return;
@@ -1651,11 +1744,14 @@ public class NotificationManagerService extends SystemService {
try {
synchronized (mNotificationList) {
final ManagedServiceInfo info = mListeners.checkServiceTokenLocked(token);
final boolean disableEffects = (hints & HINT_HOST_DISABLE_EFFECTS) != 0;
final int disableEffectsMask = HINT_HOST_DISABLE_EFFECTS
| HINT_HOST_DISABLE_NOTIFICATION_EFFECTS
| HINT_HOST_DISABLE_CALL_EFFECTS;
final boolean disableEffects = (hints & disableEffectsMask) != 0;
if (disableEffects) {
mListenersDisablingEffects.add(info);
addDisabledHints(info, hints);
} else {
mListenersDisablingEffects.remove(info);
removeDisabledHints(info, hints);
}
updateListenerHintsLocked();
updateEffectsSuppressorLocked();
@@ -1913,7 +2009,7 @@ public class NotificationManagerService extends SystemService {
@Override
public ComponentName getEffectsSuppressor() {
enforceSystemOrSystemUIOrVolume("INotificationManager.getEffectsSuppressor");
return mEffectsSuppressor;
return mEffectsSuppressors.get(0);
}
@Override
@@ -2273,9 +2369,19 @@ public class NotificationManagerService extends SystemService {
pw.print(" mListenersDisablingEffects: (");
N = mListenersDisablingEffects.size();
for (int i = 0; i < N; i++) {
final ManagedServiceInfo listener = mListenersDisablingEffects.valueAt(i);
if (i > 0) pw.print(',');
pw.print(listener.component);
final int hint = mListenersDisablingEffects.keyAt(i);
if (i > 0) pw.print(';');
pw.print("hint[" + hint + "]:");
final ArraySet<ManagedServiceInfo> listeners =
mListenersDisablingEffects.valueAt(i);
final int listenerSize = listeners.size();
for (int j = 0; j < listenerSize; j++) {
if (i > 0) pw.print(',');
final ManagedServiceInfo listener = listeners.valueAt(i);
pw.print(listener.component);
}
}
pw.println(')');
pw.println("\n mRankerServicePackageName: " + mRankerServicePackageName);
@@ -3808,7 +3914,7 @@ public class NotificationManagerService extends SystemService {
@Override
protected void onServiceRemovedLocked(ManagedServiceInfo removed) {
if (mListenersDisablingEffects.remove(removed)) {
if (removeDisabledHints(removed)) {
updateListenerHintsLocked();
updateEffectsSuppressorLocked();
}

View File

@@ -31,6 +31,7 @@ import android.util.Slog;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
public class ZenLog {
private static final String TAG = "ZenLog";
@@ -126,10 +127,11 @@ public class ZenLog {
append(TYPE_DISABLE_EFFECTS, record.getKey() + "," + reason);
}
public static void traceEffectsSuppressorChanged(ComponentName oldSuppressor,
ComponentName newSuppressor) {
append(TYPE_SUPPRESSOR_CHANGED, componentToString(oldSuppressor) + "->"
+ componentToString(newSuppressor));
public static void traceEffectsSuppressorChanged(List<ComponentName> oldSuppressors,
List<ComponentName> newSuppressors, long suppressedEffects) {
append(TYPE_SUPPRESSOR_CHANGED, "suppressed effects:" + suppressedEffects + ","
+ componentListToString(oldSuppressors) + "->"
+ componentListToString(newSuppressors));
}
public static void traceListenerHintsChanged(int oldHints, int newHints, int listenerCount) {
@@ -193,6 +195,19 @@ public class ZenLog {
return component != null ? component.toShortString() : null;
}
private static String componentListToString(List<ComponentName> components) {
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < components.size(); ++i) {
if (i > 0) {
stringBuilder.append(", ");
}
stringBuilder.append(componentToString(components.get(i)));
}
return stringBuilder.toString();
}
private static void append(int type, String msg) {
synchronized(MSGS) {
TIMES[sNext] = System.currentTimeMillis();

View File

@@ -102,7 +102,12 @@ public class ZenModeHelper {
private ZenModeConfig mConfig;
private AudioManagerInternal mAudioManager;
private PackageManager mPm;
private boolean mEffectsSuppressed;
private long mSuppressedEffects;
public static final long SUPPRESSED_EFFECT_NOTIFICATIONS = 1;
public static final long SUPPRESSED_EFFECT_CALLS = 1 << 1;
public static final long SUPPRESSED_EFFECT_ALL = SUPPRESSED_EFFECT_CALLS
| SUPPRESSED_EFFECT_NOTIFICATIONS;
public ZenModeHelper(Context context, Looper looper, ConditionProviders conditionProviders) {
mContext = context;
@@ -228,12 +233,16 @@ public class ZenModeHelper {
}
}
public void setEffectsSuppressed(boolean effectsSuppressed) {
if (mEffectsSuppressed == effectsSuppressed) return;
mEffectsSuppressed = effectsSuppressed;
public void setSuppressedEffects(long suppressedEffects) {
if (mSuppressedEffects == suppressedEffects) return;
mSuppressedEffects = suppressedEffects;
applyRestrictions();
}
public long getSuppressedEffects() {
return mSuppressedEffects;
}
public int getZenMode() {
return mZenMode;
}
@@ -484,7 +493,8 @@ public class ZenModeHelper {
synchronized (mConfig) {
dump(pw, prefix, "mConfig", mConfig);
}
pw.print(prefix); pw.print("mEffectsSuppressed="); pw.println(mEffectsSuppressed);
pw.print(prefix); pw.print("mSuppressedEffects="); pw.println(mSuppressedEffects);
mFiltering.dump(pw, prefix);
mConditions.dump(pw, prefix);
}
@@ -708,9 +718,11 @@ public class ZenModeHelper {
final boolean zen = mZenMode != Global.ZEN_MODE_OFF;
// notification restrictions
final boolean muteNotifications = mEffectsSuppressed;
final boolean muteNotifications =
(mSuppressedEffects & SUPPRESSED_EFFECT_NOTIFICATIONS) != 0;
// call restrictions
final boolean muteCalls = zen && !mConfig.allowCalls && !mConfig.allowRepeatCallers;
final boolean muteCalls = zen && !mConfig.allowCalls && !mConfig.allowRepeatCallers
|| (mSuppressedEffects & SUPPRESSED_EFFECT_CALLS) != 0;
// total silence restrictions
final boolean muteEverything = mZenMode == Global.ZEN_MODE_NO_INTERRUPTIONS;