diff options
Diffstat (limited to 'services/java/com/android/server/PowerManagerService.java')
-rw-r--r-- | services/java/com/android/server/PowerManagerService.java | 341 |
1 files changed, 175 insertions, 166 deletions
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java index e953355723b4..5c047c490e0c 100644 --- a/services/java/com/android/server/PowerManagerService.java +++ b/services/java/com/android/server/PowerManagerService.java @@ -45,6 +45,7 @@ import android.os.HandlerThread; import android.os.IBinder; import android.os.IPowerManager; import android.os.LocalPowerManager; +import android.os.Message; import android.os.Power; import android.os.PowerManager; import android.os.Process; @@ -57,6 +58,7 @@ import android.util.EventLog; import android.util.Log; import android.util.Slog; import android.view.WindowManagerPolicy; +import static android.view.WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR; import static android.provider.Settings.System.DIM_SCREEN; import static android.provider.Settings.System.SCREEN_BRIGHTNESS; import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE; @@ -76,6 +78,7 @@ import java.util.Observer; public class PowerManagerService extends IPowerManager.Stub implements LocalPowerManager, Watchdog.Monitor { + private static final int NOMINAL_FRAME_TIME_MS = 1000/60; private static final String TAG = "PowerManagerService"; static final String PARTIAL_NAME = "PowerManagerService"; @@ -131,6 +134,7 @@ public class PowerManagerService extends IPowerManager.Stub private static final int DEFAULT_SCREEN_BRIGHTNESS = 192; // flags for setPowerState + private static final int ALL_LIGHTS_OFF = 0x00000000; private static final int SCREEN_ON_BIT = 0x00000001; private static final int SCREEN_BRIGHT_BIT = 0x00000002; private static final int BUTTON_BRIGHT_BIT = 0x00000004; @@ -159,9 +163,9 @@ public class PowerManagerService extends IPowerManager.Stub boolean mAnimateScreenLights = true; - static final int ANIM_STEPS = 60/4; + static final int ANIM_STEPS = 60; // nominal # of frames at 60Hz // Slower animation for autobrightness changes - static final int AUTOBRIGHTNESS_ANIM_STEPS = 60; + static final int AUTOBRIGHTNESS_ANIM_STEPS = 2 * ANIM_STEPS; // Number of steps when performing a more immediate brightness change. static final int IMMEDIATE_ANIM_STEPS = 4; @@ -221,12 +225,11 @@ public class PowerManagerService extends IPowerManager.Stub private UnsynchronizedWakeLock mPreventScreenOnPartialLock; private UnsynchronizedWakeLock mProximityPartialLock; private HandlerThread mHandlerThread; - private HandlerThread mScreenOffThread; private Handler mScreenOffHandler; + private Handler mScreenBrightnessHandler; private Handler mHandler; private final TimeoutTask mTimeoutTask = new TimeoutTask(); - private final BrightnessState mScreenBrightness - = new BrightnessState(SCREEN_BRIGHT_BIT); + private ScreenBrightnessAnimator mScreenBrightnessAnimator; private boolean mStillNeedSleepNotification; private boolean mIsPowered = false; private IActivityManager mActivityService; @@ -271,6 +274,7 @@ public class PowerManagerService extends IPowerManager.Stub private int mWarningSpewThrottleCount; private long mWarningSpewThrottleTime; private int mAnimationSetting = ANIM_SETTING_OFF; + private float mWindowScaleAnimation; // Must match with the ISurfaceComposer constants in C++. private static final int ANIM_SETTING_ON = 0x01; @@ -285,7 +289,8 @@ public class PowerManagerService extends IPowerManager.Stub private static final boolean mSpew = false; private static final boolean mDebugProximitySensor = (false || mSpew); private static final boolean mDebugLightSensor = (false || mSpew); - + private static final boolean mDebugLightAnimation = (false || mSpew); + private native void nativeInit(); private native void nativeSetPowerState(boolean screenOn, boolean screenBright); private native void nativeStartSurfaceFlingerAnimation(int mode); @@ -487,10 +492,10 @@ public class PowerManagerService extends IPowerManager.Stub // recalculate everything setScreenOffTimeoutsLocked(); - final float windowScale = getFloat(WINDOW_ANIMATION_SCALE, 1.0f); + mWindowScaleAnimation = getFloat(WINDOW_ANIMATION_SCALE, 1.0f); final float transitionScale = getFloat(TRANSITION_ANIMATION_SCALE, 1.0f); mAnimationSetting = 0; - if (windowScale > 0.5f) { + if (mWindowScaleAnimation > 0.5f) { mAnimationSetting |= ANIM_SETTING_OFF; } if (transitionScale > 0.5f) { @@ -540,28 +545,20 @@ public class PowerManagerService extends IPowerManager.Stub } mInitComplete = false; - mScreenOffThread = new HandlerThread("PowerManagerService.mScreenOffThread") { - @Override - protected void onLooperPrepared() { - mScreenOffHandler = new Handler(); - synchronized (mScreenOffThread) { - mInitComplete = true; - mScreenOffThread.notifyAll(); - } - } - }; - mScreenOffThread.start(); + mScreenBrightnessAnimator = new ScreenBrightnessAnimator("mScreenBrightnessUpdaterThread", + Process.THREAD_PRIORITY_DISPLAY); + mScreenBrightnessAnimator.start(); - synchronized (mScreenOffThread) { + synchronized (mScreenBrightnessAnimator) { while (!mInitComplete) { try { - mScreenOffThread.wait(); + mScreenBrightnessAnimator.wait(); } catch (InterruptedException e) { // Ignore } } } - + mInitComplete = false; mHandlerThread = new HandlerThread("PowerManagerService") { @Override @@ -581,7 +578,7 @@ public class PowerManagerService extends IPowerManager.Stub } } } - + nativeInit(); synchronized (mLocks) { updateNativePowerStateLocked(); @@ -1078,7 +1075,6 @@ public class PowerManagerService extends IPowerManager.Stub int oldPokey = mPokey; int cumulative = 0; - boolean oldAwakeOnSet = mPokeAwakeOnSet; boolean awakeOnSet = false; for (PokeLock p: mPokeLocks.values()) { cumulative |= p.pokey; @@ -1198,7 +1194,7 @@ public class PowerManagerService extends IPowerManager.Stub + " mLightSensorKeyboardBrightness=" + mLightSensorKeyboardBrightness); pw.println(" mUseSoftwareAutoBrightness=" + mUseSoftwareAutoBrightness); pw.println(" mAutoBrightessEnabled=" + mAutoBrightessEnabled); - mScreenBrightness.dump(pw, " mScreenBrightness: "); + mScreenBrightnessAnimator.dump(pw, " mScreenBrightnessAnimator: "); int N = mLocks.size(); pw.println(); @@ -1430,7 +1426,7 @@ public class PowerManagerService extends IPowerManager.Stub private WindowManagerPolicy.ScreenOnListener mScreenOnListener = new WindowManagerPolicy.ScreenOnListener() { - @Override public void onScreenOn() { + public void onScreenOn() { synchronized (mLocks) { if (mPreparingForScreenOn) { mPreparingForScreenOn = false; @@ -1719,7 +1715,7 @@ public class PowerManagerService extends IPowerManager.Stub + Integer.toHexString(mPowerState) + " mSkippedScreenOn=" + mSkippedScreenOn); } - mScreenBrightness.forceValueLocked(Power.BRIGHTNESS_OFF); + mScreenBrightnessAnimator.animateTo(Power.BRIGHTNESS_OFF, SCREEN_BRIGHT_BIT, 0); } } int err = Power.setScreenState(on); @@ -1878,7 +1874,7 @@ public class PowerManagerService extends IPowerManager.Stub } mPowerState &= ~SCREEN_ON_BIT; mScreenOffReason = reason; - if (!mScreenBrightness.animating) { + if (!mScreenBrightnessAnimator.isAnimating()) { err = screenOffFinishedAnimatingLocked(reason); } else { err = 0; @@ -1952,11 +1948,11 @@ public class PowerManagerService extends IPowerManager.Stub // If the screen is not currently on, we will want to delay actually // turning the lights on if we are still getting the UI put up. - if ((oldState&SCREEN_ON_BIT) == 0 || mSkippedScreenOn) { + if ((oldState & SCREEN_ON_BIT) == 0 || mSkippedScreenOn) { // Don't turn screen on until we know we are really ready to. // This is to avoid letting the screen go on before things like the // lock screen have been displayed. - if ((mSkippedScreenOn=shouldDeferScreenOnLocked())) { + if ((mSkippedScreenOn = shouldDeferScreenOnLocked())) { newState &= ~(SCREEN_ON_BIT|SCREEN_BRIGHT_BIT); } } @@ -2016,7 +2012,7 @@ public class PowerManagerService extends IPowerManager.Stub case SCREEN_BRIGHT_BIT: default: // not possible - nominalCurrentValue = (int)mScreenBrightness.curValue; + nominalCurrentValue = (int)mScreenBrightnessAnimator.getCurrentBrightness(); break; } } @@ -2066,8 +2062,8 @@ public class PowerManagerService extends IPowerManager.Stub Binder.restoreCallingIdentity(identity); } if (!mSkippedScreenOn) { - mScreenBrightness.setTargetLocked(brightness, steps, - INITIAL_SCREEN_BRIGHTNESS, nominalCurrentValue); + int dt = steps * NOMINAL_FRAME_TIME_MS; + mScreenBrightnessAnimator.animateTo(brightness, SCREEN_BRIGHT_BIT, dt); if (DEBUG_SCREEN_ON) { RuntimeException e = new RuntimeException("here"); e.fillInStackTrace(); @@ -2110,154 +2106,165 @@ public class PowerManagerService extends IPowerManager.Stub } } - private void setLightBrightness(int mask, int value) { - int brightnessMode = (mAutoBrightessEnabled - ? LightsService.BRIGHTNESS_MODE_SENSOR - : LightsService.BRIGHTNESS_MODE_USER); - if ((mask & SCREEN_BRIGHT_BIT) != 0) { - if (DEBUG_SCREEN_ON) { - RuntimeException e = new RuntimeException("here"); - e.fillInStackTrace(); - Slog.i(TAG, "Set LCD brightness: " + value, e); - } - mLcdLight.setBrightness(value, brightnessMode); - } - if ((mask & BUTTON_BRIGHT_BIT) != 0) { - mButtonLight.setBrightness(value); - } - if ((mask & KEYBOARD_BRIGHT_BIT) != 0) { - mKeyboardLight.setBrightness(value); + /** + * Note: by design this class does not hold mLocks while calling native methods. + * Nor should it. Ever. + */ + class ScreenBrightnessAnimator extends HandlerThread { + static final int ANIMATE_LIGHTS = 10; + static final int POWER_OFF = 11; + volatile int startValue; + volatile int endValue; + volatile int currentValue; + private int currentMask; + private int duration; + private long startTimeMillis; + private final String prefix; + + public ScreenBrightnessAnimator(String name, int priority) { + super(name, priority); + prefix = name; } - } - class BrightnessState implements Runnable { - final int mask; + @Override + protected void onLooperPrepared() { + mScreenBrightnessHandler = new Handler() { + public void handleMessage(Message msg) { + int brightnessMode = (mAutoBrightessEnabled && !mInitialAnimation + ? LightsService.BRIGHTNESS_MODE_SENSOR + : LightsService.BRIGHTNESS_MODE_USER); + if (msg.what == ANIMATE_LIGHTS) { + final int mask = msg.arg1; + int value = msg.arg2; + long tStart = SystemClock.uptimeMillis(); + if ((mask & SCREEN_BRIGHT_BIT) != 0) { + if (mDebugLightAnimation) Log.v(TAG, "Set brightness: " + value); + mLcdLight.setBrightness(value, brightnessMode); + } + long elapsed = SystemClock.uptimeMillis() - tStart; + if ((mask & BUTTON_BRIGHT_BIT) != 0) { + mButtonLight.setBrightness(value); + } + if ((mask & KEYBOARD_BRIGHT_BIT) != 0) { + mKeyboardLight.setBrightness(value); + } - boolean initialized; - int targetValue; - float curValue; - float delta; - boolean animating; + if (elapsed > 100) { + Log.e(TAG, "Excessive delay setting brightness: " + elapsed + + "ms, mask=" + mask); + } - BrightnessState(int m) { - mask = m; + // Throttle brightness updates to frame refresh rate + int delay = elapsed < NOMINAL_FRAME_TIME_MS ? NOMINAL_FRAME_TIME_MS : 0; + synchronized(this) { + currentValue = value; + } + animateInternal(mask, false, delay); + } else if (msg.what == POWER_OFF) { + if (!mHeadless) { + int mode = msg.arg1; + nativeStartSurfaceFlingerAnimation(mode); + } + } + } + }; + synchronized (this) { + mInitComplete = true; + notifyAll(); + } } - public void dump(PrintWriter pw, String prefix) { - pw.println(prefix + "animating=" + animating - + " targetValue=" + targetValue - + " curValue=" + curValue - + " delta=" + delta); - } + private void animateInternal(int mask, boolean turningOff, int delay) { + synchronized (this) { + if (currentValue != endValue) { + final long now = SystemClock.elapsedRealtime(); + final int elapsed = (int) (now - startTimeMillis); + int newValue; + if (elapsed < duration) { + int delta = endValue - startValue; + newValue = startValue + delta * elapsed / duration; + newValue = Math.max(Power.BRIGHTNESS_OFF, newValue); + newValue = Math.min(Power.BRIGHTNESS_ON, newValue); + } else { + newValue = endValue; + mInitialAnimation = false; + } - void forceValueLocked(int value) { - targetValue = -1; - curValue = value; - setLightBrightness(mask, value); - if (animating) { - finishAnimationLocked(false, value); - } - } + if (mDebugLightAnimation) { + Log.v(TAG, "Animating light: " + "start:" + startValue + + ", end:" + endValue + ", elapsed:" + elapsed + + ", duration:" + duration + ", current:" + currentValue + + ", delay:" + delay); + } - void setTargetLocked(int target, int stepsToTarget, int initialValue, - int nominalCurrentValue) { - if (!initialized) { - initialized = true; - curValue = (float)initialValue; - } else if (targetValue == target) { - return; - } - targetValue = target; - delta = (targetValue - - (nominalCurrentValue >= 0 ? nominalCurrentValue : curValue)) - / stepsToTarget; - if (mSpew || DEBUG_SCREEN_ON) { - String noticeMe = nominalCurrentValue == curValue ? "" : " ******************"; - Slog.i(TAG, "setTargetLocked mask=" + mask + " curValue=" + curValue - + " target=" + target + " targetValue=" + targetValue + " delta=" + delta - + " nominalCurrentValue=" + nominalCurrentValue - + noticeMe); + if (turningOff) { + int mode = mScreenOffReason == OFF_BECAUSE_OF_PROX_SENSOR + ? 0 : mAnimationSetting; + if (mDebugLightAnimation) Log.v(TAG, "Doing power-off anim, mode=" + mode); + mScreenBrightnessHandler.obtainMessage(POWER_OFF, mode, 0).sendToTarget(); + } + Message msg = mScreenBrightnessHandler + .obtainMessage(ANIMATE_LIGHTS, mask, newValue); + mScreenBrightnessHandler.sendMessageDelayed(msg, delay); + } } - animating = true; + } - if (mSpew) { - Slog.i(TAG, "scheduling light animator"); - } - mScreenOffHandler.removeCallbacks(this); - mScreenOffHandler.post(this); + public void dump(PrintWriter pw, String string) { + pw.println(prefix + "animating: " + "start:" + startValue + ", end:" + endValue + + ", duration:" + duration + ", current:" + currentValue); } - boolean stepLocked() { - if (!animating) return false; - if (false && mSpew) { - Slog.i(TAG, "Step target " + mask + ": cur=" + curValue - + " target=" + targetValue + " delta=" + delta); - } - curValue += delta; - int curIntValue = (int)curValue; - boolean more = true; - if (delta == 0) { - curValue = curIntValue = targetValue; - more = false; - } else if (delta > 0) { - if (curIntValue >= targetValue) { - curValue = curIntValue = targetValue; - more = false; + public void animateTo(int target, int mask, int animationDuration) { + synchronized(this) { + startValue = currentValue; + endValue = target; + currentMask = mask; + duration = (int) (mWindowScaleAnimation * animationDuration); + startTimeMillis = SystemClock.elapsedRealtime(); + mInitialAnimation = currentValue == 0 && target > 0; + + if (mDebugLightAnimation) { + Log.v(TAG, "animateTo(target=" + target + ", mask=" + mask + + ", duration=" + animationDuration +")" + + ", currentValue=" + currentValue + + ", startTime=" + startTimeMillis); } - } else { - if (curIntValue <= targetValue) { - curValue = curIntValue = targetValue; - more = false; + + if (target != currentValue) { + final boolean turningOff = endValue == Power.BRIGHTNESS_OFF; + if (turningOff) { + // Cancel all pending animations since we're turning off + mScreenBrightnessHandler.removeCallbacksAndMessages(null); + screenOffFinishedAnimatingLocked(mScreenOffReason); + duration = 200; // TODO: how long should this be? + } + animateInternal(mask, turningOff, 0); } } - if (mSpew) Slog.d(TAG, "Animating curIntValue=" + curIntValue + ": " + mask); - setLightBrightness(mask, curIntValue); - finishAnimationLocked(more, curIntValue); - return more; } - void jumpToTargetLocked() { - if (mSpew) Slog.d(TAG, "jumpToTargetLocked targetValue=" + targetValue + ": " + mask); - setLightBrightness(mask, targetValue); - final int tv = targetValue; - curValue = tv; - targetValue = -1; - finishAnimationLocked(false, tv); + public int getCurrentBrightness() { + synchronized (this) { + return currentValue; + } } - private void finishAnimationLocked(boolean more, int curIntValue) { - animating = more; - if (!more) { - if (mask == SCREEN_BRIGHT_BIT && curIntValue == Power.BRIGHTNESS_OFF) { - screenOffFinishedAnimatingLocked(mScreenOffReason); - } + public boolean isAnimating() { + synchronized (this) { + return currentValue != endValue; } } - public void run() { - synchronized (mLocks) { - // we're turning off - final boolean turningOff = animating && targetValue == Power.BRIGHTNESS_OFF; - if (mAnimateScreenLights || !turningOff) { - long now = SystemClock.uptimeMillis(); - boolean more = mScreenBrightness.stepLocked(); - if (more) { - mScreenOffHandler.postAtTime(this, now+(1000/60)); - } - } else { - if (!mHeadless) { - // It's pretty scary to hold mLocks for this long, and we should - // redesign this, but it works for now. - nativeStartSurfaceFlingerAnimation( - mScreenOffReason == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR - ? 0 : mAnimationSetting); - } - mScreenBrightness.jumpToTargetLocked(); - } - } + public void cancelAnimation() { + animateTo(endValue, currentMask, 0); } } + private void setLightBrightness(int mask, int value) { + mScreenBrightnessAnimator.animateTo(value, mask, 0); + } + private int getPreferredBrightness() { if (mScreenBrightnessOverride >= 0) { return mScreenBrightnessOverride; @@ -2325,7 +2332,8 @@ public class PowerManagerService extends IPowerManager.Stub } private boolean isScreenTurningOffLocked() { - return (mScreenBrightness.animating && mScreenBrightness.targetValue == 0); + return (mScreenBrightnessAnimator.isAnimating() + && mScreenBrightnessAnimator.endValue == Power.BRIGHTNESS_OFF); } private boolean shouldLog(long time) { @@ -2346,7 +2354,7 @@ public class PowerManagerService extends IPowerManager.Stub private void forceUserActivityLocked() { if (isScreenTurningOffLocked()) { // cancel animation so userActivity will succeed - mScreenBrightness.animating = false; + mScreenBrightnessAnimator.cancelAnimation(); } boolean savedActivityAllowed = mUserActivityAllowed; mUserActivityAllowed = true; @@ -2525,6 +2533,8 @@ public class PowerManagerService extends IPowerManager.Stub } }; + private boolean mInitialAnimation; // used to prevent lightsensor changes while turning on + private void dockStateChanged(int state) { synchronized (mLocks) { mIsDocked = (state != Intent.EXTRA_DOCK_STATE_UNDOCKED); @@ -2586,10 +2596,11 @@ public class PowerManagerService extends IPowerManager.Stub } if (mAutoBrightessEnabled && mScreenBrightnessOverride < 0) { - if (!mSkippedScreenOn) { - mScreenBrightness.setTargetLocked(lcdValue, - immediate ? IMMEDIATE_ANIM_STEPS : AUTOBRIGHTNESS_ANIM_STEPS, - INITIAL_SCREEN_BRIGHTNESS, (int)mScreenBrightness.curValue); + if (!mSkippedScreenOn && !mInitialAnimation) { + int steps = immediate ? IMMEDIATE_ANIM_STEPS : AUTOBRIGHTNESS_ANIM_STEPS; + mScreenBrightnessAnimator.cancelAnimation(); + mScreenBrightnessAnimator.animateTo(lcdValue, + SCREEN_BRIGHT_BIT, steps * NOMINAL_FRAME_TIME_MS); } } if (mButtonBrightnessOverride < 0) { @@ -2641,7 +2652,7 @@ public class PowerManagerService extends IPowerManager.Stub synchronized (this) { ShutdownThread.reboot(mContext, finalReason, false); } - + } }; // ShutdownThread must run on a looper capable of displaying the UI. @@ -2995,9 +3006,7 @@ public class PowerManagerService extends IPowerManager.Stub } finally { Binder.restoreCallingIdentity(identity); } - - mScreenBrightness.targetValue = brightness; - mScreenBrightness.jumpToTargetLocked(); + mScreenBrightnessAnimator.animateTo(brightness, SCREEN_BRIGHT_BIT, 0); } } |