diff options
Diffstat (limited to 'packages/SystemUI/src')
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 0000000..e92f988 --- /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 e429801..b07e993 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 624fea5..cce8671 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 ddb03e7..9d5eccd 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(); } }; } |