summaryrefslogtreecommitdiff
path: root/services/java/com/android/server/power/DisplayPowerState.java
diff options
context:
space:
mode:
Diffstat (limited to 'services/java/com/android/server/power/DisplayPowerState.java')
-rw-r--r--services/java/com/android/server/power/DisplayPowerState.java269
1 files changed, 269 insertions, 0 deletions
diff --git a/services/java/com/android/server/power/DisplayPowerState.java b/services/java/com/android/server/power/DisplayPowerState.java
new file mode 100644
index 000000000000..ad242c08fcbc
--- /dev/null
+++ b/services/java/com/android/server/power/DisplayPowerState.java
@@ -0,0 +1,269 @@
+/*
+ * 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.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;
+
+/**
+ * Represents the current display power state and realizes it.
+ *
+ * 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 the {@link Choreographer} to
+ * apply the changes. This mechanism enables the display power state to be
+ * animated smoothly by the animation framework.
+ *
+ * This component must only be created or accessed by the {@link Looper} thread
+ * that belongs to the {@link DisplayPowerController}.
+ *
+ * We don't need to worry about holding a suspend blocker here because the
+ * {@link DisplayPowerController} does that for us whenever there is a pending invalidate.
+ */
+final class DisplayPowerState {
+ private static final String TAG = "DisplayPowerState";
+
+ private static boolean DEBUG = false;
+
+ private static final int DIRTY_SCREEN_ON = 1 << 0;
+ private static final int DIRTY_ELECTRON_BEAM = 1 << 1;
+ private static final int DIRTY_BRIGHTNESS = 1 << 2;
+
+ private static final int DIRTY_ALL = 0xffffffff;
+
+ private final Choreographer mChoreographer;
+ private final ElectronBeam mElectronBeam;
+ private final PhotonicModulator mScreenBrightnessModulator;
+
+ private int mDirty;
+ private boolean mScreenOn;
+ private float mElectronBeamLevel;
+ private int mScreenBrightness;
+
+ private Runnable mCleanListener;
+
+ public DisplayPowerState(ElectronBeam electronBean,
+ PhotonicModulator screenBrightnessModulator) {
+ mChoreographer = Choreographer.getInstance();
+ mElectronBeam = electronBean;
+ mScreenBrightnessModulator = screenBrightnessModulator;
+
+ mScreenOn = true;
+ mElectronBeamLevel = 1.0f;
+ mScreenBrightness = PowerManager.BRIGHTNESS_ON;
+ invalidate(DIRTY_ALL);
+ }
+
+ 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;
+ invalidate(DIRTY_SCREEN_ON);
+ }
+ }
+
+ /**
+ * Returns true if the screen is on.
+ */
+ public boolean isScreenOn() {
+ return mScreenOn;
+ }
+
+ /**
+ * 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 warmUp True if the electron beam should start warming up.
+ * @return True if the electron beam was prepared.
+ */
+ public boolean prepareElectronBeam(boolean warmUp) {
+ boolean success = mElectronBeam.prepare(warmUp);
+ invalidate(DIRTY_ELECTRON_BEAM);
+ return success;
+ }
+
+ /**
+ * Dismisses the electron beam surface.
+ */
+ public void dismissElectronBeam() {
+ mElectronBeam.dismiss();
+ }
+
+ /**
+ * 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;
+ invalidate(DIRTY_ELECTRON_BEAM);
+ }
+ }
+
+ /**
+ * Gets the level of the electron beam steering current.
+ */
+ public float getElectronBeamLevel() {
+ return mElectronBeamLevel;
+ }
+
+ /**
+ * 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;
+ invalidate(DIRTY_BRIGHTNESS);
+ }
+ }
+
+ /**
+ * Gets the screen brightness.
+ */
+ public int getScreenBrightness() {
+ return mScreenBrightness;
+ }
+
+ /**
+ * 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 (mDirty != 0) {
+ mCleanListener = listener;
+ return false;
+ } else {
+ mCleanListener = null;
+ return true;
+ }
+ }
+
+ public void dump(PrintWriter pw) {
+ pw.println();
+ pw.println("Display Power State:");
+ pw.println(" mDirty=" + Integer.toHexString(mDirty));
+ pw.println(" mScreenOn=" + mScreenOn);
+ pw.println(" mScreenBrightness=" + mScreenBrightness);
+ pw.println(" mElectronBeamLevel=" + mElectronBeamLevel);
+
+ mElectronBeam.dump(pw);
+ }
+
+ private void invalidate(int dirty) {
+ if (mDirty == 0) {
+ mChoreographer.postCallback(Choreographer.CALLBACK_TRAVERSAL,
+ mTraversalRunnable, null);
+ }
+
+ mDirty |= dirty;
+ }
+
+ private void apply() {
+ if (mDirty != 0) {
+ if ((mDirty & DIRTY_SCREEN_ON) != 0 && !mScreenOn) {
+ PowerManagerService.nativeSetScreenState(false);
+ }
+
+ if ((mDirty & DIRTY_ELECTRON_BEAM) != 0) {
+ mElectronBeam.draw(mElectronBeamLevel);
+ }
+
+ if ((mDirty & DIRTY_BRIGHTNESS) != 0) {
+ mScreenBrightnessModulator.setBrightness(mScreenBrightness);
+ }
+
+ if ((mDirty & DIRTY_SCREEN_ON) != 0 && mScreenOn) {
+ PowerManagerService.nativeSetScreenState(true);
+ }
+
+ mDirty = 0;
+
+ if (mCleanListener != null) {
+ mCleanListener.run();
+ }
+ }
+ }
+
+ private final Runnable mTraversalRunnable = new Runnable() {
+ @Override
+ public void run() {
+ if (mDirty != 0) {
+ apply();
+ }
+ }
+ };
+}