import android.service.notification.NotificationRankingUpdate;
import android.service.notification.StatusBarNotification;
import android.service.notification.ZenModeConfig;
+import android.telephony.PhoneStateListener;
import android.telephony.TelephonyManager;
import android.text.TextUtils;
import android.util.ArrayMap;
boolean mSystemReady;
private boolean mDisableNotificationEffects;
+ private int mCallState;
NotificationRecord mSoundNotification;
NotificationRecord mVibrateNotification;
synchronized (mNotificationList) {
mDisableNotificationEffects =
(status & StatusBarManager.DISABLE_NOTIFICATION_ALERTS) != 0;
- if (disableNotificationEffects()) {
+ if (disableNotificationEffects(null) != null) {
// cancel whatever's going on
long identity = Binder.clearCallingIdentity();
try {
mZenModeHelper.updateZenMode();
mUserProfiles.updateCache(getContext());
+ listenForCallState();
// register for various Intents
IntentFilter filter = new IntentFilter();
return keys.toArray(new String[keys.size()]);
}
- private boolean disableNotificationEffects() {
- return mDisableNotificationEffects || (mListenerHints & HINT_HOST_DISABLE_EFFECTS) != 0;
+ private String disableNotificationEffects(NotificationRecord record) {
+ if (mDisableNotificationEffects) {
+ return "booleanState";
+ }
+ if ((mListenerHints & HINT_HOST_DISABLE_EFFECTS) != 0) {
+ return "listenerHints";
+ }
+ if (mCallState != TelephonyManager.CALL_STATE_IDLE && !mZenModeHelper.isCall(record)) {
+ return "callState";
+ }
+ return null;
}
void dumpImpl(PrintWriter pw, DumpFilter filter) {
pw.println(" mSoundNotification=" + mSoundNotification);
pw.println(" mVibrateNotification=" + mVibrateNotification);
pw.println(" mDisableNotificationEffects=" + mDisableNotificationEffects);
+ pw.println(" mCallState=" + callStateToString(mCallState));
pw.println(" mSystemReady=" + mSystemReady);
}
pw.println(" mArchive=" + mArchive.toString());
}
// If we're not supposed to beep, vibrate, etc. then don't.
- if (!disableNotificationEffects()
+ final String disableEffects = disableNotificationEffects(record);
+ if (disableEffects != null) {
+ ZenLog.traceDisableEffects(record, disableEffects);
+ }
+ if (disableEffects == null
&& (!(record.isUpdate
&& (notification.flags & Notification.FLAG_ONLY_ALERT_ONCE) != 0 ))
&& (record.getUserId() == UserHandle.USER_ALL ||
}
}
+ private static String callStateToString(int state) {
+ switch (state) {
+ case TelephonyManager.CALL_STATE_IDLE: return "CALL_STATE_IDLE";
+ case TelephonyManager.CALL_STATE_RINGING: return "CALL_STATE_RINGING";
+ case TelephonyManager.CALL_STATE_OFFHOOK: return "CALL_STATE_OFFHOOK";
+ default: return "CALL_STATE_UNKNOWN_" + state;
+ }
+ }
+
+ private void listenForCallState() {
+ TelephonyManager.from(getContext()).listen(new PhoneStateListener() {
+ @Override
+ public void onCallStateChanged(int state, String incomingNumber) {
+ if (mCallState == state) return;
+ if (DBG) Slog.d(TAG, "Call state changed: " + callStateToString(state));
+ mCallState = state;
+ }
+ }, PhoneStateListener.LISTEN_CALL_STATE);
+ }
+
/**
* Generates a NotificationRankingUpdate from 'sbns', considering only
* notifications visible to the given listener.
private static final int TYPE_CONFIG = 10;
private static final int TYPE_FOLLOW_RINGER_MODE = 11;
private static final int TYPE_NOT_INTERCEPTED = 12;
+ private static final int TYPE_DISABLE_EFFECTS = 13;
private static int sNext;
private static int sSize;
+ zenModeToString(oldZen) + " -> " + zenModeToString(newZen));
}
+ public static void traceDisableEffects(NotificationRecord record, String reason) {
+ append(TYPE_DISABLE_EFFECTS, record.getKey() + "," + reason);
+ }
+
private static String subscribeResult(IConditionProvider provider, RemoteException e) {
return provider == null ? "no provider" : e != null ? e.getMessage() : "ok";
}
case TYPE_CONFIG: return "config";
case TYPE_FOLLOW_RINGER_MODE: return "follow_ringer_mode";
case TYPE_NOT_INTERCEPTED: return "not_intercepted";
+ case TYPE_DISABLE_EFFECTS: return "disable_effects";
default: return "unknown";
}
}