diff options
| author | 2014-09-18 15:27:50 -0700 | |
|---|---|---|
| committer | 2014-09-19 13:14:28 -0700 | |
| commit | 4d69e2219390bce567b0d2c986d0bd3a3182eda5 (patch) | |
| tree | b893452373448020c6c84ffba16e82f73bca518d | |
| parent | 606e4e8c98304daf756f7e89d47005573288f72a (diff) | |
Fix order of operations while pulsing the ambient display.
This change fixes several issues in how the display's power state
was coordinated to ensure that the display is not turned on until
the pulse is ready to be shown. It also greatly simplifies the
wakelock logic and makes it completely deterministic instead of
relying on timed delays.
Bug: 17516245
Change-Id: If2b96845a010f2d05c610970257d898f32ccacb7
4 files changed, 219 insertions, 154 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java new file mode 100644 index 000000000000..e92f9888ac99 --- /dev/null +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeHost.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2014 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + */ + +package com.android.systemui.doze; + +import android.annotation.NonNull; + +/** + * Interface the doze service uses to communicate with the rest of system UI. + */ +public interface DozeHost { + void addCallback(@NonNull Callback callback); + void removeCallback(@NonNull Callback callback); + void startDozing(@NonNull Runnable ready); + void pulseWhileDozing(@NonNull PulseCallback callback); + void stopDozing(); + boolean isPowerSaveActive(); + + public interface Callback { + void onNewNotifications(); + void onBuzzBeepBlinked(); + void onNotificationLight(boolean on); + void onPowerSaveChanged(boolean active); + } + + public interface PulseCallback { + void onPulseStarted(); + void onPulseFinished(); + } +}
\ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java index e429801fc7ed..b07e99379abb 100644 --- a/packages/SystemUI/src/com/android/systemui/doze/DozeService.java +++ b/packages/SystemUI/src/com/android/systemui/doze/DozeService.java @@ -27,7 +27,6 @@ import android.hardware.SensorManager; import android.hardware.TriggerEvent; import android.hardware.TriggerEventListener; import android.media.AudioAttributes; -import android.os.Handler; import android.os.PowerManager; import android.os.Vibrator; import android.service.dreams.DreamService; @@ -53,10 +52,9 @@ public class DozeService extends DreamService { private final String mTag = String.format(TAG + ".%08x", hashCode()); private final Context mContext = this; - private final Handler mHandler = new Handler(); private final DozeParameters mDozeParameters = new DozeParameters(mContext); - private Host mHost; + private DozeHost mHost; private SensorManager mSensors; private TriggerSensor mSigMotionSensor; private TriggerSensor mPickupSensor; @@ -64,9 +62,9 @@ public class DozeService extends DreamService { private PowerManager.WakeLock mWakeLock; private AlarmManager mAlarmManager; private boolean mDreaming; + private boolean mPulsing; private boolean mBroadcastReceiverRegistered; private boolean mDisplayStateSupported; - private int mDisplayStateWhenOn; private boolean mNotificationLightOn; private boolean mPowerSaveActive; private long mNotificationPulseTime; @@ -81,6 +79,8 @@ public class DozeService extends DreamService { protected void dumpOnHandler(FileDescriptor fd, PrintWriter pw, 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); @@ -100,7 +100,7 @@ public class DozeService extends DreamService { if (getApplication() instanceof SystemUIApplication) { final SystemUIApplication app = (SystemUIApplication) getApplication(); - mHost = app.getComponent(Host.class); + mHost = app.getComponent(DozeHost.class); } if (mHost == null) Log.w(TAG, "No doze service host found."); @@ -113,10 +113,10 @@ public class DozeService extends DreamService { mDozeParameters.getPulseOnPickup(), mDozeParameters.getVibrateOnPickup()); 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(); - mDisplayStateWhenOn = mDisplayStateSupported ? Display.STATE_DOZE : Display.STATE_ON; - mDisplayOff.run(); + turnDisplayOff(); } @Override @@ -128,32 +128,39 @@ public class DozeService extends DreamService { @Override public void onDreamingStarted() { super.onDreamingStarted(); - mPowerSaveActive = mHost != null && mHost.isPowerSaveActive(); + + if (mHost == null) { + finish(); + return; + } + + mPowerSaveActive = mHost.isPowerSaveActive(); if (DEBUG) Log.d(mTag, "onDreamingStarted canDoze=" + canDoze() + " mPowerSaveActive=" + mPowerSaveActive); if (mPowerSaveActive) { finishToSavePower(); return; } + mDreaming = true; listenForPulseSignals(true); rescheduleNotificationPulse(false /*predicate*/); // cancel any pending pulse alarms - requestDoze(); - } - public void stayAwake(long millis) { - if (mDreaming && millis > 0) { - if (DEBUG) Log.d(mTag, "stayAwake millis=" + millis); - mWakeLock.acquire(millis); - setDozeScreenState(mDisplayStateWhenOn); - rescheduleOff(millis); - } - } - - private void rescheduleOff(long millis) { - if (DEBUG) Log.d(TAG, "rescheduleOff millis=" + millis); - mHandler.removeCallbacks(mDisplayOff); - mHandler.postDelayed(mDisplayOff, millis); + // 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. + } + } + }); } @Override @@ -161,37 +168,52 @@ public class DozeService extends DreamService { if (DEBUG) Log.d(mTag, "onDreamingStopped isDozing=" + isDozing()); super.onDreamingStopped(); - mDreaming = false; - if (mWakeLock.isHeld()) { - mWakeLock.release(); + if (mHost == null) { + return; } + + mDreaming = false; listenForPulseSignals(false); - dozingStopped(); - mHandler.removeCallbacks(mDisplayOff); - } - @Override - public void startDozing() { - if (DEBUG) Log.d(mTag, "startDozing"); - super.startDozing(); + // Tell the host that it's over. + mHost.stopDozing(); } - private void requestDoze() { - if (mHost != null) { - mHost.requestDoze(this); + private void requestPulse() { + 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; + 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(); + } + } + }); } } - private void requestPulse() { - if (mHost != null) { - mHost.requestPulse(this); - } + private void turnDisplayOff() { + if (DEBUG) Log.d(TAG, "Display off"); + setDozeScreenState(Display.STATE_OFF); } - private void dozingStopped() { - if (mHost != null) { - mHost.dozingStopped(this); - } + private void turnDisplayOn() { + if (DEBUG) Log.d(TAG, "Display on"); + setDozeScreenState(mDisplayStateSupported ? Display.STATE_DOZE : Display.STATE_ON); } private void finishToSavePower() { @@ -222,7 +244,6 @@ public class DozeService extends DreamService { } private void listenForNotifications(boolean listen) { - if (mHost == null) return; if (listen) { resetNotificationResets(); mHost.addCallback(mHostCallback); @@ -256,8 +277,10 @@ public class DozeService extends DreamService { private PendingIntent notificationPulseIntent(long instance) { return PendingIntent.getBroadcast(mContext, 0, - new Intent(NOTIFICATION_PULSE_ACTION).setPackage(getPackageName()) - .putExtra(EXTRA_INSTANCE, instance), + new Intent(NOTIFICATION_PULSE_ACTION) + .setPackage(getPackageName()) + .putExtra(EXTRA_INSTANCE, instance) + .setFlags(Intent.FLAG_RECEIVER_FOREGROUND), PendingIntent.FLAG_UPDATE_CURRENT); } @@ -304,14 +327,6 @@ public class DozeService extends DreamService { return sb.append(']').toString(); } - private final Runnable mDisplayOff = new Runnable() { - @Override - public void run() { - if (DEBUG) Log.d(TAG, "Display off"); - setDozeScreenState(Display.STATE_OFF); - } - }; - private final BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { @@ -329,7 +344,7 @@ public class DozeService extends DreamService { } }; - private final Host.Callback mHostCallback = new Host.Callback() { + private final DozeHost.Callback mHostCallback = new DozeHost.Callback() { @Override public void onNewNotifications() { if (DEBUG) Log.d(mTag, "onNewNotifications"); @@ -361,22 +376,6 @@ public class DozeService extends DreamService { } }; - public interface Host { - void addCallback(Callback callback); - void removeCallback(Callback callback); - void requestDoze(DozeService dozeService); - void requestPulse(DozeService dozeService); - void dozingStopped(DozeService dozeService); - boolean isPowerSaveActive(); - - public interface Callback { - void onNewNotifications(); - void onBuzzBeepBlinked(); - void onNotificationLight(boolean on); - void onPowerSaveChanged(boolean active); - } - } - private class TriggerSensor extends TriggerEventListener { private final Sensor mSensor; private final boolean mConfigured; @@ -409,30 +408,37 @@ public class DozeService extends DreamService { @Override public void onTrigger(TriggerEvent event) { - if (DEBUG) Log.d(mTag, "onTrigger: " + triggerEventToString(event)); - if (mDebugVibrate) { - final Vibrator v = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE); - if (v != null) { - v.vibrate(1000, new AudioAttributes.Builder() - .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) - .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION).build()); + mWakeLock.acquire(); + try { + if (DEBUG) Log.d(mTag, "onTrigger: " + triggerEventToString(event)); + if (mDebugVibrate) { + final Vibrator v = (Vibrator) mContext.getSystemService( + Context.VIBRATOR_SERVICE); + if (v != null) { + v.vibrate(1000, new AudioAttributes.Builder() + .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION) + .setUsage(AudioAttributes.USAGE_ASSISTANCE_SONIFICATION).build()); + } } - } - requestPulse(); - setListening(true); // reregister, this sensor only fires once - - // reset the notification pulse schedule, but only if we think we were not triggered - // by a notification-related vibration - final long timeSinceNotification = System.currentTimeMillis() - mNotificationPulseTime; - final boolean withinVibrationThreshold = - timeSinceNotification < mDozeParameters.getPickupVibrationThreshold(); - if (withinVibrationThreshold) { - if (DEBUG) Log.d(mTag, "Not resetting schedule, recent notification"); - } else { - resetNotificationResets(); - } - if (mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) { - DozeLog.tracePickupPulse(withinVibrationThreshold); + + requestPulse(); + setListening(true); // reregister, this sensor only fires once + + // reset the notification pulse schedule, but only if we think we were not triggered + // by a notification-related vibration + final long timeSinceNotification = System.currentTimeMillis() - mNotificationPulseTime; + final boolean withinVibrationThreshold = + timeSinceNotification < mDozeParameters.getPickupVibrationThreshold(); + if (withinVibrationThreshold) { + if (DEBUG) Log.d(mTag, "Not resetting schedule, recent notification"); + } else { + resetNotificationResets(); + } + if (mSensor.getType() == Sensor.TYPE_PICK_UP_GESTURE) { + DozeLog.tracePickupPulse(withinVibrationThreshold); + } + } finally { + mWakeLock.release(); } } } 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 624fea518cfa..cce867114d9e 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java @@ -32,6 +32,7 @@ import static com.android.systemui.statusbar.phone.BarTransitions.MODE_WARNING; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.TimeInterpolator; +import android.annotation.NonNull; import android.app.ActivityManager; import android.app.ActivityManagerNative; import android.app.IActivityManager; @@ -115,8 +116,8 @@ import com.android.systemui.DemoMode; import com.android.systemui.EventLogTags; import com.android.systemui.FontSizeUtils; import com.android.systemui.R; +import com.android.systemui.doze.DozeHost; import com.android.systemui.doze.DozeLog; -import com.android.systemui.doze.DozeService; import com.android.systemui.keyguard.KeyguardViewMediator; import com.android.systemui.qs.QSPanel; import com.android.systemui.statusbar.ActivatableNotificationView; @@ -587,7 +588,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, startKeyguard(); mDozeServiceHost = new DozeServiceHost(); - putComponent(DozeService.Host.class, mDozeServiceHost); + putComponent(DozeHost.class, mDozeServiceHost); putComponent(PhoneStatusBar.class, this); setControllerUsers(); @@ -3994,8 +3995,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } public void wakeUpIfDozing(long time) { - if (mDozeServiceHost != null && mDozeServiceHost.isDozing() - && mScrimController.isPulsing()) { + if (mDozing && mScrimController.isPulsing()) { PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE); pm.wakeUp(time); } @@ -4027,7 +4027,7 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } } - private final class DozeServiceHost implements DozeService.Host { + private final class DozeServiceHost implements DozeHost { // Amount of time to allow to update the time shown on the screen before releasing // the wakelock. This timeout is design to compensate for the fact that we don't // currently have a way to know when time display contents have actually been @@ -4037,16 +4037,9 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, private final ArrayList<Callback> mCallbacks = new ArrayList<Callback>(); private final H mHandler = new H(); - private DozeService mCurrentDozeService; - @Override public String toString() { - return "PSB.DozeServiceHost[mCallbacks=" + mCallbacks.size() + " mCurrentDozeService=" - + mCurrentDozeService + "]"; - } - - public boolean isDozing() { - return mCurrentDozeService != null; + return "PSB.DozeServiceHost[mCallbacks=" + mCallbacks.size() + "]"; } public void firePowerSaveChanged(boolean active) { @@ -4074,32 +4067,28 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } @Override - public void addCallback(Callback callback) { + public void addCallback(@NonNull Callback callback) { mCallbacks.add(callback); } @Override - public void removeCallback(Callback callback) { + public void removeCallback(@NonNull Callback callback) { mCallbacks.remove(callback); } @Override - public void requestDoze(DozeService dozeService) { - if (dozeService == null) return; - mHandler.obtainMessage(H.REQUEST_DOZE, dozeService).sendToTarget(); + public void startDozing(@NonNull Runnable ready) { + mHandler.obtainMessage(H.MSG_START_DOZING, ready).sendToTarget(); } @Override - public void requestPulse(DozeService dozeService) { - if (dozeService == null) return; - dozeService.stayAwake(PROCESSING_TIME); - mHandler.obtainMessage(H.REQUEST_PULSE, dozeService).sendToTarget(); + public void pulseWhileDozing(@NonNull PulseCallback callback) { + mHandler.obtainMessage(H.MSG_PULSE_WHILE_DOZING, callback).sendToTarget(); } @Override - public void dozingStopped(DozeService dozeService) { - if (dozeService == null) return; - mHandler.obtainMessage(H.DOZING_STOPPED, dozeService).sendToTarget(); + public void stopDozing() { + mHandler.obtainMessage(H.MSG_STOP_DOZING).sendToTarget(); } @Override @@ -4107,26 +4096,20 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, return mBatteryController != null && mBatteryController.isPowerSave(); } - private void handleRequestDoze(DozeService dozeService) { - mCurrentDozeService = dozeService; + private void handleStartDozing(@NonNull Runnable ready) { if (!mDozing) { mDozing = true; DozeLog.traceDozing(mContext, mDozing); updateDozingState(); } - mCurrentDozeService.startDozing(); + ready.run(); } - private void handleRequestPulse(DozeService dozeService) { - if (!dozeService.equals(mCurrentDozeService)) return; - final long stayAwake = mScrimController.pulse(); - mCurrentDozeService.stayAwake(stayAwake); + private void handlePulseWhileDozing(@NonNull PulseCallback callback) { + mScrimController.pulse(callback); } - private void handleDozingStopped(DozeService dozeService) { - if (dozeService.equals(mCurrentDozeService)) { - mCurrentDozeService = null; - } + private void handleStopDozing() { if (mDozing) { mDozing = false; DozeLog.traceDozing(mContext, mDozing); @@ -4135,18 +4118,22 @@ public class PhoneStatusBar extends BaseStatusBar implements DemoMode, } private final class H extends Handler { - private static final int REQUEST_DOZE = 1; - private static final int REQUEST_PULSE = 2; - private static final int DOZING_STOPPED = 3; + private static final int MSG_START_DOZING = 1; + private static final int MSG_PULSE_WHILE_DOZING = 2; + private static final int MSG_STOP_DOZING = 3; @Override public void handleMessage(Message msg) { - if (msg.what == REQUEST_DOZE) { - handleRequestDoze((DozeService) msg.obj); - } else if (msg.what == REQUEST_PULSE) { - handleRequestPulse((DozeService) msg.obj); - } else if (msg.what == DOZING_STOPPED) { - handleDozingStopped((DozeService) msg.obj); + switch (msg.what) { + case MSG_START_DOZING: + handleStartDozing((Runnable) msg.obj); + break; + case MSG_PULSE_WHILE_DOZING: + handlePulseWhileDozing((PulseCallback) msg.obj); + break; + case MSG_STOP_DOZING: + handleStopDozing(); + break; } } } 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 ddb03e7fac68..9d5eccd04ea8 100644 --- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java +++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java @@ -19,6 +19,7 @@ package com.android.systemui.statusbar.phone; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; +import android.annotation.NonNull; import android.content.Context; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; @@ -30,6 +31,7 @@ import android.view.animation.DecelerateInterpolator; import android.view.animation.Interpolator; import com.android.systemui.R; +import com.android.systemui.doze.DozeHost; import com.android.systemui.doze.DozeLog; /** @@ -67,7 +69,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { private Runnable mOnAnimationFinished; private boolean mAnimationStarted; private boolean mDozing; - private long mPulseEndTime; + private DozeHost.PulseCallback mPulseCallback; private final Interpolator mInterpolator = new DecelerateInterpolator(); private final Interpolator mLinearOutSlowInInterpolator; @@ -137,25 +139,48 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { } /** When dozing, fade screen contents in and out using the front scrim. */ - public long pulse() { - if (!mDozing) return 0; - final long now = System.currentTimeMillis(); - if (DEBUG) Log.d(TAG, "pulse mPulseEndTime=" + mPulseEndTime + " now=" + now); - if (mPulseEndTime != 0 && mPulseEndTime > now) return mPulseEndTime - now; + public void pulse(@NonNull DozeHost.PulseCallback callback) { + if (callback == null) { + throw new IllegalArgumentException("callback must not be null"); + } + + if (!mDozing || mPulseCallback != null) { + // Pulse suppressed. + mPulseCallback.onPulseFinished(); + return; + } + + // Begin pulse. Note that it's very important that the pulse finished callback + // be invoked when we're done so that the caller can drop the pulse wakelock. + mPulseCallback = callback; mScrimInFront.post(mPulseIn); - mPulseEndTime = now + mDozeParameters.getPulseDuration(); - return mPulseEndTime - now; } public boolean isPulsing() { - return mDozing && mPulseEndTime != 0; + return mPulseCallback != null; } private void cancelPulsing() { if (DEBUG) Log.d(TAG, "Cancel pulsing"); - mScrimInFront.removeCallbacks(mPulseIn); - mScrimInFront.removeCallbacks(mPulseOut); - mPulseEndTime = 0; + + if (mPulseCallback != null) { + mScrimInFront.removeCallbacks(mPulseIn); + mScrimInFront.removeCallbacks(mPulseOut); + pulseFinished(); + } + } + + private void pulseStarted() { + if (mPulseCallback != null) { + mPulseCallback.onPulseStarted(); + } + } + + private void pulseFinished() { + if (mPulseCallback != null) { + mPulseCallback.onPulseFinished(); + mPulseCallback = null; + } } private void scheduleUpdate() { @@ -263,7 +288,6 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { anim.setStartDelay(mAnimationDelay); anim.setDuration(mDurationOverride != -1 ? mDurationOverride : ANIMATION_DURATION); anim.addListener(new AnimatorListenerAdapter() { - @Override public void onAnimationEnd(Animator animation) { if (mOnAnimationFinished != null) { @@ -316,6 +340,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { mAnimateChange = true; mOnAnimationFinished = mPulseInFinished; setScrimColor(mScrimInFront, 0); + + // Signal that the pulse is ready to turn the screen on and draw. + pulseStarted(); } }; @@ -346,7 +373,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener { public void run() { if (DEBUG) Log.d(TAG, "Pulse out finished"); DozeLog.tracePulseFinish(); - mPulseEndTime = 0; + + // Signal that the pulse is all finished so we can turn the screen off now. + pulseFinished(); } }; } |