summaryrefslogtreecommitdiffstats
path: root/services/core/java/com/android/server/power
diff options
context:
space:
mode:
authorJeff Brown <jeffbrown@google.com>2014-04-08 17:27:14 -0700
committerJeff Brown <jeffbrown@google.com>2014-04-08 21:34:32 -0700
commit131206b8a9d07400d7c98aea50cc45c38769448f (patch)
treee09f13d723f0829900c2ebc33d834c59997a01e6 /services/core/java/com/android/server/power
parent91c8f753ab841342a904fa3efa81f4c6edf2b72a (diff)
downloadframeworks_base-131206b8a9d07400d7c98aea50cc45c38769448f.zip
frameworks_base-131206b8a9d07400d7c98aea50cc45c38769448f.tar.gz
frameworks_base-131206b8a9d07400d7c98aea50cc45c38769448f.tar.bz2
Move display power controller to display manager service.
This refactoring is in preparation for enabling the display manager to have more control over the blanking state of individual displays. There are no functional changes. Some bits will be cleaned up in a subsequent patch. Bug: 13133142 Change-Id: I159a060088344d8e6fcdf9208a1f242960f7ab90
Diffstat (limited to 'services/core/java/com/android/server/power')
-rw-r--r--services/core/java/com/android/server/power/AutomaticBrightnessController.java686
-rw-r--r--services/core/java/com/android/server/power/DisplayBlanker.java25
-rw-r--r--services/core/java/com/android/server/power/DisplayPowerController.java960
-rw-r--r--services/core/java/com/android/server/power/DisplayPowerRequest.java144
-rw-r--r--services/core/java/com/android/server/power/DisplayPowerState.java421
-rw-r--r--services/core/java/com/android/server/power/ElectronBeam.java736
-rw-r--r--services/core/java/com/android/server/power/Notifier.java45
-rw-r--r--services/core/java/com/android/server/power/PowerManagerService.java125
-rw-r--r--services/core/java/com/android/server/power/RampAnimator.java137
9 files changed, 59 insertions, 3220 deletions
diff --git a/services/core/java/com/android/server/power/AutomaticBrightnessController.java b/services/core/java/com/android/server/power/AutomaticBrightnessController.java
deleted file mode 100644
index 807262a..0000000
--- a/services/core/java/com/android/server/power/AutomaticBrightnessController.java
+++ /dev/null
@@ -1,686 +0,0 @@
-/*
- * 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.server.power;
-
-import com.android.server.twilight.TwilightListener;
-import com.android.server.twilight.TwilightManager;
-import com.android.server.twilight.TwilightState;
-
-import android.content.res.Resources;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
-import android.hardware.SensorManager;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.PowerManager;
-import android.os.SystemClock;
-import android.text.format.DateUtils;
-import android.util.MathUtils;
-import android.util.Spline;
-import android.util.Slog;
-import android.util.TimeUtils;
-
-import java.io.PrintWriter;
-import java.util.Arrays;
-
-class AutomaticBrightnessController {
- private static final String TAG = "AutomaticBrightnessController";
-
- private static final boolean DEBUG = false;
- private static final boolean DEBUG_PRETEND_LIGHT_SENSOR_ABSENT = false;
-
- // If true, enables the use of the screen auto-brightness adjustment setting.
- private static final boolean USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT =
- PowerManager.useScreenAutoBrightnessAdjustmentFeature();
-
- // The maximum range of gamma adjustment possible using the screen
- // auto-brightness adjustment setting.
- private static final float SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_MAX_GAMMA = 3.0f;
-
- // Light sensor event rate in milliseconds.
- private static final int LIGHT_SENSOR_RATE_MILLIS = 1000;
-
- // Period of time in which to consider light samples in milliseconds.
- private static final int AMBIENT_LIGHT_HORIZON = 10000;
-
- // Stability requirements in milliseconds for accepting a new brightness level. This is used
- // for debouncing the light sensor. Different constants are used to debounce the light sensor
- // when adapting to brighter or darker environments. This parameter controls how quickly
- // brightness changes occur in response to an observed change in light level that exceeds the
- // hysteresis threshold.
- private static final long BRIGHTENING_LIGHT_DEBOUNCE = 4000;
- private static final long DARKENING_LIGHT_DEBOUNCE = 8000;
-
- // Hysteresis constraints for brightening or darkening.
- // The recent lux must have changed by at least this fraction relative to the
- // current ambient lux before a change will be considered.
- private static final float BRIGHTENING_LIGHT_HYSTERESIS = 0.10f;
- private static final float DARKENING_LIGHT_HYSTERESIS = 0.20f;
-
- // The intercept used for the weighting calculation. This is used in order to keep all possible
- // weighting values positive.
- private static final int WEIGHTING_INTERCEPT = AMBIENT_LIGHT_HORIZON;
-
- // How long the current sensor reading is assumed to be valid beyond the current time.
- // This provides a bit of prediction, as well as ensures that the weight for the last sample is
- // non-zero, which in turn ensures that the total weight is non-zero.
- private static final long AMBIENT_LIGHT_PREDICTION_TIME_MILLIS = 100;
-
- // If true, enables the use of the current time as an auto-brightness adjustment.
- // The basic idea here is to expand the dynamic range of auto-brightness
- // when it is especially dark outside. The light sensor tends to perform
- // poorly at low light levels so we compensate for it by making an
- // assumption about the environment.
- private static final boolean USE_TWILIGHT_ADJUSTMENT =
- PowerManager.useTwilightAdjustmentFeature();
-
- // Specifies the maximum magnitude of the time of day adjustment.
- private static final float TWILIGHT_ADJUSTMENT_MAX_GAMMA = 1.5f;
-
- // The amount of time after or before sunrise over which to start adjusting
- // the gamma. We want the change to happen gradually so that it is below the
- // threshold of perceptibility and so that the adjustment has maximum effect
- // well after dusk.
- private static final long TWILIGHT_ADJUSTMENT_TIME = DateUtils.HOUR_IN_MILLIS * 2;
-
- private static final int MSG_UPDATE_AMBIENT_LUX = 1;
-
- // Callbacks for requesting updates to the the display's power state
- private final Callbacks mCallbacks;
-
- // The sensor manager.
- private final SensorManager mSensorManager;
-
- // The light sensor, or null if not available or needed.
- private final Sensor mLightSensor;
-
- // The twilight service.
- private final TwilightManager mTwilight;
-
- // The auto-brightness spline adjustment.
- // The brightness values have been scaled to a range of 0..1.
- private final Spline mScreenAutoBrightnessSpline;
-
- // The minimum and maximum screen brightnesses.
- private final int mScreenBrightnessRangeMinimum;
- private final int mScreenBrightnessRangeMaximum;
-
- // Amount of time to delay auto-brightness after screen on while waiting for
- // the light sensor to warm-up in milliseconds.
- // May be 0 if no warm-up is required.
- private int mLightSensorWarmUpTimeConfig;
-
- // Set to true if the light sensor is enabled.
- private boolean mLightSensorEnabled;
-
- // The time when the light sensor was enabled.
- private long mLightSensorEnableTime;
-
- // The currently accepted nominal ambient light level.
- private float mAmbientLux;
-
- // True if mAmbientLux holds a valid value.
- private boolean mAmbientLuxValid;
-
- // The ambient light level threshold at which to brighten or darken the screen.
- private float mBrighteningLuxThreshold;
- private float mDarkeningLuxThreshold;
-
- // The most recent light sample.
- private float mLastObservedLux;
-
- // The time of the most light recent sample.
- private long mLastObservedLuxTime;
-
- // The number of light samples collected since the light sensor was enabled.
- private int mRecentLightSamples;
-
- // A ring buffer containing all of the recent ambient light sensor readings.
- private AmbientLightRingBuffer mAmbientLightRingBuffer;
-
- // The handler
- private AutomaticBrightnessHandler mHandler;
-
- // The screen brightness level that has been chosen by the auto-brightness
- // algorithm. The actual brightness should ramp towards this value.
- // We preserve this value even when we stop using the light sensor so
- // that we can quickly revert to the previous auto-brightness level
- // while the light sensor warms up.
- // Use -1 if there is no current auto-brightness value available.
- private int mScreenAutoBrightness = -1;
-
- // The screen auto-brightness adjustment factor in the range -1 (dimmer) to 1 (brighter)
- private float mScreenAutoBrightnessAdjustment = 0.0f;
-
- // The last screen auto-brightness gamma. (For printing in dump() only.)
- private float mLastScreenAutoBrightnessGamma = 1.0f;
-
- public AutomaticBrightnessController(Callbacks callbacks, Looper looper,
- TwilightManager twilight, SensorManager sensorManager, Spline autoBrightnessSpline,
- int lightSensorWarmUpTime, int brightnessMin, int brightnessMax) {
- mCallbacks = callbacks;
- mTwilight = twilight;
- mSensorManager = sensorManager;
- mScreenAutoBrightnessSpline = autoBrightnessSpline;
- mScreenBrightnessRangeMinimum = brightnessMin;
- mScreenBrightnessRangeMaximum = brightnessMax;
- mLightSensorWarmUpTimeConfig = lightSensorWarmUpTime;
-
- mHandler = new AutomaticBrightnessHandler(looper);
- mAmbientLightRingBuffer = new AmbientLightRingBuffer();
-
- if (!DEBUG_PRETEND_LIGHT_SENSOR_ABSENT) {
- mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
- }
-
- if (USE_TWILIGHT_ADJUSTMENT) {
- mTwilight.registerListener(mTwilightListener, mHandler);
- }
- }
-
- public int getAutomaticScreenBrightness() {
- return mScreenAutoBrightness;
- }
-
- public void updatePowerState(DisplayPowerRequest request) {
- if (setScreenAutoBrightnessAdjustment(request.screenAutoBrightnessAdjustment)
- || setLightSensorEnabled(request.wantLightSensorEnabled())) {
- updateAutoBrightness(false /*sendUpdate*/);
- }
- }
-
- public void dump(PrintWriter pw) {
- pw.println();
- pw.println("Automatic Brightness Controller Configuration:");
- pw.println(" mScreenAutoBrightnessSpline=" + mScreenAutoBrightnessSpline);
- pw.println(" mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum);
- pw.println(" mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum);
- pw.println(" mLightSensorWarmUpTimeConfig=" + mLightSensorWarmUpTimeConfig);
-
- pw.println();
- pw.println("Automatic Brightness Controller State:");
- pw.println(" mLightSensor=" + mLightSensor);
- pw.println(" mTwilight.getCurrentState()=" + mTwilight.getCurrentState());
- pw.println(" mLightSensorEnabled=" + mLightSensorEnabled);
- pw.println(" mLightSensorEnableTime=" + TimeUtils.formatUptime(mLightSensorEnableTime));
- pw.println(" mAmbientLux=" + mAmbientLux);
- pw.println(" mBrighteningLuxThreshold=" + mBrighteningLuxThreshold);
- pw.println(" mDarkeningLuxThreshold=" + mDarkeningLuxThreshold);
- pw.println(" mLastObservedLux=" + mLastObservedLux);
- pw.println(" mLastObservedLuxTime=" + TimeUtils.formatUptime(mLastObservedLuxTime));
- pw.println(" mRecentLightSamples=" + mRecentLightSamples);
- pw.println(" mAmbientLightRingBuffer=" + mAmbientLightRingBuffer);
- pw.println(" mScreenAutoBrightness=" + mScreenAutoBrightness);
- pw.println(" mScreenAutoBrightnessAdjustment=" + mScreenAutoBrightnessAdjustment);
- pw.println(" mLastScreenAutoBrightnessGamma=" + mLastScreenAutoBrightnessGamma);
- }
-
- private boolean setLightSensorEnabled(boolean enable) {
- if (enable) {
- if (!mLightSensorEnabled) {
- mLightSensorEnabled = true;
- mLightSensorEnableTime = SystemClock.uptimeMillis();
- mSensorManager.registerListener(mLightSensorListener, mLightSensor,
- LIGHT_SENSOR_RATE_MILLIS * 1000, mHandler);
- return true;
- }
- } else {
- if (mLightSensorEnabled) {
- mLightSensorEnabled = false;
- mAmbientLuxValid = false;
- mRecentLightSamples = 0;
- mAmbientLightRingBuffer.clear();
- mHandler.removeMessages(MSG_UPDATE_AMBIENT_LUX);
- mSensorManager.unregisterListener(mLightSensorListener);
- }
- }
- return false;
- }
-
- private void handleLightSensorEvent(long time, float lux) {
- mHandler.removeMessages(MSG_UPDATE_AMBIENT_LUX);
-
- applyLightSensorMeasurement(time, lux);
- updateAmbientLux(time);
- }
-
- private void applyLightSensorMeasurement(long time, float lux) {
- mRecentLightSamples++;
- mAmbientLightRingBuffer.prune(time - AMBIENT_LIGHT_HORIZON);
- mAmbientLightRingBuffer.push(time, lux);
-
- // Remember this sample value.
- mLastObservedLux = lux;
- mLastObservedLuxTime = time;
- }
-
- private boolean setScreenAutoBrightnessAdjustment(float adjustment) {
- if (adjustment != mScreenAutoBrightnessAdjustment) {
- mScreenAutoBrightnessAdjustment = adjustment;
- return true;
- }
- return false;
- }
-
- private void setAmbientLux(float lux) {
- mAmbientLux = lux;
- mBrighteningLuxThreshold = mAmbientLux * (1.0f + BRIGHTENING_LIGHT_HYSTERESIS);
- mDarkeningLuxThreshold = mAmbientLux * (1.0f - DARKENING_LIGHT_HYSTERESIS);
- }
-
- private float calculateAmbientLux(long now) {
- final int N = mAmbientLightRingBuffer.size();
- if (N == 0) {
- Slog.e(TAG, "calculateAmbientLux: No ambient light readings available");
- return -1;
- }
- float sum = 0;
- float totalWeight = 0;
- long endTime = AMBIENT_LIGHT_PREDICTION_TIME_MILLIS;
- for (int i = N - 1; i >= 0; i--) {
- long startTime = (mAmbientLightRingBuffer.getTime(i) - now);
- float weight = calculateWeight(startTime, endTime);
- float lux = mAmbientLightRingBuffer.getLux(i);
- if (DEBUG) {
- Slog.d(TAG, "calculateAmbientLux: [" +
- (startTime) + ", " +
- (endTime) + "]: lux=" + lux + ", weight=" + weight);
- }
- totalWeight += weight;
- sum += mAmbientLightRingBuffer.getLux(i) * weight;
- endTime = startTime;
- }
- if (DEBUG) {
- Slog.d(TAG, "calculateAmbientLux: totalWeight=" + totalWeight +
- ", newAmbientLux=" + (sum / totalWeight));
- }
- return sum / totalWeight;
- }
-
- private static float calculateWeight(long startDelta, long endDelta) {
- return weightIntegral(endDelta) - weightIntegral(startDelta);
- }
-
- // Evaluates the integral of y = x + WEIGHTING_INTERCEPT. This is always positive for the
- // horizon we're looking at and provides a non-linear weighting for light samples.
- private static float weightIntegral(long x) {
- return x * (x * 0.5f + WEIGHTING_INTERCEPT);
- }
-
- private long nextAmbientLightBrighteningTransition(long time) {
- final int N = mAmbientLightRingBuffer.size();
- long earliestValidTime = time;
- for (int i = N - 1; i >= 0; i--) {
- if (mAmbientLightRingBuffer.getLux(i) <= mBrighteningLuxThreshold) {
- break;
- }
- earliestValidTime = mAmbientLightRingBuffer.getTime(i);
- }
- return earliestValidTime + BRIGHTENING_LIGHT_DEBOUNCE;
- }
-
- private long nextAmbientLightDarkeningTransition(long time) {
- final int N = mAmbientLightRingBuffer.size();
- long earliestValidTime = time;
- for (int i = N - 1; i >= 0; i--) {
- if (mAmbientLightRingBuffer.getLux(i) >= mDarkeningLuxThreshold) {
- break;
- }
- earliestValidTime = mAmbientLightRingBuffer.getTime(i);
- }
- return earliestValidTime + DARKENING_LIGHT_DEBOUNCE;
- }
-
- private void updateAmbientLux() {
- long time = SystemClock.uptimeMillis();
- mAmbientLightRingBuffer.prune(time - AMBIENT_LIGHT_HORIZON);
- updateAmbientLux(time);
- }
-
- private void updateAmbientLux(long time) {
- // If the light sensor was just turned on then immediately update our initial
- // estimate of the current ambient light level.
- if (!mAmbientLuxValid) {
- final long timeWhenSensorWarmedUp =
- mLightSensorWarmUpTimeConfig + mLightSensorEnableTime;
- if (time < timeWhenSensorWarmedUp) {
- if (DEBUG) {
- Slog.d(TAG, "updateAmbientLux: Sensor not ready yet: "
- + "time=" + time
- + ", timeWhenSensorWarmedUp=" + timeWhenSensorWarmedUp);
- }
- mHandler.sendEmptyMessageAtTime(MSG_UPDATE_AMBIENT_LUX,
- timeWhenSensorWarmedUp);
- return;
- }
- setAmbientLux(calculateAmbientLux(time));
- mAmbientLuxValid = true;
- if (DEBUG) {
- Slog.d(TAG, "updateAmbientLux: Initializing: "
- + "mAmbientLightRingBuffer=" + mAmbientLightRingBuffer
- + ", mAmbientLux=" + mAmbientLux);
- }
- updateAutoBrightness(true);
- }
-
- long nextBrightenTransition = nextAmbientLightBrighteningTransition(time);
- long nextDarkenTransition = nextAmbientLightDarkeningTransition(time);
- float ambientLux = calculateAmbientLux(time);
-
- if (ambientLux >= mBrighteningLuxThreshold && nextBrightenTransition <= time
- || ambientLux <= mDarkeningLuxThreshold && nextDarkenTransition <= time) {
- setAmbientLux(ambientLux);
- if (DEBUG) {
- Slog.d(TAG, "updateAmbientLux: "
- + ((ambientLux > mAmbientLux) ? "Brightened" : "Darkened") + ": "
- + "mBrighteningLuxThreshold=" + mBrighteningLuxThreshold
- + ", mAmbientLightRingBuffer=" + mAmbientLightRingBuffer
- + ", mAmbientLux=" + mAmbientLux);
- }
- updateAutoBrightness(true);
- nextBrightenTransition = nextAmbientLightBrighteningTransition(time);
- nextDarkenTransition = nextAmbientLightDarkeningTransition(time);
- }
- long nextTransitionTime = Math.min(nextDarkenTransition, nextBrightenTransition);
- // If one of the transitions is ready to occur, but the total weighted ambient lux doesn't
- // exceed the necessary threshold, then it's possible we'll get a transition time prior to
- // now. Rather than continually checking to see whether the weighted lux exceeds the
- // threshold, schedule an update for when we'd normally expect another light sample, which
- // should be enough time to decide whether we should actually transition to the new
- // weighted ambient lux or not.
- nextTransitionTime =
- nextTransitionTime > time ? nextTransitionTime : time + LIGHT_SENSOR_RATE_MILLIS;
- if (DEBUG) {
- Slog.d(TAG, "updateAmbientLux: Scheduling ambient lux update for "
- + nextTransitionTime + TimeUtils.formatUptime(nextTransitionTime));
- }
- mHandler.sendEmptyMessageAtTime(MSG_UPDATE_AMBIENT_LUX, nextTransitionTime);
- }
-
- private void updateAutoBrightness(boolean sendUpdate) {
- if (!mAmbientLuxValid) {
- return;
- }
-
- float value = mScreenAutoBrightnessSpline.interpolate(mAmbientLux);
- float gamma = 1.0f;
-
- if (USE_SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT
- && mScreenAutoBrightnessAdjustment != 0.0f) {
- final float adjGamma = MathUtils.pow(SCREEN_AUTO_BRIGHTNESS_ADJUSTMENT_MAX_GAMMA,
- Math.min(1.0f, Math.max(-1.0f, -mScreenAutoBrightnessAdjustment)));
- gamma *= adjGamma;
- if (DEBUG) {
- Slog.d(TAG, "updateAutoBrightness: adjGamma=" + adjGamma);
- }
- }
-
- if (USE_TWILIGHT_ADJUSTMENT) {
- TwilightState state = mTwilight.getCurrentState();
- if (state != null && state.isNight()) {
- final long now = System.currentTimeMillis();
- final float earlyGamma =
- getTwilightGamma(now, state.getYesterdaySunset(), state.getTodaySunrise());
- final float lateGamma =
- getTwilightGamma(now, state.getTodaySunset(), state.getTomorrowSunrise());
- gamma *= earlyGamma * lateGamma;
- if (DEBUG) {
- Slog.d(TAG, "updateAutoBrightness: earlyGamma=" + earlyGamma
- + ", lateGamma=" + lateGamma);
- }
- }
- }
-
- if (gamma != 1.0f) {
- final float in = value;
- value = MathUtils.pow(value, gamma);
- if (DEBUG) {
- Slog.d(TAG, "updateAutoBrightness: gamma=" + gamma
- + ", in=" + in + ", out=" + value);
- }
- }
-
- int newScreenAutoBrightness =
- clampScreenBrightness(Math.round(value * PowerManager.BRIGHTNESS_ON));
- if (mScreenAutoBrightness != newScreenAutoBrightness) {
- if (DEBUG) {
- Slog.d(TAG, "updateAutoBrightness: mScreenAutoBrightness="
- + mScreenAutoBrightness + ", newScreenAutoBrightness="
- + newScreenAutoBrightness);
- }
-
- mScreenAutoBrightness = newScreenAutoBrightness;
- mLastScreenAutoBrightnessGamma = gamma;
- if (sendUpdate) {
- mCallbacks.updateBrightness();
- }
- }
- }
-
- private int clampScreenBrightness(int value) {
- return MathUtils.constrain(value,
- mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum);
- }
-
- private static float getTwilightGamma(long now, long lastSunset, long nextSunrise) {
- if (lastSunset < 0 || nextSunrise < 0
- || now < lastSunset || now > nextSunrise) {
- return 1.0f;
- }
-
- if (now < lastSunset + TWILIGHT_ADJUSTMENT_TIME) {
- return MathUtils.lerp(1.0f, TWILIGHT_ADJUSTMENT_MAX_GAMMA,
- (float)(now - lastSunset) / TWILIGHT_ADJUSTMENT_TIME);
- }
-
- if (now > nextSunrise - TWILIGHT_ADJUSTMENT_TIME) {
- return MathUtils.lerp(1.0f, TWILIGHT_ADJUSTMENT_MAX_GAMMA,
- (float)(nextSunrise - now) / TWILIGHT_ADJUSTMENT_TIME);
- }
-
- return TWILIGHT_ADJUSTMENT_MAX_GAMMA;
- }
-
- private final class AutomaticBrightnessHandler extends Handler {
- public AutomaticBrightnessHandler(Looper looper) {
- super(looper, null, true /*async*/);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_UPDATE_AMBIENT_LUX:
- updateAmbientLux();
- break;
- }
- }
- }
-
- private final SensorEventListener mLightSensorListener = new SensorEventListener() {
- @Override
- public void onSensorChanged(SensorEvent event) {
- if (mLightSensorEnabled) {
- final long time = SystemClock.uptimeMillis();
- final float lux = event.values[0];
- handleLightSensorEvent(time, lux);
- }
- }
-
- @Override
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- // Not used.
- }
- };
-
- private final TwilightListener mTwilightListener = new TwilightListener() {
- @Override
- public void onTwilightStateChanged() {
- updateAutoBrightness(true /*sendUpdate*/);
- }
- };
-
- /** Callbacks to request updates to the display's power state. */
- interface Callbacks {
- void updateBrightness();
- }
-
- private static final class AmbientLightRingBuffer{
- // Proportional extra capacity of the buffer beyond the expected number of light samples
- // in the horizon
- private static final float BUFFER_SLACK = 1.5f;
- private static final int DEFAULT_CAPACITY =
- (int) Math.ceil(AMBIENT_LIGHT_HORIZON * BUFFER_SLACK / LIGHT_SENSOR_RATE_MILLIS);
- private float[] mRingLux;
- private long[] mRingTime;
- private int mCapacity;
-
- // The first valid element and the next open slot.
- // Note that if mCount is zero then there are no valid elements.
- private int mStart;
- private int mEnd;
- private int mCount;
-
- public AmbientLightRingBuffer() {
- this(DEFAULT_CAPACITY);
- }
-
- public AmbientLightRingBuffer(int initialCapacity) {
- mCapacity = initialCapacity;
- mRingLux = new float[mCapacity];
- mRingTime = new long[mCapacity];
- }
-
- public float getLux(int index) {
- return mRingLux[offsetOf(index)];
- }
-
- public long getTime(int index) {
- return mRingTime[offsetOf(index)];
- }
-
- public void push(long time, float lux) {
- int next = mEnd;
- if (mCount == mCapacity) {
- int newSize = mCapacity * 2;
-
- float[] newRingLux = new float[newSize];
- long[] newRingTime = new long[newSize];
- int length = mCapacity - mStart;
- System.arraycopy(mRingLux, mStart, newRingLux, 0, length);
- System.arraycopy(mRingTime, mStart, newRingTime, 0, length);
- if (mStart != 0) {
- System.arraycopy(mRingLux, 0, newRingLux, length, mStart);
- System.arraycopy(mRingTime, 0, newRingTime, length, mStart);
- }
- mRingLux = newRingLux;
- mRingTime = newRingTime;
-
- next = mCapacity;
- mCapacity = newSize;
- mStart = 0;
- }
- mRingTime[next] = time;
- mRingLux[next] = lux;
- mEnd = next + 1;
- if (mEnd == mCapacity) {
- mEnd = 0;
- }
- mCount++;
- }
-
- public void prune(long horizon) {
- if (mCount == 0) {
- return;
- }
-
- while (mCount > 1) {
- int next = mStart + 1;
- if (next >= mCapacity) {
- next -= mCapacity;
- }
- if (mRingTime[next] > horizon) {
- // Some light sensors only produce data upon a change in the ambient light
- // levels, so we need to consider the previous measurement as the ambient light
- // level for all points in time up until we receive a new measurement. Thus, we
- // always want to keep the youngest element that would be removed from the
- // buffer and just set its measurement time to the horizon time since at that
- // point it is the ambient light level, and to remove it would be to drop a
- // valid data point within our horizon.
- break;
- }
- mStart = next;
- mCount -= 1;
- }
-
- if (mRingTime[mStart] < horizon) {
- mRingTime[mStart] = horizon;
- }
- }
-
- public int size() {
- return mCount;
- }
-
- public boolean isEmpty() {
- return mCount == 0;
- }
-
- public void clear() {
- mStart = 0;
- mEnd = 0;
- mCount = 0;
- }
-
- @Override
- public String toString() {
- final int length = mCapacity - mStart;
- float[] lux = new float[mCount];
- long[] time = new long[mCount];
-
- if (mCount <= length) {
- System.arraycopy(mRingLux, mStart, lux, 0, mCount);
- System.arraycopy(mRingTime, mStart, time, 0, mCount);
- } else {
- System.arraycopy(mRingLux, mStart, lux, 0, length);
- System.arraycopy(mRingLux, 0, lux, length, mCount - length);
-
- System.arraycopy(mRingTime, mStart, time, 0, length);
- System.arraycopy(mRingTime, 0, time, length, mCount - length);
- }
- return "AmbientLightRingBuffer{mCapacity=" + mCapacity
- + ", mStart=" + mStart
- + ", mEnd=" + mEnd
- + ", mCount=" + mCount
- + ", mRingLux=" + Arrays.toString(lux)
- + ", mRingTime=" + Arrays.toString(time)
- + "}";
- }
-
- private int offsetOf(int index) {
- if (index >= mCount || index < 0) {
- throw new ArrayIndexOutOfBoundsException(index);
- }
- index += mStart;
- if (index >= mCapacity) {
- index -= mCapacity;
- }
- return index;
- }
- }
-}
diff --git a/services/core/java/com/android/server/power/DisplayBlanker.java b/services/core/java/com/android/server/power/DisplayBlanker.java
deleted file mode 100644
index 6072053..0000000
--- a/services/core/java/com/android/server/power/DisplayBlanker.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * Copyright (C) 2012 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.server.power;
-
-/**
- * Blanks or unblanks all displays.
- */
-interface DisplayBlanker {
- public void blankAllDisplays();
- public void unblankAllDisplays();
-}
diff --git a/services/core/java/com/android/server/power/DisplayPowerController.java b/services/core/java/com/android/server/power/DisplayPowerController.java
deleted file mode 100644
index 6d3702a..0000000
--- a/services/core/java/com/android/server/power/DisplayPowerController.java
+++ /dev/null
@@ -1,960 +0,0 @@
-/*
- * Copyright (C) 2012 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.server.power;
-
-import com.android.server.lights.LightsManager;
-import com.android.server.twilight.TwilightListener;
-import com.android.server.twilight.TwilightManager;
-import com.android.server.twilight.TwilightState;
-
-import android.animation.Animator;
-import android.animation.ObjectAnimator;
-import android.content.Context;
-import android.content.res.Resources;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
-import android.hardware.SensorManager;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.PowerManager;
-import android.os.SystemClock;
-import android.text.format.DateUtils;
-import android.util.MathUtils;
-import android.util.Slog;
-import android.util.Spline;
-import android.util.TimeUtils;
-
-import java.io.PrintWriter;
-
-/**
- * Controls the power state of the display.
- *
- * Handles the proximity sensor, light sensor, and animations between states
- * including the screen off animation.
- *
- * This component acts independently of the rest of the power manager service.
- * In particular, it does not share any state and it only communicates
- * via asynchronous callbacks to inform the power manager that something has
- * changed.
- *
- * Everything this class does internally is serialized on its handler although
- * it may be accessed by other threads from the outside.
- *
- * Note that the power manager service guarantees that it will hold a suspend
- * blocker as long as the display is not ready. So most of the work done here
- * does not need to worry about holding a suspend blocker unless it happens
- * independently of the display ready signal.
- *
- * For debugging, you can make the electron beam and brightness animations run
- * slower by changing the "animator duration scale" option in Development Settings.
- */
-final class DisplayPowerController implements AutomaticBrightnessController.Callbacks {
- private static final String TAG = "DisplayPowerController";
-
- private static boolean DEBUG = false;
- private static final boolean DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT = false;
-
- // If true, uses the electron beam on animation.
- // We might want to turn this off if we cannot get a guarantee that the screen
- // actually turns on and starts showing new content after the call to set the
- // screen state returns. Playing the animation can also be somewhat slow.
- private static final boolean USE_ELECTRON_BEAM_ON_ANIMATION = false;
-
-
- // The minimum reduction in brightness when dimmed.
- private static final int SCREEN_DIM_MINIMUM_REDUCTION = 10;
-
- // If true, enables the use of the current time as an auto-brightness adjustment.
- // The basic idea here is to expand the dynamic range of auto-brightness
- // when it is especially dark outside. The light sensor tends to perform
- // poorly at low light levels so we compensate for it by making an
- // assumption about the environment.
- private static final boolean USE_TWILIGHT_ADJUSTMENT =
- PowerManager.useTwilightAdjustmentFeature();
-
- // Specifies the maximum magnitude of the time of day adjustment.
- private static final float TWILIGHT_ADJUSTMENT_MAX_GAMMA = 1.5f;
-
- // The amount of time after or before sunrise over which to start adjusting
- // the gamma. We want the change to happen gradually so that it is below the
- // threshold of perceptibility and so that the adjustment has maximum effect
- // well after dusk.
- private static final long TWILIGHT_ADJUSTMENT_TIME = DateUtils.HOUR_IN_MILLIS * 2;
-
- private static final int ELECTRON_BEAM_ON_ANIMATION_DURATION_MILLIS = 250;
- private static final int ELECTRON_BEAM_OFF_ANIMATION_DURATION_MILLIS = 400;
-
- private static final int MSG_UPDATE_POWER_STATE = 1;
- private static final int MSG_PROXIMITY_SENSOR_DEBOUNCED = 2;
-
- private static final int PROXIMITY_UNKNOWN = -1;
- private static final int PROXIMITY_NEGATIVE = 0;
- private static final int PROXIMITY_POSITIVE = 1;
-
- // Proximity sensor debounce delay in milliseconds for positive or negative transitions.
- private static final int PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY = 0;
- private static final int PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY = 250;
-
- // Trigger proximity if distance is less than 5 cm.
- private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f;
-
- // Brightness animation ramp rate in brightness units per second.
- private static final int BRIGHTNESS_RAMP_RATE_FAST = 200;
- private static final int BRIGHTNESS_RAMP_RATE_SLOW = 40;
-
- private final Object mLock = new Object();
-
- // Notifier for sending asynchronous notifications.
- private final Notifier mNotifier;
-
- // The display suspend blocker.
- // Held while there are pending state change notifications.
- private final SuspendBlocker mDisplaySuspendBlocker;
-
- // The display blanker.
- private final DisplayBlanker mDisplayBlanker;
-
- // Our handler.
- private final DisplayControllerHandler mHandler;
-
- // Asynchronous callbacks into the power manager service.
- // Only invoked from the handler thread while no locks are held.
- private final Callbacks mCallbacks;
- private Handler mCallbackHandler;
-
- // The lights service.
- private final LightsManager mLights;
-
- // The sensor manager.
- private final SensorManager mSensorManager;
-
- // The proximity sensor, or null if not available or needed.
- private Sensor mProximitySensor;
-
- // The doze screen brightness.
- private final int mScreenBrightnessDozeConfig;
-
- // The dim screen brightness.
- private final int mScreenBrightnessDimConfig;
-
- // The minimum allowed brightness.
- private final int mScreenBrightnessRangeMinimum;
-
- // The maximum allowed brightness.
- private final int mScreenBrightnessRangeMaximum;
-
- // True if auto-brightness should be used.
- private boolean mUseSoftwareAutoBrightnessConfig;
-
- // True if we should fade the screen while turning it off, false if we should play
- // a stylish electron beam animation instead.
- private boolean mElectronBeamFadesConfig;
-
- // The pending power request.
- // Initially null until the first call to requestPowerState.
- // Guarded by mLock.
- private DisplayPowerRequest mPendingRequestLocked;
-
- // True if a request has been made to wait for the proximity sensor to go negative.
- // Guarded by mLock.
- private boolean mPendingWaitForNegativeProximityLocked;
-
- // True if the pending power request or wait for negative proximity flag
- // has been changed since the last update occurred.
- // Guarded by mLock.
- private boolean mPendingRequestChangedLocked;
-
- // Set to true when the important parts of the pending power request have been applied.
- // The important parts are mainly the screen state. Brightness changes may occur
- // concurrently.
- // Guarded by mLock.
- private boolean mDisplayReadyLocked;
-
- // Set to true if a power state update is required.
- // Guarded by mLock.
- private boolean mPendingUpdatePowerStateLocked;
-
- /* The following state must only be accessed by the handler thread. */
-
- // The currently requested power state.
- // The power controller will progressively update its internal state to match
- // the requested power state. Initially null until the first update.
- private DisplayPowerRequest mPowerRequest;
-
- // The current power state.
- // Must only be accessed on the handler thread.
- private DisplayPowerState mPowerState;
-
- // True if the device should wait for negative proximity sensor before
- // waking up the screen. This is set to false as soon as a negative
- // proximity sensor measurement is observed or when the device is forced to
- // go to sleep by the user. While true, the screen remains off.
- private boolean mWaitingForNegativeProximity;
-
- // The actual proximity sensor threshold value.
- private float mProximityThreshold;
-
- // Set to true if the proximity sensor listener has been registered
- // with the sensor manager.
- private boolean mProximitySensorEnabled;
-
- // The debounced proximity sensor state.
- private int mProximity = PROXIMITY_UNKNOWN;
-
- // The raw non-debounced proximity sensor state.
- private int mPendingProximity = PROXIMITY_UNKNOWN;
- private long mPendingProximityDebounceTime = -1; // -1 if fully debounced
-
- // True if the screen was turned off because of the proximity sensor.
- // When the screen turns on again, we report user activity to the power manager.
- private boolean mScreenOffBecauseOfProximity;
-
- // True if the screen on is being blocked.
- private boolean mScreenOnWasBlocked;
-
- // The elapsed real time when the screen on was blocked.
- private long mScreenOnBlockStartRealTime;
-
- // True if the screen auto-brightness value is actually being used to
- // set the display brightness.
- private boolean mUsingScreenAutoBrightness;
-
- // The controller for the automatic brightness level.
- private AutomaticBrightnessController mAutomaticBrightnessController;
-
- // Animators.
- private ObjectAnimator mElectronBeamOnAnimator;
- private ObjectAnimator mElectronBeamOffAnimator;
- private RampAnimator<DisplayPowerState> mScreenBrightnessRampAnimator;
-
- /**
- * Creates the display power controller.
- */
- public DisplayPowerController(Looper looper, Context context, Notifier notifier,
- LightsManager lights, TwilightManager twilight, SensorManager sensorManager,
- SuspendBlocker displaySuspendBlocker, DisplayBlanker displayBlanker,
- Callbacks callbacks, Handler callbackHandler) {
- mHandler = new DisplayControllerHandler(looper);
- mNotifier = notifier;
- mDisplaySuspendBlocker = displaySuspendBlocker;
- mDisplayBlanker = displayBlanker;
- mCallbacks = callbacks;
- mCallbackHandler = callbackHandler;
-
- mLights = lights;
- mSensorManager = sensorManager;
-
- final Resources resources = context.getResources();
-
- mScreenBrightnessDozeConfig = clampAbsoluteBrightness(resources.getInteger(
- com.android.internal.R.integer.config_screenBrightnessDoze));
-
- mScreenBrightnessDimConfig = clampAbsoluteBrightness(resources.getInteger(
- com.android.internal.R.integer.config_screenBrightnessDim));
-
- int screenBrightnessRangeMinimum = clampAbsoluteBrightness(Math.min(resources.getInteger(
- com.android.internal.R.integer.config_screenBrightnessSettingMinimum),
- mScreenBrightnessDimConfig));
-
- mScreenBrightnessRangeMaximum = PowerManager.BRIGHTNESS_ON;
-
- mUseSoftwareAutoBrightnessConfig = resources.getBoolean(
- com.android.internal.R.bool.config_automatic_brightness_available);
- if (mUseSoftwareAutoBrightnessConfig) {
- int[] lux = resources.getIntArray(
- com.android.internal.R.array.config_autoBrightnessLevels);
- int[] screenBrightness = resources.getIntArray(
- com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
- int lightSensorWarmUpTimeConfig = resources.getInteger(
- com.android.internal.R.integer.config_lightSensorWarmupTime);
-
- Spline screenAutoBrightnessSpline = createAutoBrightnessSpline(lux, screenBrightness);
- if (screenAutoBrightnessSpline == null) {
- Slog.e(TAG, "Error in config.xml. config_autoBrightnessLcdBacklightValues "
- + "(size " + screenBrightness.length + ") "
- + "must be monotic and have exactly one more entry than "
- + "config_autoBrightnessLevels (size " + lux.length + ") "
- + "which must be strictly increasing. "
- + "Auto-brightness will be disabled.");
- mUseSoftwareAutoBrightnessConfig = false;
- } else {
- if (screenBrightness[0] < screenBrightnessRangeMinimum) {
- screenBrightnessRangeMinimum = clampAbsoluteBrightness(screenBrightness[0]);
- }
- mAutomaticBrightnessController = new AutomaticBrightnessController(this, looper,
- twilight, sensorManager, screenAutoBrightnessSpline,
- lightSensorWarmUpTimeConfig, screenBrightnessRangeMinimum,
- mScreenBrightnessRangeMaximum);
- }
- }
-
- mScreenBrightnessRangeMinimum = screenBrightnessRangeMinimum;
-
- mElectronBeamFadesConfig = resources.getBoolean(
- com.android.internal.R.bool.config_animateScreenLights);
-
- if (!DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) {
- mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
- if (mProximitySensor != null) {
- mProximityThreshold = Math.min(mProximitySensor.getMaximumRange(),
- TYPICAL_PROXIMITY_THRESHOLD);
- }
- }
-
- }
-
- /**
- * Returns true if the proximity sensor screen-off function is available.
- */
- public boolean isProximitySensorAvailable() {
- return mProximitySensor != null;
- }
-
- /**
- * Requests a new power state.
- * The controller makes a copy of the provided object and then
- * begins adjusting the power state to match what was requested.
- *
- * @param request The requested power state.
- * @param waitForNegativeProximity If true, issues a request to wait for
- * negative proximity before turning the screen back on, assuming the screen
- * was turned off by the proximity sensor.
- * @return True if display is ready, false if there are important changes that must
- * be made asynchronously (such as turning the screen on), in which case the caller
- * should grab a wake lock, watch for {@link Callbacks#onStateChanged()} then try
- * the request again later until the state converges.
- */
- public boolean requestPowerState(DisplayPowerRequest request,
- boolean waitForNegativeProximity) {
- if (DEBUG) {
- Slog.d(TAG, "requestPowerState: "
- + request + ", waitForNegativeProximity=" + waitForNegativeProximity);
- }
-
- synchronized (mLock) {
- boolean changed = false;
-
- if (waitForNegativeProximity
- && !mPendingWaitForNegativeProximityLocked) {
- mPendingWaitForNegativeProximityLocked = true;
- changed = true;
- }
-
- if (mPendingRequestLocked == null) {
- mPendingRequestLocked = new DisplayPowerRequest(request);
- changed = true;
- } else if (!mPendingRequestLocked.equals(request)) {
- mPendingRequestLocked.copyFrom(request);
- changed = true;
- }
-
- if (changed) {
- mDisplayReadyLocked = false;
- }
-
- if (changed && !mPendingRequestChangedLocked) {
- mPendingRequestChangedLocked = true;
- sendUpdatePowerStateLocked();
- }
-
- return mDisplayReadyLocked;
- }
- }
-
- private void sendUpdatePowerState() {
- synchronized (mLock) {
- sendUpdatePowerStateLocked();
- }
- }
-
- private void sendUpdatePowerStateLocked() {
- if (!mPendingUpdatePowerStateLocked) {
- mPendingUpdatePowerStateLocked = true;
- Message msg = mHandler.obtainMessage(MSG_UPDATE_POWER_STATE);
- msg.setAsynchronous(true);
- mHandler.sendMessage(msg);
- }
- }
-
- private void initialize() {
- mPowerState = new DisplayPowerState(new ElectronBeam(), mDisplayBlanker,
- mLights.getLight(LightsManager.LIGHT_ID_BACKLIGHT));
-
- mElectronBeamOnAnimator = ObjectAnimator.ofFloat(
- mPowerState, DisplayPowerState.ELECTRON_BEAM_LEVEL, 0.0f, 1.0f);
- mElectronBeamOnAnimator.setDuration(ELECTRON_BEAM_ON_ANIMATION_DURATION_MILLIS);
- mElectronBeamOnAnimator.addListener(mAnimatorListener);
-
- mElectronBeamOffAnimator = ObjectAnimator.ofFloat(
- mPowerState, DisplayPowerState.ELECTRON_BEAM_LEVEL, 1.0f, 0.0f);
- mElectronBeamOffAnimator.setDuration(ELECTRON_BEAM_OFF_ANIMATION_DURATION_MILLIS);
- mElectronBeamOffAnimator.addListener(mAnimatorListener);
-
- mScreenBrightnessRampAnimator = new RampAnimator<DisplayPowerState>(
- mPowerState, DisplayPowerState.SCREEN_BRIGHTNESS);
-
- // Initialize screen on state.
- if (mPowerState.isScreenOn()) {
- mNotifier.onScreenOn();
- } else {
- mNotifier.onScreenOff();
- }
- mNotifier.onScreenBrightness(mPowerState.getScreenBrightness());
- }
-
- private final Animator.AnimatorListener mAnimatorListener = new Animator.AnimatorListener() {
- @Override
- public void onAnimationStart(Animator animation) {
- }
- @Override
- public void onAnimationEnd(Animator animation) {
- sendUpdatePowerState();
- }
- @Override
- public void onAnimationRepeat(Animator animation) {
- }
- @Override
- public void onAnimationCancel(Animator animation) {
- }
- };
-
- private void updatePowerState() {
- // Update the power state request.
- final boolean mustNotify;
- boolean mustInitialize = false;
- boolean wasDimOrDoze = false;
-
- synchronized (mLock) {
- mPendingUpdatePowerStateLocked = false;
- if (mPendingRequestLocked == null) {
- return; // wait until first actual power request
- }
-
- if (mPowerRequest == null) {
- mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
- mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;
- mPendingWaitForNegativeProximityLocked = false;
- mPendingRequestChangedLocked = false;
- mustInitialize = true;
- } else if (mPendingRequestChangedLocked) {
- wasDimOrDoze = (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM
- || mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DOZE);
- mPowerRequest.copyFrom(mPendingRequestLocked);
- mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
- mPendingWaitForNegativeProximityLocked = false;
- mPendingRequestChangedLocked = false;
- mDisplayReadyLocked = false;
- }
-
- mustNotify = !mDisplayReadyLocked;
- }
-
- // Initialize things the first time the power state is changed.
- if (mustInitialize) {
- initialize();
- }
-
- // Apply the proximity sensor.
- if (mProximitySensor != null) {
- if (mPowerRequest.useProximitySensor
- && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) {
- setProximitySensorEnabled(true);
- if (!mScreenOffBecauseOfProximity
- && mProximity == PROXIMITY_POSITIVE) {
- mScreenOffBecauseOfProximity = true;
- sendOnProximityPositiveWithWakelock();
- }
- } else if (mWaitingForNegativeProximity
- && mScreenOffBecauseOfProximity
- && mProximity == PROXIMITY_POSITIVE
- && mPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) {
- setProximitySensorEnabled(true);
- } else {
- setProximitySensorEnabled(false);
- mWaitingForNegativeProximity = false;
- }
- if (mScreenOffBecauseOfProximity
- && mProximity != PROXIMITY_POSITIVE) {
- mScreenOffBecauseOfProximity = false;
- sendOnProximityNegativeWithWakelock();
- }
- } else {
- mWaitingForNegativeProximity = false;
- }
-
- // Turn on the light sensor if needed.
- if (mAutomaticBrightnessController != null) {
- mAutomaticBrightnessController.updatePowerState(mPowerRequest);
- }
-
- // Set the screen brightness.
- if (mPowerRequest.wantScreenOnAny()) {
- int target;
- boolean slow;
- int screenAutoBrightness = mAutomaticBrightnessController != null ?
- mAutomaticBrightnessController.getAutomaticScreenBrightness() : -1;
- if (screenAutoBrightness >= 0 && mPowerRequest.useAutoBrightness) {
- // Use current auto-brightness value.
- target = screenAutoBrightness;
- slow = mUsingScreenAutoBrightness;
- mUsingScreenAutoBrightness = true;
- } else {
- // Light sensor is disabled or not ready yet.
- // Use the current brightness setting from the request, which is expected
- // provide a nominal default value for the case where auto-brightness
- // is not ready yet.
- target = mPowerRequest.screenBrightness;
- slow = false;
- mUsingScreenAutoBrightness = false;
- }
- if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DOZE) {
- // Dim quickly to the doze state.
- target = mScreenBrightnessDozeConfig;
- slow = false;
- } else if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM) {
- // Dim quickly by at least some minimum amount.
- target = Math.min(target - SCREEN_DIM_MINIMUM_REDUCTION,
- mScreenBrightnessDimConfig);
- slow = false;
- } else if (wasDimOrDoze) {
- // Brighten quickly.
- slow = false;
- }
- animateScreenBrightness(clampScreenBrightness(target),
- slow ? BRIGHTNESS_RAMP_RATE_SLOW : BRIGHTNESS_RAMP_RATE_FAST);
- } else {
- // Screen is off. Don't bother changing the brightness.
- mUsingScreenAutoBrightness = false;
- }
-
- // Animate the screen on or off unless blocked.
- if (mScreenOffBecauseOfProximity) {
- // Screen off due to proximity.
- setScreenOn(false);
- unblockScreenOn();
- } else if (mPowerRequest.wantScreenOnAny()) {
- // Want screen on.
- // Wait for previous off animation to complete beforehand.
- // It is relatively short but if we cancel it and switch to the
- // on animation immediately then the results are pretty ugly.
- if (!mElectronBeamOffAnimator.isStarted()) {
- // Turn the screen on. The contents of the screen may not yet
- // be visible if the electron beam has not been dismissed because
- // its last frame of animation is solid black.
- setScreenOn(true);
-
- if (mPowerRequest.blockScreenOn
- && mPowerState.getElectronBeamLevel() == 0.0f) {
- blockScreenOn();
- } else {
- unblockScreenOn();
- if (USE_ELECTRON_BEAM_ON_ANIMATION) {
- if (!mElectronBeamOnAnimator.isStarted()) {
- if (mPowerState.getElectronBeamLevel() == 1.0f) {
- mPowerState.dismissElectronBeam();
- } else if (mPowerState.prepareElectronBeam(
- mElectronBeamFadesConfig ?
- ElectronBeam.MODE_FADE :
- ElectronBeam.MODE_WARM_UP)) {
- mElectronBeamOnAnimator.start();
- } else {
- mElectronBeamOnAnimator.end();
- }
- }
- } else {
- mPowerState.setElectronBeamLevel(1.0f);
- mPowerState.dismissElectronBeam();
- }
- }
- }
- } else {
- // Want screen off.
- // Wait for previous on animation to complete beforehand.
- unblockScreenOn();
- if (!mElectronBeamOnAnimator.isStarted()) {
- if (!mElectronBeamOffAnimator.isStarted()) {
- if (mPowerState.getElectronBeamLevel() == 0.0f) {
- setScreenOn(false);
- } else if (mPowerState.prepareElectronBeam(
- mElectronBeamFadesConfig ?
- ElectronBeam.MODE_FADE :
- ElectronBeam.MODE_COOL_DOWN)
- && mPowerState.isScreenOn()) {
- mElectronBeamOffAnimator.start();
- } else {
- mElectronBeamOffAnimator.end();
- }
- }
- }
- }
-
- // Report whether the display is ready for use.
- // We mostly care about the screen state here, ignoring brightness changes
- // which will be handled asynchronously.
- if (mustNotify
- && !mScreenOnWasBlocked
- && !mElectronBeamOnAnimator.isStarted()
- && !mElectronBeamOffAnimator.isStarted()
- && mPowerState.waitUntilClean(mCleanListener)) {
- synchronized (mLock) {
- if (!mPendingRequestChangedLocked) {
- mDisplayReadyLocked = true;
-
- if (DEBUG) {
- Slog.d(TAG, "Display ready!");
- }
- }
- }
- sendOnStateChangedWithWakelock();
- }
- }
-
- @Override
- public void updateBrightness() {
- sendUpdatePowerState();
- }
-
- private void blockScreenOn() {
- if (!mScreenOnWasBlocked) {
- mScreenOnWasBlocked = true;
- if (DEBUG) {
- Slog.d(TAG, "Blocked screen on.");
- mScreenOnBlockStartRealTime = SystemClock.elapsedRealtime();
- }
- }
- }
-
- private void unblockScreenOn() {
- if (mScreenOnWasBlocked) {
- mScreenOnWasBlocked = false;
- long delay = SystemClock.elapsedRealtime() - mScreenOnBlockStartRealTime;
- if (delay > 1000 || DEBUG) {
- Slog.d(TAG, "Unblocked screen on after " + delay + " ms");
- }
- }
- }
-
- private void setScreenOn(boolean on) {
- if (mPowerState.isScreenOn() != on) {
- mPowerState.setScreenOn(on);
- if (on) {
- mNotifier.onScreenOn();
- } else {
- mNotifier.onScreenOff();
- }
- }
- }
-
- private int clampScreenBrightness(int value) {
- return MathUtils.constrain(
- value, mScreenBrightnessRangeMinimum, mScreenBrightnessRangeMaximum);
- }
-
- private void animateScreenBrightness(int target, int rate) {
- if (mScreenBrightnessRampAnimator.animateTo(target, rate)) {
- mNotifier.onScreenBrightness(target);
- }
- }
-
- private final Runnable mCleanListener = new Runnable() {
- @Override
- public void run() {
- sendUpdatePowerState();
- }
- };
-
- private void setProximitySensorEnabled(boolean enable) {
- if (enable) {
- if (!mProximitySensorEnabled) {
- // Register the listener.
- // Proximity sensor state already cleared initially.
- mProximitySensorEnabled = true;
- mSensorManager.registerListener(mProximitySensorListener, mProximitySensor,
- SensorManager.SENSOR_DELAY_NORMAL, mHandler);
- }
- } else {
- if (mProximitySensorEnabled) {
- // Unregister the listener.
- // Clear the proximity sensor state for next time.
- mProximitySensorEnabled = false;
- mProximity = PROXIMITY_UNKNOWN;
- mPendingProximity = PROXIMITY_UNKNOWN;
- mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
- mSensorManager.unregisterListener(mProximitySensorListener);
- clearPendingProximityDebounceTime(); // release wake lock (must be last)
- }
- }
- }
-
- private void handleProximitySensorEvent(long time, boolean positive) {
- if (mProximitySensorEnabled) {
- if (mPendingProximity == PROXIMITY_NEGATIVE && !positive) {
- return; // no change
- }
- if (mPendingProximity == PROXIMITY_POSITIVE && positive) {
- return; // no change
- }
-
- // Only accept a proximity sensor reading if it remains
- // stable for the entire debounce delay. We hold a wake lock while
- // debouncing the sensor.
- mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
- if (positive) {
- mPendingProximity = PROXIMITY_POSITIVE;
- setPendingProximityDebounceTime(
- time + PROXIMITY_SENSOR_POSITIVE_DEBOUNCE_DELAY); // acquire wake lock
- } else {
- mPendingProximity = PROXIMITY_NEGATIVE;
- setPendingProximityDebounceTime(
- time + PROXIMITY_SENSOR_NEGATIVE_DEBOUNCE_DELAY); // acquire wake lock
- }
-
- // Debounce the new sensor reading.
- debounceProximitySensor();
- }
- }
-
- private void debounceProximitySensor() {
- if (mProximitySensorEnabled
- && mPendingProximity != PROXIMITY_UNKNOWN
- && mPendingProximityDebounceTime >= 0) {
- final long now = SystemClock.uptimeMillis();
- if (mPendingProximityDebounceTime <= now) {
- // Sensor reading accepted. Apply the change then release the wake lock.
- mProximity = mPendingProximity;
- updatePowerState();
- clearPendingProximityDebounceTime(); // release wake lock (must be last)
- } else {
- // Need to wait a little longer.
- // Debounce again later. We continue holding a wake lock while waiting.
- Message msg = mHandler.obtainMessage(MSG_PROXIMITY_SENSOR_DEBOUNCED);
- msg.setAsynchronous(true);
- mHandler.sendMessageAtTime(msg, mPendingProximityDebounceTime);
- }
- }
- }
-
- private void clearPendingProximityDebounceTime() {
- if (mPendingProximityDebounceTime >= 0) {
- mPendingProximityDebounceTime = -1;
- mDisplaySuspendBlocker.release(); // release wake lock
- }
- }
-
- private void setPendingProximityDebounceTime(long debounceTime) {
- if (mPendingProximityDebounceTime < 0) {
- mDisplaySuspendBlocker.acquire(); // acquire wake lock
- }
- mPendingProximityDebounceTime = debounceTime;
- }
-
- private void sendOnStateChangedWithWakelock() {
- mDisplaySuspendBlocker.acquire();
- mCallbackHandler.post(mOnStateChangedRunnable);
- }
-
- private final Runnable mOnStateChangedRunnable = new Runnable() {
- @Override
- public void run() {
- mCallbacks.onStateChanged();
- mDisplaySuspendBlocker.release();
- }
- };
-
- private void sendOnProximityPositiveWithWakelock() {
- mDisplaySuspendBlocker.acquire();
- mCallbackHandler.post(mOnProximityPositiveRunnable);
- }
-
- private final Runnable mOnProximityPositiveRunnable = new Runnable() {
- @Override
- public void run() {
- mCallbacks.onProximityPositive();
- mDisplaySuspendBlocker.release();
- }
- };
-
- private void sendOnProximityNegativeWithWakelock() {
- mDisplaySuspendBlocker.acquire();
- mCallbackHandler.post(mOnProximityNegativeRunnable);
- }
-
- private final Runnable mOnProximityNegativeRunnable = new Runnable() {
- @Override
- public void run() {
- mCallbacks.onProximityNegative();
- mDisplaySuspendBlocker.release();
- }
- };
-
- public void dump(final PrintWriter pw) {
- synchronized (mLock) {
- pw.println();
- pw.println("Display Controller Locked State:");
- pw.println(" mDisplayReadyLocked=" + mDisplayReadyLocked);
- pw.println(" mPendingRequestLocked=" + mPendingRequestLocked);
- pw.println(" mPendingRequestChangedLocked=" + mPendingRequestChangedLocked);
- pw.println(" mPendingWaitForNegativeProximityLocked="
- + mPendingWaitForNegativeProximityLocked);
- pw.println(" mPendingUpdatePowerStateLocked=" + mPendingUpdatePowerStateLocked);
- }
-
- pw.println();
- pw.println("Display Controller Configuration:");
- pw.println(" mScreenBrightnessDozeConfig=" + mScreenBrightnessDozeConfig);
- pw.println(" mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig);
- pw.println(" mScreenBrightnessRangeMinimum=" + mScreenBrightnessRangeMinimum);
- pw.println(" mScreenBrightnessRangeMaximum=" + mScreenBrightnessRangeMaximum);
- pw.println(" mUseSoftwareAutoBrightnessConfig="
- + mUseSoftwareAutoBrightnessConfig);
-
- mHandler.runWithScissors(new Runnable() {
- @Override
- public void run() {
- dumpLocal(pw);
- }
- }, 1000);
- }
-
- private void dumpLocal(PrintWriter pw) {
- pw.println();
- pw.println("Display Controller Thread State:");
- pw.println(" mPowerRequest=" + mPowerRequest);
- pw.println(" mWaitingForNegativeProximity=" + mWaitingForNegativeProximity);
-
- pw.println(" mProximitySensor=" + mProximitySensor);
- pw.println(" mProximitySensorEnabled=" + mProximitySensorEnabled);
- pw.println(" mProximityThreshold=" + mProximityThreshold);
- pw.println(" mProximity=" + proximityToString(mProximity));
- pw.println(" mPendingProximity=" + proximityToString(mPendingProximity));
- pw.println(" mPendingProximityDebounceTime="
- + TimeUtils.formatUptime(mPendingProximityDebounceTime));
- pw.println(" mScreenOffBecauseOfProximity=" + mScreenOffBecauseOfProximity);
- pw.println(" mUsingScreenAutoBrightness=" + mUsingScreenAutoBrightness);
-
- if (mElectronBeamOnAnimator != null) {
- pw.println(" mElectronBeamOnAnimator.isStarted()=" +
- mElectronBeamOnAnimator.isStarted());
- }
- if (mElectronBeamOffAnimator != null) {
- pw.println(" mElectronBeamOffAnimator.isStarted()=" +
- mElectronBeamOffAnimator.isStarted());
- }
-
- if (mPowerState != null) {
- mPowerState.dump(pw);
- }
-
- if (mAutomaticBrightnessController != null) {
- mAutomaticBrightnessController.dump(pw);
- }
-
- }
-
- private static String proximityToString(int state) {
- switch (state) {
- case PROXIMITY_UNKNOWN:
- return "Unknown";
- case PROXIMITY_NEGATIVE:
- return "Negative";
- case PROXIMITY_POSITIVE:
- return "Positive";
- default:
- return Integer.toString(state);
- }
- }
-
- private static Spline createAutoBrightnessSpline(int[] lux, int[] brightness) {
- try {
- final int n = brightness.length;
- float[] x = new float[n];
- float[] y = new float[n];
- y[0] = normalizeAbsoluteBrightness(brightness[0]);
- for (int i = 1; i < n; i++) {
- x[i] = lux[i - 1];
- y[i] = normalizeAbsoluteBrightness(brightness[i]);
- }
-
- Spline spline = Spline.createMonotoneCubicSpline(x, y);
- if (DEBUG) {
- Slog.d(TAG, "Auto-brightness spline: " + spline);
- for (float v = 1f; v < lux[lux.length - 1] * 1.25f; v *= 1.25f) {
- Slog.d(TAG, String.format(" %7.1f: %7.1f", v, spline.interpolate(v)));
- }
- }
- return spline;
- } catch (IllegalArgumentException ex) {
- Slog.e(TAG, "Could not create auto-brightness spline.", ex);
- return null;
- }
- }
-
- private static float normalizeAbsoluteBrightness(int value) {
- return (float)clampAbsoluteBrightness(value) / PowerManager.BRIGHTNESS_ON;
- }
-
- private static int clampAbsoluteBrightness(int value) {
- return MathUtils.constrain(value, PowerManager.BRIGHTNESS_OFF, PowerManager.BRIGHTNESS_ON);
- }
-
- /**
- * Asynchronous callbacks from the power controller to the power manager service.
- */
- public interface Callbacks {
- void onStateChanged();
- void onProximityPositive();
- void onProximityNegative();
- }
-
- private final class DisplayControllerHandler extends Handler {
- public DisplayControllerHandler(Looper looper) {
- super(looper, null, true /*async*/);
- }
-
- @Override
- public void handleMessage(Message msg) {
- switch (msg.what) {
- case MSG_UPDATE_POWER_STATE:
- updatePowerState();
- break;
-
- case MSG_PROXIMITY_SENSOR_DEBOUNCED:
- debounceProximitySensor();
- break;
- }
- }
- }
-
- private final SensorEventListener mProximitySensorListener = new SensorEventListener() {
- @Override
- public void onSensorChanged(SensorEvent event) {
- if (mProximitySensorEnabled) {
- final long time = SystemClock.uptimeMillis();
- final float distance = event.values[0];
- boolean positive = distance >= 0.0f && distance < mProximityThreshold;
- handleProximitySensorEvent(time, positive);
- }
- }
-
- @Override
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- // Not used.
- }
- };
-}
diff --git a/services/core/java/com/android/server/power/DisplayPowerRequest.java b/services/core/java/com/android/server/power/DisplayPowerRequest.java
deleted file mode 100644
index c5e46cb..0000000
--- a/services/core/java/com/android/server/power/DisplayPowerRequest.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Copyright (C) 2012 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.server.power;
-
-import android.os.PowerManager;
-
-/**
- * Describes the requested power state of the display.
- *
- * This object is intended to describe the general characteristics of the
- * power state, such as whether the screen should be on or off and the current
- * brightness controls leaving the {@link DisplayPowerController} to manage the
- * details of how the transitions between states should occur. The goal is for
- * the {@link PowerManagerService} to focus on the global power state and not
- * have to micro-manage screen off animations, auto-brightness and other effects.
- */
-final class DisplayPowerRequest {
- public static final int SCREEN_STATE_OFF = 0;
- public static final int SCREEN_STATE_DOZE = 1;
- public static final int SCREEN_STATE_DIM = 2;
- public static final int SCREEN_STATE_BRIGHT = 3;
-
- // The requested minimum screen power state: off, doze, dim or bright.
- public int screenState;
-
- // If true, the proximity sensor overrides the screen state when an object is
- // nearby, turning it off temporarily until the object is moved away.
- public boolean useProximitySensor;
-
- // The desired screen brightness in the range 0 (minimum / off) to 255 (brightest).
- // The display power controller may choose to clamp the brightness.
- // When auto-brightness is enabled, this field should specify a nominal default
- // value to use while waiting for the light sensor to report enough data.
- public int screenBrightness;
-
- // The screen auto-brightness adjustment factor in the range -1 (dimmer) to 1 (brighter).
- public float screenAutoBrightnessAdjustment;
-
- // If true, enables automatic brightness control.
- public boolean useAutoBrightness;
-
- // If true, prevents the screen from completely turning on if it is currently off.
- // The display does not enter a "ready" state if this flag is true and screen on is
- // blocked. The window manager policy blocks screen on while it prepares the keyguard to
- // prevent the user from seeing intermediate updates.
- //
- // Technically, we may not block the screen itself from turning on (because that introduces
- // extra unnecessary latency) but we do prevent content on screen from becoming
- // visible to the user.
- public boolean blockScreenOn;
-
- public DisplayPowerRequest() {
- screenState = SCREEN_STATE_BRIGHT;
- useProximitySensor = false;
- screenBrightness = PowerManager.BRIGHTNESS_ON;
- screenAutoBrightnessAdjustment = 0.0f;
- useAutoBrightness = false;
- blockScreenOn = false;
- }
-
- public DisplayPowerRequest(DisplayPowerRequest other) {
- copyFrom(other);
- }
-
- // Returns true if we want the screen on in any mode, including doze.
- public boolean wantScreenOnAny() {
- return screenState != SCREEN_STATE_OFF;
- }
-
- // Returns true if we want the screen on in a normal mode, excluding doze.
- // This is usually what we want to tell the rest of the system. For compatibility
- // reasons, we pretend the screen is off when dozing.
- public boolean wantScreenOnNormal() {
- return screenState == SCREEN_STATE_DIM || screenState == SCREEN_STATE_BRIGHT;
- }
-
- public boolean wantLightSensorEnabled() {
- // Specifically, we don't want the light sensor while dozing.
- return useAutoBrightness && wantScreenOnNormal();
- }
-
- public void copyFrom(DisplayPowerRequest other) {
- screenState = other.screenState;
- useProximitySensor = other.useProximitySensor;
- screenBrightness = other.screenBrightness;
- screenAutoBrightnessAdjustment = other.screenAutoBrightnessAdjustment;
- useAutoBrightness = other.useAutoBrightness;
- blockScreenOn = other.blockScreenOn;
- }
-
- @Override
- public boolean equals(Object o) {
- return o instanceof DisplayPowerRequest
- && equals((DisplayPowerRequest)o);
- }
-
- public boolean equals(DisplayPowerRequest other) {
- return other != null
- && screenState == other.screenState
- && useProximitySensor == other.useProximitySensor
- && screenBrightness == other.screenBrightness
- && screenAutoBrightnessAdjustment == other.screenAutoBrightnessAdjustment
- && useAutoBrightness == other.useAutoBrightness
- && blockScreenOn == other.blockScreenOn;
- }
-
- @Override
- public int hashCode() {
- return 0; // don't care
- }
-
- @Override
- public String toString() {
- return "screenState=" + screenState
- + ", useProximitySensor=" + useProximitySensor
- + ", screenBrightness=" + screenBrightness
- + ", screenAutoBrightnessAdjustment=" + screenAutoBrightnessAdjustment
- + ", useAutoBrightness=" + useAutoBrightness
- + ", blockScreenOn=" + blockScreenOn;
- }
-
- public static boolean wantScreenOn(int state) {
- switch(state) {
- case SCREEN_STATE_DIM:
- case SCREEN_STATE_BRIGHT:
- return true;
- }
- return false;
- }
-}
diff --git a/services/core/java/com/android/server/power/DisplayPowerState.java b/services/core/java/com/android/server/power/DisplayPowerState.java
deleted file mode 100644
index 8e331ad..0000000
--- a/services/core/java/com/android/server/power/DisplayPowerState.java
+++ /dev/null
@@ -1,421 +0,0 @@
-/*
- * Copyright (C) 2012 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.server.power;
-
-import com.android.server.lights.Light;
-
-import android.os.AsyncTask;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.PowerManager;
-import android.util.FloatProperty;
-import android.util.IntProperty;
-import android.util.Slog;
-import android.view.Choreographer;
-
-import java.io.PrintWriter;
-
-/**
- * Controls the display power state.
- * <p>
- * This component is similar in nature to a {@link View} except that it describes
- * the properties of a display. When properties are changed, the component
- * invalidates itself and posts a callback to apply the changes in a consistent order.
- * This mechanism enables multiple properties of the display power state to be animated
- * together smoothly by the animation framework. Some of the work to blank or unblank
- * the display is done on a separate thread to avoid blocking the looper.
- * </p><p>
- * This component must only be created or accessed by the {@link Looper} thread
- * that belongs to the {@link DisplayPowerController}.
- * </p><p>
- * We don't need to worry about holding a suspend blocker here because the
- * {@link PowerManagerService} does that for us whenever there is a change
- * in progress.
- * </p>
- */
-final class DisplayPowerState {
- private static final String TAG = "DisplayPowerState";
-
- private static boolean DEBUG = false;
-
- private final Handler mHandler;
- private final Choreographer mChoreographer;
- private final ElectronBeam mElectronBeam;
- private final DisplayBlanker mDisplayBlanker;
- private final Light mBacklight;
- private final PhotonicModulator mPhotonicModulator;
-
- private boolean mScreenOn;
- private int mScreenBrightness;
- private boolean mScreenReady;
- private boolean mScreenUpdatePending;
-
- private boolean mElectronBeamPrepared;
- private float mElectronBeamLevel;
- private boolean mElectronBeamReady;
- private boolean mElectronBeamDrawPending;
-
- private Runnable mCleanListener;
-
- public DisplayPowerState(ElectronBeam electronBean,
- DisplayBlanker displayBlanker, Light backlight) {
- mHandler = new Handler(true /*async*/);
- mChoreographer = Choreographer.getInstance();
- mElectronBeam = electronBean;
- mDisplayBlanker = displayBlanker;
- mBacklight = backlight;
- mPhotonicModulator = new PhotonicModulator();
-
- // At boot time, we know that the screen is on and the electron beam
- // animation is not playing. We don't know the screen's brightness though,
- // so prepare to set it to a known state when the state is next applied.
- // Although we set the brightness to full on here, the display power controller
- // will reset the brightness to a new level immediately before the changes
- // actually have a chance to be applied.
- mScreenOn = true;
- mScreenBrightness = PowerManager.BRIGHTNESS_ON;
- scheduleScreenUpdate();
-
- mElectronBeamPrepared = false;
- mElectronBeamLevel = 1.0f;
- mElectronBeamReady = true;
- }
-
- public static final FloatProperty<DisplayPowerState> ELECTRON_BEAM_LEVEL =
- new FloatProperty<DisplayPowerState>("electronBeamLevel") {
- @Override
- public void setValue(DisplayPowerState object, float value) {
- object.setElectronBeamLevel(value);
- }
-
- @Override
- public Float get(DisplayPowerState object) {
- return object.getElectronBeamLevel();
- }
- };
-
- public static final IntProperty<DisplayPowerState> SCREEN_BRIGHTNESS =
- new IntProperty<DisplayPowerState>("screenBrightness") {
- @Override
- public void setValue(DisplayPowerState object, int value) {
- object.setScreenBrightness(value);
- }
-
- @Override
- public Integer get(DisplayPowerState object) {
- return object.getScreenBrightness();
- }
- };
-
- /**
- * Sets whether the screen is on or off.
- */
- public void setScreenOn(boolean on) {
- if (mScreenOn != on) {
- if (DEBUG) {
- Slog.d(TAG, "setScreenOn: on=" + on);
- }
-
- mScreenOn = on;
- mScreenReady = false;
- scheduleScreenUpdate();
- }
- }
-
- /**
- * Returns true if the screen is on.
- */
- public boolean isScreenOn() {
- return mScreenOn;
- }
-
- /**
- * Sets the display brightness.
- *
- * @param brightness The brightness, ranges from 0 (minimum / off) to 255 (brightest).
- */
- public void setScreenBrightness(int brightness) {
- if (mScreenBrightness != brightness) {
- if (DEBUG) {
- Slog.d(TAG, "setScreenBrightness: brightness=" + brightness);
- }
-
- mScreenBrightness = brightness;
- if (mScreenOn) {
- mScreenReady = false;
- scheduleScreenUpdate();
- }
- }
- }
-
- /**
- * Gets the screen brightness.
- */
- public int getScreenBrightness() {
- return mScreenBrightness;
- }
-
- /**
- * Prepares the electron beam to turn on or off.
- * This method should be called before starting an animation because it
- * can take a fair amount of time to prepare the electron beam surface.
- *
- * @param mode The electron beam animation mode to prepare.
- * @return True if the electron beam was prepared.
- */
- public boolean prepareElectronBeam(int mode) {
- if (!mElectronBeam.prepare(mode)) {
- mElectronBeamPrepared = false;
- mElectronBeamReady = true;
- return false;
- }
-
- mElectronBeamPrepared = true;
- mElectronBeamReady = false;
- scheduleElectronBeamDraw();
- return true;
- }
-
- /**
- * Dismisses the electron beam surface.
- */
- public void dismissElectronBeam() {
- mElectronBeam.dismiss();
- mElectronBeamPrepared = false;
- mElectronBeamReady = true;
- }
-
- /**
- * Sets the level of the electron beam steering current.
- *
- * The display is blanked when the level is 0.0. In normal use, the electron
- * beam should have a value of 1.0. The electron beam is unstable in between
- * these states and the picture quality may be compromised. For best effect,
- * the electron beam should be warmed up or cooled off slowly.
- *
- * Warning: Electron beam emits harmful radiation. Avoid direct exposure to
- * skin or eyes.
- *
- * @param level The level, ranges from 0.0 (full off) to 1.0 (full on).
- */
- public void setElectronBeamLevel(float level) {
- if (mElectronBeamLevel != level) {
- if (DEBUG) {
- Slog.d(TAG, "setElectronBeamLevel: level=" + level);
- }
-
- mElectronBeamLevel = level;
- if (mScreenOn) {
- mScreenReady = false;
- scheduleScreenUpdate(); // update backlight brightness
- }
- if (mElectronBeamPrepared) {
- mElectronBeamReady = false;
- scheduleElectronBeamDraw();
- }
- }
- }
-
- /**
- * Gets the level of the electron beam steering current.
- */
- public float getElectronBeamLevel() {
- return mElectronBeamLevel;
- }
-
- /**
- * Returns true if no properties have been invalidated.
- * Otherwise, returns false and promises to invoke the specified listener
- * when the properties have all been applied.
- * The listener always overrides any previously set listener.
- */
- public boolean waitUntilClean(Runnable listener) {
- if (!mScreenReady || !mElectronBeamReady) {
- mCleanListener = listener;
- return false;
- } else {
- mCleanListener = null;
- return true;
- }
- }
-
- public void dump(PrintWriter pw) {
- pw.println();
- pw.println("Display Power State:");
- pw.println(" mScreenOn=" + mScreenOn);
- pw.println(" mScreenBrightness=" + mScreenBrightness);
- pw.println(" mScreenReady=" + mScreenReady);
- pw.println(" mScreenUpdatePending=" + mScreenUpdatePending);
- pw.println(" mElectronBeamPrepared=" + mElectronBeamPrepared);
- pw.println(" mElectronBeamLevel=" + mElectronBeamLevel);
- pw.println(" mElectronBeamReady=" + mElectronBeamReady);
- pw.println(" mElectronBeamDrawPending=" + mElectronBeamDrawPending);
-
- mPhotonicModulator.dump(pw);
- mElectronBeam.dump(pw);
- }
-
- private void scheduleScreenUpdate() {
- if (!mScreenUpdatePending) {
- mScreenUpdatePending = true;
- postScreenUpdateThreadSafe();
- }
- }
-
- private void postScreenUpdateThreadSafe() {
- mHandler.removeCallbacks(mScreenUpdateRunnable);
- mHandler.post(mScreenUpdateRunnable);
- }
-
- private void scheduleElectronBeamDraw() {
- if (!mElectronBeamDrawPending) {
- mElectronBeamDrawPending = true;
- mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL,
- mElectronBeamDrawRunnable, null);
- }
- }
-
- private void invokeCleanListenerIfNeeded() {
- final Runnable listener = mCleanListener;
- if (listener != null && mScreenReady && mElectronBeamReady) {
- mCleanListener = null;
- listener.run();
- }
- }
-
- private final Runnable mScreenUpdateRunnable = new Runnable() {
- @Override
- public void run() {
- mScreenUpdatePending = false;
-
- int brightness = mScreenOn && mElectronBeamLevel > 0f ? mScreenBrightness : 0;
- if (mPhotonicModulator.setState(mScreenOn, brightness)) {
- if (DEBUG) {
- Slog.d(TAG, "Screen ready");
- }
- mScreenReady = true;
- invokeCleanListenerIfNeeded();
- } else {
- if (DEBUG) {
- Slog.d(TAG, "Screen not ready");
- }
- }
- }
- };
-
- private final Runnable mElectronBeamDrawRunnable = new Runnable() {
- @Override
- public void run() {
- mElectronBeamDrawPending = false;
-
- if (mElectronBeamPrepared) {
- mElectronBeam.draw(mElectronBeamLevel);
- }
-
- mElectronBeamReady = true;
- invokeCleanListenerIfNeeded();
- }
- };
-
- /**
- * Updates the state of the screen and backlight asynchronously on a separate thread.
- */
- private final class PhotonicModulator {
- private static final boolean INITIAL_SCREEN_ON = false; // unknown, assume off
- private static final int INITIAL_BACKLIGHT = -1; // unknown
-
- private final Object mLock = new Object();
-
- private boolean mPendingOn = INITIAL_SCREEN_ON;
- private int mPendingBacklight = INITIAL_BACKLIGHT;
- private boolean mActualOn = INITIAL_SCREEN_ON;
- private int mActualBacklight = INITIAL_BACKLIGHT;
- private boolean mChangeInProgress;
-
- public boolean setState(boolean on, int backlight) {
- synchronized (mLock) {
- if (on != mPendingOn || backlight != mPendingBacklight) {
- if (DEBUG) {
- Slog.d(TAG, "Requesting new screen state: on=" + on
- + ", backlight=" + backlight);
- }
-
- mPendingOn = on;
- mPendingBacklight = backlight;
-
- if (!mChangeInProgress) {
- mChangeInProgress = true;
- AsyncTask.THREAD_POOL_EXECUTOR.execute(mTask);
- }
- }
- return !mChangeInProgress;
- }
- }
-
- public void dump(PrintWriter pw) {
- pw.println();
- pw.println("Photonic Modulator State:");
- pw.println(" mPendingOn=" + mPendingOn);
- pw.println(" mPendingBacklight=" + mPendingBacklight);
- pw.println(" mActualOn=" + mActualOn);
- pw.println(" mActualBacklight=" + mActualBacklight);
- pw.println(" mChangeInProgress=" + mChangeInProgress);
- }
-
- private final Runnable mTask = new Runnable() {
- @Override
- public void run() {
- // Apply pending changes until done.
- for (;;) {
- final boolean on;
- final boolean onChanged;
- final int backlight;
- final boolean backlightChanged;
- synchronized (mLock) {
- on = mPendingOn;
- onChanged = (on != mActualOn);
- backlight = mPendingBacklight;
- backlightChanged = (backlight != mActualBacklight);
- if (!onChanged && !backlightChanged) {
- mChangeInProgress = false;
- break;
- }
- mActualOn = on;
- mActualBacklight = backlight;
- }
-
- if (DEBUG) {
- Slog.d(TAG, "Updating screen state: on=" + on
- + ", backlight=" + backlight);
- }
- if (onChanged && on) {
- mDisplayBlanker.unblankAllDisplays();
- }
- if (backlightChanged) {
- mBacklight.setBrightness(backlight);
- }
- if (onChanged && !on) {
- mDisplayBlanker.blankAllDisplays();
- }
- }
-
- // Let the outer class know that all changes have been applied.
- postScreenUpdateThreadSafe();
- }
- };
- }
-}
diff --git a/services/core/java/com/android/server/power/ElectronBeam.java b/services/core/java/com/android/server/power/ElectronBeam.java
deleted file mode 100644
index 64921d7..0000000
--- a/services/core/java/com/android/server/power/ElectronBeam.java
+++ /dev/null
@@ -1,736 +0,0 @@
-/*
- * Copyright (C) 2012 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.server.power;
-
-import java.io.PrintWriter;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.FloatBuffer;
-
-import android.graphics.PixelFormat;
-import android.graphics.SurfaceTexture;
-import android.hardware.display.DisplayManagerInternal;
-import android.hardware.display.DisplayManagerInternal.DisplayTransactionListener;
-import android.opengl.EGL14;
-import android.opengl.EGLConfig;
-import android.opengl.EGLContext;
-import android.opengl.EGLDisplay;
-import android.opengl.EGLSurface;
-import android.opengl.GLES10;
-import android.opengl.GLES11Ext;
-import android.os.Looper;
-import android.util.FloatMath;
-import android.util.Slog;
-import android.view.Display;
-import android.view.DisplayInfo;
-import android.view.Surface.OutOfResourcesException;
-import android.view.Surface;
-import android.view.SurfaceControl;
-import android.view.SurfaceSession;
-
-import com.android.server.LocalServices;
-
-/**
- * Bzzzoooop! *crackle*
- * <p>
- * Animates a screen transition from on to off or off to on by applying
- * some GL transformations to a screenshot.
- * </p><p>
- * This component must only be created or accessed by the {@link Looper} thread
- * that belongs to the {@link DisplayPowerController}.
- * </p>
- */
-final class ElectronBeam {
- private static final String TAG = "ElectronBeam";
-
- private static final boolean DEBUG = false;
-
- // The layer for the electron beam surface.
- // This is currently hardcoded to be one layer above the boot animation.
- private static final int ELECTRON_BEAM_LAYER = 0x40000001;
-
- // The relative proportion of the animation to spend performing
- // the horizontal stretch effect. The remainder is spent performing
- // the vertical stretch effect.
- private static final float HSTRETCH_DURATION = 0.5f;
- private static final float VSTRETCH_DURATION = 1.0f - HSTRETCH_DURATION;
-
- // The number of frames to draw when preparing the animation so that it will
- // be ready to run smoothly. We use 3 frames because we are triple-buffered.
- // See code for details.
- private static final int DEJANK_FRAMES = 3;
-
- // Set to true when the animation context has been fully prepared.
- private boolean mPrepared;
- private int mMode;
-
- private final DisplayManagerInternal mDisplayManagerInternal;
- private int mDisplayLayerStack; // layer stack associated with primary display
- private int mDisplayWidth; // real width, not rotated
- private int mDisplayHeight; // real height, not rotated
- private SurfaceSession mSurfaceSession;
- private SurfaceControl mSurfaceControl;
- private Surface mSurface;
- private NaturalSurfaceLayout mSurfaceLayout;
- private EGLDisplay mEglDisplay;
- private EGLConfig mEglConfig;
- private EGLContext mEglContext;
- private EGLSurface mEglSurface;
- private boolean mSurfaceVisible;
- private float mSurfaceAlpha;
-
- // Texture names. We only use one texture, which contains the screenshot.
- private final int[] mTexNames = new int[1];
- private boolean mTexNamesGenerated;
- private final float mTexMatrix[] = new float[16];
-
- // Vertex and corresponding texture coordinates.
- // We have 4 2D vertices, so 8 elements. The vertices form a quad.
- private final FloatBuffer mVertexBuffer = createNativeFloatBuffer(8);
- private final FloatBuffer mTexCoordBuffer = createNativeFloatBuffer(8);
-
- /**
- * Animates an electron beam warming up.
- */
- public static final int MODE_WARM_UP = 0;
-
- /**
- * Animates an electron beam shutting off.
- */
- public static final int MODE_COOL_DOWN = 1;
-
- /**
- * Animates a simple dim layer to fade the contents of the screen in or out progressively.
- */
- public static final int MODE_FADE = 2;
-
-
- public ElectronBeam() {
- mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
- }
-
- /**
- * Warms up the electron beam in preparation for turning on or off.
- * This method prepares a GL context, and captures a screen shot.
- *
- * @param mode The desired mode for the upcoming animation.
- * @return True if the electron beam is ready, false if it is uncontrollable.
- */
- public boolean prepare(int mode) {
- if (DEBUG) {
- Slog.d(TAG, "prepare: mode=" + mode);
- }
-
- mMode = mode;
-
- // Get the display size and layer stack.
- // This is not expected to change while the electron beam surface is showing.
- DisplayInfo displayInfo = mDisplayManagerInternal.getDisplayInfo(Display.DEFAULT_DISPLAY);
- mDisplayLayerStack = displayInfo.layerStack;
- mDisplayWidth = displayInfo.getNaturalWidth();
- mDisplayHeight = displayInfo.getNaturalHeight();
-
- // Prepare the surface for drawing.
- if (!tryPrepare()) {
- dismiss();
- return false;
- }
-
- // Done.
- mPrepared = true;
-
- // Dejanking optimization.
- // Some GL drivers can introduce a lot of lag in the first few frames as they
- // initialize their state and allocate graphics buffers for rendering.
- // Work around this problem by rendering the first frame of the animation a few
- // times. The rest of the animation should run smoothly thereafter.
- // The frames we draw here aren't visible because we are essentially just
- // painting the screenshot as-is.
- if (mode == MODE_COOL_DOWN) {
- for (int i = 0; i < DEJANK_FRAMES; i++) {
- draw(1.0f);
- }
- }
- return true;
- }
-
- private boolean tryPrepare() {
- if (createSurface()) {
- if (mMode == MODE_FADE) {
- return true;
- }
- return createEglContext()
- && createEglSurface()
- && captureScreenshotTextureAndSetViewport();
- }
- return false;
- }
-
- /**
- * Dismisses the electron beam animation surface and cleans up.
- *
- * To prevent stray photons from leaking out after the electron beam has been
- * turned off, it is a good idea to defer dismissing the animation until the
- * electron beam has been turned back on fully.
- */
- public void dismiss() {
- if (DEBUG) {
- Slog.d(TAG, "dismiss");
- }
-
- destroyScreenshotTexture();
- destroyEglSurface();
- destroySurface();
- mPrepared = false;
- }
-
- /**
- * Draws an animation frame showing the electron beam activated at the
- * specified level.
- *
- * @param level The electron beam level.
- * @return True if successful.
- */
- public boolean draw(float level) {
- if (DEBUG) {
- Slog.d(TAG, "drawFrame: level=" + level);
- }
-
- if (!mPrepared) {
- return false;
- }
-
- if (mMode == MODE_FADE) {
- return showSurface(1.0f - level);
- }
-
- if (!attachEglContext()) {
- return false;
- }
- try {
- // Clear frame to solid black.
- GLES10.glClearColor(0f, 0f, 0f, 1f);
- GLES10.glClear(GLES10.GL_COLOR_BUFFER_BIT);
-
- // Draw the frame.
- if (level < HSTRETCH_DURATION) {
- drawHStretch(1.0f - (level / HSTRETCH_DURATION));
- } else {
- drawVStretch(1.0f - ((level - HSTRETCH_DURATION) / VSTRETCH_DURATION));
- }
- if (checkGlErrors("drawFrame")) {
- return false;
- }
-
- EGL14.eglSwapBuffers(mEglDisplay, mEglSurface);
- } finally {
- detachEglContext();
- }
- return showSurface(1.0f);
- }
-
- /**
- * Draws a frame where the content of the electron beam is collapsing inwards upon
- * itself vertically with red / green / blue channels dispersing and eventually
- * merging down to a single horizontal line.
- *
- * @param stretch The stretch factor. 0.0 is no collapse, 1.0 is full collapse.
- */
- private void drawVStretch(float stretch) {
- // compute interpolation scale factors for each color channel
- final float ar = scurve(stretch, 7.5f);
- final float ag = scurve(stretch, 8.0f);
- final float ab = scurve(stretch, 8.5f);
- if (DEBUG) {
- Slog.d(TAG, "drawVStretch: stretch=" + stretch
- + ", ar=" + ar + ", ag=" + ag + ", ab=" + ab);
- }
-
- // set blending
- GLES10.glBlendFunc(GLES10.GL_ONE, GLES10.GL_ONE);
- GLES10.glEnable(GLES10.GL_BLEND);
-
- // bind vertex buffer
- GLES10.glVertexPointer(2, GLES10.GL_FLOAT, 0, mVertexBuffer);
- GLES10.glEnableClientState(GLES10.GL_VERTEX_ARRAY);
-
- // set-up texturing
- GLES10.glDisable(GLES10.GL_TEXTURE_2D);
- GLES10.glEnable(GLES11Ext.GL_TEXTURE_EXTERNAL_OES);
-
- // bind texture and set blending for drawing planes
- GLES10.glBindTexture(GLES11Ext.GL_TEXTURE_EXTERNAL_OES, mTexNames[0]);
- GLES10.glTexEnvx(GLES10.GL_TEXTURE_ENV, GLES10.GL_TEXTURE_ENV_MODE,
- mMode == MODE_WARM_UP ? GLES10.GL_MODULATE : GLES10.GL_REPLACE);
- GLES10.glTexParameterx(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
- GLES10.GL_TEXTURE_MAG_FILTER, GLES10.GL_LINEAR);
- GLES10.glTexParameterx(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
- GLES10.GL_TEXTURE_MIN_FILTER, GLES10.GL_LINEAR);
- GLES10.glTexParameterx(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
- GLES10.GL_TEXTURE_WRAP_S, GLES10.GL_CLAMP_TO_EDGE);
- GLES10.glTexParameterx(GLES11Ext.GL_TEXTURE_EXTERNAL_OES,
- GLES10.GL_TEXTURE_WRAP_T, GLES10.GL_CLAMP_TO_EDGE);
- GLES10.glEnable(GLES11Ext.GL_TEXTURE_EXTERNAL_OES);
- GLES10.glTexCoordPointer(2, GLES10.GL_FLOAT, 0, mTexCoordBuffer);
- GLES10.glEnableClientState(GLES10.GL_TEXTURE_COORD_ARRAY);
-
- // draw the red plane
- setVStretchQuad(mVertexBuffer, mDisplayWidth, mDisplayHeight, ar);
- GLES10.glColorMask(true, false, false, true);
- GLES10.glDrawArrays(GLES10.GL_TRIANGLE_FAN, 0, 4);
-
- // draw the green plane
- setVStretchQuad(mVertexBuffer, mDisplayWidth, mDisplayHeight, ag);
- GLES10.glColorMask(false, true, false, true);
- GLES10.glDrawArrays(GLES10.GL_TRIANGLE_FAN, 0, 4);
-
- // draw the blue plane
- setVStretchQuad(mVertexBuffer, mDisplayWidth, mDisplayHeight, ab);
- GLES10.glColorMask(false, false, true, true);
- GLES10.glDrawArrays(GLES10.GL_TRIANGLE_FAN, 0, 4);
-
- // clean up after drawing planes
- GLES10.glDisable(GLES11Ext.GL_TEXTURE_EXTERNAL_OES);
- GLES10.glDisableClientState(GLES10.GL_TEXTURE_COORD_ARRAY);
- GLES10.glColorMask(true, true, true, true);
-
- // draw the white highlight (we use the last vertices)
- if (mMode == MODE_COOL_DOWN) {
- GLES10.glColor4f(ag, ag, ag, 1.0f);
- GLES10.glDrawArrays(GLES10.GL_TRIANGLE_FAN, 0, 4);
- }
-
- // clean up
- GLES10.glDisableClientState(GLES10.GL_VERTEX_ARRAY);
- GLES10.glDisable(GLES10.GL_BLEND);
- }
-
- /**
- * Draws a frame where the electron beam has been stretched out into
- * a thin white horizontal line that fades as it collapses inwards.
- *
- * @param stretch The stretch factor. 0.0 is maximum stretch / no fade,
- * 1.0 is collapsed / maximum fade.
- */
- private void drawHStretch(float stretch) {
- // compute interpolation scale factor
- final float ag = scurve(stretch, 8.0f);
- if (DEBUG) {
- Slog.d(TAG, "drawHStretch: stretch=" + stretch + ", ag=" + ag);
- }
-
- if (stretch < 1.0f) {
- // bind vertex buffer
- GLES10.glVertexPointer(2, GLES10.GL_FLOAT, 0, mVertexBuffer);
- GLES10.glEnableClientState(GLES10.GL_VERTEX_ARRAY);
-
- // draw narrow fading white line
- setHStretchQuad(mVertexBuffer, mDisplayWidth, mDisplayHeight, ag);
- GLES10.glColor4f(1.0f - ag*0.75f, 1.0f - ag*0.75f, 1.0f - ag*0.75f, 1.0f);
- GLES10.glDrawArrays(GLES10.GL_TRIANGLE_FAN, 0, 4);
-
- // clean up
- GLES10.glDisableClientState(GLES10.GL_VERTEX_ARRAY);
- }
- }
-
- private static void setVStretchQuad(FloatBuffer vtx, float dw, float dh, float a) {
- final float w = dw + (dw * a);
- final float h = dh - (dh * a);
- final float x = (dw - w) * 0.5f;
- final float y = (dh - h) * 0.5f;
- setQuad(vtx, x, y, w, h);
- }
-
- private static void setHStretchQuad(FloatBuffer vtx, float dw, float dh, float a) {
- final float w = 2 * dw * (1.0f - a);
- final float h = 1.0f;
- final float x = (dw - w) * 0.5f;
- final float y = (dh - h) * 0.5f;
- setQuad(vtx, x, y, w, h);
- }
-
- private static void setQuad(FloatBuffer vtx, float x, float y, float w, float h) {
- if (DEBUG) {
- Slog.d(TAG, "setQuad: x=" + x + ", y=" + y + ", w=" + w + ", h=" + h);
- }
- vtx.put(0, x);
- vtx.put(1, y);
- vtx.put(2, x);
- vtx.put(3, y + h);
- vtx.put(4, x + w);
- vtx.put(5, y + h);
- vtx.put(6, x + w);
- vtx.put(7, y);
- }
-
- private boolean captureScreenshotTextureAndSetViewport() {
- if (!attachEglContext()) {
- return false;
- }
- try {
- if (!mTexNamesGenerated) {
- GLES10.glGenTextures(1, mTexNames, 0);
- if (checkGlErrors("glGenTextures")) {
- return false;
- }
- mTexNamesGenerated = true;
- }
-
- final SurfaceTexture st = new SurfaceTexture(mTexNames[0]);
- final Surface s = new Surface(st);
- try {
- SurfaceControl.screenshot(SurfaceControl.getBuiltInDisplay(
- SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN), s);
- } finally {
- s.release();
- }
-
- st.updateTexImage();
- st.getTransformMatrix(mTexMatrix);
-
- // Set up texture coordinates for a quad.
- // We might need to change this if the texture ends up being
- // a different size from the display for some reason.
- mTexCoordBuffer.put(0, 0f); mTexCoordBuffer.put(1, 0f);
- mTexCoordBuffer.put(2, 0f); mTexCoordBuffer.put(3, 1f);
- mTexCoordBuffer.put(4, 1f); mTexCoordBuffer.put(5, 1f);
- mTexCoordBuffer.put(6, 1f); mTexCoordBuffer.put(7, 0f);
-
- // Set up our viewport.
- GLES10.glViewport(0, 0, mDisplayWidth, mDisplayHeight);
- GLES10.glMatrixMode(GLES10.GL_PROJECTION);
- GLES10.glLoadIdentity();
- GLES10.glOrthof(0, mDisplayWidth, 0, mDisplayHeight, 0, 1);
- GLES10.glMatrixMode(GLES10.GL_MODELVIEW);
- GLES10.glLoadIdentity();
- GLES10.glMatrixMode(GLES10.GL_TEXTURE);
- GLES10.glLoadIdentity();
- GLES10.glLoadMatrixf(mTexMatrix, 0);
- } finally {
- detachEglContext();
- }
- return true;
- }
-
- private void destroyScreenshotTexture() {
- if (mTexNamesGenerated) {
- mTexNamesGenerated = false;
- if (attachEglContext()) {
- try {
- GLES10.glDeleteTextures(1, mTexNames, 0);
- checkGlErrors("glDeleteTextures");
- } finally {
- detachEglContext();
- }
- }
- }
- }
-
- private boolean createEglContext() {
- if (mEglDisplay == null) {
- mEglDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
- if (mEglDisplay == EGL14.EGL_NO_DISPLAY) {
- logEglError("eglGetDisplay");
- return false;
- }
-
- int[] version = new int[2];
- if (!EGL14.eglInitialize(mEglDisplay, version, 0, version, 1)) {
- mEglDisplay = null;
- logEglError("eglInitialize");
- return false;
- }
- }
-
- if (mEglConfig == null) {
- int[] eglConfigAttribList = new int[] {
- EGL14.EGL_RED_SIZE, 8,
- EGL14.EGL_GREEN_SIZE, 8,
- EGL14.EGL_BLUE_SIZE, 8,
- EGL14.EGL_ALPHA_SIZE, 8,
- EGL14.EGL_NONE
- };
- int[] numEglConfigs = new int[1];
- EGLConfig[] eglConfigs = new EGLConfig[1];
- if (!EGL14.eglChooseConfig(mEglDisplay, eglConfigAttribList, 0,
- eglConfigs, 0, eglConfigs.length, numEglConfigs, 0)) {
- logEglError("eglChooseConfig");
- return false;
- }
- mEglConfig = eglConfigs[0];
- }
-
- if (mEglContext == null) {
- int[] eglContextAttribList = new int[] {
- EGL14.EGL_NONE
- };
- mEglContext = EGL14.eglCreateContext(mEglDisplay, mEglConfig,
- EGL14.EGL_NO_CONTEXT, eglContextAttribList, 0);
- if (mEglContext == null) {
- logEglError("eglCreateContext");
- return false;
- }
- }
- return true;
- }
-
- /* not used because it is too expensive to create / destroy contexts all of the time
- private void destroyEglContext() {
- if (mEglContext != null) {
- if (!EGL14.eglDestroyContext(mEglDisplay, mEglContext)) {
- logEglError("eglDestroyContext");
- }
- mEglContext = null;
- }
- }*/
-
- private boolean createSurface() {
- if (mSurfaceSession == null) {
- mSurfaceSession = new SurfaceSession();
- }
-
- SurfaceControl.openTransaction();
- try {
- if (mSurfaceControl == null) {
- try {
- int flags;
- if (mMode == MODE_FADE) {
- flags = SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN;
- } else {
- flags = SurfaceControl.OPAQUE | SurfaceControl.HIDDEN;
- }
- mSurfaceControl = new SurfaceControl(mSurfaceSession,
- "ElectronBeam", mDisplayWidth, mDisplayHeight,
- PixelFormat.OPAQUE, flags);
- } catch (OutOfResourcesException ex) {
- Slog.e(TAG, "Unable to create surface.", ex);
- return false;
- }
- }
-
- mSurfaceControl.setLayerStack(mDisplayLayerStack);
- mSurfaceControl.setSize(mDisplayWidth, mDisplayHeight);
- mSurface = new Surface();
- mSurface.copyFrom(mSurfaceControl);
-
- mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManagerInternal, mSurfaceControl);
- mSurfaceLayout.onDisplayTransaction();
- } finally {
- SurfaceControl.closeTransaction();
- }
- return true;
- }
-
- private boolean createEglSurface() {
- if (mEglSurface == null) {
- int[] eglSurfaceAttribList = new int[] {
- EGL14.EGL_NONE
- };
- // turn our SurfaceControl into a Surface
- mEglSurface = EGL14.eglCreateWindowSurface(mEglDisplay, mEglConfig, mSurface,
- eglSurfaceAttribList, 0);
- if (mEglSurface == null) {
- logEglError("eglCreateWindowSurface");
- return false;
- }
- }
- return true;
- }
-
- private void destroyEglSurface() {
- if (mEglSurface != null) {
- if (!EGL14.eglDestroySurface(mEglDisplay, mEglSurface)) {
- logEglError("eglDestroySurface");
- }
- mEglSurface = null;
- }
- }
-
- private void destroySurface() {
- if (mSurfaceControl != null) {
- mSurfaceLayout.dispose();
- mSurfaceLayout = null;
- SurfaceControl.openTransaction();
- try {
- mSurfaceControl.destroy();
- mSurface.release();
- } finally {
- SurfaceControl.closeTransaction();
- }
- mSurfaceControl = null;
- mSurfaceVisible = false;
- mSurfaceAlpha = 0f;
- }
- }
-
- private boolean showSurface(float alpha) {
- if (!mSurfaceVisible || mSurfaceAlpha != alpha) {
- SurfaceControl.openTransaction();
- try {
- mSurfaceControl.setLayer(ELECTRON_BEAM_LAYER);
- mSurfaceControl.setAlpha(alpha);
- mSurfaceControl.show();
- } finally {
- SurfaceControl.closeTransaction();
- }
- mSurfaceVisible = true;
- mSurfaceAlpha = alpha;
- }
- return true;
- }
-
- private boolean attachEglContext() {
- if (mEglSurface == null) {
- return false;
- }
- if (!EGL14.eglMakeCurrent(mEglDisplay, mEglSurface, mEglSurface, mEglContext)) {
- logEglError("eglMakeCurrent");
- return false;
- }
- return true;
- }
-
- private void detachEglContext() {
- if (mEglDisplay != null) {
- EGL14.eglMakeCurrent(mEglDisplay,
- EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_CONTEXT);
- }
- }
-
- /**
- * Interpolates a value in the range 0 .. 1 along a sigmoid curve
- * yielding a result in the range 0 .. 1 scaled such that:
- * scurve(0) == 0, scurve(0.5) == 0.5, scurve(1) == 1.
- */
- private static float scurve(float value, float s) {
- // A basic sigmoid has the form y = 1.0f / FloatMap.exp(-x * s).
- // Here we take the input datum and shift it by 0.5 so that the
- // domain spans the range -0.5 .. 0.5 instead of 0 .. 1.
- final float x = value - 0.5f;
-
- // Next apply the sigmoid function to the scaled value
- // which produces a value in the range 0 .. 1 so we subtract
- // 0.5 to get a value in the range -0.5 .. 0.5 instead.
- final float y = sigmoid(x, s) - 0.5f;
-
- // To obtain the desired boundary conditions we need to scale
- // the result so that it fills a range of -1 .. 1.
- final float v = sigmoid(0.5f, s) - 0.5f;
-
- // And finally remap the value back to a range of 0 .. 1.
- return y / v * 0.5f + 0.5f;
- }
-
- private static float sigmoid(float x, float s) {
- return 1.0f / (1.0f + FloatMath.exp(-x * s));
- }
-
- private static FloatBuffer createNativeFloatBuffer(int size) {
- ByteBuffer bb = ByteBuffer.allocateDirect(size * 4);
- bb.order(ByteOrder.nativeOrder());
- return bb.asFloatBuffer();
- }
-
- private static void logEglError(String func) {
- Slog.e(TAG, func + " failed: error " + EGL14.eglGetError(), new Throwable());
- }
-
- private static boolean checkGlErrors(String func) {
- return checkGlErrors(func, true);
- }
-
- private static boolean checkGlErrors(String func, boolean log) {
- boolean hadError = false;
- int error;
- while ((error = GLES10.glGetError()) != GLES10.GL_NO_ERROR) {
- if (log) {
- Slog.e(TAG, func + " failed: error " + error, new Throwable());
- }
- hadError = true;
- }
- return hadError;
- }
-
- public void dump(PrintWriter pw) {
- pw.println();
- pw.println("Electron Beam State:");
- pw.println(" mPrepared=" + mPrepared);
- pw.println(" mMode=" + mMode);
- pw.println(" mDisplayLayerStack=" + mDisplayLayerStack);
- pw.println(" mDisplayWidth=" + mDisplayWidth);
- pw.println(" mDisplayHeight=" + mDisplayHeight);
- pw.println(" mSurfaceVisible=" + mSurfaceVisible);
- pw.println(" mSurfaceAlpha=" + mSurfaceAlpha);
- }
-
- /**
- * Keeps a surface aligned with the natural orientation of the device.
- * Updates the position and transformation of the matrix whenever the display
- * is rotated. This is a little tricky because the display transaction
- * callback can be invoked on any thread, not necessarily the thread that
- * owns the electron beam.
- */
- private static final class NaturalSurfaceLayout implements DisplayTransactionListener {
- private final DisplayManagerInternal mDisplayManagerInternal;
- private SurfaceControl mSurfaceControl;
-
- public NaturalSurfaceLayout(DisplayManagerInternal displayManagerInternal,
- SurfaceControl surfaceControl) {
- mDisplayManagerInternal = displayManagerInternal;
- mSurfaceControl = surfaceControl;
- mDisplayManagerInternal.registerDisplayTransactionListener(this);
- }
-
- public void dispose() {
- synchronized (this) {
- mSurfaceControl = null;
- }
- mDisplayManagerInternal.unregisterDisplayTransactionListener(this);
- }
-
- @Override
- public void onDisplayTransaction() {
- synchronized (this) {
- if (mSurfaceControl == null) {
- return;
- }
-
- DisplayInfo displayInfo =
- mDisplayManagerInternal.getDisplayInfo(Display.DEFAULT_DISPLAY);
- switch (displayInfo.rotation) {
- case Surface.ROTATION_0:
- mSurfaceControl.setPosition(0, 0);
- mSurfaceControl.setMatrix(1, 0, 0, 1);
- break;
- case Surface.ROTATION_90:
- mSurfaceControl.setPosition(0, displayInfo.logicalHeight);
- mSurfaceControl.setMatrix(0, -1, 1, 0);
- break;
- case Surface.ROTATION_180:
- mSurfaceControl.setPosition(displayInfo.logicalWidth, displayInfo.logicalHeight);
- mSurfaceControl.setMatrix(-1, 0, 0, -1);
- break;
- case Surface.ROTATION_270:
- mSurfaceControl.setPosition(displayInfo.logicalWidth, 0);
- mSurfaceControl.setMatrix(0, 1, -1, 0);
- break;
- }
- }
- }
- }
-}
diff --git a/services/core/java/com/android/server/power/Notifier.java b/services/core/java/com/android/server/power/Notifier.java
index 81af636..ac4a128 100644
--- a/services/core/java/com/android/server/power/Notifier.java
+++ b/services/core/java/com/android/server/power/Notifier.java
@@ -227,51 +227,6 @@ final class Notifier {
}
/**
- * Called when the screen is turned on.
- */
- public void onScreenOn() {
- if (DEBUG) {
- Slog.d(TAG, "onScreenOn");
- }
-
- try {
- mBatteryStats.noteScreenOn();
- } catch (RemoteException ex) {
- // Ignore
- }
- }
-
- /**
- * Called when the screen is turned off.
- */
- public void onScreenOff() {
- if (DEBUG) {
- Slog.d(TAG, "onScreenOff");
- }
-
- try {
- mBatteryStats.noteScreenOff();
- } catch (RemoteException ex) {
- // Ignore
- }
- }
-
- /**
- * Called when the screen changes brightness.
- */
- public void onScreenBrightness(int brightness) {
- if (DEBUG) {
- Slog.d(TAG, "onScreenBrightness: brightness=" + brightness);
- }
-
- try {
- mBatteryStats.noteScreenBrightness(brightness);
- } catch (RemoteException ex) {
- // Ignore
- }
- }
-
- /**
* Called when the device is waking up from sleep and the
* display is about to be turned on.
*/
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index b85a506..90363d7 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -24,7 +24,6 @@ import com.android.server.LocalServices;
import com.android.server.ServiceThread;
import com.android.server.lights.Light;
import com.android.server.lights.LightsManager;
-import com.android.server.twilight.TwilightManager;
import com.android.server.Watchdog;
import android.Manifest;
@@ -39,6 +38,7 @@ import android.database.ContentObserver;
import android.hardware.SensorManager;
import android.hardware.SystemSensorManager;
import android.hardware.display.DisplayManagerInternal;
+import android.hardware.display.DisplayManagerInternal.DisplayPowerRequest;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.Binder;
@@ -177,7 +177,6 @@ public final class PowerManagerService extends com.android.server.SystemService
private PowerManagerHandler mHandler;
private WindowManagerPolicy mPolicy;
private Notifier mNotifier;
- private DisplayPowerController mDisplayPowerController;
private WirelessChargerDetector mWirelessChargerDetector;
private SettingsObserver mSettingsObserver;
private DreamManagerInternal mDreamManager;
@@ -258,9 +257,6 @@ public final class PowerManagerService extends com.android.server.SystemService
// screen is coming up.
private final ScreenOnBlockerImpl mScreenOnBlocker;
- // The display blanker used to turn the screen on or off.
- private final DisplayBlankerImpl mDisplayBlanker;
-
// True if systemReady() has been called.
private boolean mSystemReady;
@@ -418,7 +414,6 @@ public final class PowerManagerService extends com.android.server.SystemService
mHoldingDisplaySuspendBlocker = true;
mScreenOnBlocker = new ScreenOnBlockerImpl();
- mDisplayBlanker = new DisplayBlankerImpl();
mWakefulness = WAKEFULNESS_AWAKE;
}
@@ -458,7 +453,7 @@ public final class PowerManagerService extends com.android.server.SystemService
// into the activity manager to check permissions. Unfortunately the
// activity manager is not running when the constructor is called, so we
// have to defer setting the screen state until this point.
- mDisplayBlanker.unblankAllDisplays();
+ mDisplayPowerCallbacks.unblankAllDisplays();
}
void setPolicy(WindowManagerPolicy policy) {
@@ -485,20 +480,16 @@ public final class PowerManagerService extends com.android.server.SystemService
mAppOps, createSuspendBlockerLocked("PowerManagerService.Broadcasts"),
mScreenOnBlocker, mPolicy);
- // The display power controller runs on the power manager service's
- // own handler thread to ensure timely operation.
- mDisplayPowerController = new DisplayPowerController(mHandler.getLooper(),
- mContext, mNotifier, mLightsManager,
- LocalServices.getService(TwilightManager.class), sensorManager,
- mDisplaySuspendBlocker, mDisplayBlanker,
- mDisplayPowerControllerCallbacks, mHandler);
-
mWirelessChargerDetector = new WirelessChargerDetector(sensorManager,
createSuspendBlockerLocked("PowerManagerService.WirelessChargerDetector"),
mHandler);
mSettingsObserver = new SettingsObserver(mHandler);
mAttentionLight = mLightsManager.getLight(LightsManager.LIGHT_ID_ATTENTION);
+ // Initialize display power management.
+ mDisplayManagerInternal.initPowerManagement(
+ mDisplayPowerCallbacks, mHandler, sensorManager);
+
// Register for broadcasts from other components of the system.
IntentFilter filter = new IntentFilter();
filter.addAction(Intent.ACTION_BATTERY_CHANGED);
@@ -823,7 +814,7 @@ public final class PowerManagerService extends com.android.server.SystemService
return true;
case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
- return mSystemReady && mDisplayPowerController.isProximitySensorAvailable();
+ return mSystemReady && mDisplayManagerInternal.isProximitySensorAvailable();
default:
return false;
@@ -1646,7 +1637,7 @@ public final class PowerManagerService extends com.android.server.SystemService
mDisplayPowerRequest.blockScreenOn = mScreenOnBlocker.isHeld();
- mDisplayReady = mDisplayPowerController.requestPowerState(mDisplayPowerRequest,
+ mDisplayReady = mDisplayManagerInternal.requestPowerState(mDisplayPowerRequest,
mRequestWaitForNegativeProximity);
mRequestWaitForNegativeProximity = false;
@@ -1688,8 +1679,10 @@ public final class PowerManagerService extends com.android.server.SystemService
return DisplayPowerRequest.SCREEN_STATE_DIM;
}
- private final DisplayPowerController.Callbacks mDisplayPowerControllerCallbacks =
- new DisplayPowerController.Callbacks() {
+ private final DisplayManagerInternal.DisplayPowerCallbacks mDisplayPowerCallbacks =
+ new DisplayManagerInternal.DisplayPowerCallbacks() {
+ private boolean mBlanked;
+
@Override
public void onStateChanged() {
synchronized (mLock) {
@@ -1717,6 +1710,51 @@ public final class PowerManagerService extends com.android.server.SystemService
updatePowerStateLocked();
}
}
+
+ @Override
+ public void acquireSuspendBlocker() {
+ mDisplaySuspendBlocker.acquire();
+ }
+
+ @Override
+ public void releaseSuspendBlocker() {
+ mDisplaySuspendBlocker.release();
+ }
+
+ @Override
+ public void blankAllDisplays() {
+ synchronized (this) {
+ mBlanked = true;
+ mDisplayManagerInternal.blankAllDisplaysFromPowerManager();
+ if (!mDecoupleInteractiveModeFromDisplayConfig) {
+ setInteractiveModeLocked(false);
+ }
+ if (!mDecoupleAutoSuspendModeFromDisplayConfig) {
+ setAutoSuspendModeLocked(true);
+ }
+ }
+ }
+
+ @Override
+ public void unblankAllDisplays() {
+ synchronized (this) {
+ if (!mDecoupleAutoSuspendModeFromDisplayConfig) {
+ setAutoSuspendModeLocked(false);
+ }
+ if (!mDecoupleInteractiveModeFromDisplayConfig) {
+ setInteractiveModeLocked(true);
+ }
+ mDisplayManagerInternal.unblankAllDisplaysFromPowerManager();
+ mBlanked = false;
+ }
+ }
+
+ @Override
+ public String toString() {
+ synchronized (this) {
+ return "blanked=" + mBlanked;
+ }
+ }
};
private boolean shouldUseProximitySensorLocked() {
@@ -2047,7 +2085,6 @@ public final class PowerManagerService extends com.android.server.SystemService
private void dumpInternal(PrintWriter pw) {
pw.println("POWER MANAGER (dumpsys power)\n");
- final DisplayPowerController dpc;
final WirelessChargerDetector wcd;
synchronized (mLock) {
pw.println("Power Manager State:");
@@ -2152,16 +2189,11 @@ public final class PowerManagerService extends com.android.server.SystemService
pw.println("Screen On Blocker: " + mScreenOnBlocker);
pw.println();
- pw.println("Display Blanker: " + mDisplayBlanker);
+ pw.println("Display Power: " + mDisplayPowerCallbacks);
- dpc = mDisplayPowerController;
wcd = mWirelessChargerDetector;
}
- if (dpc != null) {
- dpc.dump(pw);
- }
-
if (wcd != null) {
wcd.dump(pw);
}
@@ -2499,45 +2531,6 @@ public final class PowerManagerService extends com.android.server.SystemService
}
}
- private final class DisplayBlankerImpl implements DisplayBlanker {
- private boolean mBlanked;
-
- @Override
- public void blankAllDisplays() {
- synchronized (this) {
- mBlanked = true;
- mDisplayManagerInternal.blankAllDisplaysFromPowerManager();
- if (!mDecoupleInteractiveModeFromDisplayConfig) {
- setInteractiveModeLocked(false);
- }
- if (!mDecoupleAutoSuspendModeFromDisplayConfig) {
- setAutoSuspendModeLocked(true);
- }
- }
- }
-
- @Override
- public void unblankAllDisplays() {
- synchronized (this) {
- if (!mDecoupleAutoSuspendModeFromDisplayConfig) {
- setAutoSuspendModeLocked(false);
- }
- if (!mDecoupleInteractiveModeFromDisplayConfig) {
- setInteractiveModeLocked(true);
- }
- mDisplayManagerInternal.unblankAllDisplaysFromPowerManager();
- mBlanked = false;
- }
- }
-
- @Override
- public String toString() {
- synchronized (this) {
- return "blanked=" + mBlanked;
- }
- }
- }
-
private final class BinderService extends IPowerManager.Stub {
@Override // Binder call
public void acquireWakeLockWithUid(IBinder lock, int flags, String tag,
@@ -2874,7 +2867,7 @@ public final class PowerManagerService extends com.android.server.SystemService
*
* @param adj The overridden brightness, or Float.NaN to disable the override.
*
- * @see Settings.System#SCREEN_AUTO_BRIGHTNESS_ADJ
+ * @see android.provider.Settings.System#SCREEN_AUTO_BRIGHTNESS_ADJ
*/
@Override // Binder call
public void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float adj) {
diff --git a/services/core/java/com/android/server/power/RampAnimator.java b/services/core/java/com/android/server/power/RampAnimator.java
deleted file mode 100644
index 4a4f080..0000000
--- a/services/core/java/com/android/server/power/RampAnimator.java
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (C) 2012 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.server.power;
-
-import android.animation.ValueAnimator;
-import android.util.IntProperty;
-import android.view.Choreographer;
-
-/**
- * A custom animator that progressively updates a property value at
- * a given variable rate until it reaches a particular target value.
- */
-final class RampAnimator<T> {
- private final T mObject;
- private final IntProperty<T> mProperty;
- private final Choreographer mChoreographer;
-
- private int mCurrentValue;
- private int mTargetValue;
- private int mRate;
-
- private boolean mAnimating;
- private float mAnimatedValue; // higher precision copy of mCurrentValue
- private long mLastFrameTimeNanos;
-
- private boolean mFirstTime = true;
-
- public RampAnimator(T object, IntProperty<T> property) {
- mObject = object;
- mProperty = property;
- mChoreographer = Choreographer.getInstance();
- }
-
- /**
- * Starts animating towards the specified value.
- *
- * If this is the first time the property is being set, the value jumps
- * directly to the target.
- *
- * @param target The target value.
- * @param rate The convergence rate, in units per second.
- * @return True if the target differs from the previous target.
- */
- public boolean animateTo(int target, int rate) {
- // Immediately jump to the target the first time.
- if (mFirstTime) {
- mFirstTime = false;
- mProperty.setValue(mObject, target);
- mCurrentValue = target;
- return true;
- }
-
- // Adjust the rate based on the closest target.
- // If a faster rate is specified, then use the new rate so that we converge
- // more rapidly based on the new request.
- // If a slower rate is specified, then use the new rate only if the current
- // value is somewhere in between the new and the old target meaning that
- // we will be ramping in a different direction to get there.
- // Otherwise, continue at the previous rate.
- if (!mAnimating
- || rate > mRate
- || (target <= mCurrentValue && mCurrentValue <= mTargetValue)
- || (mTargetValue <= mCurrentValue && mCurrentValue <= target)) {
- mRate = rate;
- }
-
- final boolean changed = (mTargetValue != target);
- mTargetValue = target;
-
- // Start animating.
- if (!mAnimating && target != mCurrentValue) {
- mAnimating = true;
- mAnimatedValue = mCurrentValue;
- mLastFrameTimeNanos = System.nanoTime();
- postCallback();
- }
-
- return changed;
- }
-
- private void postCallback() {
- mChoreographer.postCallback(Choreographer.CALLBACK_ANIMATION, mCallback, null);
- }
-
- private final Runnable mCallback = new Runnable() {
- @Override // Choreographer callback
- public void run() {
- final long frameTimeNanos = mChoreographer.getFrameTimeNanos();
- final float timeDelta = (frameTimeNanos - mLastFrameTimeNanos)
- * 0.000000001f;
- mLastFrameTimeNanos = frameTimeNanos;
-
- // Advance the animated value towards the target at the specified rate
- // and clamp to the target. This gives us the new current value but
- // we keep the animated value around to allow for fractional increments
- // towards the target.
- final float scale = ValueAnimator.getDurationScale();
- if (scale == 0) {
- // Animation off.
- mAnimatedValue = mTargetValue;
- } else {
- final float amount = timeDelta * mRate / scale;
- if (mTargetValue > mCurrentValue) {
- mAnimatedValue = Math.min(mAnimatedValue + amount, mTargetValue);
- } else {
- mAnimatedValue = Math.max(mAnimatedValue - amount, mTargetValue);
- }
- }
- final int oldCurrentValue = mCurrentValue;
- mCurrentValue = Math.round(mAnimatedValue);
-
- if (oldCurrentValue != mCurrentValue) {
- mProperty.setValue(mObject, mCurrentValue);
- }
-
- if (mTargetValue != mCurrentValue) {
- postCallback();
- } else {
- mAnimating = false;
- }
- }
- };
-}