Fields Summary |
---|
private static final String | TAG |
private static final boolean | DEBUG |
private static final String | ACTION_BASE |
private static final String | PULSE_ACTION |
private static final String | NOTIFICATION_PULSE_ACTION |
private static final String | EXTRA_INSTANCE |
private static final int | EARLIEST_LIGHT_PULSE_AFTER_START_MSEarliest time we pulse due to a notification light after the service started.
Incoming notification light events during the blackout period are
delayed to the earliest time defined by this constant.
This delay avoids a pulse immediately after screen off, at which
point the notification light is re-enabled again by NoMan. |
private final String | mTag |
private final android.content.Context | mContext |
private final com.android.systemui.statusbar.phone.DozeParameters | mDozeParameters |
private final android.os.Handler | mHandler |
private DozeHost | mHost |
private android.hardware.SensorManager | mSensors |
private TriggerSensor | mSigMotionSensor |
private TriggerSensor | mPickupSensor |
private android.os.PowerManager | mPowerManager |
private PowerManager.WakeLock | mWakeLock |
private android.app.AlarmManager | mAlarmManager |
private android.app.UiModeManager | mUiModeManager |
private boolean | mDreaming |
private boolean | mPulsing |
private boolean | mBroadcastReceiverRegistered |
private boolean | mDisplayStateSupported |
private boolean | mNotificationLightOn |
private boolean | mPowerSaveActive |
private boolean | mCarMode |
private long | mNotificationPulseTime |
private long | mEarliestPulseDueToLight |
private int | mScheduleResetsRemaining |
private final android.content.BroadcastReceiver | mBroadcastReceiver |
private final DozeHost.Callback | mHostCallback |
Methods Summary |
---|
private void | continuePulsing(int reason)
mHost.pulseWhileDozing(new DozeHost.PulseCallback() {
@Override
public void onPulseStarted() {
if (mPulsing && mDreaming) {
turnDisplayOn();
}
}
@Override
public void onPulseFinished() {
if (mPulsing && mDreaming) {
mPulsing = false;
turnDisplayOff();
}
mWakeLock.release(); // needs to be unconditional to balance acquire
}
}, reason);
|
protected void | dumpOnHandler(java.io.FileDescriptor fd, java.io.PrintWriter pw, java.lang.String[] args)
super.dumpOnHandler(fd, pw, args);
pw.print(" mDreaming: "); pw.println(mDreaming);
pw.print(" mPulsing: "); pw.println(mPulsing);
pw.print(" mWakeLock: held="); pw.println(mWakeLock.isHeld());
pw.print(" mHost: "); pw.println(mHost);
pw.print(" mBroadcastReceiverRegistered: "); pw.println(mBroadcastReceiverRegistered);
pw.print(" mSigMotionSensor: "); pw.println(mSigMotionSensor);
pw.print(" mPickupSensor:"); pw.println(mPickupSensor);
pw.print(" mDisplayStateSupported: "); pw.println(mDisplayStateSupported);
pw.print(" mNotificationLightOn: "); pw.println(mNotificationLightOn);
pw.print(" mPowerSaveActive: "); pw.println(mPowerSaveActive);
pw.print(" mCarMode: "); pw.println(mCarMode);
pw.print(" mNotificationPulseTime: "); pw.println(mNotificationPulseTime);
pw.print(" mScheduleResetsRemaining: "); pw.println(mScheduleResetsRemaining);
mDozeParameters.dump(pw);
|
private void | finishForCarMode()
Log.w(mTag, "Exiting ambient mode, not allowed in car mode");
finish();
|
private void | finishToSavePower()
Log.w(mTag, "Exiting ambient mode due to low power battery saver");
finish();
|
private void | listenForBroadcasts(boolean listen)
if (listen) {
final IntentFilter filter = new IntentFilter(PULSE_ACTION);
filter.addAction(NOTIFICATION_PULSE_ACTION);
filter.addAction(UiModeManager.ACTION_ENTER_CAR_MODE);
mContext.registerReceiver(mBroadcastReceiver, filter);
mBroadcastReceiverRegistered = true;
} else {
if (mBroadcastReceiverRegistered) {
mContext.unregisterReceiver(mBroadcastReceiver);
}
mBroadcastReceiverRegistered = false;
}
|
private void | listenForNotifications(boolean listen)
if (listen) {
resetNotificationResets();
mHost.addCallback(mHostCallback);
// Continue to pulse for existing LEDs.
mNotificationLightOn = mHost.isNotificationLightOn();
if (mNotificationLightOn) {
updateNotificationPulseDueToLight();
}
} else {
mHost.removeCallback(mHostCallback);
}
|
private void | listenForPulseSignals(boolean listen)
if (DEBUG) Log.d(mTag, "listenForPulseSignals: " + listen);
mSigMotionSensor.setListening(listen);
mPickupSensor.setListening(listen);
listenForBroadcasts(listen);
listenForNotifications(listen);
|
private android.app.PendingIntent | notificationPulseIntent(long instance)
return PendingIntent.getBroadcast(mContext, 0,
new Intent(NOTIFICATION_PULSE_ACTION)
.setPackage(getPackageName())
.putExtra(EXTRA_INSTANCE, instance)
.setFlags(Intent.FLAG_RECEIVER_FOREGROUND),
PendingIntent.FLAG_UPDATE_CURRENT);
|
public void | onAttachedToWindow()
if (DEBUG) Log.d(mTag, "onAttachedToWindow");
super.onAttachedToWindow();
|
public void | onCreate()
if (DEBUG) Log.d(mTag, "onCreate");
super.onCreate();
if (getApplication() instanceof SystemUIApplication) {
final SystemUIApplication app = (SystemUIApplication) getApplication();
mHost = app.getComponent(DozeHost.class);
}
if (mHost == null) Log.w(TAG, "No doze service host found.");
setWindowless(true);
mSensors = (SensorManager) mContext.getSystemService(Context.SENSOR_SERVICE);
mSigMotionSensor = new TriggerSensor(Sensor.TYPE_SIGNIFICANT_MOTION,
mDozeParameters.getPulseOnSigMotion(), mDozeParameters.getVibrateOnSigMotion(),
DozeLog.PULSE_REASON_SENSOR_SIGMOTION);
mPickupSensor = new TriggerSensor(Sensor.TYPE_PICK_UP_GESTURE,
mDozeParameters.getPulseOnPickup(), mDozeParameters.getVibrateOnPickup(),
DozeLog.PULSE_REASON_SENSOR_PICKUP);
mPowerManager = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
mWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, mTag);
mWakeLock.setReferenceCounted(true);
mAlarmManager = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
mDisplayStateSupported = mDozeParameters.getDisplayStateSupported();
mUiModeManager = (UiModeManager) mContext.getSystemService(Context.UI_MODE_SERVICE);
turnDisplayOff();
|
public void | onDreamingStarted()
super.onDreamingStarted();
if (mHost == null) {
finish();
return;
}
mPowerSaveActive = mHost.isPowerSaveActive();
mCarMode = mUiModeManager.getCurrentModeType() == Configuration.UI_MODE_TYPE_CAR;
if (DEBUG) Log.d(mTag, "onDreamingStarted canDoze=" + canDoze() + " mPowerSaveActive="
+ mPowerSaveActive + " mCarMode=" + mCarMode);
if (mPowerSaveActive) {
finishToSavePower();
return;
}
if (mCarMode) {
finishForCarMode();
return;
}
mDreaming = true;
rescheduleNotificationPulse(false /*predicate*/); // cancel any pending pulse alarms
mEarliestPulseDueToLight = System.currentTimeMillis() + EARLIEST_LIGHT_PULSE_AFTER_START_MS;
listenForPulseSignals(true);
// Ask the host to get things ready to start dozing.
// Once ready, we call startDozing() at which point the CPU may suspend
// and we will need to acquire a wakelock to do work.
mHost.startDozing(new Runnable() {
@Override
public void run() {
if (mDreaming) {
startDozing();
// From this point until onDreamingStopped we will need to hold a
// wakelock whenever we are doing work. Note that we never call
// stopDozing because can we just keep dozing until the bitter end.
}
}
});
|
public void | onDreamingStopped()
if (DEBUG) Log.d(mTag, "onDreamingStopped isDozing=" + isDozing());
super.onDreamingStopped();
if (mHost == null) {
return;
}
mDreaming = false;
listenForPulseSignals(false);
// Tell the host that it's over.
mHost.stopDozing();
|
private void | requestPulse(int reason)
if (mHost != null && mDreaming && !mPulsing) {
// Let the host know we want to pulse. Wait for it to be ready, then
// turn the screen on. When finished, turn the screen off again.
// Here we need a wakelock to stay awake until the pulse is finished.
mWakeLock.acquire();
mPulsing = true;
if (!mDozeParameters.getProxCheckBeforePulse()) {
// skip proximity check
continuePulsing(reason);
return;
}
final long start = SystemClock.uptimeMillis();
final boolean nonBlocking = reason == DozeLog.PULSE_REASON_SENSOR_PICKUP
&& mDozeParameters.getPickupPerformsProxCheck();
if (nonBlocking) {
// proximity check is only done to capture statistics, continue pulsing
continuePulsing(reason);
}
// perform a proximity check
new ProximityCheck() {
@Override
public void onProximityResult(int result) {
final boolean isNear = result == RESULT_NEAR;
final long end = SystemClock.uptimeMillis();
DozeLog.traceProximityResult(isNear, end - start, reason);
if (nonBlocking) {
// we already continued
return;
}
// avoid pulsing in pockets
if (isNear) {
mPulsing = false;
mWakeLock.release();
return;
}
// not in-pocket, continue pulsing
continuePulsing(reason);
}
}.check();
}
|
private void | rescheduleNotificationPulse(boolean predicate)
if (DEBUG) Log.d(mTag, "rescheduleNotificationPulse predicate=" + predicate);
final PendingIntent notificationPulseIntent = notificationPulseIntent(0);
mAlarmManager.cancel(notificationPulseIntent);
if (!predicate) {
if (DEBUG) Log.d(mTag, " don't reschedule: predicate is false");
return;
}
final PulseSchedule schedule = mDozeParameters.getPulseSchedule();
if (schedule == null) {
if (DEBUG) Log.d(mTag, " don't reschedule: schedule is null");
return;
}
final long now = System.currentTimeMillis();
final long time = schedule.getNextTime(now, mNotificationPulseTime);
if (time <= 0) {
if (DEBUG) Log.d(mTag, " don't reschedule: time is " + time);
return;
}
final long delta = time - now;
if (delta <= 0) {
if (DEBUG) Log.d(mTag, " don't reschedule: delta is " + delta);
return;
}
final long instance = time - mNotificationPulseTime;
if (DEBUG) Log.d(mTag, "Scheduling pulse " + instance + " in " + delta + "ms for "
+ new Date(time));
mAlarmManager.setExact(AlarmManager.RTC_WAKEUP, time, notificationPulseIntent(instance));
|
private void | resetNotificationResets()
if (DEBUG) Log.d(mTag, "resetNotificationResets");
mScheduleResetsRemaining = mDozeParameters.getPulseScheduleResets();
|
private static java.lang.String | triggerEventToString(android.hardware.TriggerEvent event)
if (event == null) return null;
final StringBuilder sb = new StringBuilder("TriggerEvent[")
.append(event.timestamp).append(',")
.append(event.sensor.getName());
if (event.values != null) {
for (int i = 0; i < event.values.length; i++) {
sb.append(',").append(event.values[i]);
}
}
return sb.append(']").toString();
|
private void | turnDisplayOff()
if (DEBUG) Log.d(mTag, "Display off");
setDozeScreenState(Display.STATE_OFF);
|
private void | turnDisplayOn()
if (DEBUG) Log.d(mTag, "Display on");
setDozeScreenState(mDisplayStateSupported ? Display.STATE_DOZE : Display.STATE_ON);
|
private void | updateNotificationPulse(long notificationTimeMs)
if (DEBUG) Log.d(mTag, "updateNotificationPulse notificationTimeMs=" + notificationTimeMs);
if (!mDozeParameters.getPulseOnNotifications()) return;
if (mScheduleResetsRemaining <= 0) {
if (DEBUG) Log.d(mTag, "No more schedule resets remaining");
return;
}
final long pulseDuration = mDozeParameters.getPulseDuration(false /*pickup*/);
if ((notificationTimeMs - mNotificationPulseTime) < pulseDuration) {
if (DEBUG) Log.d(mTag, "Recently updated, not resetting schedule");
return;
}
mScheduleResetsRemaining--;
if (DEBUG) Log.d(mTag, "mScheduleResetsRemaining = " + mScheduleResetsRemaining);
mNotificationPulseTime = notificationTimeMs;
rescheduleNotificationPulse(true /*predicate*/);
|
private void | updateNotificationPulseDueToLight()
long timeMs = System.currentTimeMillis();
timeMs = Math.max(timeMs, mEarliestPulseDueToLight);
updateNotificationPulse(timeMs);
|