Doze: Follow the notification light.
- Send the notification light info up to SystemUI from NoMan.
- Doze mode will now periodically pulse the display (once)
if the notification light is active.
- Change "tease" terminology to "pulse", which is the singular.
Maintain the multi-pulse on buzz-beep-blink for now as extra
emphasis.
- Scrim controller now always takes number of pulses as an arg,
to support a single pulse (used for notification light, and
eventually pickup once available).
- Dial down the display brightness when pulsing.
Bug:15863249
Change-Id: Ifb208a27e82b66cff1d0c04e5b7f758098ea29cf
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
index 13c15f5..943a294 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java
@@ -19,6 +19,8 @@
import static android.os.PowerManager.BRIGHTNESS_OFF;
import static android.os.PowerManager.BRIGHTNESS_ON;
+import android.app.AlarmManager;
+import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@@ -42,12 +44,16 @@
import java.io.FileDescriptor;
import java.io.PrintWriter;
+import java.util.Date;
public class DozeService extends DreamService {
private static final String TAG = "DozeService";
private static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
- private static final String TEASE_ACTION = "com.android.systemui.doze.tease";
+ private static final String ACTION_BASE = "com.android.systemui.doze";
+ private static final String PULSE_ACTION = ACTION_BASE + ".pulse";
+ private static final String NOTIFICATION_PULSE_ACTION = ACTION_BASE + ".notification_pulse";
+ private static final String EXTRA_PULSES = "pulses";
private final String mTag = String.format(TAG + ".%08x", hashCode());
private final Context mContext = this;
@@ -58,13 +64,18 @@
private Sensor mSigMotionSensor;
private PowerManager mPowerManager;
private PowerManager.WakeLock mWakeLock;
+ private AlarmManager mAlarmManager;
private int mMaxBrightness;
private boolean mDreaming;
- private boolean mTeaseReceiverRegistered;
+ private boolean mBroadcastReceiverRegistered;
private boolean mSigMotionConfigured;
private boolean mSigMotionEnabled;
private boolean mDisplayStateSupported;
private int mDisplayStateWhenOn;
+ private boolean mNotificationLightOn;
+ private PendingIntent mNotificationPulseIntent;
+ private int mMultipulseCount;
+ private int mNotificationPulseInterval;
public DozeService() {
if (DEBUG) Log.d(mTag, "new DozeService()");
@@ -75,12 +86,15 @@
protected void dumpOnHandler(FileDescriptor fd, PrintWriter pw, String[] args) {
super.dumpOnHandler(fd, pw, args);
pw.print(" mDreaming: "); pw.println(mDreaming);
- pw.print(" mTeaseReceiverRegistered: "); pw.println(mTeaseReceiverRegistered);
+ pw.print(" mBroadcastReceiverRegistered: "); pw.println(mBroadcastReceiverRegistered);
pw.print(" mSigMotionSensor: "); pw.println(mSigMotionSensor);
pw.print(" mSigMotionConfigured: "); pw.println(mSigMotionConfigured);
pw.print(" mSigMotionEnabled: "); pw.println(mSigMotionEnabled);
pw.print(" mMaxBrightness: "); pw.println(mMaxBrightness);
pw.print(" mDisplayStateSupported: "); pw.println(mDisplayStateSupported);
+ pw.print(" mNotificationLightOn: "); pw.println(mNotificationLightOn);
+ pw.print(" mMultipulseCount: "); pw.println(mMultipulseCount);
+ pw.print(" mNotificationPulseInterval: "); pw.println(mNotificationPulseInterval);
}
@Override
@@ -99,14 +113,21 @@
mSigMotionSensor = mSensors.getDefaultSensor(Sensor.TYPE_SIGNIFICANT_MOTION);
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, mTag);
+ mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
final Resources res = mContext.getResources();
- mSigMotionConfigured = SystemProperties.getBoolean("doze.tease.sigmotion",
- res.getBoolean(R.bool.doze_tease_on_significant_motion));
+ mSigMotionConfigured = SystemProperties.getBoolean("doze.pulse.sigmotion",
+ res.getBoolean(R.bool.doze_pulse_on_significant_motion));
mDisplayStateSupported = SystemProperties.getBoolean("doze.display.supported",
res.getBoolean(R.bool.doze_display_state_supported));
- mMaxBrightness = MathUtils.constrain(res.getInteger(R.integer.doze_tease_brightness),
+ mMaxBrightness = MathUtils.constrain(res.getInteger(R.integer.doze_pulse_brightness),
BRIGHTNESS_OFF, BRIGHTNESS_ON);
-
+ mNotificationPulseIntent = PendingIntent.getBroadcast(mContext, 0,
+ new Intent(NOTIFICATION_PULSE_ACTION).setPackage(getPackageName()),
+ PendingIntent.FLAG_CANCEL_CURRENT);
+ mMultipulseCount = SystemProperties.getInt("doze.multipulses",
+ res.getInteger(R.integer.doze_multipulse_count));
+ mNotificationPulseInterval = SystemProperties.getInt("doze.notification.pulse",
+ res.getInteger(R.integer.doze_notification_pulse_interval));
mDisplayStateWhenOn = mDisplayStateSupported ? Display.STATE_DOZE : Display.STATE_ON;
setDozeScreenState(mDisplayStateWhenOn);
}
@@ -122,7 +143,7 @@
super.onDreamingStarted();
if (DEBUG) Log.d(mTag, "onDreamingStarted canDoze=" + canDoze());
mDreaming = true;
- listenForTeaseSignals(true);
+ listenForPulseSignals(true);
requestDoze();
}
@@ -160,7 +181,7 @@
if (mWakeLock.isHeld()) {
mWakeLock.release();
}
- listenForTeaseSignals(false);
+ listenForPulseSignals(false);
stopDozing();
dozingStopped();
}
@@ -187,9 +208,17 @@
}
}
- private void requestTease() {
+ private void requestMultipulse() {
+ requestPulse(mMultipulseCount);
+ }
+
+ private void requestPulse() {
+ requestPulse(1);
+ }
+
+ private void requestPulse(int pulses) {
if (mHost != null) {
- mHost.requestTease(this);
+ mHost.requestPulse(pulses, this);
}
}
@@ -199,10 +228,10 @@
}
}
- private void listenForTeaseSignals(boolean listen) {
- if (DEBUG) Log.d(mTag, "listenForTeaseSignals: " + listen);
+ private void listenForPulseSignals(boolean listen) {
+ if (DEBUG) Log.d(mTag, "listenForPulseSignals: " + listen);
listenForSignificantMotion(listen);
- listenForBroadcast(listen);
+ listenForBroadcasts(listen);
listenForNotifications(listen);
}
@@ -216,15 +245,17 @@
}
}
- private void listenForBroadcast(boolean listen) {
+ private void listenForBroadcasts(boolean listen) {
if (listen) {
- mContext.registerReceiver(mTeaseReceiver, new IntentFilter(TEASE_ACTION));
- mTeaseReceiverRegistered = true;
+ final IntentFilter filter = new IntentFilter(PULSE_ACTION);
+ filter.addAction(NOTIFICATION_PULSE_ACTION);
+ mContext.registerReceiver(mBroadcastReceiver, filter);
+ mBroadcastReceiverRegistered = true;
} else {
- if (mTeaseReceiverRegistered) {
- mContext.unregisterReceiver(mTeaseReceiver);
+ if (mBroadcastReceiverRegistered) {
+ mContext.unregisterReceiver(mBroadcastReceiver);
}
- mTeaseReceiverRegistered = false;
+ mBroadcastReceiverRegistered = false;
}
}
@@ -237,6 +268,15 @@
}
}
+ private void rescheduleNotificationPulse() {
+ mAlarmManager.cancel(mNotificationPulseIntent);
+ if (mNotificationLightOn) {
+ final long time = System.currentTimeMillis() + mNotificationPulseInterval;
+ if (DEBUG) Log.d(TAG, "Scheduling pulse for " + new Date(time));
+ mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, time, mNotificationPulseIntent);
+ }
+ }
+
private static String triggerEventToString(TriggerEvent event) {
if (event == null) return null;
final StringBuilder sb = new StringBuilder("TriggerEvent[")
@@ -269,16 +309,23 @@
v.vibrate(1000);
}
}
- requestTease();
+ requestPulse();
listenForSignificantMotion(true); // reregister, this sensor only fires once
}
};
- private final BroadcastReceiver mTeaseReceiver = new BroadcastReceiver() {
+ private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
- if (DEBUG) Log.d(mTag, "Received tease intent");
- requestTease();
+ if (PULSE_ACTION.equals(intent.getAction())) {
+ if (DEBUG) Log.d(mTag, "Received pulse intent");
+ requestPulse(intent.getIntExtra(EXTRA_PULSES, mMultipulseCount));
+ }
+ if (NOTIFICATION_PULSE_ACTION.equals(intent.getAction())) {
+ if (DEBUG) Log.d(mTag, "Received notification pulse intent");
+ requestPulse();
+ rescheduleNotificationPulse();
+ }
}
};
@@ -288,10 +335,19 @@
if (DEBUG) Log.d(mTag, "onNewNotifications");
// noop for now
}
+
@Override
public void onBuzzBeepBlinked() {
if (DEBUG) Log.d(mTag, "onBuzzBeepBlinked");
- requestTease();
+ requestMultipulse();
+ }
+
+ @Override
+ public void onNotificationLight(boolean on) {
+ if (DEBUG) Log.d(mTag, "onNotificationLight on=" + on);
+ if (mNotificationLightOn == on) return;
+ mNotificationLightOn = on;
+ rescheduleNotificationPulse();
}
};
@@ -299,12 +355,13 @@
void addCallback(Callback callback);
void removeCallback(Callback callback);
void requestDoze(DozeService dozeService);
- void requestTease(DozeService dozeService);
+ void requestPulse(int pulses, DozeService dozeService);
void dozingStopped(DozeService dozeService);
public interface Callback {
void onNewNotifications();
void onBuzzBeepBlinked();
+ void onNotificationLight(boolean on);
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index a82c907..9107790 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -55,6 +55,8 @@
private static final int MSG_SHOW_RECENT_APPS = 14 << MSG_SHIFT;
private static final int MSG_HIDE_RECENT_APPS = 15 << MSG_SHIFT;
private static final int MSG_BUZZ_BEEP_BLINKED = 16 << MSG_SHIFT;
+ private static final int MSG_NOTIFICATION_LIGHT_OFF = 17 << MSG_SHIFT;
+ private static final int MSG_NOTIFICATION_LIGHT_PULSE = 18 << MSG_SHIFT;
public static final int FLAG_EXCLUDE_NONE = 0;
public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -95,6 +97,8 @@
public void hideSearchPanel();
public void setWindowState(int window, int state);
public void buzzBeepBlinked();
+ public void notificationLightOff();
+ public void notificationLightPulse(int argb, int onMillis, int offMillis);
}
public CommandQueue(Callbacks callbacks, StatusBarIconList list) {
@@ -230,6 +234,19 @@
}
}
+ public void notificationLightOff() {
+ synchronized (mList) {
+ mHandler.sendEmptyMessage(MSG_NOTIFICATION_LIGHT_OFF);
+ }
+ }
+
+ public void notificationLightPulse(int argb, int onMillis, int offMillis) {
+ synchronized (mList) {
+ mHandler.obtainMessage(MSG_NOTIFICATION_LIGHT_PULSE, onMillis, offMillis, argb)
+ .sendToTarget();
+ }
+ }
+
private final class H extends Handler {
public void handleMessage(Message msg) {
final int what = msg.what & MSG_MASK;
@@ -306,7 +323,12 @@
case MSG_BUZZ_BEEP_BLINKED:
mCallbacks.buzzBeepBlinked();
break;
-
+ case MSG_NOTIFICATION_LIGHT_OFF:
+ mCallbacks.notificationLightOff();
+ break;
+ case MSG_NOTIFICATION_LIGHT_PULSE:
+ mCallbacks.notificationLightPulse((Integer) msg.obj, msg.arg1, msg.arg2);
+ break;
}
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index e38bada..99b0259 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -2336,6 +2336,20 @@
}
}
+ @Override
+ public void notificationLightOff() {
+ if (mDozeServiceHost != null) {
+ mDozeServiceHost.fireNotificationLight(false);
+ }
+ }
+
+ @Override
+ public void notificationLightPulse(int argb, int onMillis, int offMillis) {
+ if (mDozeServiceHost != null) {
+ mDozeServiceHost.fireNotificationLight(true);
+ }
+ }
+
@Override // CommandQueue
public void setSystemUiVisibility(int vis, int mask) {
final int oldVal = mSystemUiVisibility;
@@ -3799,6 +3813,12 @@
}
}
+ public void fireNotificationLight(boolean on) {
+ for (Callback callback : mCallbacks) {
+ callback.onNotificationLight(on);
+ }
+ }
+
public void fireNewNotifications() {
for (Callback callback : mCallbacks) {
callback.onNewNotifications();
@@ -3823,10 +3843,10 @@
}
@Override
- public void requestTease(DozeService dozeService) {
+ public void requestPulse(int pulses, DozeService dozeService) {
if (dozeService == null) return;
dozeService.stayAwake(PROCESSING_TIME);
- mHandler.obtainMessage(H.REQUEST_TEASE, dozeService).sendToTarget();
+ mHandler.obtainMessage(H.REQUEST_PULSE, pulses, 0, dozeService).sendToTarget();
}
@Override
@@ -3845,9 +3865,9 @@
mCurrentDozeService.startDozing();
}
- private void handleRequestTease(DozeService dozeService) {
+ private void handleRequestPulse(int pulses, DozeService dozeService) {
if (!dozeService.equals(mCurrentDozeService)) return;
- final long stayAwake = mScrimController.tease();
+ final long stayAwake = mScrimController.pulse(pulses);
mCurrentDozeService.stayAwake(stayAwake);
}
@@ -3863,15 +3883,15 @@
private final class H extends Handler {
private static final int REQUEST_DOZE = 1;
- private static final int REQUEST_TEASE = 2;
+ private static final int REQUEST_PULSE = 2;
private static final int DOZING_STOPPED = 3;
@Override
public void handleMessage(Message msg) {
if (msg.what == REQUEST_DOZE) {
handleRequestDoze((DozeService) msg.obj);
- } else if (msg.what == REQUEST_TEASE) {
- handleRequestTease((DozeService) msg.obj);
+ } else if (msg.what == REQUEST_PULSE) {
+ handleRequestPulse(msg.arg1, (DozeService) msg.obj);
} else if (msg.what == DOZING_STOPPED) {
handleDozingStopped((DozeService) msg.obj);
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 7bce664..cbd66aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -43,14 +43,13 @@
private static final long ANIMATION_DURATION = 220;
private static final int TAG_KEY_ANIM = R.id.scrim;
- private static final int NUM_TEASES = 3;
- private static final long TEASE_IN_ANIMATION_DURATION = 1000;
- private static final long TEASE_VISIBLE_DURATION = 2000;
- private static final long TEASE_OUT_ANIMATION_DURATION = 1000;
- private static final long TEASE_INVISIBLE_DURATION = 1000;
- private static final long TEASE_DURATION = TEASE_IN_ANIMATION_DURATION
- + TEASE_VISIBLE_DURATION + TEASE_OUT_ANIMATION_DURATION + TEASE_INVISIBLE_DURATION;
- private static final long PRE_TEASE_DELAY = 1000;
+ private static final long PULSE_IN_ANIMATION_DURATION = 1000;
+ private static final long PULSE_VISIBLE_DURATION = 2000;
+ private static final long PULSE_OUT_ANIMATION_DURATION = 1000;
+ private static final long PULSE_INVISIBLE_DURATION = 1000;
+ private static final long PULSE_DURATION = PULSE_IN_ANIMATION_DURATION
+ + PULSE_VISIBLE_DURATION + PULSE_OUT_ANIMATION_DURATION + PULSE_INVISIBLE_DURATION;
+ private static final long PRE_PULSE_DELAY = 1000;
private final View mScrimBehind;
private final View mScrimInFront;
@@ -70,7 +69,7 @@
private Runnable mOnAnimationFinished;
private boolean mAnimationStarted;
private boolean mDozing;
- private int mTeasesRemaining;
+ private int mPulsesRemaining;
private final Interpolator mInterpolator = new DecelerateInterpolator();
public ScrimController(View scrimBehind, View scrimInFront) {
@@ -126,23 +125,23 @@
if (mDozing == dozing) return;
mDozing = dozing;
if (!mDozing) {
- cancelTeasing();
+ cancelPulsing();
}
scheduleUpdate();
}
/** When dozing, fade screen contents in and out a few times using the front scrim. */
- public long tease() {
+ public long pulse(int pulses) {
if (!mDozing) return 0;
- mTeasesRemaining = NUM_TEASES;
- mScrimInFront.postDelayed(mTeaseIn, PRE_TEASE_DELAY);
- return PRE_TEASE_DELAY + NUM_TEASES * TEASE_DURATION;
+ mPulsesRemaining = Math.max(pulses, mPulsesRemaining);
+ mScrimInFront.postDelayed(mPulseIn, PRE_PULSE_DELAY);
+ return PRE_PULSE_DELAY + mPulsesRemaining * PULSE_DURATION;
}
- private void cancelTeasing() {
- mTeasesRemaining = 0;
- mScrimInFront.removeCallbacks(mTeaseIn);
- mScrimInFront.removeCallbacks(mTeaseOut);
+ private void cancelPulsing() {
+ mPulsesRemaining = 0;
+ mScrimInFront.removeCallbacks(mPulseIn);
+ mScrimInFront.removeCallbacks(mPulseOut);
}
private void scheduleUpdate() {
@@ -285,49 +284,49 @@
return true;
}
- private final Runnable mTeaseIn = new Runnable() {
+ private final Runnable mPulseIn = new Runnable() {
@Override
public void run() {
- if (DEBUG) Log.d(TAG, "Tease in, mDozing=" + mDozing
- + " mTeasesRemaining=" + mTeasesRemaining);
- if (!mDozing || mTeasesRemaining == 0) return;
- mTeasesRemaining--;
- mDurationOverride = TEASE_IN_ANIMATION_DURATION;
+ if (DEBUG) Log.d(TAG, "Pulse in, mDozing=" + mDozing
+ + " mPulsesRemaining=" + mPulsesRemaining);
+ if (!mDozing || mPulsesRemaining == 0) return;
+ mPulsesRemaining--;
+ mDurationOverride = PULSE_IN_ANIMATION_DURATION;
mAnimationDelay = 0;
mAnimateChange = true;
- mOnAnimationFinished = mTeaseInFinished;
+ mOnAnimationFinished = mPulseInFinished;
setScrimColor(mScrimInFront, 0);
}
};
- private final Runnable mTeaseInFinished = new Runnable() {
+ private final Runnable mPulseInFinished = new Runnable() {
@Override
public void run() {
- if (DEBUG) Log.d(TAG, "Tease in finished, mDozing=" + mDozing);
+ if (DEBUG) Log.d(TAG, "Pulse in finished, mDozing=" + mDozing);
if (!mDozing) return;
- mScrimInFront.postDelayed(mTeaseOut, TEASE_VISIBLE_DURATION);
+ mScrimInFront.postDelayed(mPulseOut, PULSE_VISIBLE_DURATION);
}
};
- private final Runnable mTeaseOut = new Runnable() {
+ private final Runnable mPulseOut = new Runnable() {
@Override
public void run() {
- if (DEBUG) Log.d(TAG, "Tease in finished, mDozing=" + mDozing);
+ if (DEBUG) Log.d(TAG, "Pulse out, mDozing=" + mDozing);
if (!mDozing) return;
- mDurationOverride = TEASE_OUT_ANIMATION_DURATION;
+ mDurationOverride = PULSE_OUT_ANIMATION_DURATION;
mAnimationDelay = 0;
mAnimateChange = true;
- mOnAnimationFinished = mTeaseOutFinished;
+ mOnAnimationFinished = mPulseOutFinished;
setScrimColor(mScrimInFront, 1);
}
};
- private final Runnable mTeaseOutFinished = new Runnable() {
+ private final Runnable mPulseOutFinished = new Runnable() {
@Override
public void run() {
- if (DEBUG) Log.d(TAG, "Tease out finished, mTeasesRemaining=" + mTeasesRemaining);
- if (mTeasesRemaining > 0) {
- mScrimInFront.postDelayed(mTeaseIn, TEASE_INVISIBLE_DURATION);
+ if (DEBUG) Log.d(TAG, "Pulse out finished, mPulsesRemaining=" + mPulsesRemaining);
+ if (mPulsesRemaining > 0) {
+ mScrimInFront.postDelayed(mPulseIn, PULSE_INVISIBLE_DURATION);
}
}
};
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index a123bf7..049add5 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -99,6 +99,14 @@
public void buzzBeepBlinked() {
}
+ @Override // CommandQueue
+ public void notificationLightOff() {
+ }
+
+ @Override // CommandQueue
+ public void notificationLightPulse(int argb, int onMillis, int offMillis) {
+ }
+
@Override
protected WindowManager.LayoutParams getSearchLayoutParams(
LayoutParams layoutParams) {