summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--api/current.txt3
-rw-r--r--cmds/svc/src/com/android/commands/svc/PowerCommand.java2
-rw-r--r--core/java/android/app/ContextImpl.java3
-rw-r--r--core/java/android/os/IPowerManager.aidl38
-rw-r--r--core/java/android/os/LocalPowerManager.java18
-rw-r--r--core/java/android/os/PowerManager.java159
-rw-r--r--core/java/android/os/WorkSource.java18
-rw-r--r--core/java/android/provider/Settings.java2
-rw-r--r--core/java/android/service/dreams/DreamManagerService.java4
-rw-r--r--core/java/android/util/TimeUtils.java13
-rw-r--r--core/java/android/view/WindowManagerPolicy.java34
-rw-r--r--core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java12
-rw-r--r--core/tests/coretests/src/android/os/BrightnessLimit.java2
-rw-r--r--packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java2
-rw-r--r--packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessController.java19
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java14
-rwxr-xr-xpolicy/src/com/android/internal/policy/impl/PhoneWindowManager.java173
-rw-r--r--services/java/com/android/server/DevicePolicyManagerService.java6
-rw-r--r--services/java/com/android/server/DockObserver.java11
-rw-r--r--services/java/com/android/server/SystemServer.java6
-rw-r--r--services/java/com/android/server/Watchdog.java2
-rw-r--r--services/java/com/android/server/power/DisplayPowerController.java992
-rw-r--r--services/java/com/android/server/power/DisplayPowerRequest.java96
-rw-r--r--services/java/com/android/server/power/DisplayPowerState.java269
-rw-r--r--services/java/com/android/server/power/ElectronBeam.java652
-rw-r--r--services/java/com/android/server/power/Notifier.java458
-rw-r--r--services/java/com/android/server/power/PhotonicModulator.java87
-rw-r--r--services/java/com/android/server/power/PowerManagerService.java4428
-rw-r--r--services/java/com/android/server/power/RampAnimator.java131
-rw-r--r--services/java/com/android/server/power/SuspendBlocker.java43
-rwxr-xr-xservices/java/com/android/server/wm/WindowManagerService.java23
-rw-r--r--services/jni/com_android_server_LightsService.cpp5
-rw-r--r--services/jni/com_android_server_input_InputManagerService.cpp8
-rw-r--r--services/jni/com_android_server_power_PowerManagerService.cpp126
-rw-r--r--services/jni/com_android_server_power_PowerManagerService.h1
-rw-r--r--tests/StatusBar/src/com/android/statusbartest/PowerTest.java39
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java2
-rw-r--r--tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java31
38 files changed, 4642 insertions, 3290 deletions
diff --git a/api/current.txt b/api/current.txt
index 2235ece..c77e497 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -16269,6 +16269,7 @@ package android.os {
method public android.os.PowerManager.WakeLock newWakeLock(int, java.lang.String);
method public void reboot(java.lang.String);
method public void userActivity(long, boolean);
+ method public void wakeUp(long);
field public static final int ACQUIRE_CAUSES_WAKEUP = 268435456; // 0x10000000
field public static final deprecated int FULL_WAKE_LOCK = 26; // 0x1a
field public static final int ON_AFTER_RELEASE = 536870912; // 0x20000000
@@ -18759,7 +18760,7 @@ package android.provider {
field public static final android.net.Uri DEFAULT_NOTIFICATION_URI;
field public static final android.net.Uri DEFAULT_RINGTONE_URI;
field public static final deprecated java.lang.String DEVICE_PROVISIONED = "device_provisioned";
- field public static final java.lang.String DIM_SCREEN = "dim_screen";
+ field public static final deprecated java.lang.String DIM_SCREEN = "dim_screen";
field public static final java.lang.String DTMF_TONE_WHEN_DIALING = "dtmf_tone";
field public static final java.lang.String END_BUTTON_BEHAVIOR = "end_button_behavior";
field public static final java.lang.String FONT_SCALE = "font_scale";
diff --git a/cmds/svc/src/com/android/commands/svc/PowerCommand.java b/cmds/svc/src/com/android/commands/svc/PowerCommand.java
index e1d6619..deef2a3 100644
--- a/cmds/svc/src/com/android/commands/svc/PowerCommand.java
+++ b/cmds/svc/src/com/android/commands/svc/PowerCommand.java
@@ -64,7 +64,7 @@ public class PowerCommand extends Svc.Command {
= IPowerManager.Stub.asInterface(ServiceManager.getService(Context.POWER_SERVICE));
try {
IBinder lock = new Binder();
- pm.acquireWakeLock(PowerManager.FULL_WAKE_LOCK, lock, "svc power", null);
+ pm.acquireWakeLock(lock, PowerManager.FULL_WAKE_LOCK, "svc power", null);
pm.setStayOnSetting(val);
pm.releaseWakeLock(lock, 0);
}
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 1ef14eb..fd4c304 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -418,7 +418,8 @@ class ContextImpl extends Context {
public Object createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(POWER_SERVICE);
IPowerManager service = IPowerManager.Stub.asInterface(b);
- return new PowerManager(service, ctx.mMainThread.getHandler());
+ return new PowerManager(ctx.getOuterContext(),
+ service, ctx.mMainThread.getHandler());
}});
registerService(SEARCH_SERVICE, new ServiceFetcher() {
diff --git a/core/java/android/os/IPowerManager.aidl b/core/java/android/os/IPowerManager.aidl
index 270e9be..7aee644 100644
--- a/core/java/android/os/IPowerManager.aidl
+++ b/core/java/android/os/IPowerManager.aidl
@@ -23,27 +23,33 @@ import android.os.WorkSource;
interface IPowerManager
{
- // WARNING: changes in acquireWakeLock() signature must be reflected in IPowerManager.cpp/h
- void acquireWakeLock(int flags, IBinder lock, String tag, in WorkSource ws);
- void updateWakeLockWorkSource(IBinder lock, in WorkSource ws);
- void goToSleep(long time);
- void goToSleepWithReason(long time, int reason);
- // WARNING: changes in releaseWakeLock() signature must be reflected in IPowerManager.cpp/h
+ // WARNING: The first two methods must remain the first two methods because their
+ // transaction numbers must not change unless IPowerManager.cpp is also updated.
+ void acquireWakeLock(IBinder lock, int flags, String tag, in WorkSource ws);
void releaseWakeLock(IBinder lock, int flags);
- void userActivity(long when, boolean noChangeLights);
- void userActivityWithForce(long when, boolean noChangeLights, boolean force);
+
+ void updateWakeLockWorkSource(IBinder lock, in WorkSource ws);
+ boolean isWakeLockLevelSupported(int level);
+
+ void userActivity(long time, int event, int flags);
+ void wakeUp(long time);
+ void goToSleep(long time, int reason);
+
+ boolean isScreenOn();
+ void reboot(String reason);
+ void crash(String message);
+
void clearUserActivityTimeout(long now, long timeout);
void setPokeLock(int pokey, IBinder lock, String tag);
- int getSupportedWakeLockFlags();
void setStayOnSetting(int val);
- void setMaximumScreenOffTimeount(int timeMs);
+ void setMaximumScreenOffTimeoutFromDeviceAdmin(int timeMs);
void preventScreenOn(boolean prevent);
- boolean isScreenOn();
- void reboot(String reason);
- void crash(String message);
- // sets the brightness of the backlights (screen, keyboard, button) 0-255
- void setBacklightBrightness(int brightness);
+ // temporarily overrides the screen brightness settings to allow the user to
+ // see the effect of a settings change without applying it immediately
+ void setTemporaryScreenBrightnessSettingOverride(int brightness);
+ void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float adj);
+
+ // sets the attention light (used by phone app only)
void setAttentionLight(boolean on, int color);
- void setAutoBrightnessAdjustment(float adj);
}
diff --git a/core/java/android/os/LocalPowerManager.java b/core/java/android/os/LocalPowerManager.java
index 09336c7..519315c 100644
--- a/core/java/android/os/LocalPowerManager.java
+++ b/core/java/android/os/LocalPowerManager.java
@@ -18,25 +18,11 @@ package android.os;
/** @hide */
public interface LocalPowerManager {
+ // FIXME: Replace poke locks with something else.
+
public static final int POKE_LOCK_IGNORE_TOUCH_EVENTS = 0x1;
public static final int POKE_LOCK_SHORT_TIMEOUT = 0x2;
public static final int POKE_LOCK_MEDIUM_TIMEOUT = 0x4;
public static final int POKE_LOCK_TIMEOUT_MASK = 0x6;
-
- void goToSleep(long time);
-
- // notify power manager when keyboard is opened/closed
- void setKeyboardVisibility(boolean visible);
-
- // when the keyguard is up, it manages the power state, and userActivity doesn't do anything.
- void enableUserActivity(boolean enabled);
-
- // the same as the method on PowerManager
- void userActivity(long time, boolean noChangeLights, int eventType);
-
- boolean isScreenOn();
-
- void setScreenBrightnessOverride(int brightness);
- void setButtonBrightnessOverride(int brightness);
}
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index a757303..efdbcac 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -16,6 +16,7 @@
package android.os;
+import android.content.Context;
import android.util.Log;
/**
@@ -42,8 +43,8 @@ import android.util.Log;
* wl.release();
* }
* </p><p>
- * The following flags are defined, with varying effects on system power.
- * <i>These flags are mutually exclusive - you may only specify one of them.</i>
+ * The following wake lock levels are defined, with varying effects on system power.
+ * <i>These levels are mutually exclusive - you may only specify one of them.</i>
*
* <table border="2" width="85%" align="center" frame="hsides" rules="rows">
* <thead>
@@ -177,7 +178,7 @@ public final class PowerManager {
/**
* Wake lock level: Turns the screen off when the proximity sensor activates.
* <p>
- * Since not all devices have proximity sensors, use {@link #getSupportedWakeLockFlags}
+ * Since not all devices have proximity sensors, use {@link #isWakeLockLevelSupported}
* to determine whether this wake lock level is supported.
* </p>
*
@@ -227,28 +228,23 @@ public final class PowerManager {
public static final int WAIT_FOR_PROXIMITY_NEGATIVE = 1;
/**
- * Brightness value to use when battery is low.
- * @hide
- */
- public static final int BRIGHTNESS_LOW_BATTERY = 10;
-
- /**
* Brightness value for fully on.
* @hide
*/
public static final int BRIGHTNESS_ON = 255;
/**
- * Brightness value for dim backlight.
+ * Brightness value for fully off.
* @hide
*/
- public static final int BRIGHTNESS_DIM = 20;
+ public static final int BRIGHTNESS_OFF = 0;
/**
- * Brightness value for fully off.
+ * A nominal default brightness value.
+ * Use {@link #getDefaultScreenBrightnessSetting()} instead.
* @hide
*/
- public static final int BRIGHTNESS_OFF = 0;
+ private static final int BRIGHTNESS_DEFAULT = 102;
// Note: Be sure to update android.os.BatteryStats and PowerManager.h
// if adding or modifying user activity event constants.
@@ -271,18 +267,82 @@ public final class PowerManager {
*/
public static final int USER_ACTIVITY_EVENT_TOUCH = 2;
+ /**
+ * User activity flag: Do not restart the user activity timeout or brighten
+ * the display in response to user activity if it is already dimmed.
+ * @hide
+ */
+ public static final int USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS = 1 << 0;
+
+ /**
+ * Special wake lock tag used for the wake lock in the Window Manager that handles the
+ * {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} flag.
+ * @hide
+ */
+ public static final String KEEP_SCREEN_ON_FLAG_TAG = "KEEP_SCREEN_ON_FLAG";
+
+ /**
+ * Go to sleep reason code: Going to sleep due by user request.
+ * @hide
+ */
+ public static final int GO_TO_SLEEP_REASON_USER = 0;
+
+ /**
+ * Go to sleep reason code: Going to sleep due by request of the
+ * device administration policy.
+ * @hide
+ */
+ public static final int GO_TO_SLEEP_REASON_DEVICE_ADMIN = 1;
+
+ /**
+ * Go to sleep reason code: Going to sleep due to a screen timeout.
+ * @hide
+ */
+ public static final int GO_TO_SLEEP_REASON_TIMEOUT = 2;
+
+ final Context mContext;
final IPowerManager mService;
final Handler mHandler;
/**
* {@hide}
*/
- public PowerManager(IPowerManager service, Handler handler) {
+ public PowerManager(Context context, IPowerManager service, Handler handler) {
+ mContext = context;
mService = service;
mHandler = handler;
}
/**
+ * Gets the minimum supported screen brightness setting.
+ * The screen may be allowed to become dimmer than this value but
+ * this is the minimum value that can be set by the user.
+ * @hide
+ */
+ public int getMinimumScreenBrightnessSetting() {
+ return mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_screenBrightnessDim);
+ }
+
+ /**
+ * Gets the maximum supported screen brightness setting.
+ * The screen may be allowed to become dimmer than this value but
+ * this is the maximum value that can be set by the user.
+ * @hide
+ */
+ public int getMaximumScreenBrightnessSetting() {
+ return BRIGHTNESS_ON;
+ }
+
+ /**
+ * Gets the default screen brightness setting.
+ * @hide
+ */
+ public int getDefaultScreenBrightnessSetting() {
+ return BRIGHTNESS_DEFAULT;
+ }
+
+ /**
* Creates a new wake lock with the specified level and flags.
* <p>
* The {@code levelAndFlags} parameter specifies a wake lock level and optional flags
@@ -360,8 +420,10 @@ public final class PowerManager {
/**
* Notifies the power manager that user activity happened.
* <p>
- * Turns the device from whatever state it's in to full on, and resets
- * the auto-off timer.
+ * Resets the auto-off timer and brightens the screen if the device
+ * is not asleep. This is what happens normally when a key or the touch
+ * screen is pressed or when some other user activity occurs.
+ * This method does not wake up the device if it has been put to sleep.
* </p><p>
* Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
* </p>
@@ -375,10 +437,14 @@ public final class PowerManager {
* We want the device to stay on while the button is down, but we're about
* to turn off the screen so we don't want the keyboard backlight to turn on again.
* Otherwise the lights flash on and then off and it looks weird.
+ *
+ * @see #wakeUp
+ * @see #goToSleep
*/
public void userActivity(long when, boolean noChangeLights) {
try {
- mService.userActivity(when, noChangeLights);
+ mService.userActivity(when, USER_ACTIVITY_EVENT_OTHER,
+ noChangeLights ? USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS : 0);
} catch (RemoteException e) {
}
}
@@ -386,8 +452,8 @@ public final class PowerManager {
/**
* Forces the device to go to sleep.
* <p>
- * Overrides all the wake locks that are held. This is what happen when the power
- * key is pressed to turn off the screen.
+ * Overrides all the wake locks that are held.
+ * This is what happens when the power key is pressed to turn off the screen.
* </p><p>
* Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
* </p>
@@ -396,10 +462,37 @@ public final class PowerManager {
* {@link SystemClock#uptimeMillis()} time base. This timestamp is used to correctly
* order the user activity with other power management functions. It should be set
* to the timestamp of the input event that caused the request to go to sleep.
+ *
+ * @see #userActivity
+ * @see #wakeUp
*/
public void goToSleep(long time) {
try {
- mService.goToSleep(time);
+ mService.goToSleep(time, GO_TO_SLEEP_REASON_USER);
+ } catch (RemoteException e) {
+ }
+ }
+
+ /**
+ * Forces the device to wake up from sleep.
+ * <p>
+ * If the device is currently asleep, wakes it up, otherwise does nothing.
+ * This is what happens when the power key is pressed to turn on the screen.
+ * </p><p>
+ * Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
+ * </p>
+ *
+ * @param time The time when the request to wake up was issued, in the
+ * {@link SystemClock#uptimeMillis()} time base. This timestamp is used to correctly
+ * order the user activity with other power management functions. It should be set
+ * to the timestamp of the input event that caused the request to wake up.
+ *
+ * @see #userActivity
+ * @see #goToSleep
+ */
+ public void wakeUp(long time) {
+ try {
+ mService.wakeUp(time);
} catch (RemoteException e) {
}
}
@@ -416,34 +509,24 @@ public final class PowerManager {
*/
public void setBacklightBrightness(int brightness) {
try {
- mService.setBacklightBrightness(brightness);
+ mService.setTemporaryScreenBrightnessSettingOverride(brightness);
} catch (RemoteException e) {
}
}
/**
- * Returns the set of wake lock levels and flags for {@link #newWakeLock}
- * that are supported on the device.
- * <p>
- * For example, to test to see if the {@link #PROXIMITY_SCREEN_OFF_WAKE_LOCK}
- * is supported:
- * {@samplecode
- * PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
- * int supportedFlags = pm.getSupportedWakeLockFlags();
- * boolean proximitySupported = ((supportedFlags & PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)
- * == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK);
- * }
- * </p>
+ * Returns true if the specified wake lock level is supported.
*
- * @return The set of supported WakeLock flags.
+ * @param level The wake lock level to check.
+ * @return True if the specified wake lock level is supported.
*
* {@hide}
*/
- public int getSupportedWakeLockFlags() {
+ public boolean isWakeLockLevelSupported(int level) {
try {
- return mService.getSupportedWakeLockFlags();
+ return mService.isWakeLockLevelSupported(level);
} catch (RemoteException e) {
- return 0;
+ return false;
}
}
@@ -593,7 +676,7 @@ public final class PowerManager {
// been explicitly released by the keyguard.
mHandler.removeCallbacks(mReleaser);
try {
- mService.acquireWakeLock(mFlags, mToken, mTag, mWorkSource);
+ mService.acquireWakeLock(mToken, mFlags, mTag, mWorkSource);
} catch (RemoteException e) {
}
mHeld = true;
diff --git a/core/java/android/os/WorkSource.java b/core/java/android/os/WorkSource.java
index a85f4fa..ba77df7 100644
--- a/core/java/android/os/WorkSource.java
+++ b/core/java/android/os/WorkSource.java
@@ -1,5 +1,9 @@
package android.os;
+import com.android.internal.util.ArrayUtils;
+
+import java.util.Arrays;
+
/**
* Describes the source of some work that may be done by someone else.
* Currently the public representation of what a work source is is not
@@ -313,6 +317,20 @@ public class WorkSource implements Parcelable {
dest.writeIntArray(mUids);
}
+ @Override
+ public String toString() {
+ StringBuilder result = new StringBuilder();
+ result.append("{WorkSource: uids=[");
+ for (int i = 0; i < mNum; i++) {
+ if (i != 0) {
+ result.append(", ");
+ }
+ result.append(mUids[i]);
+ }
+ result.append("]}");
+ return result.toString();
+ }
+
public static final Parcelable.Creator<WorkSource> CREATOR
= new Parcelable.Creator<WorkSource>() {
public WorkSource createFromParcel(Parcel in) {
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 01252f0..e08ec1f 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1381,7 +1381,9 @@ public final class Settings {
/**
* Whether or not to dim the screen. 0=no 1=yes
+ * @deprecated This setting is no longer used.
*/
+ @Deprecated
public static final String DIM_SCREEN = "dim_screen";
/**
diff --git a/core/java/android/service/dreams/DreamManagerService.java b/core/java/android/service/dreams/DreamManagerService.java
index dd177cb..fc3f501 100644
--- a/core/java/android/service/dreams/DreamManagerService.java
+++ b/core/java/android/service/dreams/DreamManagerService.java
@@ -123,7 +123,9 @@ public class DreamManagerService
// IDreamManager method
@Override
public boolean isDreaming() {
- return mCurrentDream != null;
+ synchronized (mLock) {
+ return mCurrentDreamToken != null;
+ }
}
public void bindDreamComponentL(ComponentName componentName, boolean test) {
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
index 7d33ff4a..5a4f322 100644
--- a/core/java/android/util/TimeUtils.java
+++ b/core/java/android/util/TimeUtils.java
@@ -18,6 +18,7 @@ package android.util;
import android.content.res.Resources;
import android.content.res.XmlResourceParser;
+import android.os.SystemClock;
import android.text.format.DateUtils;
import com.android.internal.util.XmlUtils;
@@ -391,6 +392,18 @@ public class TimeUtils {
formatDuration(time-now, pw, 0);
}
+ /** @hide Just for debugging; not internationalized. */
+ public static String formatUptime(long time) {
+ final long diff = time - SystemClock.uptimeMillis();
+ if (diff > 0) {
+ return time + " (in " + diff + " ms)";
+ }
+ if (diff < 0) {
+ return time + " (" + -diff + " ms ago)";
+ }
+ return time + " (now)";
+ }
+
/**
* Convert a System.currentTimeMillis() value to a time of day value like
* that printed in logs. MM-DD HH:MM:SS.MMM
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 407bae5..7aa3bb4 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -22,7 +22,6 @@ import android.content.res.Configuration;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.IBinder;
-import android.os.LocalPowerManager;
import android.os.Looper;
import android.view.animation.Animation;
@@ -115,11 +114,11 @@ public interface WindowManagerPolicy {
public final static int ACTION_PASS_TO_USER = 0x00000001;
/**
- * This key event should extend the user activity timeout and turn the lights on.
+ * This key event should wake the device.
* To be returned from {@link #interceptKeyBeforeQueueing}.
* Do not return this and {@link #ACTION_GO_TO_SLEEP} or {@link #ACTION_PASS_TO_USER}.
*/
- public final static int ACTION_POKE_USER_ACTIVITY = 0x00000002;
+ public final static int ACTION_WAKE_UP = 0x00000002;
/**
* This key event should put the device to sleep (and engage keyguard if necessary)
@@ -473,11 +472,9 @@ public interface WindowManagerPolicy {
* Perform initialization of the policy.
*
* @param context The system context we are running in.
- * @param powerManager
*/
public void init(Context context, IWindowManager windowManager,
- WindowManagerFuncs windowManagerFuncs,
- LocalPowerManager powerManager);
+ WindowManagerFuncs windowManagerFuncs);
/**
* Called by window manager once it has the initial, default native
@@ -1093,31 +1090,6 @@ public interface WindowManagerPolicy {
public void lockNow();
/**
- * Check to see if a screensaver should be run instead of powering off the screen on timeout.
- *
- * @return true if the screensaver should run, false if the screen should turn off.
- *
- * @hide
- */
- public boolean isScreenSaverEnabled();
-
- /**
- * Start the screensaver (if it is enabled and not yet running).
- *
- * @return Whether the screensaver was successfully started.
- *
- * @hide
- */
- public boolean startScreenSaver();
-
- /**
- * Stop the screensaver if it is running.
- *
- * @hide
- */
- public void stopScreenSaver();
-
- /**
* Set the last used input method window state. This state is used to make IME transition
* smooth.
* @hide
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
index 6630601..216344d 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
@@ -500,19 +500,15 @@ public class ConnectivityManagerTestActivity extends Activity {
log("Turn screen off");
PowerManager pm =
(PowerManager) getSystemService(Context.POWER_SERVICE);
- pm.goToSleep(SystemClock.uptimeMillis() + 100);
+ pm.goToSleep(SystemClock.uptimeMillis());
}
// Turn screen on
public void turnScreenOn() {
log("Turn screen on");
- IPowerManager mPowerManagerService = IPowerManager.Stub.asInterface(
- ServiceManager.getService("power"));;
- try {
- mPowerManagerService.userActivityWithForce(SystemClock.uptimeMillis(), false, true);
- } catch (Exception e) {
- log(e.toString());
- }
+ PowerManager pm =
+ (PowerManager) getSystemService(Context.POWER_SERVICE);
+ pm.wakeUp(SystemClock.uptimeMillis());
}
/**
diff --git a/core/tests/coretests/src/android/os/BrightnessLimit.java b/core/tests/coretests/src/android/os/BrightnessLimit.java
index 5e9b906..f4a5e09 100644
--- a/core/tests/coretests/src/android/os/BrightnessLimit.java
+++ b/core/tests/coretests/src/android/os/BrightnessLimit.java
@@ -49,7 +49,7 @@ public class BrightnessLimit extends Activity implements OnClickListener {
ServiceManager.getService("power"));
if (power != null) {
try {
- power.setBacklightBrightness(0);
+ power.setTemporaryScreenBrightnessSettingOverride(0);
} catch (RemoteException darn) {
}
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
index 18e7faa..9208cae 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsHelper.java
@@ -109,7 +109,7 @@ public class SettingsHelper {
IPowerManager power = IPowerManager.Stub.asInterface(
ServiceManager.getService("power"));
if (power != null) {
- power.setBacklightBrightness(brightness);
+ power.setTemporaryScreenBrightnessSettingOverride(brightness);
}
} catch (RemoteException doe) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessController.java
index 3ba36af..457e9dd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessController.java
@@ -20,6 +20,7 @@ import android.content.ContentResolver;
import android.content.Context;
import android.os.AsyncTask;
import android.os.IPowerManager;
+import android.os.PowerManager;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.provider.Settings;
@@ -31,8 +32,8 @@ import android.widget.CompoundButton;
public class BrightnessController implements ToggleSlider.Listener {
private static final String TAG = "StatusBar.BrightnessController";
- private static final int MINIMUM_BACKLIGHT = android.os.PowerManager.BRIGHTNESS_DIM;
- private static final int MAXIMUM_BACKLIGHT = android.os.PowerManager.BRIGHTNESS_ON;
+ private final int mMinimumBacklight;
+ private final int mMaximumBacklight;
private Context mContext;
private ToggleSlider mControl;
@@ -42,6 +43,10 @@ public class BrightnessController implements ToggleSlider.Listener {
mContext = context;
mControl = control;
+ PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+ mMinimumBacklight = pm.getMinimumScreenBrightnessSetting();
+ mMaximumBacklight = pm.getMaximumScreenBrightnessSetting();
+
boolean automaticAvailable = context.getResources().getBoolean(
com.android.internal.R.bool.config_automatic_brightness_available);
mPower = IPowerManager.Stub.asInterface(ServiceManager.getService("power"));
@@ -65,11 +70,11 @@ public class BrightnessController implements ToggleSlider.Listener {
value = Settings.System.getInt(mContext.getContentResolver(),
Settings.System.SCREEN_BRIGHTNESS);
} catch (SettingNotFoundException ex) {
- value = MAXIMUM_BACKLIGHT;
+ value = mMaximumBacklight;
}
- control.setMax(MAXIMUM_BACKLIGHT - MINIMUM_BACKLIGHT);
- control.setValue(value - MINIMUM_BACKLIGHT);
+ control.setMax(mMaximumBacklight - mMinimumBacklight);
+ control.setValue(value - mMinimumBacklight);
control.setOnChangedListener(this);
}
@@ -78,7 +83,7 @@ public class BrightnessController implements ToggleSlider.Listener {
setMode(automatic ? Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC
: Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
if (!automatic) {
- final int val = value + MINIMUM_BACKLIGHT;
+ final int val = value + mMinimumBacklight;
setBrightness(val);
if (!tracking) {
AsyncTask.execute(new Runnable() {
@@ -98,7 +103,7 @@ public class BrightnessController implements ToggleSlider.Listener {
private void setBrightness(int brightness) {
try {
- mPower.setBacklightBrightness(brightness);
+ mPower.setTemporaryScreenBrightnessSettingOverride(brightness);
} catch (RemoteException ex) {
}
}
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
index 4b6863e..1f58ea1 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
@@ -33,7 +33,6 @@ import android.content.IntentFilter;
import android.media.AudioManager;
import android.media.SoundPool;
import android.os.Handler;
-import android.os.LocalPowerManager;
import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
@@ -157,10 +156,6 @@ public class KeyguardViewMediator implements KeyguardViewCallback {
private boolean mSuppressNextLockSound = true;
- /** Low level access to the power manager for enableUserActivity. Having this
- * requires that we run in the system process. */
- LocalPowerManager mRealPowerManager;
-
/** High level access to the power manager for WakeLocks */
private PowerManager mPM;
@@ -358,11 +353,9 @@ public class KeyguardViewMediator implements KeyguardViewCallback {
};
- public KeyguardViewMediator(Context context, PhoneWindowManager callback,
- LocalPowerManager powerManager) {
+ public KeyguardViewMediator(Context context, PhoneWindowManager callback) {
mContext = context;
mCallback = callback;
- mRealPowerManager = powerManager;
mPM = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
mWakeLock = mPM.newWakeLock(
PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "keyguard");
@@ -1032,7 +1025,7 @@ public class KeyguardViewMediator implements KeyguardViewCallback {
if (DEBUG) Log.d(TAG, "handleKeyguardDone");
handleHide();
if (wakeup) {
- mPM.userActivity(SystemClock.uptimeMillis(), true);
+ mPM.wakeUp(SystemClock.uptimeMillis());
}
mWakeLock.release();
mContext.sendBroadcast(mUserPresentIntent);
@@ -1165,7 +1158,8 @@ public class KeyguardViewMediator implements KeyguardViewCallback {
// disable user activity if we are shown and not hidden
if (DEBUG) Log.d(TAG, "adjustUserActivityLocked mShowing: " + mShowing + " mHidden: " + mHidden);
boolean enabled = !mShowing || mHidden;
- mRealPowerManager.enableUserActivity(enabled);
+ // FIXME: Replace this with a new timeout control mechanism.
+ //mRealPowerManager.enableUserActivity(enabled);
if (!enabled && mScreenOn) {
// reinstate our short screen timeout policy
pokeWakelock();
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 769b513..c036e1b 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -45,7 +45,6 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.IRemoteCallback;
-import android.os.LocalPowerManager;
import android.os.Looper;
import android.os.Message;
import android.os.Messenger;
@@ -170,9 +169,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
static final boolean ENABLE_CAR_DOCK_HOME_CAPTURE = true;
static final boolean ENABLE_DESK_DOCK_HOME_CAPTURE = false;
- // Should screen savers use their own timeout, or the SCREEN_OFF_TIMEOUT?
- static final boolean SEPARATE_TIMEOUT_FOR_SCREEN_SAVER = false;
-
static final int LONG_PRESS_POWER_NOTHING = 0;
static final int LONG_PRESS_POWER_GLOBAL_ACTIONS = 1;
static final int LONG_PRESS_POWER_SHUT_OFF = 2;
@@ -280,7 +276,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Context mContext;
IWindowManager mWindowManager;
WindowManagerFuncs mWindowManagerFuncs;
- LocalPowerManager mPowerManager;
+ PowerManager mPowerManager;
IStatusBarService mStatusBarService;
final Object mServiceAquireLock = new Object();
Vibrator mVibrator; // Vibrator for giving feedback of orientation changes
@@ -474,13 +470,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
int mLockScreenTimeout;
boolean mLockScreenTimerActive;
- // visual screen saver support
- boolean mScreenSaverFeatureAvailable;
- int mScreenSaverTimeout = 0;
- boolean mScreenSaverEnabledByUser = false;
- boolean mScreenSaverMayRun = true; // false if a wakelock is held
- boolean mPluggedIn;
-
// Behavior of ENDCALL Button. (See Settings.System.END_BUTTON_BEHAVIOR.)
int mEndcallBehavior;
@@ -572,12 +561,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Settings.Secure.DEFAULT_INPUT_METHOD), false, this);
resolver.registerContentObserver(Settings.System.getUriFor(
"fancy_rotation_anim"), false, this);
- resolver.registerContentObserver(Settings.Secure.getUriFor(
- Settings.Secure.SCREENSAVER_ENABLED), false, this);
- if (SEPARATE_TIMEOUT_FOR_SCREEN_SAVER) {
- resolver.registerContentObserver(Settings.Secure.getUriFor(
- "screensaver_timeout"), false, this);
- } // otherwise SCREEN_OFF_TIMEOUT will do nicely
updateSettings();
}
@@ -863,16 +846,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
/** {@inheritDoc} */
public void init(Context context, IWindowManager windowManager,
- WindowManagerFuncs windowManagerFuncs,
- LocalPowerManager powerManager) {
+ WindowManagerFuncs windowManagerFuncs) {
mContext = context;
mWindowManager = windowManager;
mWindowManagerFuncs = windowManagerFuncs;
- mPowerManager = powerManager;
mHeadless = "1".equals(SystemProperties.get("ro.config.headless", "0"));
if (!mHeadless) {
// don't create KeyguardViewMediator if headless
- mKeyguardMediator = new KeyguardViewMediator(context, this, powerManager);
+ mKeyguardMediator = new KeyguardViewMediator(context, this);
}
mHandler = new PolicyHandler();
mOrientationListener = new MyOrientationListener(mContext);
@@ -898,8 +879,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mDeskDockIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
- PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
- mBroadcastWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
+ mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
+ mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"PhoneWindowManager.mBroadcastWakeLock");
mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
mLidOpenRotation = readRotation(
@@ -932,14 +913,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Intent.EXTRA_DOCK_STATE_UNDOCKED);
}
- // watch the plug to know whether to trigger the screen saver
- filter = new IntentFilter();
- filter.addAction(Intent.ACTION_BATTERY_CHANGED);
- intent = context.registerReceiver(mPowerReceiver, filter);
- if (intent != null) {
- mPluggedIn = (0 != intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0));
- }
-
mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
mLongPressVibePattern = getLongIntArray(mContext.getResources(),
com.android.internal.R.array.config_longPressVibePattern);
@@ -1121,26 +1094,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mHasSoftInput = hasSoftInput;
updateRotation = true;
}
-
- // dreams
- mScreenSaverFeatureAvailable = mContext.getResources().getBoolean(
- com.android.internal.R.bool.config_enableDreams);
-
- mScreenSaverEnabledByUser = 0 != Settings.Secure.getInt(resolver,
- Settings.Secure.SCREENSAVER_ENABLED, 0);
-
- if (SEPARATE_TIMEOUT_FOR_SCREEN_SAVER) {
- mScreenSaverTimeout = Settings.Secure.getInt(resolver,
- "screensaver_timeout", 0);
- } else {
- mScreenSaverTimeout = Settings.System.getInt(resolver,
- Settings.System.SCREEN_OFF_TIMEOUT, 0);
- if (mScreenSaverTimeout > 0) {
- // We actually want to activate the screensaver just before the
- // power manager's screen timeout
- mScreenSaverTimeout -= 5000;
- }
- }
}
if (updateRotation) {
updateRotation(true);
@@ -3018,12 +2971,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mKeyguardMediator.onWakeKeyWhenKeyguardShowingTq(
KeyEvent.KEYCODE_POWER, mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED);
} else {
- mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
- PowerManager.USER_ACTIVITY_EVENT_BUTTON);
+ mPowerManager.wakeUp(SystemClock.uptimeMillis());
}
} else if (!mLidControlsSleep) {
- mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
- PowerManager.USER_ACTIVITY_EVENT_OTHER);
+ mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
}
}
@@ -3182,6 +3133,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
/** {@inheritDoc} */
@Override
public int interceptKeyBeforeQueueing(KeyEvent event, int policyFlags, boolean isScreenOn) {
+ if (!mSystemBooted) {
+ // If we have not yet booted, don't let key events do anything.
+ return 0;
+ }
+
final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
final boolean canceled = event.isCanceled();
final int keyCode = event.getKeyCode();
@@ -3197,14 +3153,17 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mKeyguardMediator.isShowingAndNotHidden() :
mKeyguardMediator.isShowing()));
- if (!mSystemBooted) {
- // If we have not yet booted, don't let key events do anything.
- return 0;
+ if (keyCode == KeyEvent.KEYCODE_POWER) {
+ policyFlags |= WindowManagerPolicy.FLAG_WAKE;
}
+ final boolean isWakeKey = (policyFlags & (WindowManagerPolicy.FLAG_WAKE
+ | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
if (DEBUG_INPUT) {
Log.d(TAG, "interceptKeyTq keycode=" + keyCode
- + " screenIsOn=" + isScreenOn + " keyguardActive=" + keyguardActive);
+ + " screenIsOn=" + isScreenOn + " keyguardActive=" + keyguardActive
+ + " policyFlags=" + Integer.toHexString(policyFlags)
+ + " isWakeKey=" + isWakeKey);
}
if (down && (policyFlags & WindowManagerPolicy.FLAG_VIRTUAL) != 0
@@ -3212,12 +3171,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
}
- if (keyCode == KeyEvent.KEYCODE_POWER) {
- policyFlags |= WindowManagerPolicy.FLAG_WAKE;
- }
- final boolean isWakeKey = (policyFlags & (WindowManagerPolicy.FLAG_WAKE
- | WindowManagerPolicy.FLAG_WAKE_DROPPED)) != 0;
-
// Basic policy based on screen state and keyguard.
// FIXME: This policy isn't quite correct. We shouldn't care whether the screen
// is on or off, really. We should care about whether the device is in an
@@ -3241,7 +3194,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mDockMode != Intent.EXTRA_DOCK_STATE_UNDOCKED);
} else {
// Otherwise, wake the device ourselves.
- result |= ACTION_POKE_USER_ACTIVITY;
+ result |= ACTION_WAKE_UP;
}
}
}
@@ -3346,7 +3299,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
if ((mEndcallBehavior
& Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
- result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
+ result = (result & ~ACTION_WAKE_UP) | ACTION_GO_TO_SLEEP;
}
}
}
@@ -3388,7 +3341,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mPowerKeyTriggered = false;
cancelPendingScreenshotChordAction();
if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) {
- result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
+ result = (result & ~ACTION_WAKE_UP) | ACTION_GO_TO_SLEEP;
}
mPendingPowerKeyUpCanceled = false;
}
@@ -3473,7 +3426,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mKeyguardMediator.onWakeMotionWhenKeyguardShowingTq();
} else {
// Otherwise, wake the device ourselves.
- result |= ACTION_POKE_USER_ACTIVITY;
+ result |= ACTION_WAKE_UP;
}
}
return result;
@@ -3553,15 +3506,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
};
- BroadcastReceiver mPowerReceiver = new BroadcastReceiver() {
- public void onReceive(Context context, Intent intent) {
- if (Intent.ACTION_BATTERY_CHANGED.equals(intent.getAction())) {
- mPluggedIn = (0 != intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, 0));
- if (localLOGV) Log.v(TAG, "BATTERY_CHANGED: " + intent + " plugged=" + mPluggedIn);
- }
- }
- };
-
/** {@inheritDoc} */
public void screenTurnedOff(int why) {
EventLog.writeEvent(70000, 0);
@@ -4035,62 +3979,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
- private IDreamManager getDreamManager() {
- if (!mScreenSaverFeatureAvailable) {
- return null;
- }
-
- IDreamManager sandman = IDreamManager.Stub.asInterface(
- ServiceManager.checkService("dreams"));
- if (sandman == null) {
- Log.w(TAG, "Unable to find IDreamManager");
- }
- return sandman;
- }
-
- @Override
- public boolean isScreenSaverEnabled() {
- return (mScreenSaverFeatureAvailable && mScreenSaverEnabledByUser
- && mScreenSaverMayRun && mScreenOnEarly && mPluggedIn);
- }
-
- @Override
- public boolean startScreenSaver() {
- synchronized (mLock) {
- if (isScreenSaverEnabled()) {
- IDreamManager dm = getDreamManager();
- if (dm == null) return false;
-
- try {
- if (localLOGV) Log.v(TAG, "startScreenSaver: entering dreamland...");
-
- dm.dream();
- return true;
- } catch (RemoteException ex) {
- // too bad, so sad, oh mom, oh dad
- }
- }
- }
- return false;
- }
-
- @Override
- public void stopScreenSaver() {
- synchronized (mLock) {
- IDreamManager dm = getDreamManager();
- if (dm == null) return;
-
- try {
- if (!dm.isDreaming()) return;
-
- if (localLOGV) Log.v(TAG, "stopScreenSaver: awakening...");
-
- dm.awaken();
- } catch (RemoteException ex) {
- }
- }
- }
-
Runnable mScreenLockTimeout = new Runnable() {
public void run() {
synchronized (this) {
@@ -4134,8 +4022,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
private void applyLidSwitchState() {
- mPowerManager.setKeyboardVisibility(isBuiltInKeyboardVisible());
-
if (mLidState == LID_CLOSED && mLidControlsSleep) {
mPowerManager.goToSleep(SystemClock.uptimeMillis());
}
@@ -4317,24 +4203,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
public void screenOnStartedLw() {
- // The window manager has just grabbed a wake lock. This is our cue to disable the screen
- // saver.
- synchronized (mLock) {
- mScreenSaverMayRun = false;
- }
}
public void screenOnStoppedLw() {
if (mPowerManager.isScreenOn()) {
if (mKeyguardMediator != null && !mKeyguardMediator.isShowingAndNotHidden()) {
long curTime = SystemClock.uptimeMillis();
- mPowerManager.userActivity(curTime, false, PowerManager.USER_ACTIVITY_EVENT_OTHER);
- }
-
- synchronized (mLock) {
- // even if the keyguard is up, now that all the wakelocks have been released, we
- // should re-enable the screen saver
- mScreenSaverMayRun = true;
+ mPowerManager.userActivity(curTime, false);
}
}
}
diff --git a/services/java/com/android/server/DevicePolicyManagerService.java b/services/java/com/android/server/DevicePolicyManagerService.java
index ea19d6e..f966a33 100644
--- a/services/java/com/android/server/DevicePolicyManagerService.java
+++ b/services/java/com/android/server/DevicePolicyManagerService.java
@@ -1626,7 +1626,7 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
mLastMaximumTimeToLock = timeMs;
try {
- getIPowerManager().setMaximumScreenOffTimeount((int)timeMs);
+ getIPowerManager().setMaximumScreenOffTimeoutFromDeviceAdmin((int)timeMs);
} catch (RemoteException e) {
Slog.w(TAG, "Failure talking with power manager", e);
}
@@ -1667,8 +1667,8 @@ public class DevicePolicyManagerService extends IDevicePolicyManager.Stub {
long ident = Binder.clearCallingIdentity();
try {
// Power off the display
- mIPowerManager.goToSleepWithReason(SystemClock.uptimeMillis(),
- WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN);
+ getIPowerManager().goToSleep(SystemClock.uptimeMillis(),
+ PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN);
// Ensure the device is locked
getWindowManager().lockNow();
} catch (RemoteException e) {
diff --git a/services/java/com/android/server/DockObserver.java b/services/java/com/android/server/DockObserver.java
index 6f050d3..8bdd7be 100644
--- a/services/java/com/android/server/DockObserver.java
+++ b/services/java/com/android/server/DockObserver.java
@@ -33,6 +33,7 @@ import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
import android.os.ServiceManager;
+import android.os.PowerManager;
import android.os.SystemClock;
import android.os.UEventObserver;
import android.provider.Settings;
@@ -64,11 +65,8 @@ class DockObserver extends UEventObserver {
private final Context mContext;
- private PowerManagerService mPowerManager;
-
- public DockObserver(Context context, PowerManagerService pm) {
+ public DockObserver(Context context) {
mContext = context;
- mPowerManager = pm;
init(); // set initial status
startObserving(DOCK_UEVENT_MATCH);
@@ -94,8 +92,9 @@ class DockObserver extends UEventObserver {
&& mPreviousDockState != Intent.EXTRA_DOCK_STATE_LE_DESK
&& mPreviousDockState != Intent.EXTRA_DOCK_STATE_HE_DESK) ||
mDockState != Intent.EXTRA_DOCK_STATE_UNDOCKED) {
- mPowerManager.userActivityWithForce(SystemClock.uptimeMillis(),
- false, true);
+ PowerManager pm =
+ (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
+ pm.wakeUp(SystemClock.uptimeMillis());
}
update();
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index e8350c1..c471dd2 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -50,6 +50,7 @@ import com.android.internal.os.SamplingProfilerIntegration;
import com.android.internal.widget.LockSettingsService;
import com.android.server.accessibility.AccessibilityManagerService;
import com.android.server.am.ActivityManagerService;
+import com.android.server.am.BatteryStatsService;
import com.android.server.display.DisplayManagerService;
import com.android.server.input.InputManagerService;
import com.android.server.net.NetworkPolicyManagerService;
@@ -230,7 +231,8 @@ class ServerThread extends Thread {
// only initialize the power service after we have started the
// lights service, content providers and the battery service.
- power.init(context, lights, ActivityManagerService.self(), battery, display);
+ power.init(context, lights, ActivityManagerService.self(), battery,
+ BatteryStatsService.getService(), display);
Slog.i(TAG, "Alarm Manager");
alarm = new AlarmManagerService(context);
@@ -553,7 +555,7 @@ class ServerThread extends Thread {
try {
Slog.i(TAG, "Dock Observer");
// Listen for dock station changes
- dock = new DockObserver(context, power);
+ dock = new DockObserver(context);
} catch (Throwable e) {
reportWtf("starting DockObserver", e);
}
diff --git a/services/java/com/android/server/Watchdog.java b/services/java/com/android/server/Watchdog.java
index c5b4a07..9edfad6 100644
--- a/services/java/com/android/server/Watchdog.java
+++ b/services/java/com/android/server/Watchdog.java
@@ -349,7 +349,7 @@ public class Watchdog extends Thread {
}
if (mMinScreenOff >= 0 && (mPower == null ||
- mPower.timeSinceScreenOn() < mMinScreenOff)) {
+ mPower.timeSinceScreenWasLastOn() < mMinScreenOff)) {
return "screen";
}
diff --git a/services/java/com/android/server/power/DisplayPowerController.java b/services/java/com/android/server/power/DisplayPowerController.java
new file mode 100644
index 0000000..50d3f81
--- /dev/null
+++ b/services/java/com/android/server/power/DisplayPowerController.java
@@ -0,0 +1,992 @@
+/*
+ * 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.LightsService;
+
+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.hardware.SystemSensorManager;
+import android.os.AsyncTask;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.SystemClock;
+import android.util.Slog;
+import android.util.TimeUtils;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Arrays;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.Executor;
+
+/**
+ * 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 {
+ private static final String TAG = "DisplayPowerController";
+
+ private static boolean DEBUG = false;
+ private static final boolean DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT = false;
+ private static final boolean DEBUG_PRETEND_LIGHT_SENSOR_ABSENT = false;
+
+ private static final int ELECTRON_BEAM_ON_ANIMATION_DURATION_MILLIS = 300;
+ private static final int ELECTRON_BEAM_OFF_ANIMATION_DURATION_MILLIS = 600;
+
+ private static final int MSG_UPDATE_POWER_STATE = 1;
+ private static final int MSG_PROXIMITY_SENSOR_DEBOUNCED = 2;
+ private static final int MSG_LIGHT_SENSOR_DEBOUNCED = 3;
+
+ 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.
+ private static final int PROXIMITY_SENSOR_DEBOUNCE_DELAY = 250;
+
+ // Trigger proximity if distance is less than 5 cm.
+ private static final float TYPICAL_PROXIMITY_THRESHOLD = 5.0f;
+
+ // Light sensor event rate in microseconds.
+ private static final int LIGHT_SENSOR_RATE = 1000000;
+
+ // 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 = 50;
+
+ // Filter time constant in milliseconds for computing a moving
+ // average of light samples. Different constants are used
+ // to adapt to brighter or dimmer environments.
+ private static final long BRIGHTENING_LIGHT_TIME_CONSTANT = 2500; // 2.5 sec
+ private static final long DIMMING_LIGHT_TIME_CONSTANT = 10000; // 10 sec
+
+ private final Object mLock = new Object();
+
+ // Notifier for sending asynchronous notifications.
+ private final Notifier mNotifier;
+
+ // A suspend blocker.
+ private final SuspendBlocker mSuspendBlocker;
+
+ // 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 LightsService mLights;
+
+ // The sensor manager.
+ private final SensorManager mSensorManager;
+
+ // The proximity sensor, or null if not available or needed.
+ private Sensor mProximitySensor;
+
+ // The light sensor, or null if not available or needed.
+ private Sensor mLightSensor;
+
+ // The dim screen brightness.
+ private final int mScreenBrightnessDimConfig;
+
+ // Auto-brightness.
+ private boolean mUseSoftwareAutoBrightnessConfig;
+ private int[] mAutoBrightnessLevelsConfig;
+ private int[] mAutoBrightnessLcdBacklightValuesConfig;
+
+ // 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;
+
+ // 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;
+
+ // 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;
+
+ // 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 average light sensor value.
+ private float mLightMeasurement;
+
+ // True if the light sensor measurement is valid.
+ private boolean mLightMeasurementValid;
+
+ // The number of light sensor samples that have been collected since the
+ // last time a light sensor reading was accepted.
+ private int mRecentLightSamples;
+
+ // The moving average of recent light sensor values.
+ private float mRecentLightAverage;
+
+ // True if recent light samples are getting brighter than the previous
+ // stable light measurement.
+ private boolean mRecentLightBrightening;
+
+ // The time constant to use for filtering based on whether the
+ // light appears to be brightening or dimming.
+ private long mRecentLightTimeConstant;
+
+ // The most recent light sample.
+ private float mLastLightSample;
+
+ // The time of the most light recent sample.
+ private long mLastLightSampleTime;
+
+ // The upcoming debounce light sensor time.
+ // This is only valid when mLightMeasurementValue && mRecentLightSamples >= 1.
+ private long mPendingLightSensorDebounceTime;
+
+ // 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;
+
+ // True if the screen auto-brightness value is actually being used to
+ // set the display brightness.
+ private boolean mUsingScreenAutoBrightness;
+
+ // Animators.
+ private ObjectAnimator mElectronBeamOnAnimator;
+ private ObjectAnimator mElectronBeamOffAnimator;
+ private RampAnimator<DisplayPowerState> mScreenBrightnessRampAnimator;
+
+ /**
+ * Creates the display power controller.
+ */
+ public DisplayPowerController(Looper looper, Context context, Notifier notifier,
+ LightsService lights, SuspendBlocker suspendBlocker,
+ Callbacks callbacks, Handler callbackHandler) {
+ mHandler = new DisplayControllerHandler(looper);
+ mNotifier = notifier;
+ mSuspendBlocker = suspendBlocker;
+ mCallbacks = callbacks;
+ mCallbackHandler = callbackHandler;
+
+ mLights = lights;
+ mSensorManager = new SystemSensorManager(mHandler.getLooper());
+
+ final Resources resources = context.getResources();
+ mScreenBrightnessDimConfig = resources.getInteger(
+ com.android.internal.R.integer.config_screenBrightnessDim);
+ mUseSoftwareAutoBrightnessConfig = resources.getBoolean(
+ com.android.internal.R.bool.config_automatic_brightness_available);
+ if (mUseSoftwareAutoBrightnessConfig) {
+ mAutoBrightnessLevelsConfig = resources.getIntArray(
+ com.android.internal.R.array.config_autoBrightnessLevels);
+ mAutoBrightnessLcdBacklightValuesConfig = resources.getIntArray(
+ com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
+ if (mAutoBrightnessLcdBacklightValuesConfig.length
+ != mAutoBrightnessLevelsConfig.length + 1) {
+ Slog.e(TAG, "Error in config.xml. config_autoBrightnessLcdBacklightValues "
+ + "(size " + mAutoBrightnessLcdBacklightValuesConfig.length + ") "
+ + "should have exactly one more entry than "
+ + "config_autoBrightnessLevels (size "
+ + mAutoBrightnessLevelsConfig.length + "). "
+ + "Auto-brightness will be disabled.");
+ mUseSoftwareAutoBrightnessConfig = false;
+ }
+
+ mLightSensorWarmUpTimeConfig = resources.getInteger(
+ com.android.internal.R.integer.config_lightSensorWarmupTime);
+ }
+
+ if (!DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) {
+ mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
+ if (mProximitySensor != null) {
+ mProximityThreshold = Math.min(mProximitySensor.getMaximumRange(),
+ TYPICAL_PROXIMITY_THRESHOLD);
+ }
+ }
+
+ if (mUseSoftwareAutoBrightnessConfig
+ && !DEBUG_PRETEND_LIGHT_SENSOR_ABSENT) {
+ mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
+ }
+ }
+
+ /**
+ * 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() {
+ final Executor executor = AsyncTask.THREAD_POOL_EXECUTOR;
+ mPowerState = new DisplayPowerState(new ElectronBeam(),
+ new PhotonicModulator(executor,
+ mLights.getLight(LightsService.LIGHT_ID_BACKLIGHT),
+ mSuspendBlocker));
+
+ 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);
+ }
+
+ 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;
+ synchronized (mLock) {
+ mPendingUpdatePowerStateLocked = false;
+ if (mPendingRequestLocked == null) {
+ return; // wait until first actual power request
+ }
+
+ if (mPowerRequest == null) {
+ mPowerRequest = new DisplayPowerRequest(mPendingRequestLocked);
+ mWaitingForNegativeProximity = mPendingWaitForNegativeProximityLocked;
+ mPendingRequestChangedLocked = false;
+ mustInitialize = true;
+ } else if (mPendingRequestChangedLocked) {
+ mPowerRequest.copyFrom(mPendingRequestLocked);
+ mWaitingForNegativeProximity |= mPendingWaitForNegativeProximityLocked;
+ mPendingRequestChangedLocked = false;
+ mDisplayReadyLocked = false;
+ }
+
+ mustNotify = !mDisplayReadyLocked;
+ }
+
+ // Initialize things the first time the power state is changed.
+ if (mustInitialize) {
+ initialize();
+ }
+
+ // Clear a request to wait for negative proximity if needed.
+ if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_OFF
+ || mProximity == PROXIMITY_NEGATIVE
+ || mProximitySensor == null) {
+ mWaitingForNegativeProximity = false;
+ }
+
+ // Turn on the proximity sensor if needed.
+ if (mProximitySensor != null) {
+ setProximitySensorEnabled(mPowerRequest.useProximitySensor
+ || mWaitingForNegativeProximity);
+ if (mProximitySensorEnabled && mProximity == PROXIMITY_POSITIVE) {
+ mScreenOffBecauseOfProximity = true;
+ setScreenOn(false);
+ } else if (mScreenOffBecauseOfProximity) {
+ mScreenOffBecauseOfProximity = false;
+ sendOnProximityNegative();
+ }
+ }
+
+ // Turn on the light sensor if needed.
+ if (mLightSensor != null) {
+ setLightSensorEnabled(mPowerRequest.useAutoBrightness
+ && wantScreenOn(mPowerRequest.screenState));
+ }
+
+ // Set the screen brightness.
+ if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_DIM) {
+ // Screen is dimmed. Overrides everything else.
+ animateScreenBrightness(mScreenBrightnessDimConfig, BRIGHTNESS_RAMP_RATE_FAST);
+ mUsingScreenAutoBrightness = false;
+ } else if (mPowerRequest.screenState == DisplayPowerRequest.SCREEN_STATE_BRIGHT) {
+ if (mScreenAutoBrightness >= 0 && mLightSensorEnabled) {
+ // Use current auto-brightness value.
+ animateScreenBrightness(
+ Math.max(mScreenAutoBrightness, mScreenBrightnessDimConfig),
+ mUsingScreenAutoBrightness ? BRIGHTNESS_RAMP_RATE_SLOW :
+ BRIGHTNESS_RAMP_RATE_FAST);
+ 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.
+ animateScreenBrightness(
+ Math.max(mPowerRequest.screenBrightness, mScreenBrightnessDimConfig),
+ BRIGHTNESS_RAMP_RATE_FAST);
+ mUsingScreenAutoBrightness = false;
+ }
+ } else {
+ // Screen is off. Don't bother changing the brightness.
+ mUsingScreenAutoBrightness = false;
+ }
+
+ // Animate the screen on or off.
+ if (!mScreenOffBecauseOfProximity) {
+ if (wantScreenOn(mPowerRequest.screenState)) {
+ // 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()) {
+ setScreenOn(true);
+ if (!mElectronBeamOnAnimator.isStarted()) {
+ if (mPowerState.getElectronBeamLevel() == 1.0f) {
+ mPowerState.dismissElectronBeam();
+ } else if (mPowerState.prepareElectronBeam(true)) {
+ mElectronBeamOnAnimator.start();
+ } else {
+ mElectronBeamOnAnimator.end();
+ }
+ }
+ }
+ } else {
+ // Want screen off.
+ // Wait for previous on animation to complete beforehand.
+ if (!mElectronBeamOnAnimator.isStarted()) {
+ if (!mElectronBeamOffAnimator.isStarted()) {
+ if (mPowerState.getElectronBeamLevel() == 0.0f) {
+ setScreenOn(false);
+ } else if (mPowerState.prepareElectronBeam(false)
+ && 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
+ && !mElectronBeamOnAnimator.isStarted()
+ && !mElectronBeamOffAnimator.isStarted()
+ && mPowerState.waitUntilClean(mCleanListener)) {
+ synchronized (mLock) {
+ if (!mPendingRequestChangedLocked) {
+ mDisplayReadyLocked = true;
+ }
+ }
+ sendOnStateChanged();
+ }
+ }
+
+ private void setScreenOn(boolean on) {
+ if (!mPowerState.isScreenOn() == on) {
+ mPowerState.setScreenOn(on);
+ if (on) {
+ mNotifier.onScreenOn();
+ } else {
+ mNotifier.onScreenOff();
+ }
+ }
+ }
+
+ 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) {
+ mProximitySensorEnabled = true;
+ mPendingProximity = PROXIMITY_UNKNOWN;
+ mSensorManager.registerListener(mProximitySensorListener, mProximitySensor,
+ SensorManager.SENSOR_DELAY_NORMAL, mHandler);
+ }
+ } else {
+ if (mProximitySensorEnabled) {
+ mProximitySensorEnabled = false;
+ mProximity = PROXIMITY_UNKNOWN;
+ mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
+ mSensorManager.unregisterListener(mProximitySensorListener);
+ }
+ }
+ }
+
+ private void handleProximitySensorEvent(long time, boolean positive) {
+ 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.
+ mHandler.removeMessages(MSG_PROXIMITY_SENSOR_DEBOUNCED);
+ mPendingProximity = positive ? PROXIMITY_POSITIVE : PROXIMITY_NEGATIVE;
+ mPendingProximityDebounceTime = time + PROXIMITY_SENSOR_DEBOUNCE_DELAY;
+ debounceProximitySensor();
+ }
+
+ private void debounceProximitySensor() {
+ if (mPendingProximity != PROXIMITY_UNKNOWN) {
+ final long now = SystemClock.uptimeMillis();
+ if (mPendingProximityDebounceTime <= now) {
+ mProximity = mPendingProximity;
+ sendUpdatePowerState();
+ } else {
+ Message msg = mHandler.obtainMessage(MSG_PROXIMITY_SENSOR_DEBOUNCED);
+ msg.setAsynchronous(true);
+ mHandler.sendMessageAtTime(msg, mPendingProximityDebounceTime);
+ }
+ }
+ }
+
+ private void setLightSensorEnabled(boolean enable) {
+ if (enable) {
+ if (!mLightSensorEnabled) {
+ mLightSensorEnabled = true;
+ mLightSensorEnableTime = SystemClock.uptimeMillis();
+ mSensorManager.registerListener(mLightSensorListener, mLightSensor,
+ LIGHT_SENSOR_RATE, mHandler);
+ }
+ } else {
+ if (mLightSensorEnabled) {
+ mLightSensorEnabled = false;
+ mLightMeasurementValid = false;
+ updateAutoBrightness(false);
+ mHandler.removeMessages(MSG_LIGHT_SENSOR_DEBOUNCED);
+ mSensorManager.unregisterListener(mLightSensorListener);
+ }
+ }
+ }
+
+ private void handleLightSensorEvent(long time, float lux) {
+ // Take the first few readings during the warm-up period and apply them
+ // immediately without debouncing.
+ if (!mLightMeasurementValid
+ || (time - mLightSensorEnableTime) < mLightSensorWarmUpTimeConfig) {
+ mLightMeasurement = lux;
+ mLightMeasurementValid = true;
+ mRecentLightSamples = 0;
+ updateAutoBrightness(true);
+ }
+
+ // Update our moving average.
+ if (lux != mLightMeasurement && (mRecentLightSamples == 0
+ || (lux < mLightMeasurement && mRecentLightBrightening)
+ || (lux > mLightMeasurement && !mRecentLightBrightening))) {
+ // If the newest light sample doesn't seem to be going in the
+ // same general direction as recent samples, then start over.
+ setRecentLight(time, lux, lux > mLightMeasurement);
+ mPendingLightSensorDebounceTime = time + mRecentLightTimeConstant;
+ } else if (mRecentLightSamples >= 1) {
+ // Add the newest light sample to the moving average.
+ accumulateRecentLight(time, lux);
+ }
+ if (DEBUG) {
+ Slog.d(TAG, "handleLightSensorEvent: lux=" + lux
+ + ", mLightMeasurementValid=" + mLightMeasurementValid
+ + ", mLightMeasurement=" + mLightMeasurement
+ + ", mRecentLightSamples=" + mRecentLightSamples
+ + ", mRecentLightAverage=" + mRecentLightAverage
+ + ", mRecentLightBrightening=" + mRecentLightBrightening
+ + ", mRecentLightTimeConstant=" + mRecentLightTimeConstant
+ + ", mPendingLightSensorDebounceTime="
+ + TimeUtils.formatUptime(mPendingLightSensorDebounceTime));
+ }
+
+ // Debounce.
+ mHandler.removeMessages(MSG_LIGHT_SENSOR_DEBOUNCED);
+ debounceLightSensor();
+ }
+
+ private void setRecentLight(long time, float lux, boolean brightening) {
+ mRecentLightBrightening = brightening;
+ mRecentLightTimeConstant = brightening ?
+ BRIGHTENING_LIGHT_TIME_CONSTANT : DIMMING_LIGHT_TIME_CONSTANT;
+ mRecentLightSamples = 1;
+ mRecentLightAverage = lux;
+ mLastLightSample = lux;
+ mLastLightSampleTime = time;
+ }
+
+ private void accumulateRecentLight(long time, float lux) {
+ final long timeDelta = time - mLastLightSampleTime;
+ mRecentLightSamples += 1;
+ mRecentLightAverage += (lux - mRecentLightAverage) *
+ timeDelta / (mRecentLightTimeConstant + timeDelta);
+ mLastLightSample = lux;
+ mLastLightSampleTime = time;
+ }
+
+ private void debounceLightSensor() {
+ if (mLightMeasurementValid && mRecentLightSamples >= 1) {
+ final long now = SystemClock.uptimeMillis();
+ if (mPendingLightSensorDebounceTime <= now) {
+ accumulateRecentLight(now, mLastLightSample);
+ mLightMeasurement = mRecentLightAverage;
+
+ if (DEBUG) {
+ Slog.d(TAG, "debounceLightSensor: Accepted new measurement "
+ + mLightMeasurement + " after "
+ + (now - mPendingLightSensorDebounceTime
+ + mRecentLightTimeConstant) + " ms based on "
+ + mRecentLightSamples + " recent samples.");
+ }
+
+ updateAutoBrightness(true);
+
+ // Now that we have debounced the light sensor data, we have the
+ // option of either leaving the sensor in a debounced state or
+ // restarting the debounce cycle by setting mRecentLightSamples to 0.
+ //
+ // If we leave the sensor debounced, then new average light measurements
+ // may be accepted immediately as long as they are trending in the same
+ // direction as they were before. If the measurements start
+ // jittering or trending in the opposite direction then the debounce
+ // cycle will automatically be restarted. The benefit is that the
+ // auto-brightness control can be more responsive to changes over a
+ // broad range.
+ //
+ // For now, we choose to be more responsive and leave the following line
+ // commented out.
+ //
+ // mRecentLightSamples = 0;
+ } else {
+ Message msg = mHandler.obtainMessage(MSG_LIGHT_SENSOR_DEBOUNCED);
+ msg.setAsynchronous(true);
+ mHandler.sendMessageAtTime(msg, mPendingLightSensorDebounceTime);
+ }
+ }
+ }
+
+ private void updateAutoBrightness(boolean sendUpdate) {
+ if (!mLightMeasurementValid) {
+ return;
+ }
+
+ final int newScreenAutoBrightness = mapLuxToBrightness(mLightMeasurement,
+ mAutoBrightnessLevelsConfig,
+ mAutoBrightnessLcdBacklightValuesConfig);
+ if (mScreenAutoBrightness != newScreenAutoBrightness) {
+ if (DEBUG) {
+ Slog.d(TAG, "updateAutoBrightness: mScreenAutoBrightness="
+ + mScreenAutoBrightness);
+ }
+
+ mScreenAutoBrightness = newScreenAutoBrightness;
+ if (sendUpdate) {
+ sendUpdatePowerState();
+ }
+ }
+ }
+
+ /**
+ * Maps a light sensor measurement in lux to a brightness value given
+ * a table of lux breakpoint values and a table of brightnesses that
+ * is one element larger.
+ */
+ private static int mapLuxToBrightness(float lux,
+ int[] fromLux, int[] toBrightness) {
+ // TODO implement interpolation and possibly range expansion
+ int level = 0;
+ final int count = fromLux.length;
+ while (level < count && lux >= fromLux[level]) {
+ level += 1;
+ }
+ return toBrightness[level];
+ }
+
+ private void sendOnStateChanged() {
+ mCallbackHandler.post(mOnStateChangedRunnable);
+ }
+
+ private final Runnable mOnStateChangedRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mCallbacks.onStateChanged();
+ }
+ };
+
+ private void sendOnProximityNegative() {
+ mCallbackHandler.post(mOnProximityNegativeRunnable);
+ }
+
+ private final Runnable mOnProximityNegativeRunnable = new Runnable() {
+ @Override
+ public void run() {
+ mCallbacks.onProximityNegative();
+ }
+ };
+
+ public void dump(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(" mScreenBrightnessDimConfig=" + mScreenBrightnessDimConfig);
+ pw.println(" mUseSoftwareAutoBrightnessConfig="
+ + mUseSoftwareAutoBrightnessConfig);
+ pw.println(" mAutoBrightnessLevelsConfig="
+ + Arrays.toString(mAutoBrightnessLevelsConfig));
+ pw.println(" mAutoBrightnessLcdBacklightValuesConfig="
+ + Arrays.toString(mAutoBrightnessLcdBacklightValuesConfig));
+ pw.println(" mLightSensorWarmUpTimeConfig=" + mLightSensorWarmUpTimeConfig);
+
+ if (Looper.myLooper() == mHandler.getLooper()) {
+ dumpLocal(pw);
+ } else {
+ final StringWriter out = new StringWriter();
+ final CountDownLatch latch = new CountDownLatch(1);
+ Message msg = Message.obtain(mHandler, new Runnable() {
+ @Override
+ public void run() {
+ PrintWriter localpw = new PrintWriter(out);
+ try {
+ dumpLocal(localpw);
+ } finally {
+ localpw.flush();
+ latch.countDown();
+ }
+ }
+ });
+ msg.setAsynchronous(true);
+ mHandler.sendMessage(msg);
+ try {
+ latch.await();
+ pw.print(out.toString());
+ } catch (InterruptedException ex) {
+ pw.println();
+ pw.println("Failed to dump thread state due to interrupted exception!");
+ }
+ }
+ }
+
+ 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(" mLightSensor=" + mLightSensor);
+ pw.println(" mLightSensorEnabled=" + mLightSensorEnabled);
+ pw.println(" mLightSensorEnableTime="
+ + TimeUtils.formatUptime(mLightSensorEnableTime));
+ pw.println(" mLightMeasurement=" + mLightMeasurement);
+ pw.println(" mLightMeasurementValid=" + mLightMeasurementValid);
+ pw.println(" mLastLightSample=" + mLastLightSample);
+ pw.println(" mLastLightSampleTime="
+ + TimeUtils.formatUptime(mLastLightSampleTime));
+ pw.println(" mRecentLightSamples=" + mRecentLightSamples);
+ pw.println(" mRecentLightAverage=" + mRecentLightAverage);
+ pw.println(" mRecentLightBrightening=" + mRecentLightBrightening);
+ pw.println(" mRecentLightTimeConstant=" + mRecentLightTimeConstant);
+ pw.println(" mPendingLightSensorDebounceTime="
+ + TimeUtils.formatUptime(mPendingLightSensorDebounceTime));
+ pw.println(" mScreenAutoBrightness=" + mScreenAutoBrightness);
+ 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);
+ }
+ }
+
+ 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 boolean wantScreenOn(int state) {
+ switch (state) {
+ case DisplayPowerRequest.SCREEN_STATE_BRIGHT:
+ case DisplayPowerRequest.SCREEN_STATE_DIM:
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Asynchronous callbacks from the power controller to the power manager service.
+ */
+ public interface Callbacks {
+ void onStateChanged();
+ void onProximityNegative();
+ }
+
+ private final class DisplayControllerHandler extends Handler {
+ public DisplayControllerHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_UPDATE_POWER_STATE:
+ updatePowerState();
+ break;
+
+ case MSG_PROXIMITY_SENSOR_DEBOUNCED:
+ debounceProximitySensor();
+ break;
+
+ case MSG_LIGHT_SENSOR_DEBOUNCED:
+ debounceLightSensor();
+ 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.
+ }
+ };
+
+ 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.
+ }
+ };
+}
diff --git a/services/java/com/android/server/power/DisplayPowerRequest.java b/services/java/com/android/server/power/DisplayPowerRequest.java
new file mode 100644
index 0000000..7e4607e
--- /dev/null
+++ b/services/java/com/android/server/power/DisplayPowerRequest.java
@@ -0,0 +1,96 @@
+/*
+ * 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_DIM = 1;
+ public static final int SCREEN_STATE_BRIGHT = 2;
+
+ // The requested minimum screen power state: off, 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;
+
+ // If true, enables automatic brightness control.
+ public boolean useAutoBrightness;
+
+ public DisplayPowerRequest() {
+ screenState = SCREEN_STATE_BRIGHT;
+ useProximitySensor = false;
+ screenBrightness = PowerManager.BRIGHTNESS_ON;
+ useAutoBrightness = false;
+ }
+
+ public DisplayPowerRequest(DisplayPowerRequest other) {
+ copyFrom(other);
+ }
+
+ public void copyFrom(DisplayPowerRequest other) {
+ screenState = other.screenState;
+ useProximitySensor = other.useProximitySensor;
+ screenBrightness = other.screenBrightness;
+ useAutoBrightness = other.useAutoBrightness;
+ }
+
+ @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
+ && useAutoBrightness == other.useAutoBrightness;
+ }
+
+ @Override
+ public int hashCode() {
+ return 0; // don't care
+ }
+
+ @Override
+ public String toString() {
+ return "screenState=" + screenState
+ + ", useProximitySensor=" + useProximitySensor
+ + ", screenBrightness=" + screenBrightness
+ + ", useAutoBrightness=" + useAutoBrightness;
+ }
+}
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 0000000..ad242c0
--- /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();
+ }
+ }
+ };
+}
diff --git a/services/java/com/android/server/power/ElectronBeam.java b/services/java/com/android/server/power/ElectronBeam.java
new file mode 100644
index 0000000..5472148
--- /dev/null
+++ b/services/java/com/android/server/power/ElectronBeam.java
@@ -0,0 +1,652 @@
+/*
+ * 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.graphics.Bitmap;
+import android.graphics.PixelFormat;
+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.GLUtils;
+import android.os.Looper;
+import android.os.Process;
+import android.util.FloatMath;
+import android.util.Slog;
+import android.view.Display;
+import android.view.DisplayInfo;
+import android.view.Surface;
+import android.view.SurfaceSession;
+import android.view.WindowManagerImpl;
+
+import java.io.PrintWriter;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
+import java.nio.FloatBuffer;
+
+/**
+ * Bzzzoooop! *crackle*
+ *
+ * Animates a screen transition from on to off or off to on by applying
+ * some GL transformations to a screenshot.
+ *
+ * This component must only be created or accessed by the {@link Looper} thread
+ * that belongs to the {@link DisplayPowerController}.
+ */
+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.3f;
+ private static final float VSTRETCH_DURATION = 1.0f - HSTRETCH_DURATION;
+
+ // Set to true when the animation context has been fully prepared.
+ private boolean mPrepared;
+ private boolean mWarmUp;
+
+ private final DisplayInfo mDisplayInfo = new DisplayInfo();
+ private int mDisplayLayerStack; // layer stack associated with primary display
+ private int mDisplayRotation;
+ private int mDisplayWidth; // real width, not rotated
+ private int mDisplayHeight; // real height, not rotated
+ private SurfaceSession mSurfaceSession;
+ private Surface mSurface;
+ private EGLDisplay mEglDisplay;
+ private EGLConfig mEglConfig;
+ private EGLContext mEglContext;
+ private EGLSurface mEglSurface;
+ private boolean mSurfaceVisible;
+
+ // Texture names. We only use one texture, which contains the screenshot.
+ private final int[] mTexNames = new int[1];
+ private boolean mTexNamesGenerated;
+
+ // 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);
+
+ public ElectronBeam() {
+ }
+
+ /**
+ * Warms up the electron beam in preparation for turning on or off.
+ * This method prepares a GL context, and captures a screen shot.
+ *
+ * @param warmUp True if the electron beam is about to be turned on, false if
+ * it is about to be turned off.
+ * @return True if the electron beam is ready, false if it is uncontrollable.
+ */
+ public boolean prepare(boolean warmUp) {
+ if (DEBUG) {
+ Slog.d(TAG, "prepare: warmUp=" + warmUp);
+ }
+
+ mWarmUp = warmUp;
+
+ // Get the display size and adjust it for rotation.
+ Display display = WindowManagerImpl.getDefault().getDefaultDisplay();
+ display.getDisplayInfo(mDisplayInfo);
+ mDisplayLayerStack = display.getDisplayId();
+ mDisplayRotation = mDisplayInfo.rotation;
+ if (mDisplayRotation == Surface.ROTATION_90
+ || mDisplayRotation == Surface.ROTATION_270) {
+ mDisplayWidth = mDisplayInfo.logicalHeight;
+ mDisplayHeight = mDisplayInfo.logicalWidth;
+ } else {
+ mDisplayWidth = mDisplayInfo.logicalWidth;
+ mDisplayHeight = mDisplayInfo.logicalHeight;
+ }
+
+ // Prepare the surface for drawing.
+ if (!createEglContext()
+ || !createEglSurface()
+ || !captureScreenshotTextureAndSetViewport()) {
+ dismiss();
+ return false;
+ }
+
+ mPrepared = true;
+ return true;
+ }
+
+ /**
+ * 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();
+ 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 (!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 showEglSurface();
+ }
+
+ /**
+ * 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);
+
+ // bind texture and set blending for drawing planes
+ GLES10.glBindTexture(GLES10.GL_TEXTURE_2D, mTexNames[0]);
+ GLES10.glTexEnvx(GLES10.GL_TEXTURE_ENV, GLES10.GL_TEXTURE_ENV_MODE,
+ mWarmUp ? GLES10.GL_MODULATE : GLES10.GL_REPLACE);
+ GLES10.glTexParameterx(GLES10.GL_TEXTURE_2D,
+ GLES10.GL_TEXTURE_MAG_FILTER, GLES10.GL_LINEAR);
+ GLES10.glTexParameterx(GLES10.GL_TEXTURE_2D,
+ GLES10.GL_TEXTURE_MIN_FILTER, GLES10.GL_LINEAR);
+ GLES10.glTexParameterx(GLES10.GL_TEXTURE_2D,
+ GLES10.GL_TEXTURE_WRAP_S, GLES10.GL_CLAMP_TO_EDGE);
+ GLES10.glTexParameterx(GLES10.GL_TEXTURE_2D,
+ GLES10.GL_TEXTURE_WRAP_T, GLES10.GL_CLAMP_TO_EDGE);
+ GLES10.glEnable(GLES10.GL_TEXTURE_2D);
+ 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(GLES10.GL_TEXTURE_2D);
+ GLES10.glDisableClientState(GLES10.GL_TEXTURE_COORD_ARRAY);
+ GLES10.glColorMask(true, true, true, true);
+
+ // draw the white highlight (we use the last vertices)
+ if (!mWarmUp) {
+ 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 expands outwards.
+ *
+ * @param stretch The stretch factor. 0.0 is no stretch / no fade,
+ * 1.0 is maximum stretch / 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, 1.0f - ag, 1.0f - ag, 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 = dw + (dw * 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() {
+ // TODO: Use a SurfaceTexture to avoid the extra texture upload.
+ Bitmap bitmap = Surface.screenshot(mDisplayWidth, mDisplayHeight,
+ 0, ELECTRON_BEAM_LAYER - 1);
+ if (bitmap == null) {
+ Slog.e(TAG, "Could not take a screenshot!");
+ return false;
+ }
+ try {
+ if (!attachEglContext()) {
+ return false;
+ }
+ try {
+ if (!mTexNamesGenerated) {
+ GLES10.glGenTextures(1, mTexNames, 0);
+ if (checkGlErrors("glGenTextures")) {
+ return false;
+ }
+ mTexNamesGenerated = true;
+ }
+
+ GLES10.glBindTexture(GLES10.GL_TEXTURE_2D, mTexNames[0]);
+ if (checkGlErrors("glBindTexture")) {
+ return false;
+ }
+
+ float u = 1.0f;
+ float v = 1.0f;
+ GLUtils.texImage2D(GLES10.GL_TEXTURE_2D, 0, bitmap, 0);
+ if (checkGlErrors("glTexImage2D, first try", false)) {
+ // Try a power of two size texture instead.
+ int tw = nextPowerOfTwo(mDisplayWidth);
+ int th = nextPowerOfTwo(mDisplayHeight);
+ int format = GLUtils.getInternalFormat(bitmap);
+ GLES10.glTexImage2D(GLES10.GL_TEXTURE_2D, 0,
+ format, tw, th, 0,
+ format, GLES10.GL_UNSIGNED_BYTE, null);
+ if (checkGlErrors("glTexImage2D, second try")) {
+ return false;
+ }
+
+ GLUtils.texSubImage2D(GLES10.GL_TEXTURE_2D, 0, 0, 0, bitmap);
+ if (checkGlErrors("glTexSubImage2D")) {
+ return false;
+ }
+
+ u = (float)mDisplayWidth / tw;
+ v = (float)mDisplayHeight / th;
+ }
+
+ // 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, v);
+ mTexCoordBuffer.put(2, 0f);
+ mTexCoordBuffer.put(3, 0f);
+ mTexCoordBuffer.put(4, u);
+ mTexCoordBuffer.put(5, 0f);
+ mTexCoordBuffer.put(6, u);
+ mTexCoordBuffer.put(7, v);
+
+ // 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();
+ } finally {
+ detachEglContext();
+ }
+ } finally {
+ bitmap.recycle();
+ }
+ 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 createEglSurface() {
+ if (mSurfaceSession == null) {
+ mSurfaceSession = new SurfaceSession();
+ }
+
+ Surface.openTransaction();
+ try {
+ if (mSurface == null) {
+ try {
+ mSurface = new Surface(mSurfaceSession, Process.myPid(),
+ "ElectronBeam", mDisplayLayerStack, mDisplayWidth, mDisplayHeight,
+ PixelFormat.OPAQUE, Surface.OPAQUE | Surface.HIDDEN);
+ } catch (Surface.OutOfResourcesException ex) {
+ Slog.e(TAG, "Unable to create surface.", ex);
+ return false;
+ }
+ }
+
+ mSurface.setSize(mDisplayWidth, mDisplayHeight);
+
+ switch (mDisplayRotation) {
+ case Surface.ROTATION_0:
+ mSurface.setPosition(0, 0);
+ mSurface.setMatrix(1, 0, 0, 1);
+ break;
+ case Surface.ROTATION_90:
+ mSurface.setPosition(0, mDisplayWidth);
+ mSurface.setMatrix(0, -1, 1, 0);
+ break;
+ case Surface.ROTATION_180:
+ mSurface.setPosition(mDisplayWidth, mDisplayHeight);
+ mSurface.setMatrix(-1, 0, 0, -1);
+ break;
+ case Surface.ROTATION_270:
+ mSurface.setPosition(mDisplayHeight, 0);
+ mSurface.setMatrix(0, 1, -1, 0);
+ break;
+ }
+ } finally {
+ Surface.closeTransaction();
+ }
+
+ if (mEglSurface == null) {
+ int[] eglSurfaceAttribList = new int[] {
+ EGL14.EGL_NONE
+ };
+ 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;
+ }
+
+ if (mSurface != null) {
+ Surface.openTransaction();
+ try {
+ mSurface.destroy();
+ } finally {
+ Surface.closeTransaction();
+ }
+ mSurface = null;
+ mSurfaceVisible = false;
+ }
+ }
+
+ private boolean showEglSurface() {
+ if (!mSurfaceVisible) {
+ Surface.openTransaction();
+ try {
+ mSurface.setLayer(ELECTRON_BEAM_LAYER);
+ mSurface.show();
+ } finally {
+ Surface.closeTransaction();
+ }
+ mSurfaceVisible = true;
+ }
+ 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 int nextPowerOfTwo(int value) {
+ return 1 << (32 - Integer.numberOfLeadingZeros(value));
+ }
+
+ 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(" mWarmUp=" + mWarmUp);
+ pw.println(" mDisplayLayerStack=" + mDisplayLayerStack);
+ pw.println(" mDisplayRotation=" + mDisplayRotation);
+ pw.println(" mDisplayWidth=" + mDisplayWidth);
+ pw.println(" mDisplayHeight=" + mDisplayHeight);
+ pw.println(" mSurfaceVisible=" + mSurfaceVisible);
+ }
+}
diff --git a/services/java/com/android/server/power/Notifier.java b/services/java/com/android/server/power/Notifier.java
new file mode 100644
index 0000000..37384d2
--- /dev/null
+++ b/services/java/com/android/server/power/Notifier.java
@@ -0,0 +1,458 @@
+/*
+ * 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.internal.app.IBatteryStats;
+import com.android.server.EventLogTags;
+
+import android.app.ActivityManagerNative;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.BatteryStats;
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.PowerManager;
+import android.os.Process;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.os.WorkSource;
+import android.util.EventLog;
+import android.util.Slog;
+import android.view.WindowManagerPolicy;
+import android.view.WindowManagerPolicy.ScreenOnListener;
+
+/**
+ * Sends broadcasts about important power state changes.
+ *
+ * This methods of this class may be called by the power manager service while
+ * its lock is being held. Internally it takes care of sending broadcasts to
+ * notify other components of the system or applications asynchronously.
+ *
+ * The notifier is designed to collapse unnecessary broadcasts when it is not
+ * possible for the system to have observed an intermediate state.
+ *
+ * For example, if the device wakes up, goes to sleep and wakes up again immediately
+ * before the go to sleep broadcast has been sent, then no broadcast will be
+ * sent about the system going to sleep and waking up.
+ */
+final class Notifier {
+ private static final String TAG = "PowerManagerNotifier";
+
+ private static final boolean DEBUG = false;
+
+ private static final int POWER_STATE_UNKNOWN = 0;
+ private static final int POWER_STATE_AWAKE = 1;
+ private static final int POWER_STATE_ASLEEP = 2;
+
+ private static final int MSG_USER_ACTIVITY = 1;
+ private static final int MSG_BROADCAST = 2;
+
+ private final Object mLock = new Object();
+
+ private final Context mContext;
+ private final IBatteryStats mBatteryStats;
+ private final SuspendBlocker mSuspendBlocker;
+ private final WindowManagerPolicy mPolicy;
+ private final ScreenOnListener mScreenOnListener;
+
+ private final NotifierHandler mHandler;
+ private final Intent mScreenOnIntent;
+ private final Intent mScreenOffIntent;
+
+ // The current power state.
+ private int mActualPowerState;
+ private int mLastGoToSleepReason;
+
+ // The currently broadcasted power state. This reflects what other parts of the
+ // system have observed.
+ private int mBroadcastedPowerState;
+ private boolean mBroadcastInProgress;
+ private long mBroadcastStartTime;
+
+ // True if a user activity message should be sent.
+ private boolean mUserActivityPending;
+
+ public Notifier(Looper looper, Context context, IBatteryStats batteryStats,
+ SuspendBlocker suspendBlocker, WindowManagerPolicy policy,
+ ScreenOnListener screenOnListener) {
+ mContext = context;
+ mBatteryStats = batteryStats;
+ mSuspendBlocker = suspendBlocker;
+ mPolicy = policy;
+ mScreenOnListener = screenOnListener;
+
+ mHandler = new NotifierHandler(looper);
+ mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
+ mScreenOnIntent.addFlags(
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
+ mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
+ mScreenOffIntent.addFlags(
+ Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
+ }
+
+ /**
+ * Called when a wake lock is acquired.
+ */
+ public void onWakeLockAcquired(int flags, String tag, int ownerUid, int ownerPid,
+ WorkSource workSource) {
+ if (DEBUG) {
+ Slog.d(TAG, "onWakeLockAcquired: flags=" + flags + ", tag=\"" + tag
+ + "\", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid
+ + ", workSource=" + workSource);
+ }
+
+ if (!isWakeLockAlreadyReportedToBatteryStats(tag, ownerUid)) {
+ try {
+ final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
+ if (workSource != null) {
+ mBatteryStats.noteStartWakelockFromSource(
+ workSource, ownerPid, tag, monitorType);
+ } else {
+ mBatteryStats.noteStartWakelock(
+ ownerUid, ownerPid, tag, monitorType);
+ }
+ } catch (RemoteException ex) {
+ // Ignore
+ }
+ }
+ }
+
+ /**
+ * Called when a wake lock is released.
+ */
+ public void onWakeLockReleased(int flags, String tag, int ownerUid, int ownerPid,
+ WorkSource workSource) {
+ if (DEBUG) {
+ Slog.d(TAG, "onWakeLockReleased: flags=" + flags + ", tag=\"" + tag
+ + "\", ownerUid=" + ownerUid + ", ownerPid=" + ownerPid
+ + ", workSource=" + workSource);
+ }
+
+ if (!isWakeLockAlreadyReportedToBatteryStats(tag, ownerUid)) {
+ try {
+ final int monitorType = getBatteryStatsWakeLockMonitorType(flags);
+ if (workSource != null) {
+ mBatteryStats.noteStopWakelockFromSource(
+ workSource, ownerPid, tag, monitorType);
+ } else {
+ mBatteryStats.noteStopWakelock(
+ ownerUid, ownerPid, tag, monitorType);
+ }
+ } catch (RemoteException ex) {
+ // Ignore
+ }
+ }
+ }
+
+ private static boolean isWakeLockAlreadyReportedToBatteryStats(String tag, int uid) {
+ // The window manager already takes care of reporting battery stats associated
+ // with the use of the KEEP_SCREEN_ON_FLAG.
+ // TODO: Use a WorkSource to handle this situation instead of hardcoding it here.
+ return uid == Process.SYSTEM_UID
+ && tag.equals(PowerManager.KEEP_SCREEN_ON_FLAG_TAG);
+ }
+
+ private static int getBatteryStatsWakeLockMonitorType(int flags) {
+ switch (flags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
+ case PowerManager.PARTIAL_WAKE_LOCK:
+ case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
+ return BatteryStats.WAKE_TYPE_PARTIAL;
+ default:
+ return BatteryStats.WAKE_TYPE_FULL;
+ }
+ }
+
+ /**
+ * 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.
+ */
+ public void onWakeUpStarted() {
+ if (DEBUG) {
+ Slog.d(TAG, "onWakeUpStarted");
+ }
+
+ synchronized (mLock) {
+ if (mActualPowerState != POWER_STATE_AWAKE) {
+ mActualPowerState = POWER_STATE_AWAKE;
+ updatePendingBroadcastLocked();
+ }
+ }
+ }
+
+ /**
+ * Called when the device has finished waking up from sleep
+ * and the display has been turned on.
+ */
+ public void onWakeUpFinished() {
+ if (DEBUG) {
+ Slog.d(TAG, "onWakeUpFinished");
+ }
+ }
+
+ /**
+ * Called when the device is going to sleep.
+ */
+ public void onGoToSleepStarted(int reason) {
+ if (DEBUG) {
+ Slog.d(TAG, "onGoToSleepStarted");
+ }
+
+ synchronized (mLock) {
+ mLastGoToSleepReason = reason;
+ }
+ }
+
+ /**
+ * Called when the device has finished going to sleep and the
+ * display has been turned off.
+ *
+ * This is a good time to make transitions that we don't want the user to see,
+ * such as bringing the key guard to focus. There's no guarantee for this,
+ * however because the user could turn the device on again at any time.
+ * Some things may need to be protected by other mechanisms that defer screen on.
+ */
+ public void onGoToSleepFinished() {
+ if (DEBUG) {
+ Slog.d(TAG, "onGoToSleepFinished");
+ }
+
+ synchronized (mLock) {
+ if (mActualPowerState != POWER_STATE_ASLEEP) {
+ mActualPowerState = POWER_STATE_ASLEEP;
+ if (mUserActivityPending) {
+ mUserActivityPending = false;
+ mHandler.removeMessages(MSG_USER_ACTIVITY);
+ }
+ updatePendingBroadcastLocked();
+ }
+ }
+ }
+
+ /**
+ * Called when there has been user activity.
+ */
+ public void onUserActivity(int event, int uid) {
+ if (DEBUG) {
+ Slog.d(TAG, "onUserActivity: event=" + event + ", uid=" + uid);
+ }
+
+ try {
+ mBatteryStats.noteUserActivity(uid, event);
+ } catch (RemoteException ex) {
+ // Ignore
+ }
+
+ synchronized (mLock) {
+ if (!mUserActivityPending) {
+ mUserActivityPending = true;
+ Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY);
+ msg.setAsynchronous(true);
+ mHandler.sendMessage(msg);
+ }
+ }
+ }
+
+ private void updatePendingBroadcastLocked() {
+ if (!mBroadcastInProgress
+ && mActualPowerState != POWER_STATE_UNKNOWN
+ && mActualPowerState != mBroadcastedPowerState) {
+ mBroadcastInProgress = true;
+ mSuspendBlocker.acquire();
+ Message msg = mHandler.obtainMessage(MSG_BROADCAST);
+ msg.setAsynchronous(true);
+ mHandler.sendMessage(msg);
+ }
+ }
+
+ private void sendUserActivity() {
+ synchronized (mLock) {
+ if (!mUserActivityPending) {
+ return;
+ }
+ mUserActivityPending = false;
+ }
+
+ mPolicy.userActivity();
+ }
+
+ private void sendNextBroadcast() {
+ final int powerState;
+ final int goToSleepReason;
+ synchronized (mLock) {
+ if (mActualPowerState == POWER_STATE_UNKNOWN
+ || mActualPowerState == mBroadcastedPowerState) {
+ mBroadcastInProgress = false;
+ mSuspendBlocker.release();
+ return;
+ }
+
+ powerState = mActualPowerState;
+ goToSleepReason = mLastGoToSleepReason;
+
+ mBroadcastedPowerState = powerState;
+ mBroadcastStartTime = SystemClock.uptimeMillis();
+ }
+
+ EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, 1);
+
+ if (powerState == POWER_STATE_AWAKE) {
+ sendWakeUpBroadcast();
+ } else {
+ sendGoToSleepBroadcast(goToSleepReason);
+ }
+ }
+
+ private void sendWakeUpBroadcast() {
+ if (DEBUG) {
+ Slog.d(TAG, "Sending wake up broadcast.");
+ }
+
+ EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, 0, 0, 0);
+
+ mPolicy.screenTurningOn(mScreenOnListener);
+ try {
+ ActivityManagerNative.getDefault().wakingUp();
+ } catch (RemoteException e) {
+ // ignore it
+ }
+
+ if (ActivityManagerNative.isSystemReady()) {
+ mContext.sendOrderedBroadcast(mScreenOnIntent, null,
+ mWakeUpBroadcastDone, mHandler, 0, null, null);
+ } else {
+ EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2, 1);
+ sendNextBroadcast();
+ }
+ }
+
+ private final BroadcastReceiver mWakeUpBroadcastDone = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 1,
+ SystemClock.uptimeMillis() - mBroadcastStartTime, 1);
+ sendNextBroadcast();
+ }
+ };
+
+ private void sendGoToSleepBroadcast(int reason) {
+ if (DEBUG) {
+ Slog.d(TAG, "Sending go to sleep broadcast.");
+ }
+
+ int why = WindowManagerPolicy.OFF_BECAUSE_OF_USER;
+ switch (reason) {
+ case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:
+ why = WindowManagerPolicy.OFF_BECAUSE_OF_ADMIN;
+ break;
+ case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:
+ why = WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT;
+ break;
+ }
+
+ EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, why, 0, 0);
+
+ mPolicy.screenTurnedOff(why);
+ try {
+ ActivityManagerNative.getDefault().goingToSleep();
+ } catch (RemoteException e) {
+ // ignore it.
+ }
+
+ if (ActivityManagerNative.isSystemReady()) {
+ mContext.sendOrderedBroadcast(mScreenOffIntent, null,
+ mGoToSleepBroadcastDone, mHandler, 0, null, null);
+ } else {
+ EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3, 1);
+ sendNextBroadcast();
+ }
+ }
+
+ private final BroadcastReceiver mGoToSleepBroadcastDone = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 0,
+ SystemClock.uptimeMillis() - mBroadcastStartTime, 1);
+ sendNextBroadcast();
+ }
+ };
+
+ private final class NotifierHandler extends Handler {
+ public NotifierHandler(Looper looper) {
+ super(looper);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_USER_ACTIVITY:
+ sendUserActivity();
+ break;
+
+ case MSG_BROADCAST:
+ sendNextBroadcast();
+ break;
+ }
+ }
+ }
+}
diff --git a/services/java/com/android/server/power/PhotonicModulator.java b/services/java/com/android/server/power/PhotonicModulator.java
new file mode 100644
index 0000000..f7c9c7d
--- /dev/null
+++ b/services/java/com/android/server/power/PhotonicModulator.java
@@ -0,0 +1,87 @@
+/*
+ * 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.LightsService;
+
+import java.util.concurrent.Executor;
+
+/**
+ * Sets the value of a light asynchronously.
+ *
+ * This is done to avoid blocking the looper on devices for which
+ * setting the backlight brightness is especially slow.
+ */
+final class PhotonicModulator {
+ private static final int UNKNOWN_LIGHT_VALUE = -1;
+
+ private final Object mLock = new Object();
+
+ private final LightsService.Light mLight;
+ private final Executor mExecutor;
+ private final SuspendBlocker mSuspendBlocker;
+
+ private boolean mPendingChange;
+ private int mPendingLightValue;
+ private int mActualLightValue;
+
+ public PhotonicModulator(Executor executor, LightsService.Light light,
+ SuspendBlocker suspendBlocker) {
+ mExecutor = executor;
+ mLight = light;
+ mSuspendBlocker = suspendBlocker;
+ mPendingLightValue = UNKNOWN_LIGHT_VALUE;
+ mActualLightValue = UNKNOWN_LIGHT_VALUE;
+ }
+
+ /**
+ * Asynchronously sets the backlight brightness.
+ *
+ * @param lightValue The new light value, from 0 to 255.
+ */
+ public void setBrightness(int lightValue) {
+ synchronized (mLock) {
+ if (lightValue != mPendingLightValue) {
+ mPendingLightValue = lightValue;
+ if (!mPendingChange) {
+ mPendingChange = true;
+ mSuspendBlocker.acquire();
+ mExecutor.execute(mTask);
+ }
+ }
+ }
+ }
+
+ private final Runnable mTask = new Runnable() {
+ @Override
+ public void run() {
+ for (;;) {
+ final int newLightValue;
+ synchronized (mLock) {
+ newLightValue = mPendingLightValue;
+ if (newLightValue == mActualLightValue) {
+ mSuspendBlocker.release();
+ mPendingChange = false;
+ return;
+ }
+ mActualLightValue = newLightValue;
+ }
+ mLight.setBrightness(newLightValue);
+ }
+ }
+ };
+}
diff --git a/services/java/com/android/server/power/PowerManagerService.java b/services/java/com/android/server/power/PowerManagerService.java
index 2630239..2d91e6c 100644
--- a/services/java/com/android/server/power/PowerManagerService.java
+++ b/services/java/com/android/server/power/PowerManagerService.java
@@ -21,2767 +21,1432 @@ import com.android.server.BatteryService;
import com.android.server.EventLogTags;
import com.android.server.LightsService;
import com.android.server.Watchdog;
-import com.android.server.am.BatteryStatsService;
+import com.android.server.am.ActivityManagerService;
import com.android.server.display.DisplayManagerService;
-import android.app.ActivityManagerNative;
-import android.app.IActivityManager;
+import android.Manifest;
import android.content.BroadcastReceiver;
-import android.content.ContentQueryMap;
import android.content.ContentResolver;
-import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.database.ContentObserver;
-import android.database.Cursor;
-import android.hardware.Sensor;
-import android.hardware.SensorEvent;
-import android.hardware.SensorEventListener;
-import android.hardware.SensorManager;
-import android.hardware.SystemSensorManager;
+import android.net.Uri;
import android.os.BatteryManager;
-import android.os.BatteryStats;
import android.os.Binder;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.os.IPowerManager;
-import android.os.LocalPowerManager;
+import android.os.Looper;
import android.os.Message;
import android.os.PowerManager;
import android.os.Process;
import android.os.RemoteException;
+import android.os.ServiceManager;
import android.os.SystemClock;
-import android.os.SystemProperties;
import android.os.WorkSource;
import android.provider.Settings;
+import android.service.dreams.IDreamManager;
import android.util.EventLog;
import android.util.Log;
import android.util.Slog;
+import android.util.TimeUtils;
import android.view.WindowManagerPolicy;
-import static android.view.WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR;
-import static android.provider.Settings.System.DIM_SCREEN;
-import static android.provider.Settings.System.SCREEN_BRIGHTNESS;
-import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE;
-import static android.provider.Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC;
-import static android.provider.Settings.System.SCREEN_OFF_TIMEOUT;
-import static android.provider.Settings.System.STAY_ON_WHILE_PLUGGED_IN;
-import static android.provider.Settings.System.WINDOW_ANIMATION_SCALE;
-import static android.provider.Settings.System.TRANSITION_ANIMATION_SCALE;
import java.io.FileDescriptor;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Observable;
-import java.util.Observer;
-public class PowerManagerService extends IPowerManager.Stub
- implements LocalPowerManager, Watchdog.Monitor {
- private static final int NOMINAL_FRAME_TIME_MS = 1000/60;
+import libcore.util.Objects;
+/**
+ * The power manager service is responsible for coordinating power management
+ * functions on the device.
+ */
+public final class PowerManagerService extends IPowerManager.Stub
+ implements Watchdog.Monitor {
private static final String TAG = "PowerManagerService";
- static final String PARTIAL_NAME = "PowerManagerService";
- // could be either static or controllable at runtime
private static final boolean DEBUG = false;
- private static final boolean DEBUG_PROXIMITY_SENSOR = (false || DEBUG);
- private static final boolean DEBUG_LIGHT_SENSOR = (false || DEBUG);
- private static final boolean DEBUG_LIGHT_ANIMATION = (false || DEBUG);
- private static final boolean DEBUG_SCREEN_ON = false;
-
- // Wake lock that ensures that the CPU is running. The screen might not be on.
- private static final int PARTIAL_WAKE_LOCK_ID = 1;
-
- // Wake lock that ensures that the screen is on.
- private static final int FULL_WAKE_LOCK_ID = 2;
-
- private static final boolean LOG_PARTIAL_WL = false;
+ private static final boolean DEBUG_SPEW = DEBUG && true;
+
+ // Message: Sent when a user activity timeout occurs to update the power state.
+ private static final int MSG_USER_ACTIVITY_TIMEOUT = 1;
+ // Message: Sent when the device enters or exits a napping or dreaming state.
+ private static final int MSG_SANDMAN = 2;
+
+ // Dirty bit: mWakeLocks changed
+ private static final int DIRTY_WAKE_LOCKS = 1 << 0;
+ // Dirty bit: mWakefulness changed
+ private static final int DIRTY_WAKEFULNESS = 1 << 1;
+ // Dirty bit: user activity was poked or may have timed out
+ private static final int DIRTY_USER_ACTIVITY = 1 << 2;
+ // Dirty bit: actual display power state was updated asynchronously
+ private static final int DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED = 1 << 3;
+ // Dirty bit: mBootCompleted changed
+ private static final int DIRTY_BOOT_COMPLETED = 1 << 4;
+ // Dirty bit: settings changed
+ private static final int DIRTY_SETTINGS = 1 << 5;
+ // Dirty bit: mIsPowered changed
+ private static final int DIRTY_IS_POWERED = 1 << 6;
+ // Dirty bit: mStayOn changed
+ private static final int DIRTY_STAY_ON = 1 << 7;
+ // Dirty bit: battery state changed
+ private static final int DIRTY_BATTERY_STATE = 1 << 8;
+
+ // Wakefulness: The device is asleep and can only be awoken by a call to wakeUp().
+ // The screen should be off or in the process of being turned off by the display controller.
+ private static final int WAKEFULNESS_ASLEEP = 0;
+ // Wakefulness: The device is fully awake. It can be put to sleep by a call to goToSleep().
+ // When the user activity timeout expires, the device may start napping.
+ private static final int WAKEFULNESS_AWAKE = 1;
+ // Wakefulness: The device is napping. It is deciding whether to dream or go to sleep
+ // but hasn't gotten around to it yet. It can be awoken by a call to wakeUp(), which
+ // ends the nap. User activity may brighten the screen but does not end the nap.
+ private static final int WAKEFULNESS_NAPPING = 2;
+ // Wakefulness: The device is dreaming. It can be awoken by a call to wakeUp(),
+ // which ends the dream. The device goes to sleep when goToSleep() is called, when
+ // the dream ends or when unplugged.
+ // User activity may brighten the screen but does not end the dream.
+ private static final int WAKEFULNESS_DREAMING = 3;
+
+ // Summarizes the state of all active wakelocks.
+ private static final int WAKE_LOCK_CPU = 1 << 0;
+ private static final int WAKE_LOCK_SCREEN_BRIGHT = 1 << 1;
+ private static final int WAKE_LOCK_SCREEN_DIM = 1 << 2;
+ private static final int WAKE_LOCK_BUTTON_BRIGHT = 1 << 3;
+ private static final int WAKE_LOCK_PROXIMITY_SCREEN_OFF = 1 << 4;
+
+ // Summarizes the user activity state.
+ private static final int USER_ACTIVITY_SCREEN_BRIGHT = 1 << 0;
+ private static final int USER_ACTIVITY_SCREEN_DIM = 1 << 1;
+
+ // Default and minimum screen off timeout in milliseconds.
+ private static final int DEFAULT_SCREEN_OFF_TIMEOUT = 15 * 1000;
+ private static final int MINIMUM_SCREEN_OFF_TIMEOUT = 10 * 1000;
+
+ // The screen dim duration, in seconds.
+ // This is subtracted from the end of the screen off timeout so the
+ // minimum screen off timeout should be longer than this.
+ private static final int SCREEN_DIM_DURATION = 7 * 1000;
- private static final int LOCK_MASK = PowerManager.PARTIAL_WAKE_LOCK
- | PowerManager.SCREEN_DIM_WAKE_LOCK
- | PowerManager.SCREEN_BRIGHT_WAKE_LOCK
- | PowerManager.FULL_WAKE_LOCK
- | PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK;
-
- // time since last state: time since last event:
- // The short keylight delay comes from secure settings; this is the default.
- private static final int SHORT_KEYLIGHT_DELAY_DEFAULT = 6000; // t+6 sec
- private static final int MEDIUM_KEYLIGHT_DELAY = 15000; // t+15 sec
- private static final int LONG_KEYLIGHT_DELAY = 6000; // t+6 sec
- private static final int LONG_DIM_TIME = 7000; // t+N-5 sec
-
- // How long to wait to debounce light sensor changes in milliseconds
- private static final int LIGHT_SENSOR_DELAY = 2000;
-
- // light sensor events rate in microseconds
- private static final int LIGHT_SENSOR_RATE = 1000000;
-
- // Expansion of range of light values when applying scale from light
- // sensor brightness setting, in the [0..255] brightness range.
- private static final int LIGHT_SENSOR_RANGE_EXPANSION = 20;
-
- // Scaling factor of the light sensor brightness setting when applying
- // it to the final brightness.
- private static final int LIGHT_SENSOR_OFFSET_SCALE = 8;
-
- // For debouncing the proximity sensor in milliseconds
- private static final int PROXIMITY_SENSOR_DELAY = 1000;
-
- // trigger proximity if distance is less than 5 cm
- private static final float PROXIMITY_THRESHOLD = 5.0f;
-
- // Cached secure settings; see updateSettingsValues()
- private int mShortKeylightDelay = SHORT_KEYLIGHT_DELAY_DEFAULT;
-
- // Default timeout for screen off, if not found in settings database = 15 seconds.
- private static final int DEFAULT_SCREEN_OFF_TIMEOUT = 15000;
-
- // Screen brightness should always have a value, but just in case...
- private static final int DEFAULT_SCREEN_BRIGHTNESS = 192;
-
- // Threshold for BRIGHTNESS_LOW_BATTERY (percentage)
- // Screen will stay dim if battery level is <= LOW_BATTERY_THRESHOLD
- private static final int LOW_BATTERY_THRESHOLD = 10;
-
- // flags for setPowerState
- private static final int ALL_LIGHTS_OFF = 0x00000000;
- private static final int SCREEN_ON_BIT = 0x00000001;
- private static final int SCREEN_BRIGHT_BIT = 0x00000002;
- private static final int BUTTON_BRIGHT_BIT = 0x00000004;
- private static final int KEYBOARD_BRIGHT_BIT = 0x00000008;
- private static final int BATTERY_LOW_BIT = 0x00000010;
-
- // values for setPowerState
-
- // SCREEN_OFF == everything off
- private static final int SCREEN_OFF = 0x00000000;
-
- // SCREEN_DIM == screen on, screen backlight dim
- private static final int SCREEN_DIM = SCREEN_ON_BIT;
-
- // SCREEN_BRIGHT == screen on, screen backlight bright
- private static final int SCREEN_BRIGHT = SCREEN_ON_BIT | SCREEN_BRIGHT_BIT;
-
- // SCREEN_BUTTON_BRIGHT == screen on, screen and button backlights bright
- private static final int SCREEN_BUTTON_BRIGHT = SCREEN_BRIGHT | BUTTON_BRIGHT_BIT;
-
- // SCREEN_BUTTON_BRIGHT == screen on, screen, button and keyboard backlights bright
- private static final int ALL_BRIGHT = SCREEN_BUTTON_BRIGHT | KEYBOARD_BRIGHT_BIT;
-
- // used for noChangeLights in setPowerState()
- private static final int LIGHTS_MASK = SCREEN_BRIGHT_BIT | BUTTON_BRIGHT_BIT | KEYBOARD_BRIGHT_BIT;
-
- // animate screen lights in PowerManager (as opposed to SurfaceFlinger)
- boolean mAnimateScreenLights = true;
-
- static final int ANIM_STEPS = 60; // nominal # of frames at 60Hz
- // Slower animation for autobrightness changes
- static final int AUTOBRIGHTNESS_ANIM_STEPS = 2 * ANIM_STEPS;
- // Even slower animation for autodimness changes. Set to max to effectively disable dimming.
- // Note 100 is used to keep the mWindowScaleAnimation scaling below from overflowing an int.
- static final int AUTODIMNESS_ANIM_STEPS = Integer.MAX_VALUE / (NOMINAL_FRAME_TIME_MS * 100);
- // Number of steps when performing a more immediate brightness change.
- static final int IMMEDIATE_ANIM_STEPS = 4;
-
- // These magic numbers are the initial state of the LEDs at boot. Ideally
- // we should read them from the driver, but our current hardware returns 0
- // for the initial value. Oops!
- static final int INITIAL_SCREEN_BRIGHTNESS = 255;
- static final int INITIAL_BUTTON_BRIGHTNESS = PowerManager.BRIGHTNESS_OFF;
- static final int INITIAL_KEYBOARD_BRIGHTNESS = PowerManager.BRIGHTNESS_OFF;
-
- private final int MY_UID;
- private final int MY_PID;
-
- private boolean mDoneBooting = false;
- private boolean mBootCompleted = false;
- private boolean mHeadless = false;
- private int mStayOnConditions = 0;
- private final int[] mBroadcastQueue = new int[] { -1, -1, -1 };
- private final int[] mBroadcastWhy = new int[3];
- private boolean mPreparingForScreenOn = false;
- private boolean mSkippedScreenOn = false;
- private boolean mInitialized = false;
- private int mPartialCount = 0;
- private int mPowerState;
- // mScreenOffReason can be WindowManagerPolicy.OFF_BECAUSE_OF_USER,
- // WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT or WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR
- private int mScreenOffReason;
- private int mUserState;
- private boolean mKeyboardVisible = false;
- private boolean mUserActivityAllowed = true;
- private int mProximityWakeLockCount = 0;
- private boolean mProximitySensorEnabled = false;
- private boolean mProximitySensorActive = false;
- private int mProximityPendingValue = -1; // -1 == nothing, 0 == inactive, 1 == active
- private long mLastProximityEventTime;
- private int mScreenOffTimeoutSetting;
- private int mMaximumScreenOffTimeout = Integer.MAX_VALUE;
- private int mKeylightDelay;
- private int mDimDelay;
- private int mScreenOffDelay;
- private int mWakeLockState;
- private long mLastEventTime = 0;
- private long mScreenOffTime;
- private volatile WindowManagerPolicy mPolicy;
- private final LockList mLocks = new LockList();
- private Intent mScreenOffIntent;
- private Intent mScreenOnIntent;
- private LightsService mLightsService;
private Context mContext;
- private LightsService.Light mLcdLight;
- private LightsService.Light mButtonLight;
- private LightsService.Light mKeyboardLight;
- private LightsService.Light mAttentionLight;
- private UnsynchronizedWakeLock mBroadcastWakeLock;
- private UnsynchronizedWakeLock mStayOnWhilePluggedInScreenDimLock;
- private UnsynchronizedWakeLock mStayOnWhilePluggedInPartialLock;
- private UnsynchronizedWakeLock mPreventScreenOnPartialLock;
- private UnsynchronizedWakeLock mProximityPartialLock;
- private HandlerThread mHandlerThread;
- private Handler mScreenOffHandler;
- private Handler mScreenBrightnessHandler;
- private Handler mHandler;
- private final TimeoutTask mTimeoutTask = new TimeoutTask();
- private ScreenBrightnessAnimator mScreenBrightnessAnimator;
- private boolean mWaitingForFirstLightSensor = false;
- private boolean mStillNeedSleepNotification;
- private boolean mIsPowered = false;
- private IActivityManager mActivityService;
- private IBatteryStats mBatteryStats;
+ private LightsService mLightsService;
private BatteryService mBatteryService;
- private DisplayManagerService mDisplayManagerService;
- private SensorManager mSensorManager;
- private Sensor mProximitySensor;
- private Sensor mLightSensor;
- private boolean mLightSensorEnabled;
- private float mLightSensorValue = -1;
- private boolean mProxIgnoredBecauseScreenTurnedOff = false;
- private int mHighestLightSensorValue = -1;
- private boolean mLightSensorPendingDecrease = false;
- private boolean mLightSensorPendingIncrease = false;
- private float mLightSensorPendingValue = -1;
- private float mLightSensorAdjustSetting = 0;
- private int mLightSensorScreenBrightness = -1;
- private int mLightSensorButtonBrightness = -1;
- private int mLightSensorKeyboardBrightness = -1;
- private boolean mDimScreen = true;
- private boolean mIsDocked = false;
- private long mNextTimeout;
- private volatile int mPokey = 0;
- private volatile boolean mPokeAwakeOnSet = false;
- private volatile boolean mInitComplete = false;
- private final HashMap<IBinder,PokeLock> mPokeLocks = new HashMap<IBinder,PokeLock>();
- // mLastScreenOnTime is the time the screen was last turned on
- private long mLastScreenOnTime;
- private boolean mPreventScreenOn;
- private int mScreenBrightnessSetting = DEFAULT_SCREEN_BRIGHTNESS;
- private int mScreenBrightnessOverride = -1;
- private int mButtonBrightnessOverride = -1;
- private int mScreenBrightnessDim;
- private boolean mUseSoftwareAutoBrightness;
- private boolean mAutoBrightessEnabled;
- private int[] mAutoBrightnessLevels;
- private int[] mLcdBacklightValues;
- private int[] mButtonBacklightValues;
- private int[] mKeyboardBacklightValues;
- private int mLightSensorWarmupTime;
- boolean mUnplugTurnsOnScreen;
- private int mWarningSpewThrottleCount;
- private long mWarningSpewThrottleTime;
- private int mAnimationSetting = ANIM_SETTING_OFF;
- private float mWindowScaleAnimation;
-
- // Must match with the ISurfaceComposer constants in C++.
- private static final int ANIM_SETTING_ON = 0x01;
- private static final int ANIM_SETTING_OFF = 0x10;
+ private IBatteryStats mBatteryStats;
+ private HandlerThread mHandlerThread;
+ private PowerManagerHandler mHandler;
+ private WindowManagerPolicy mPolicy;
+ private Notifier mNotifier;
+ private DisplayPowerController mDisplayPowerController;
+ private SettingsObserver mSettingsObserver;
+ private IDreamManager mDreamManager;
+ private LightsService.Light mAttentionLight;
- private native void nativeInit();
- private native void nativeSetPowerState(boolean screenOn, boolean screenBright);
- private native void nativeStartSurfaceFlingerAnimation(int mode);
- private static native void nativeAcquireWakeLock(int lock, String id);
- private static native void nativeReleaseWakeLock(String id);
- private static native int nativeSetScreenState(boolean on);
- private static native void nativeShutdown();
- private static native void nativeReboot(String reason) throws IOException;
+ private final Object mLock = new Object();
- /*
- static PrintStream mLog;
- static {
- try {
- mLog = new PrintStream("/data/power.log");
- }
- catch (FileNotFoundException e) {
- android.util.Slog.e(TAG, "Life is hard", e);
- }
- }
- static class Log {
- static void d(String tag, String s) {
- mLog.println(s);
- android.util.Slog.d(tag, s);
- }
- static void i(String tag, String s) {
- mLog.println(s);
- android.util.Slog.i(tag, s);
- }
- static void w(String tag, String s) {
- mLog.println(s);
- android.util.Slog.w(tag, s);
- }
- static void e(String tag, String s) {
- mLog.println(s);
- android.util.Slog.e(tag, s);
- }
- }
- */
+ // A bitfield that indicates what parts of the power state have
+ // changed and need to be recalculated.
+ private int mDirty;
- /**
- * This class works around a deadlock between the lock in PowerManager.WakeLock
- * and our synchronizing on mLocks. PowerManager.WakeLock synchronizes on its
- * mToken object so it can be accessed from any thread, but it calls into here
- * with its lock held. This class is essentially a reimplementation of
- * PowerManager.WakeLock, but without that extra synchronized block, because we'll
- * only call it with our own locks held.
- */
- private class UnsynchronizedWakeLock {
- int mFlags;
- String mTag;
- IBinder mToken;
- int mCount = 0;
- boolean mRefCounted;
- boolean mHeld;
-
- UnsynchronizedWakeLock(int flags, String tag, boolean refCounted) {
- mFlags = flags;
- mTag = tag;
- mToken = new Binder();
- mRefCounted = refCounted;
- }
+ // Indicates whether the device is awake or asleep or somewhere in between.
+ // This is distinct from the screen power state, which is managed separately.
+ private int mWakefulness;
- public void acquire() {
- if (!mRefCounted || mCount++ == 0) {
- long ident = Binder.clearCallingIdentity();
- try {
- PowerManagerService.this.acquireWakeLockLocked(mFlags, mToken,
- MY_UID, MY_PID, mTag, null);
- mHeld = true;
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
- }
- }
+ // True if MSG_SANDMAN has been scheduled.
+ private boolean mSandmanScheduled;
- public void release() {
- if (!mRefCounted || --mCount == 0) {
- PowerManagerService.this.releaseWakeLockLocked(mToken, 0, false);
- mHeld = false;
- }
- if (mCount < 0) {
- throw new RuntimeException("WakeLock under-locked " + mTag);
- }
- }
+ // Table of all suspend blockers.
+ // There should only be a few of these.
+ private final ArrayList<SuspendBlocker> mSuspendBlockers = new ArrayList<SuspendBlocker>();
- public boolean isHeld()
- {
- return mHeld;
- }
+ // Table of all wake locks acquired by applications.
+ private final ArrayList<WakeLock> mWakeLocks = new ArrayList<WakeLock>();
- public String toString() {
- return "UnsynchronizedWakeLock(mFlags=0x" + Integer.toHexString(mFlags)
- + " mCount=" + mCount + " mHeld=" + mHeld + ")";
- }
- }
+ // A bitfield that summarizes the state of all active wakelocks.
+ private int mWakeLockSummary;
- private final class BatteryReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- synchronized (mLocks) {
- boolean wasPowered = mIsPowered;
- mIsPowered = mBatteryService.isPowered();
-
- if (mIsPowered != wasPowered) {
- // update mStayOnWhilePluggedIn wake lock
- updateWakeLockLocked();
-
- // treat plugging and unplugging the devices as a user activity.
- // users find it disconcerting when they unplug the device
- // and it shuts off right away.
- // to avoid turning on the screen when unplugging, we only trigger
- // user activity when screen was already on.
- // temporarily set mUserActivityAllowed to true so this will work
- // even when the keyguard is on.
- // However, you can also set config_unplugTurnsOnScreen to have it
- // turn on. Some devices want this because they don't have a
- // charging LED.
- synchronized (mLocks) {
- if (!wasPowered || (mPowerState & SCREEN_ON_BIT) != 0 ||
- mUnplugTurnsOnScreen) {
- forceUserActivityLocked();
- }
- }
+ // If true, instructs the display controller to wait for the proximity sensor to
+ // go negative before turning the screen on.
+ private boolean mRequestWaitForNegativeProximity;
- // stop the screensaver if we're now unplugged
- if (mPolicy != null && wasPowered) {
- mPolicy.stopScreenSaver();
- }
- }
- }
- }
- }
+ // Timestamp of the last time the device was awoken or put to sleep.
+ private long mLastWakeTime;
+ private long mLastSleepTime;
- private final class BootCompletedReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- bootCompleted();
- }
- }
+ // True if we need to send a wake up or go to sleep finished notification
+ // when the display is ready.
+ private boolean mSendWakeUpFinishedNotificationWhenReady;
+ private boolean mSendGoToSleepFinishedNotificationWhenReady;
- private final class DockReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- int state = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
- Intent.EXTRA_DOCK_STATE_UNDOCKED);
- dockStateChanged(state);
- }
- }
-
- /**
- * Set the setting that determines whether the device stays on when plugged in.
- * The argument is a bit string, with each bit specifying a power source that,
- * when the device is connected to that source, causes the device to stay on.
- * See {@link android.os.BatteryManager} for the list of power sources that
- * can be specified. Current values include {@link android.os.BatteryManager#BATTERY_PLUGGED_AC}
- * and {@link android.os.BatteryManager#BATTERY_PLUGGED_USB}
- * @param val an {@code int} containing the bits that specify which power sources
- * should cause the device to stay on.
- */
- public void setStayOnSetting(int val) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SETTINGS, null);
- Settings.System.putInt(mContext.getContentResolver(),
- Settings.System.STAY_ON_WHILE_PLUGGED_IN, val);
- }
+ // Timestamp of the last call to user activity.
+ private long mLastUserActivityTime;
+ private long mLastUserActivityTimeNoChangeLights;
- public void setMaximumScreenOffTimeount(int timeMs) {
- mContext.enforceCallingOrSelfPermission(
- android.Manifest.permission.WRITE_SECURE_SETTINGS, null);
- synchronized (mLocks) {
- mMaximumScreenOffTimeout = timeMs;
- // recalculate everything
- setScreenOffTimeoutsLocked();
- }
- }
+ // A bitfield that summarizes the effect of the user activity timer.
+ // A zero value indicates that the user activity timer has expired.
+ private int mUserActivitySummary;
- int getStayOnConditionsLocked() {
- return mMaximumScreenOffTimeout <= 0 || mMaximumScreenOffTimeout == Integer.MAX_VALUE
- ? mStayOnConditions : 0;
- }
+ // The desired display power state. The actual state may lag behind the
+ // requested because it is updated asynchronously by the display power controller.
+ private final DisplayPowerRequest mDisplayPowerRequest = new DisplayPowerRequest();
- private class SettingsObserver implements Observer {
- private int getInt(String name, int defValue) {
- ContentValues values = mSettings.getValues(name);
- Integer iVal = values != null ? values.getAsInteger(Settings.System.VALUE) : null;
- return iVal != null ? iVal : defValue;
- }
+ // The time the screen was last turned off, in elapsedRealtime() timebase.
+ private long mLastScreenOffEventElapsedRealTime;
- private float getFloat(String name, float defValue) {
- ContentValues values = mSettings.getValues(name);
- Float fVal = values != null ? values.getAsFloat(Settings.System.VALUE) : null;
- return fVal != null ? fVal : defValue;
- }
+ // True if the display power state has been fully applied, which means the display
+ // is actually on or actually off or whatever was requested.
+ private boolean mDisplayReady;
- public void update(Observable o, Object arg) {
- synchronized (mLocks) {
- // STAY_ON_WHILE_PLUGGED_IN, default to when plugged into AC
- mStayOnConditions = getInt(STAY_ON_WHILE_PLUGGED_IN,
- BatteryManager.BATTERY_PLUGGED_AC);
- updateWakeLockLocked();
+ // True if holding a wake-lock to block suspend of the CPU.
+ private boolean mHoldingWakeLockSuspendBlocker;
- // SCREEN_OFF_TIMEOUT, default to 15 seconds
- mScreenOffTimeoutSetting = getInt(SCREEN_OFF_TIMEOUT, DEFAULT_SCREEN_OFF_TIMEOUT);
+ // The suspend blocker used to keep the CPU alive when wake locks have been acquired.
+ private final SuspendBlocker mWakeLockSuspendBlocker;
- // DIM_SCREEN
- //mDimScreen = getInt(DIM_SCREEN) != 0;
+ // True if systemReady() has been called.
+ private boolean mSystemReady;
- mScreenBrightnessSetting = getInt(SCREEN_BRIGHTNESS, DEFAULT_SCREEN_BRIGHTNESS);
- mLightSensorAdjustSetting = 0; //getFloat(SCREEN_AUTO_BRIGHTNESS_ADJ, 0);
+ // True if boot completed occurred. We keep the screen on until this happens.
+ private boolean mBootCompleted;
- // SCREEN_BRIGHTNESS_MODE, default to manual
- setScreenBrightnessMode(getInt(SCREEN_BRIGHTNESS_MODE,
- Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL));
+ // True if the device is plugged into a power source.
+ private boolean mIsPowered;
- // recalculate everything
- setScreenOffTimeoutsLocked();
+ // True if the device should wake up when plugged or unplugged.
+ private boolean mWakeUpWhenPluggedOrUnpluggedConfig;
- mWindowScaleAnimation = getFloat(WINDOW_ANIMATION_SCALE, 1.0f);
- final float transitionScale = getFloat(TRANSITION_ANIMATION_SCALE, 1.0f);
- mAnimationSetting = 0;
- if (mWindowScaleAnimation > 0.5f) {
- mAnimationSetting |= ANIM_SETTING_OFF;
- }
- if (transitionScale > 0.5f) {
- // Uncomment this if you want the screen-on animation.
- // mAnimationSetting |= ANIM_SETTING_ON;
- }
- }
- }
- }
+ // True if dreams are supported on this device.
+ private boolean mDreamsSupportedConfig;
- public PowerManagerService() {
- // Hack to get our uid... should have a func for this.
- long token = Binder.clearCallingIdentity();
- MY_UID = Process.myUid();
- MY_PID = Process.myPid();
- Binder.restoreCallingIdentity(token);
+ // True if dreams are enabled by the user.
+ private boolean mDreamsEnabledSetting;
- // assume nothing is on yet
- mUserState = mPowerState = 0;
+ // The screen off timeout setting value in milliseconds.
+ private int mScreenOffTimeoutSetting;
- // Add ourself to the Watchdog monitors.
- Watchdog.getInstance().addMonitor(this);
+ // The maximum allowable screen off timeout according to the device
+ // administration policy. Overrides other settings.
+ private int mMaximumScreenOffTimeoutFromDeviceAdmin = Integer.MAX_VALUE;
- nativeInit();
- }
+ // The stay on while plugged in setting.
+ // A bitfield of battery conditions under which to make the screen stay on.
+ private int mStayOnWhilePluggedInSetting;
- private ContentQueryMap mSettings;
+ // True if the device should stay on.
+ private boolean mStayOn;
- public void init(Context context, LightsService lights, IActivityManager activity,
- BatteryService battery, DisplayManagerService displayManagerService) {
- mLightsService = lights;
- mContext = context;
- mActivityService = activity;
- mBatteryStats = BatteryStatsService.getService();
- mBatteryService = battery;
- mDisplayManagerService = displayManagerService;
-
- mLcdLight = lights.getLight(LightsService.LIGHT_ID_BACKLIGHT);
- mButtonLight = lights.getLight(LightsService.LIGHT_ID_BUTTONS);
- mKeyboardLight = lights.getLight(LightsService.LIGHT_ID_KEYBOARD);
- mAttentionLight = lights.getLight(LightsService.LIGHT_ID_ATTENTION);
- mHeadless = "1".equals(SystemProperties.get("ro.config.headless", "0"));
-
- mInitComplete = false;
- mScreenBrightnessAnimator = new ScreenBrightnessAnimator("mScreenBrightnessUpdaterThread",
- Process.THREAD_PRIORITY_DISPLAY);
- mScreenBrightnessAnimator.start();
-
- synchronized (mScreenBrightnessAnimator) {
- while (!mInitComplete) {
- try {
- mScreenBrightnessAnimator.wait();
- } catch (InterruptedException e) {
- // Ignore
- }
- }
- }
+ // Screen brightness setting limits.
+ private int mScreenBrightnessSettingMinimum;
+ private int mScreenBrightnessSettingMaximum;
+ private int mScreenBrightnessSettingDefault;
- mInitComplete = false;
- mHandlerThread = new HandlerThread("PowerManagerService") {
- @Override
- protected void onLooperPrepared() {
- super.onLooperPrepared();
- initInThread();
- }
- };
- mHandlerThread.start();
+ // The screen brightness setting, from 0 to 255.
+ // Use -1 if no value has been set.
+ private int mScreenBrightnessSetting;
- synchronized (mHandlerThread) {
- while (!mInitComplete) {
- try {
- mHandlerThread.wait();
- } catch (InterruptedException e) {
- // Ignore
- }
- }
- }
-
- synchronized (mLocks) {
- updateNativePowerStateLocked();
- // We make sure to start out with the screen on due to user activity.
- // (They did just boot their device, after all.)
- forceUserActivityLocked();
- mInitialized = true;
- }
- }
-
- void initInThread() {
- mHandler = new Handler();
+ // The screen brightness mode.
+ // One of the Settings.System.SCREEN_BRIGHTNESS_MODE_* constants.
+ private int mScreenBrightnessModeSetting;
- mBroadcastWakeLock = new UnsynchronizedWakeLock(
- PowerManager.PARTIAL_WAKE_LOCK, "sleep_broadcast", true);
- mStayOnWhilePluggedInScreenDimLock = new UnsynchronizedWakeLock(
- PowerManager.SCREEN_DIM_WAKE_LOCK, "StayOnWhilePluggedIn Screen Dim", false);
- mStayOnWhilePluggedInPartialLock = new UnsynchronizedWakeLock(
- PowerManager.PARTIAL_WAKE_LOCK, "StayOnWhilePluggedIn Partial", false);
- mPreventScreenOnPartialLock = new UnsynchronizedWakeLock(
- PowerManager.PARTIAL_WAKE_LOCK, "PreventScreenOn Partial", false);
- mProximityPartialLock = new UnsynchronizedWakeLock(
- PowerManager.PARTIAL_WAKE_LOCK, "Proximity Partial", false);
+ // The screen brightness setting override from the window manager
+ // to allow the current foreground activity to override the brightness.
+ // Use -1 to disable.
+ private int mScreenBrightnessOverrideFromWindowManager = -1;
- mScreenOnIntent = new Intent(Intent.ACTION_SCREEN_ON);
- mScreenOnIntent.addFlags(
- Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
- mScreenOffIntent = new Intent(Intent.ACTION_SCREEN_OFF);
- mScreenOffIntent.addFlags(
- Intent.FLAG_RECEIVER_REGISTERED_ONLY | Intent.FLAG_RECEIVER_FOREGROUND);
+ // The screen brightness setting override from the settings application
+ // to temporarily adjust the brightness until next updated,
+ // Use -1 to disable.
+ private int mTemporaryScreenBrightnessSettingOverride = -1;
- Resources resources = mContext.getResources();
+ private native void nativeInit();
+ private static native void nativeShutdown();
+ private static native void nativeReboot(String reason) throws IOException;
- mAnimateScreenLights = resources.getBoolean(
- com.android.internal.R.bool.config_animateScreenLights);
+ private static native void nativeSetPowerState(boolean screenOn, boolean screenBright);
+ private static native void nativeAcquireSuspendBlocker(String name);
+ private static native void nativeReleaseSuspendBlocker(String name);
- mUnplugTurnsOnScreen = resources.getBoolean(
- com.android.internal.R.bool.config_unplugTurnsOnScreen);
+ static native void nativeSetScreenState(boolean on);
- mScreenBrightnessDim = resources.getInteger(
- com.android.internal.R.integer.config_screenBrightnessDim);
-
- // read settings for auto-brightness
- mUseSoftwareAutoBrightness = resources.getBoolean(
- com.android.internal.R.bool.config_automatic_brightness_available);
- if (mUseSoftwareAutoBrightness) {
- mAutoBrightnessLevels = resources.getIntArray(
- com.android.internal.R.array.config_autoBrightnessLevels);
- mLcdBacklightValues = resources.getIntArray(
- com.android.internal.R.array.config_autoBrightnessLcdBacklightValues);
- mButtonBacklightValues = resources.getIntArray(
- com.android.internal.R.array.config_autoBrightnessButtonBacklightValues);
- mKeyboardBacklightValues = resources.getIntArray(
- com.android.internal.R.array.config_autoBrightnessKeyboardBacklightValues);
- mLightSensorWarmupTime = resources.getInteger(
- com.android.internal.R.integer.config_lightSensorWarmupTime);
- }
-
- ContentResolver resolver = mContext.getContentResolver();
- Cursor settingsCursor = resolver.query(Settings.System.CONTENT_URI, null,
- "(" + Settings.System.NAME + "=?) or ("
- + Settings.System.NAME + "=?) or ("
- + Settings.System.NAME + "=?) or ("
- + Settings.System.NAME + "=?) or ("
- + Settings.System.NAME + "=?) or ("
- + Settings.System.NAME + "=?) or ("
- + Settings.System.NAME + "=?) or ("
- + Settings.System.NAME + "=?)",
- new String[]{STAY_ON_WHILE_PLUGGED_IN, SCREEN_OFF_TIMEOUT, DIM_SCREEN, SCREEN_BRIGHTNESS,
- SCREEN_BRIGHTNESS_MODE, /*SCREEN_AUTO_BRIGHTNESS_ADJ,*/
- WINDOW_ANIMATION_SCALE, TRANSITION_ANIMATION_SCALE},
- null);
- mSettings = new ContentQueryMap(settingsCursor, Settings.System.NAME, true, mHandler);
- SettingsObserver settingsObserver = new SettingsObserver();
- mSettings.addObserver(settingsObserver);
-
- // pretend that the settings changed so we will get their initial state
- settingsObserver.update(mSettings, null);
-
- // register for the battery changed notifications
- IntentFilter filter = new IntentFilter();
- filter.addAction(Intent.ACTION_BATTERY_CHANGED);
- mContext.registerReceiver(new BatteryReceiver(), filter);
- filter = new IntentFilter();
- filter.addAction(Intent.ACTION_BOOT_COMPLETED);
- mContext.registerReceiver(new BootCompletedReceiver(), filter);
- filter = new IntentFilter();
- filter.addAction(Intent.ACTION_DOCK_EVENT);
- mContext.registerReceiver(new DockReceiver(), filter);
-
- // Listen for secure settings changes
- mContext.getContentResolver().registerContentObserver(
- Settings.Secure.CONTENT_URI, true,
- new ContentObserver(new Handler()) {
- public void onChange(boolean selfChange) {
- updateSettingsValues();
- }
- });
- updateSettingsValues();
-
- synchronized (mHandlerThread) {
- mInitComplete = true;
- mHandlerThread.notifyAll();
+ public PowerManagerService() {
+ synchronized (mLock) {
+ mWakeLockSuspendBlocker = createSuspendBlockerLocked("PowerManagerService");
+ mWakeLockSuspendBlocker.acquire();
+ mHoldingWakeLockSuspendBlocker = true;
+ mWakefulness = WAKEFULNESS_AWAKE;
}
- }
- /**
- * Low-level function turn the device off immediately, without trying
- * to be clean. Most people should use
- * {@link com.android.server.power.internal.app.ShutdownThread} for a clean shutdown.
- */
- public static void lowLevelShutdown() {
- nativeShutdown();
+ nativeInit();
}
/**
- * Low-level function to reboot the device.
- *
- * @param reason code to pass to the kernel (e.g. "recovery"), or null.
- * @throws IOException if reboot fails for some reason (eg, lack of
- * permission)
+ * Initialize the power manager.
+ * Must be called before any other functions within the power manager are called.
*/
- public static void lowLevelReboot(String reason) throws IOException {
- nativeReboot(reason);
+ public void init(Context context, LightsService ls,
+ ActivityManagerService am, BatteryService bs, IBatteryStats bss,
+ DisplayManagerService dm) {
+ mContext = context;
+ mLightsService = ls;
+ mBatteryService = bs;
+ mBatteryStats = bss;
+ mHandlerThread = new HandlerThread(TAG);
+ mHandlerThread.start();
+ mHandler = new PowerManagerHandler(mHandlerThread.getLooper());
+
+ Watchdog.getInstance().addMonitor(this);
}
- private class WakeLock implements IBinder.DeathRecipient
- {
- WakeLock(int f, IBinder b, String t, int u, int p) {
- super();
- flags = f;
- binder = b;
- tag = t;
- uid = u == MY_UID ? Process.SYSTEM_UID : u;
- pid = p;
- if (u != MY_UID || (
- !"KEEP_SCREEN_ON_FLAG".equals(tag)
- && !"KeyInputQueue".equals(tag))) {
- monitorType = (f & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK
- ? BatteryStats.WAKE_TYPE_PARTIAL
- : BatteryStats.WAKE_TYPE_FULL;
- } else {
- monitorType = -1;
- }
- try {
- b.linkToDeath(this, 0);
- } catch (RemoteException e) {
- binderDied();
- }
- }
- public void binderDied() {
- synchronized (mLocks) {
- releaseWakeLockLocked(this.binder, 0, true);
- }
- }
- final int flags;
- final IBinder binder;
- final String tag;
- final int uid;
- final int pid;
- final int monitorType;
- WorkSource ws;
- boolean activated = true;
- int minState;
- }
-
- private void updateWakeLockLocked() {
- final int stayOnConditions = getStayOnConditionsLocked();
- if (stayOnConditions != 0 && mBatteryService.isPowered(stayOnConditions)) {
- // keep the device on if we're plugged in and mStayOnWhilePluggedIn is set.
- mStayOnWhilePluggedInScreenDimLock.acquire();
- mStayOnWhilePluggedInPartialLock.acquire();
- } else {
- mStayOnWhilePluggedInScreenDimLock.release();
- mStayOnWhilePluggedInPartialLock.release();
+ public void setPolicy(WindowManagerPolicy policy) {
+ synchronized (mLock) {
+ mPolicy = policy;
}
}
- private boolean isScreenLock(int flags)
- {
- int n = flags & LOCK_MASK;
- return n == PowerManager.FULL_WAKE_LOCK
- || n == PowerManager.SCREEN_BRIGHT_WAKE_LOCK
- || n == PowerManager.SCREEN_DIM_WAKE_LOCK
- || n == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK;
+ public void systemReady() {
+ synchronized (mLock) {
+ mSystemReady = true;
+
+ PowerManager pm = (PowerManager)mContext.getSystemService(Context.POWER_SERVICE);
+ mScreenBrightnessSettingMinimum = pm.getMinimumScreenBrightnessSetting();
+ mScreenBrightnessSettingMaximum = pm.getMaximumScreenBrightnessSetting();
+ mScreenBrightnessSettingDefault = pm.getDefaultScreenBrightnessSetting();
+
+ mNotifier = new Notifier(mHandler.getLooper(), mContext, mBatteryStats,
+ createSuspendBlockerLocked("PowerManagerService.Broadcasts"),
+ mPolicy, mScreenOnListener);
+ mDisplayPowerController = new DisplayPowerController(mHandler.getLooper(),
+ mContext, mNotifier, mLightsService,
+ createSuspendBlockerLocked("PowerManagerService.Display"),
+ mDisplayPowerControllerCallbacks, mHandler);
+
+ mSettingsObserver = new SettingsObserver(mHandler);
+ mAttentionLight = mLightsService.getLight(LightsService.LIGHT_ID_ATTENTION);
+
+ // Register for broadcasts from other components of the system.
+ IntentFilter filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_BATTERY_CHANGED);
+ mContext.registerReceiver(new BatteryReceiver(), filter);
+
+ filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_BOOT_COMPLETED);
+ mContext.registerReceiver(new BootCompletedReceiver(), filter);
+
+ filter = new IntentFilter();
+ filter.addAction(Intent.ACTION_DOCK_EVENT);
+ mContext.registerReceiver(new DockReceiver(), filter);
+
+ // Register for settings changes.
+ final ContentResolver resolver = mContext.getContentResolver();
+ resolver.registerContentObserver(Settings.Secure.getUriFor(
+ Settings.Secure.SCREENSAVER_ENABLED), false, mSettingsObserver);
+ resolver.registerContentObserver(Settings.System.getUriFor(
+ Settings.System.SCREEN_OFF_TIMEOUT), false, mSettingsObserver);
+ resolver.registerContentObserver(Settings.System.getUriFor(
+ Settings.System.STAY_ON_WHILE_PLUGGED_IN), false, mSettingsObserver);
+ resolver.registerContentObserver(Settings.System.getUriFor(
+ Settings.System.SCREEN_BRIGHTNESS), false, mSettingsObserver);
+ resolver.registerContentObserver(Settings.System.getUriFor(
+ Settings.System.SCREEN_BRIGHTNESS_MODE), false, mSettingsObserver);
+
+ // Go.
+ readConfigurationLocked();
+ updateSettingsLocked();
+ mDirty |= DIRTY_BATTERY_STATE;
+ updatePowerStateLocked();
+ }
+ }
+
+ private void readConfigurationLocked() {
+ final Resources resources = mContext.getResources();
+
+ mWakeUpWhenPluggedOrUnpluggedConfig = resources.getBoolean(
+ com.android.internal.R.bool.config_unplugTurnsOnScreen);
+ mDreamsSupportedConfig = resources.getBoolean(
+ com.android.internal.R.bool.config_enableDreams);
}
- void enforceWakeSourcePermission(int uid, int pid) {
- if (uid == Process.myUid()) {
- return;
+ private void updateSettingsLocked() {
+ final ContentResolver resolver = mContext.getContentResolver();
+
+ mDreamsEnabledSetting = (Settings.Secure.getInt(resolver,
+ Settings.Secure.SCREENSAVER_ENABLED, 0) != 0);
+ mScreenOffTimeoutSetting = Settings.System.getInt(resolver,
+ Settings.System.SCREEN_OFF_TIMEOUT, DEFAULT_SCREEN_OFF_TIMEOUT);
+ mStayOnWhilePluggedInSetting = Settings.System.getInt(resolver,
+ Settings.System.STAY_ON_WHILE_PLUGGED_IN,
+ BatteryManager.BATTERY_PLUGGED_AC);
+
+ final int oldScreenBrightnessSetting = mScreenBrightnessSetting;
+ mScreenBrightnessSetting = Settings.System.getInt(resolver,
+ Settings.System.SCREEN_BRIGHTNESS, mScreenBrightnessSettingDefault);
+ if (oldScreenBrightnessSetting != mScreenBrightnessSetting) {
+ mTemporaryScreenBrightnessSettingOverride = -1;
}
- mContext.enforcePermission(android.Manifest.permission.UPDATE_DEVICE_STATS,
- pid, uid, null);
+
+ mScreenBrightnessModeSetting = Settings.System.getInt(resolver,
+ Settings.System.SCREEN_BRIGHTNESS_MODE,
+ Settings.System.SCREEN_BRIGHTNESS_MODE_MANUAL);
+
+ mDirty |= DIRTY_SETTINGS;
}
- public void acquireWakeLock(int flags, IBinder lock, String tag, WorkSource ws) {
- int uid = Binder.getCallingUid();
- int pid = Binder.getCallingPid();
- if (uid != Process.myUid()) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
+ private void handleSettingsChangedLocked() {
+ updateSettingsLocked();
+ updatePowerStateLocked();
+ }
+
+ @Override // Binder call
+ public void acquireWakeLock(IBinder lock, int flags, String tag, WorkSource ws) {
+ if (lock == null) {
+ throw new IllegalArgumentException("lock must not be null");
}
- if (ws != null) {
- enforceWakeSourcePermission(uid, pid);
+ PowerManager.validateWakeLockParameters(flags, tag);
+
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
+ if (ws != null && ws.size() != 0) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.UPDATE_DEVICE_STATS, null);
+ } else {
+ ws = null;
}
- long ident = Binder.clearCallingIdentity();
+
+ final int uid = Binder.getCallingUid();
+ final int pid = Binder.getCallingPid();
+ final long ident = Binder.clearCallingIdentity();
try {
- synchronized (mLocks) {
- acquireWakeLockLocked(flags, lock, uid, pid, tag, ws);
- }
+ acquireWakeLockInternal(lock, flags, tag, ws, uid, pid);
} finally {
Binder.restoreCallingIdentity(ident);
}
}
- void noteStartWakeLocked(WakeLock wl, WorkSource ws) {
- if (wl.monitorType >= 0) {
- long origId = Binder.clearCallingIdentity();
- try {
- if (ws != null) {
- mBatteryStats.noteStartWakelockFromSource(ws, wl.pid, wl.tag,
- wl.monitorType);
- } else {
- mBatteryStats.noteStartWakelock(wl.uid, wl.pid, wl.tag, wl.monitorType);
+ private void acquireWakeLockInternal(IBinder lock, int flags, String tag, WorkSource ws,
+ int uid, int pid) {
+ synchronized (mLock) {
+ if (DEBUG_SPEW) {
+ Slog.d(TAG, "acquireWakeLockInternal: lock=" + Objects.hashCode(lock)
+ + ", flags=0x" + Integer.toHexString(flags)
+ + ", tag=\"" + tag + "\", ws=" + ws + ", uid=" + uid + ", pid=" + pid);
+ }
+
+ WakeLock wakeLock;
+ int index = findWakeLockIndexLocked(lock);
+ if (index >= 0) {
+ wakeLock = mWakeLocks.get(index);
+ if (!wakeLock.hasSameProperties(flags, tag, ws, uid, pid)) {
+ // Update existing wake lock. This shouldn't happen but is harmless.
+ notifyWakeLockReleasedLocked(wakeLock);
+ wakeLock.updateProperties(flags, tag, ws, uid, pid);
+ notifyWakeLockAcquiredLocked(wakeLock);
}
- } catch (RemoteException e) {
- // Ignore
- } finally {
- Binder.restoreCallingIdentity(origId);
+ } else {
+ wakeLock = new WakeLock(lock, flags, tag, ws, uid, pid);
+ try {
+ lock.linkToDeath(wakeLock, 0);
+ } catch (RemoteException ex) {
+ throw new IllegalArgumentException("Wake lock is already dead.");
+ }
+ notifyWakeLockAcquiredLocked(wakeLock);
+ mWakeLocks.add(wakeLock);
}
+
+ applyWakeLockFlagsOnAcquireLocked(wakeLock);
+ mDirty |= DIRTY_WAKE_LOCKS;
+ updatePowerStateLocked();
}
}
- void noteStopWakeLocked(WakeLock wl, WorkSource ws) {
- if (wl.monitorType >= 0) {
- long origId = Binder.clearCallingIdentity();
- try {
- if (ws != null) {
- mBatteryStats.noteStopWakelockFromSource(ws, wl.pid, wl.tag,
- wl.monitorType);
- } else {
- mBatteryStats.noteStopWakelock(wl.uid, wl.pid, wl.tag, wl.monitorType);
- }
- } catch (RemoteException e) {
- // Ignore
- } finally {
- Binder.restoreCallingIdentity(origId);
- }
+ private void applyWakeLockFlagsOnAcquireLocked(WakeLock wakeLock) {
+ if ((wakeLock.mFlags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
+ wakeUpNoUpdateLocked(SystemClock.uptimeMillis());
}
}
- public void acquireWakeLockLocked(int flags, IBinder lock, int uid, int pid, String tag,
- WorkSource ws) {
- if (DEBUG) {
- Slog.d(TAG, "acquireWakeLock flags=0x" + Integer.toHexString(flags) + " tag=" + tag);
+ @Override // Binder call
+ public void releaseWakeLock(IBinder lock, int flags) {
+ if (lock == null) {
+ throw new IllegalArgumentException("lock must not be null");
}
- if (ws != null && ws.size() == 0) {
- ws = null;
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ releaseWakeLockInternal(lock, flags);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
+ }
- int index = mLocks.getIndex(lock);
- WakeLock wl;
- boolean newlock;
- boolean diffsource;
- WorkSource oldsource;
- if (index < 0) {
- wl = new WakeLock(flags, lock, tag, uid, pid);
- switch (wl.flags & LOCK_MASK)
- {
- case PowerManager.FULL_WAKE_LOCK:
- if (mUseSoftwareAutoBrightness) {
- wl.minState = SCREEN_BRIGHT;
- } else {
- wl.minState = (mKeyboardVisible ? ALL_BRIGHT : SCREEN_BUTTON_BRIGHT);
- }
- break;
- case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
- wl.minState = SCREEN_BRIGHT;
- break;
- case PowerManager.SCREEN_DIM_WAKE_LOCK:
- wl.minState = SCREEN_DIM;
- break;
- case PowerManager.PARTIAL_WAKE_LOCK:
- case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
- break;
- default:
- // just log and bail. we're in the server, so don't
- // throw an exception.
- Slog.e(TAG, "bad wakelock type for lock '" + tag + "' "
- + " flags=" + flags);
- return;
- }
- mLocks.addLock(wl);
- if (ws != null) {
- wl.ws = new WorkSource(ws);
+ private void releaseWakeLockInternal(IBinder lock, int flags) {
+ synchronized (mLock) {
+ if (DEBUG_SPEW) {
+ Slog.d(TAG, "releaseWakeLockInternal: lock=" + Objects.hashCode(lock)
+ + ", flags=0x" + Integer.toHexString(flags));
}
- newlock = true;
- diffsource = false;
- oldsource = null;
- } else {
- wl = mLocks.get(index);
- newlock = false;
- oldsource = wl.ws;
- if (oldsource != null) {
- if (ws == null) {
- wl.ws = null;
- diffsource = true;
- } else {
- diffsource = oldsource.diff(ws);
- }
- } else if (ws != null) {
- diffsource = true;
- } else {
- diffsource = false;
+
+ int index = findWakeLockIndexLocked(lock);
+ if (index < 0) {
+ return;
}
- if (diffsource) {
- wl.ws = new WorkSource(ws);
+
+ WakeLock wakeLock = mWakeLocks.get(index);
+ mWakeLocks.remove(index);
+ notifyWakeLockReleasedLocked(wakeLock);
+ wakeLock.mLock.unlinkToDeath(wakeLock, 0);
+
+ if ((flags & PowerManager.WAIT_FOR_PROXIMITY_NEGATIVE) != 0) {
+ mRequestWaitForNegativeProximity = true;
}
+
+ applyWakeLockFlagsOnReleaseLocked(wakeLock);
+ mDirty |= DIRTY_WAKE_LOCKS;
+ updatePowerStateLocked();
}
- if (isScreenLock(flags)) {
- // if this causes a wakeup, we reactivate all of the locks and
- // set it to whatever they want. otherwise, we modulate that
- // by the current state so we never turn it more on than
- // it already is.
- if ((flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) {
- mProximityWakeLockCount++;
- if (mProximityWakeLockCount == 1) {
- enableProximityLockLocked();
- }
- } else {
- if ((wl.flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
- int oldWakeLockState = mWakeLockState;
- mWakeLockState = mLocks.reactivateScreenLocksLocked();
-
- // Disable proximity sensor if if user presses power key while we are in the
- // "waiting for proximity sensor to go negative" state.
- if ((mWakeLockState & SCREEN_ON_BIT) != 0
- && mProximitySensorActive && mProximityWakeLockCount == 0) {
- mProximitySensorActive = false;
- }
+ }
- if (DEBUG) {
- Slog.d(TAG, "wakeup here mUserState=0x" + Integer.toHexString(mUserState)
- + " mWakeLockState=0x"
- + Integer.toHexString(mWakeLockState)
- + " previous wakeLockState=0x"
- + Integer.toHexString(oldWakeLockState));
- }
- } else {
- if (DEBUG) {
- Slog.d(TAG, "here mUserState=0x" + Integer.toHexString(mUserState)
- + " mLocks.gatherState()=0x"
- + Integer.toHexString(mLocks.gatherState())
- + " mWakeLockState=0x" + Integer.toHexString(mWakeLockState));
- }
- mWakeLockState = (mUserState | mWakeLockState) & mLocks.gatherState();
- }
- setPowerState(mWakeLockState | mUserState);
+ private void handleWakeLockDeath(WakeLock wakeLock) {
+ synchronized (mLock) {
+ if (DEBUG_SPEW) {
+ Slog.d(TAG, "handleWakeLockDeath: lock=" + Objects.hashCode(wakeLock.mLock));
}
- }
- else if ((flags & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK) {
- if (newlock) {
- mPartialCount++;
- if (mPartialCount == 1) {
- if (LOG_PARTIAL_WL) {
- EventLog.writeEvent(EventLogTags.POWER_PARTIAL_WAKE_STATE, 1, tag);
- }
- }
+
+ int index = mWakeLocks.indexOf(wakeLock);
+ if (index < 0) {
+ return;
}
- nativeAcquireWakeLock(PARTIAL_WAKE_LOCK_ID, PARTIAL_NAME);
- }
- if (diffsource) {
- // If the lock sources have changed, need to first release the
- // old ones.
- noteStopWakeLocked(wl, oldsource);
+ mWakeLocks.remove(index);
+ notifyWakeLockReleasedLocked(wakeLock);
+
+ applyWakeLockFlagsOnReleaseLocked(wakeLock);
+ mDirty |= DIRTY_WAKE_LOCKS;
+ updatePowerStateLocked();
}
- if (newlock || diffsource) {
- noteStartWakeLocked(wl, ws);
+ }
+
+ private void applyWakeLockFlagsOnReleaseLocked(WakeLock wakeLock) {
+ if ((wakeLock.mFlags & PowerManager.ON_AFTER_RELEASE) != 0) {
+ userActivityNoUpdateLocked(SystemClock.uptimeMillis(),
+ PowerManager.USER_ACTIVITY_EVENT_OTHER,
+ PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS,
+ wakeLock.mOwnerUid);
}
}
+ @Override // Binder call
public void updateWakeLockWorkSource(IBinder lock, WorkSource ws) {
- int uid = Binder.getCallingUid();
- int pid = Binder.getCallingPid();
- if (ws != null && ws.size() == 0) {
+ if (lock == null) {
+ throw new IllegalArgumentException("lock must not be null");
+ }
+
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
+ if (ws != null && ws.size() != 0) {
+ mContext.enforceCallingOrSelfPermission(
+ android.Manifest.permission.UPDATE_DEVICE_STATS, null);
+ } else {
ws = null;
}
- if (ws != null) {
- enforceWakeSourcePermission(uid, pid);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ updateWakeLockWorkSourceInternal(lock, ws);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
- synchronized (mLocks) {
- int index = mLocks.getIndex(lock);
+ }
+
+ private void updateWakeLockWorkSourceInternal(IBinder lock, WorkSource ws) {
+ synchronized (mLock) {
+ int index = findWakeLockIndexLocked(lock);
if (index < 0) {
throw new IllegalArgumentException("Wake lock not active");
}
- WakeLock wl = mLocks.get(index);
- WorkSource oldsource = wl.ws;
- wl.ws = ws != null ? new WorkSource(ws) : null;
- noteStopWakeLocked(wl, oldsource);
- noteStartWakeLocked(wl, ws);
+
+ WakeLock wakeLock = mWakeLocks.get(index);
+ if (!wakeLock.hasSameWorkSource(ws)) {
+ notifyWakeLockReleasedLocked(wakeLock);
+ wakeLock.updateWorkSource(ws);
+ notifyWakeLockAcquiredLocked(wakeLock);
+ }
}
}
- public void releaseWakeLock(IBinder lock, int flags) {
- int uid = Binder.getCallingUid();
- if (uid != Process.myUid()) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WAKE_LOCK, null);
+ private int findWakeLockIndexLocked(IBinder lock) {
+ final int count = mWakeLocks.size();
+ for (int i = 0; i < count; i++) {
+ if (mWakeLocks.get(i).mLock == lock) {
+ return i;
+ }
}
+ return -1;
+ }
- synchronized (mLocks) {
- releaseWakeLockLocked(lock, flags, false);
+ private void notifyWakeLockAcquiredLocked(WakeLock wakeLock) {
+ if (mSystemReady) {
+ mNotifier.onWakeLockAcquired(wakeLock.mFlags, wakeLock.mTag,
+ wakeLock.mOwnerUid, wakeLock.mOwnerPid, wakeLock.mWorkSource);
}
}
- private void releaseWakeLockLocked(IBinder lock, int flags, boolean death) {
- WakeLock wl = mLocks.removeLock(lock);
- if (wl == null) {
- return;
+ private void notifyWakeLockReleasedLocked(WakeLock wakeLock) {
+ if (mSystemReady) {
+ mNotifier.onWakeLockReleased(wakeLock.mFlags, wakeLock.mTag,
+ wakeLock.mOwnerUid, wakeLock.mOwnerPid, wakeLock.mWorkSource);
}
+ }
- if (DEBUG) {
- Slog.d(TAG, "releaseWakeLock flags=0x"
- + Integer.toHexString(wl.flags) + " tag=" + wl.tag);
+ @Override // Binder call
+ public boolean isWakeLockLevelSupported(int level) {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ return isWakeLockLevelSupportedInternal(level);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
+ }
- if (isScreenLock(wl.flags)) {
- if ((wl.flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK) {
- mProximityWakeLockCount--;
- if (mProximityWakeLockCount == 0) {
- if (mProximitySensorActive &&
- ((flags & PowerManager.WAIT_FOR_PROXIMITY_NEGATIVE) != 0)) {
- // wait for proximity sensor to go negative before disabling sensor
- if (DEBUG_PROXIMITY_SENSOR) {
- Slog.d(TAG, "waiting for proximity sensor to go negative");
- }
- } else {
- disableProximityLockLocked();
- }
- }
- } else {
- mWakeLockState = mLocks.gatherState();
- // goes in the middle to reduce flicker
- if ((wl.flags & PowerManager.ON_AFTER_RELEASE) != 0) {
- userActivity(SystemClock.uptimeMillis(), -1, false, PowerManager.USER_ACTIVITY_EVENT_OTHER, false, true);
- }
- setPowerState(mWakeLockState | mUserState);
- }
- }
- else if ((wl.flags & LOCK_MASK) == PowerManager.PARTIAL_WAKE_LOCK) {
- mPartialCount--;
- if (mPartialCount == 0) {
- if (LOG_PARTIAL_WL) {
- EventLog.writeEvent(EventLogTags.POWER_PARTIAL_WAKE_STATE, 0, wl.tag);
- }
- nativeReleaseWakeLock(PARTIAL_NAME);
- }
- }
- // Unlink the lock from the binder.
- wl.binder.unlinkToDeath(wl, 0);
+ private boolean isWakeLockLevelSupportedInternal(int level) {
+ synchronized (mLock) {
+ switch (level) {
+ case PowerManager.PARTIAL_WAKE_LOCK:
+ case PowerManager.SCREEN_DIM_WAKE_LOCK:
+ case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
+ case PowerManager.FULL_WAKE_LOCK:
+ return true;
- noteStopWakeLocked(wl, wl.ws);
- }
+ case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
+ return mSystemReady && mDisplayPowerController.isProximitySensorAvailable();
- private class PokeLock implements IBinder.DeathRecipient
- {
- PokeLock(int p, IBinder b, String t) {
- super();
- this.pokey = p;
- this.binder = b;
- this.tag = t;
- try {
- b.linkToDeath(this, 0);
- } catch (RemoteException e) {
- binderDied();
+ default:
+ return false;
}
}
- public void binderDied() {
- setPokeLock(0, this.binder, this.tag);
- }
- int pokey;
- IBinder binder;
- String tag;
- boolean awakeOnSet;
}
- public void setPokeLock(int pokey, IBinder token, String tag) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
- if (token == null) {
- Slog.e(TAG, "setPokeLock got null token for tag='" + tag + "'");
- return;
- }
-
- if ((pokey & POKE_LOCK_TIMEOUT_MASK) == POKE_LOCK_TIMEOUT_MASK) {
- throw new IllegalArgumentException("setPokeLock can't have both POKE_LOCK_SHORT_TIMEOUT"
- + " and POKE_LOCK_MEDIUM_TIMEOUT");
+ @Override // Binder call
+ public void userActivity(long eventTime, int event, int flags) {
+ if (eventTime > SystemClock.uptimeMillis()) {
+ throw new IllegalArgumentException("event time must not be in the future");
}
- synchronized (mLocks) {
- if (pokey != 0) {
- PokeLock p = mPokeLocks.get(token);
- int oldPokey = 0;
- if (p != null) {
- oldPokey = p.pokey;
- p.pokey = pokey;
- } else {
- p = new PokeLock(pokey, token, tag);
- mPokeLocks.put(token, p);
- }
- int oldTimeout = oldPokey & POKE_LOCK_TIMEOUT_MASK;
- int newTimeout = pokey & POKE_LOCK_TIMEOUT_MASK;
- if (((mPowerState & SCREEN_ON_BIT) == 0) && (oldTimeout != newTimeout)) {
- p.awakeOnSet = true;
- }
- } else {
- PokeLock rLock = mPokeLocks.remove(token);
- if (rLock != null) {
- token.unlinkToDeath(rLock, 0);
- }
- }
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
- int oldPokey = mPokey;
- int cumulative = 0;
- boolean awakeOnSet = false;
- for (PokeLock p: mPokeLocks.values()) {
- cumulative |= p.pokey;
- if (p.awakeOnSet) {
- awakeOnSet = true;
- }
- }
- mPokey = cumulative;
- mPokeAwakeOnSet = awakeOnSet;
+ final int uid = Binder.getCallingUid();
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ userActivityInternal(eventTime, event, flags, uid);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
- int oldCumulativeTimeout = oldPokey & POKE_LOCK_TIMEOUT_MASK;
- int newCumulativeTimeout = pokey & POKE_LOCK_TIMEOUT_MASK;
+ // Called from native code.
+ private void userActivityFromNative(long eventTime, int event, int flags) {
+ userActivityInternal(eventTime, event, flags, Process.SYSTEM_UID);
+ }
- if (oldCumulativeTimeout != newCumulativeTimeout) {
- setScreenOffTimeoutsLocked();
- // reset the countdown timer, but use the existing nextState so it doesn't
- // change anything
- setTimeoutLocked(SystemClock.uptimeMillis(), mTimeoutTask.nextState);
+ private void userActivityInternal(long eventTime, int event, int flags, int uid) {
+ synchronized (mLock) {
+ if (userActivityNoUpdateLocked(eventTime, event, flags, uid)) {
+ updatePowerStateLocked();
}
}
}
- private static String lockType(int type)
- {
- switch (type)
- {
- case PowerManager.FULL_WAKE_LOCK:
- return "FULL_WAKE_LOCK ";
- case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
- return "SCREEN_BRIGHT_WAKE_LOCK ";
- case PowerManager.SCREEN_DIM_WAKE_LOCK:
- return "SCREEN_DIM_WAKE_LOCK ";
- case PowerManager.PARTIAL_WAKE_LOCK:
- return "PARTIAL_WAKE_LOCK ";
- case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
- return "PROXIMITY_SCREEN_OFF_WAKE_LOCK";
- default:
- return "??? ";
+ private boolean userActivityNoUpdateLocked(long eventTime, int event, int flags, int uid) {
+ if (DEBUG_SPEW) {
+ Slog.d(TAG, "userActivityNoUpdateLocked: eventTime=" + eventTime
+ + ", event=" + event + ", flags=0x" + Integer.toHexString(flags)
+ + ", uid=" + uid);
}
- }
-
- private static String dumpPowerState(int state) {
- return (((state & KEYBOARD_BRIGHT_BIT) != 0)
- ? "KEYBOARD_BRIGHT_BIT " : "")
- + (((state & SCREEN_BRIGHT_BIT) != 0)
- ? "SCREEN_BRIGHT_BIT " : "")
- + (((state & SCREEN_ON_BIT) != 0)
- ? "SCREEN_ON_BIT " : "")
- + (((state & BUTTON_BRIGHT_BIT) != 0)
- ? "BUTTON_BRIGHT_BIT " : "")
- + (((state & BATTERY_LOW_BIT) != 0)
- ? "BATTERY_LOW_BIT " : "");
- }
- @Override
- public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
- != PackageManager.PERMISSION_GRANTED) {
- pw.println("Permission Denial: can't dump PowerManager from from pid="
- + Binder.getCallingPid()
- + ", uid=" + Binder.getCallingUid());
- return;
+ if (eventTime < mLastSleepTime || eventTime < mLastWakeTime
+ || mWakefulness == WAKEFULNESS_ASLEEP || !mBootCompleted || !mSystemReady) {
+ return false;
}
- long now = SystemClock.uptimeMillis();
+ mNotifier.onUserActivity(event, uid);
- synchronized (mLocks) {
- pw.println("Power Manager State:");
- pw.println(" mIsPowered=" + mIsPowered
- + " mPowerState=" + mPowerState
- + " mScreenOffTime=" + (SystemClock.elapsedRealtime()-mScreenOffTime)
- + " ms");
- pw.println(" mPartialCount=" + mPartialCount);
- pw.println(" mWakeLockState=" + dumpPowerState(mWakeLockState));
- pw.println(" mUserState=" + dumpPowerState(mUserState));
- pw.println(" mPowerState=" + dumpPowerState(mPowerState));
- pw.println(" mLocks.gather=" + dumpPowerState(mLocks.gatherState()));
- pw.println(" mNextTimeout=" + mNextTimeout + " now=" + now
- + " " + ((mNextTimeout-now)/1000) + "s from now");
- pw.println(" mDimScreen=" + mDimScreen
- + " mStayOnConditions=" + mStayOnConditions
- + " mPreparingForScreenOn=" + mPreparingForScreenOn
- + " mSkippedScreenOn=" + mSkippedScreenOn);
- pw.println(" mScreenOffReason=" + mScreenOffReason
- + " mUserState=" + mUserState);
- pw.println(" mBroadcastQueue={" + mBroadcastQueue[0] + ',' + mBroadcastQueue[1]
- + ',' + mBroadcastQueue[2] + "}");
- pw.println(" mBroadcastWhy={" + mBroadcastWhy[0] + ',' + mBroadcastWhy[1]
- + ',' + mBroadcastWhy[2] + "}");
- pw.println(" mPokey=" + mPokey + " mPokeAwakeonSet=" + mPokeAwakeOnSet);
- pw.println(" mKeyboardVisible=" + mKeyboardVisible
- + " mUserActivityAllowed=" + mUserActivityAllowed);
- pw.println(" mKeylightDelay=" + mKeylightDelay + " mDimDelay=" + mDimDelay
- + " mScreenOffDelay=" + mScreenOffDelay);
- pw.println(" mPreventScreenOn=" + mPreventScreenOn
- + " mScreenBrightnessOverride=" + mScreenBrightnessOverride
- + " mButtonBrightnessOverride=" + mButtonBrightnessOverride);
- pw.println(" mScreenOffTimeoutSetting=" + mScreenOffTimeoutSetting
- + " mMaximumScreenOffTimeout=" + mMaximumScreenOffTimeout);
- pw.println(" mLastScreenOnTime=" + mLastScreenOnTime);
- pw.println(" mBroadcastWakeLock=" + mBroadcastWakeLock);
- pw.println(" mStayOnWhilePluggedInScreenDimLock=" + mStayOnWhilePluggedInScreenDimLock);
- pw.println(" mStayOnWhilePluggedInPartialLock=" + mStayOnWhilePluggedInPartialLock);
- pw.println(" mPreventScreenOnPartialLock=" + mPreventScreenOnPartialLock);
- pw.println(" mProximityPartialLock=" + mProximityPartialLock);
- pw.println(" mProximityWakeLockCount=" + mProximityWakeLockCount);
- pw.println(" mProximitySensorEnabled=" + mProximitySensorEnabled);
- pw.println(" mProximitySensorActive=" + mProximitySensorActive);
- pw.println(" mProximityPendingValue=" + mProximityPendingValue);
- pw.println(" mLastProximityEventTime=" + mLastProximityEventTime);
- pw.println(" mLightSensorEnabled=" + mLightSensorEnabled
- + " mLightSensorAdjustSetting=" + mLightSensorAdjustSetting);
- pw.println(" mLightSensorValue=" + mLightSensorValue
- + " mLightSensorPendingValue=" + mLightSensorPendingValue);
- pw.println(" mHighestLightSensorValue=" + mHighestLightSensorValue
- + " mWaitingForFirstLightSensor=" + mWaitingForFirstLightSensor);
- pw.println(" mLightSensorPendingDecrease=" + mLightSensorPendingDecrease
- + " mLightSensorPendingIncrease=" + mLightSensorPendingIncrease);
- pw.println(" mLightSensorScreenBrightness=" + mLightSensorScreenBrightness
- + " mLightSensorButtonBrightness=" + mLightSensorButtonBrightness
- + " mLightSensorKeyboardBrightness=" + mLightSensorKeyboardBrightness);
- pw.println(" mUseSoftwareAutoBrightness=" + mUseSoftwareAutoBrightness);
- pw.println(" mAutoBrightessEnabled=" + mAutoBrightessEnabled);
- mScreenBrightnessAnimator.dump(pw, "mScreenBrightnessAnimator: ");
-
- int N = mLocks.size();
- pw.println();
- pw.println("mLocks.size=" + N + ":");
- for (int i=0; i<N; i++) {
- WakeLock wl = mLocks.get(i);
- String type = lockType(wl.flags & LOCK_MASK);
- String acquireCausesWakeup = "";
- if ((wl.flags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
- acquireCausesWakeup = "ACQUIRE_CAUSES_WAKEUP ";
- }
- String activated = "";
- if (wl.activated) {
- activated = " activated";
- }
- pw.println(" " + type + " '" + wl.tag + "'" + acquireCausesWakeup
- + activated + " (minState=" + wl.minState + ", uid=" + wl.uid
- + ", pid=" + wl.pid + ")");
+ if ((flags & PowerManager.USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS) != 0) {
+ if (eventTime > mLastUserActivityTimeNoChangeLights
+ && eventTime > mLastUserActivityTime) {
+ mLastUserActivityTimeNoChangeLights = eventTime;
+ mDirty |= DIRTY_USER_ACTIVITY;
+ return true;
}
-
- pw.println();
- pw.println("mPokeLocks.size=" + mPokeLocks.size() + ":");
- for (PokeLock p: mPokeLocks.values()) {
- pw.println(" poke lock '" + p.tag + "':"
- + ((p.pokey & POKE_LOCK_IGNORE_TOUCH_EVENTS) != 0
- ? " POKE_LOCK_IGNORE_TOUCH_EVENTS" : "")
- + ((p.pokey & POKE_LOCK_SHORT_TIMEOUT) != 0
- ? " POKE_LOCK_SHORT_TIMEOUT" : "")
- + ((p.pokey & POKE_LOCK_MEDIUM_TIMEOUT) != 0
- ? " POKE_LOCK_MEDIUM_TIMEOUT" : ""));
+ } else {
+ if (eventTime > mLastUserActivityTime) {
+ mLastUserActivityTime = eventTime;
+ mDirty |= DIRTY_USER_ACTIVITY;
+ return true;
}
-
- pw.println();
}
+ return false;
}
- private void setTimeoutLocked(long now, int nextState) {
- setTimeoutLocked(now, -1, nextState);
- }
-
- // If they gave a timeoutOverride it is the number of seconds
- // to screen-off. Figure out where in the countdown cycle we
- // should jump to.
- private void setTimeoutLocked(long now, final long originalTimeoutOverride, int nextState) {
- long timeoutOverride = originalTimeoutOverride;
- if (mBootCompleted) {
- synchronized (mLocks) {
- long when = 0;
- if (timeoutOverride <= 0) {
- switch (nextState)
- {
- case SCREEN_BRIGHT:
- when = now + mKeylightDelay;
- break;
- case SCREEN_DIM:
- if (mDimDelay >= 0) {
- when = now + mDimDelay;
- break;
- } else {
- Slog.w(TAG, "mDimDelay=" + mDimDelay + " while trying to dim");
- }
- case SCREEN_OFF:
- synchronized (mLocks) {
- when = now + mScreenOffDelay;
- }
- break;
- default:
- when = now;
- break;
- }
- } else {
- override: {
- if (timeoutOverride <= mScreenOffDelay) {
- when = now + timeoutOverride;
- nextState = SCREEN_OFF;
- break override;
- }
- timeoutOverride -= mScreenOffDelay;
-
- if (mDimDelay >= 0) {
- if (timeoutOverride <= mDimDelay) {
- when = now + timeoutOverride;
- nextState = SCREEN_DIM;
- break override;
- }
- timeoutOverride -= mDimDelay;
- }
+ @Override // Binder call
+ public void wakeUp(long eventTime) {
+ if (eventTime > SystemClock.uptimeMillis()) {
+ throw new IllegalArgumentException("event time must not be in the future");
+ }
- when = now + timeoutOverride;
- nextState = SCREEN_BRIGHT;
- }
- }
- if (DEBUG) {
- Slog.d(TAG, "setTimeoutLocked now=" + now
- + " timeoutOverride=" + timeoutOverride
- + " nextState=" + nextState + " when=" + when);
- }
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
- mHandler.removeCallbacks(mTimeoutTask);
- mTimeoutTask.nextState = nextState;
- mTimeoutTask.remainingTimeoutOverride = timeoutOverride > 0
- ? (originalTimeoutOverride - timeoutOverride)
- : -1;
- mHandler.postAtTime(mTimeoutTask, when);
- mNextTimeout = when; // for debugging
- }
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ wakeUpInternal(eventTime);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
}
- private void cancelTimerLocked()
- {
- mHandler.removeCallbacks(mTimeoutTask);
- mTimeoutTask.nextState = -1;
+ // Called from native code.
+ private void wakeUpFromNative(long eventTime) {
+ wakeUpInternal(eventTime);
}
- private class TimeoutTask implements Runnable
- {
- int nextState; // access should be synchronized on mLocks
- long remainingTimeoutOverride;
- public void run()
- {
- synchronized (mLocks) {
- if (DEBUG) {
- Slog.d(TAG, "user activity timeout timed out nextState=" + this.nextState);
- }
-
- if (nextState == -1) {
- return;
- }
-
- mUserState = this.nextState;
- setPowerState(this.nextState | mWakeLockState);
-
- long now = SystemClock.uptimeMillis();
-
- switch (this.nextState)
- {
- case SCREEN_BRIGHT:
- if (mDimDelay >= 0) {
- setTimeoutLocked(now, remainingTimeoutOverride, SCREEN_DIM);
- break;
- }
- case SCREEN_DIM:
- setTimeoutLocked(now, remainingTimeoutOverride, SCREEN_OFF);
- break;
- }
+ private void wakeUpInternal(long eventTime) {
+ synchronized (mLock) {
+ if (wakeUpNoUpdateLocked(eventTime)) {
+ updatePowerStateLocked();
}
}
}
- private void sendNotificationLocked(boolean on, int why) {
- if (!mInitialized) {
- // No notifications sent until first initialization is done.
- // This is so that when we are moving from our initial state
- // which looks like the screen was off to it being on, we do not
- // go through the process of waiting for the higher-level user
- // space to be ready before turning up the display brightness.
- // (And also do not send needless broadcasts about the screen.)
- return;
+ private boolean wakeUpNoUpdateLocked(long eventTime) {
+ if (DEBUG_SPEW) {
+ Slog.d(TAG, "wakeUpNoUpdateLocked: eventTime=" + eventTime);
}
- if (DEBUG_SCREEN_ON) {
- RuntimeException here = new RuntimeException("here");
- here.fillInStackTrace();
- Slog.i(TAG, "sendNotificationLocked: " + on, here);
+ if (eventTime < mLastSleepTime || mWakefulness == WAKEFULNESS_AWAKE
+ || !mBootCompleted || !mSystemReady) {
+ return false;
}
- if (!on) {
- mStillNeedSleepNotification = false;
+ switch (mWakefulness) {
+ case WAKEFULNESS_ASLEEP:
+ Slog.i(TAG, "Waking up from sleep...");
+ mNotifier.onWakeUpStarted();
+ mSendWakeUpFinishedNotificationWhenReady = true;
+ mSendGoToSleepFinishedNotificationWhenReady = false;
+ break;
+ case WAKEFULNESS_DREAMING:
+ Slog.i(TAG, "Waking up from dream...");
+ break;
+ case WAKEFULNESS_NAPPING:
+ Slog.i(TAG, "Waking up from nap...");
+ break;
}
- // Add to the queue.
- int index = 0;
- while (mBroadcastQueue[index] != -1) {
- index++;
- }
- mBroadcastQueue[index] = on ? 1 : 0;
- mBroadcastWhy[index] = why;
+ mLastWakeTime = eventTime;
+ mWakefulness = WAKEFULNESS_AWAKE;
+ mDirty |= DIRTY_WAKEFULNESS;
- // If we added it position 2, then there is a pair that can be stripped.
- // If we added it position 1 and we're turning the screen off, we can strip
- // the pair and do nothing, because the screen is already off, and therefore
- // keyguard has already been enabled.
- // However, if we added it at position 1 and we're turning it on, then position
- // 0 was to turn it off, and we can't strip that, because keyguard needs to come
- // on, so have to run the queue then.
- if (index == 2) {
- // While we're collapsing them, if it's going off, and the new reason
- // is more significant than the first, then use the new one.
- if (!on && mBroadcastWhy[0] > why) {
- mBroadcastWhy[0] = why;
- }
- mBroadcastQueue[0] = on ? 1 : 0;
- mBroadcastQueue[1] = -1;
- mBroadcastQueue[2] = -1;
- EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 1, mBroadcastWakeLock.mCount);
- mBroadcastWakeLock.release();
- EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 1, mBroadcastWakeLock.mCount);
- mBroadcastWakeLock.release();
- index = 0;
- }
- if (index == 1 && !on) {
- mBroadcastQueue[0] = -1;
- mBroadcastQueue[1] = -1;
- index = -1;
- // The wake lock was being held, but we're not actually going to do any
- // broadcasts, so release the wake lock.
- EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 1, mBroadcastWakeLock.mCount);
- mBroadcastWakeLock.release();
- }
-
- // The broadcast queue has changed; make sure the screen is on if it
- // is now possible for it to be.
- if (mSkippedScreenOn) {
- updateLightsLocked(mPowerState, SCREEN_ON_BIT);
- }
-
- // Now send the message.
- if (index >= 0) {
- // Acquire the broadcast wake lock before changing the power
- // state. It will be release after the broadcast is sent.
- // We always increment the ref count for each notification in the queue
- // and always decrement when that notification is handled.
- mBroadcastWakeLock.acquire();
- EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND, mBroadcastWakeLock.mCount);
- mHandler.post(mNotificationTask);
- }
- }
-
- private WindowManagerPolicy.ScreenOnListener mScreenOnListener =
- new WindowManagerPolicy.ScreenOnListener() {
- public void onScreenOn() {
- synchronized (mLocks) {
- if (mPreparingForScreenOn) {
- mPreparingForScreenOn = false;
- updateLightsLocked(mPowerState, SCREEN_ON_BIT);
- EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP,
- 4, mBroadcastWakeLock.mCount);
- mBroadcastWakeLock.release();
- }
- }
- }
- };
-
- private Runnable mNotificationTask = new Runnable()
- {
- public void run()
- {
- while (true) {
- int value;
- int why;
- WindowManagerPolicy policy;
- synchronized (mLocks) {
- value = mBroadcastQueue[0];
- why = mBroadcastWhy[0];
- for (int i=0; i<2; i++) {
- mBroadcastQueue[i] = mBroadcastQueue[i+1];
- mBroadcastWhy[i] = mBroadcastWhy[i+1];
- }
- policy = getPolicyLocked();
- if (value == 1 && !mPreparingForScreenOn) {
- mPreparingForScreenOn = true;
- mBroadcastWakeLock.acquire();
- EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_SEND,
- mBroadcastWakeLock.mCount);
- }
- }
- if (value == 1) {
- mScreenOnStart = SystemClock.uptimeMillis();
-
- policy.screenTurningOn(mScreenOnListener);
- try {
- ActivityManagerNative.getDefault().wakingUp();
- } catch (RemoteException e) {
- // ignore it
- }
-
- if (DEBUG) {
- Slog.d(TAG, "mBroadcastWakeLock=" + mBroadcastWakeLock);
- }
- if (mContext != null && ActivityManagerNative.isSystemReady()) {
- mContext.sendOrderedBroadcast(mScreenOnIntent, null,
- mScreenOnBroadcastDone, mHandler, 0, null, null);
- } else {
- synchronized (mLocks) {
- EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 2,
- mBroadcastWakeLock.mCount);
- mBroadcastWakeLock.release();
- }
- }
- }
- else if (value == 0) {
- mScreenOffStart = SystemClock.uptimeMillis();
-
- policy.screenTurnedOff(why);
- try {
- ActivityManagerNative.getDefault().goingToSleep();
- } catch (RemoteException e) {
- // ignore it.
- }
-
- if (mContext != null && ActivityManagerNative.isSystemReady()) {
- mContext.sendOrderedBroadcast(mScreenOffIntent, null,
- mScreenOffBroadcastDone, mHandler, 0, null, null);
- } else {
- synchronized (mLocks) {
- EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_STOP, 3,
- mBroadcastWakeLock.mCount);
- updateLightsLocked(mPowerState, SCREEN_ON_BIT);
- mBroadcastWakeLock.release();
- }
- }
- }
- else {
- // If we're in this case, then this handler is running for a previous
- // paired transaction. mBroadcastWakeLock will already have been released.
- break;
- }
- }
- }
- };
-
- long mScreenOnStart;
- private BroadcastReceiver mScreenOnBroadcastDone = new BroadcastReceiver() {
- public void onReceive(Context context, Intent intent) {
- synchronized (mLocks) {
- EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 1,
- SystemClock.uptimeMillis() - mScreenOnStart, mBroadcastWakeLock.mCount);
- mBroadcastWakeLock.release();
- }
- }
- };
+ userActivityNoUpdateLocked(
+ eventTime, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
+ return true;
+ }
- long mScreenOffStart;
- private BroadcastReceiver mScreenOffBroadcastDone = new BroadcastReceiver() {
- public void onReceive(Context context, Intent intent) {
- synchronized (mLocks) {
- EventLog.writeEvent(EventLogTags.POWER_SCREEN_BROADCAST_DONE, 0,
- SystemClock.uptimeMillis() - mScreenOffStart, mBroadcastWakeLock.mCount);
- mBroadcastWakeLock.release();
- }
+ @Override // Binder call
+ public void goToSleep(long eventTime, int reason) {
+ if (eventTime > SystemClock.uptimeMillis()) {
+ throw new IllegalArgumentException("event time must not be in the future");
}
- };
- /**
- * Prevents the screen from turning on even if it *should* turn on due
- * to a subsequent full wake lock being acquired.
- * <p>
- * This is a temporary hack that allows an activity to "cover up" any
- * display glitches that happen during the activity's startup
- * sequence. (Specifically, this API was added to work around a
- * cosmetic bug in the "incoming call" sequence, where the lock screen
- * would flicker briefly before the incoming call UI became visible.)
- * TODO: There ought to be a more elegant way of doing this,
- * probably by having the PowerManager and ActivityManager
- * work together to let apps specify that the screen on/off
- * state should be synchronized with the Activity lifecycle.
- * <p>
- * Note that calling preventScreenOn(true) will NOT turn the screen
- * off if it's currently on. (This API only affects *future*
- * acquisitions of full wake locks.)
- * But calling preventScreenOn(false) WILL turn the screen on if
- * it's currently off because of a prior preventScreenOn(true) call.
- * <p>
- * Any call to preventScreenOn(true) MUST be followed promptly by a call
- * to preventScreenOn(false). In fact, if the preventScreenOn(false)
- * call doesn't occur within 5 seconds, we'll turn the screen back on
- * ourselves (and log a warning about it); this prevents a buggy app
- * from disabling the screen forever.)
- * <p>
- * TODO: this feature should really be controlled by a new type of poke
- * lock (rather than an IPowerManager call).
- */
- public void preventScreenOn(boolean prevent) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
- synchronized (mLocks) {
- if (prevent) {
- // First of all, grab a partial wake lock to
- // make sure the CPU stays on during the entire
- // preventScreenOn(true) -> preventScreenOn(false) sequence.
- mPreventScreenOnPartialLock.acquire();
-
- // Post a forceReenableScreen() call (for 5 seconds in the
- // future) to make sure the matching preventScreenOn(false) call
- // has happened by then.
- mHandler.removeCallbacks(mForceReenableScreenTask);
- mHandler.postDelayed(mForceReenableScreenTask, 5000);
-
- // Finally, set the flag that prevents the screen from turning on.
- // (Below, in setPowerState(), we'll check mPreventScreenOn and
- // we *won't* call setScreenStateLocked(true) if it's set.)
- mPreventScreenOn = true;
- } else {
- // (Re)enable the screen.
- mPreventScreenOn = false;
-
- // We're "undoing" a the prior preventScreenOn(true) call, so we
- // no longer need the 5-second safeguard.
- mHandler.removeCallbacks(mForceReenableScreenTask);
-
- // Forcibly turn on the screen if it's supposed to be on. (This
- // handles the case where the screen is currently off because of
- // a prior preventScreenOn(true) call.)
- if (!mProximitySensorActive && (mPowerState & SCREEN_ON_BIT) != 0) {
- if (DEBUG) {
- Slog.d(TAG,
- "preventScreenOn: turning on after a prior preventScreenOn(true)!");
- }
- int err = setScreenStateLocked(true);
- if (err != 0) {
- Slog.w(TAG, "preventScreenOn: error from setScreenStateLocked(): " + err);
- }
- }
-
- // Release the partial wake lock that we held during the
- // preventScreenOn(true) -> preventScreenOn(false) sequence.
- mPreventScreenOnPartialLock.release();
- }
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ goToSleepInternal(eventTime, reason);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
}
- public void setScreenBrightnessOverride(int brightness) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
+ // Called from native code.
+ private void goToSleepFromNative(long eventTime, int reason) {
+ goToSleepInternal(eventTime, reason);
+ }
- if (DEBUG) Slog.d(TAG, "setScreenBrightnessOverride " + brightness);
- synchronized (mLocks) {
- if (mScreenBrightnessOverride != brightness) {
- mScreenBrightnessOverride = brightness;
- if (isScreenOn()) {
- updateLightsLocked(mPowerState, SCREEN_ON_BIT);
- }
+ private void goToSleepInternal(long eventTime, int reason) {
+ synchronized (mLock) {
+ if (goToSleepNoUpdateLocked(eventTime, reason)) {
+ updatePowerStateLocked();
}
}
}
- public void setButtonBrightnessOverride(int brightness) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
+ private boolean goToSleepNoUpdateLocked(long eventTime, int reason) {
+ if (DEBUG_SPEW) {
+ Slog.d(TAG, "goToSleepNoUpdateLocked: eventTime=" + eventTime + ", reason=" + reason);
+ }
- if (DEBUG) Slog.d(TAG, "setButtonBrightnessOverride " + brightness);
- synchronized (mLocks) {
- if (mButtonBrightnessOverride != brightness) {
- mButtonBrightnessOverride = brightness;
- if (isScreenOn()) {
- updateLightsLocked(mPowerState, BUTTON_BRIGHT_BIT | KEYBOARD_BRIGHT_BIT);
- }
+ if (eventTime < mLastWakeTime || mWakefulness == WAKEFULNESS_ASLEEP
+ || !mBootCompleted || !mSystemReady) {
+ return false;
+ }
+
+ switch (reason) {
+ case PowerManager.GO_TO_SLEEP_REASON_DEVICE_ADMIN:
+ Slog.i(TAG, "Going to sleep due to device administration policy...");
+ break;
+ case PowerManager.GO_TO_SLEEP_REASON_TIMEOUT:
+ Slog.i(TAG, "Going to sleep due to screen timeout...");
+ break;
+ default:
+ Slog.i(TAG, "Going to sleep by user request...");
+ reason = PowerManager.GO_TO_SLEEP_REASON_USER;
+ break;
+ }
+
+ mLastSleepTime = eventTime;
+ mDirty |= DIRTY_WAKEFULNESS;
+ mWakefulness = WAKEFULNESS_ASLEEP;
+ mNotifier.onGoToSleepStarted(reason);
+ mSendGoToSleepFinishedNotificationWhenReady = true;
+ mSendWakeUpFinishedNotificationWhenReady = false;
+
+ // Report the number of wake locks that will be cleared by going to sleep.
+ int numWakeLocksCleared = 0;
+ final int numWakeLocks = mWakeLocks.size();
+ for (int i = 0; i < numWakeLocks; i++) {
+ final WakeLock wakeLock = mWakeLocks.get(i);
+ switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
+ case PowerManager.FULL_WAKE_LOCK:
+ case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
+ case PowerManager.SCREEN_DIM_WAKE_LOCK:
+ numWakeLocksCleared += 1;
+ break;
}
}
+ EventLog.writeEvent(EventLogTags.POWER_SLEEP_REQUESTED, numWakeLocksCleared);
+ return true;
}
/**
- * Sanity-check that gets called 5 seconds after any call to
- * preventScreenOn(true). This ensures that the original call
- * is followed promptly by a call to preventScreenOn(false).
+ * Updates the global power state based on dirty bits recorded in mDirty.
+ *
+ * This is the main function that performs power state transitions.
+ * We centralize them here so that we can recompute the power state completely
+ * each time something important changes, and ensure that we do it the same
+ * way each time. The point is to gather all of the transition logic here.
*/
- private void forceReenableScreen() {
- // We shouldn't get here at all if mPreventScreenOn is false, since
- // we should have already removed any existing
- // mForceReenableScreenTask messages...
- if (!mPreventScreenOn) {
- Slog.w(TAG, "forceReenableScreen: mPreventScreenOn is false, nothing to do");
+ private void updatePowerStateLocked() {
+ if (!mSystemReady || mDirty == 0) {
return;
}
- // Uh oh. It's been 5 seconds since a call to
- // preventScreenOn(true) and we haven't re-enabled the screen yet.
- // This means the app that called preventScreenOn(true) is either
- // slow (i.e. it took more than 5 seconds to call preventScreenOn(false)),
- // or buggy (i.e. it forgot to call preventScreenOn(false), or
- // crashed before doing so.)
-
- // Log a warning, and forcibly turn the screen back on.
- Slog.w(TAG, "App called preventScreenOn(true) but didn't promptly reenable the screen! "
- + "Forcing the screen back on...");
- preventScreenOn(false);
- }
+ // Phase 0: Basic state updates.
+ updateIsPoweredLocked(mDirty);
+ updateStayOnLocked(mDirty);
- private Runnable mForceReenableScreenTask = new Runnable() {
- public void run() {
- forceReenableScreen();
- }
- };
+ // Phase 1: Update wakefulness.
+ // Loop because the wake lock and user activity computations are influenced
+ // by changes in wakefulness.
+ final long now = SystemClock.uptimeMillis();
+ int dirtyPhase2 = 0;
+ for (;;) {
+ int dirtyPhase1 = mDirty;
+ dirtyPhase2 |= dirtyPhase1;
+ mDirty = 0;
- private int setScreenStateLocked(boolean on) {
- if (DEBUG_SCREEN_ON) {
- RuntimeException e = new RuntimeException("here");
- e.fillInStackTrace();
- Slog.i(TAG, "Set screen state: " + on, e);
- }
- if (on) {
- if (mInitialized && ((mPowerState & SCREEN_ON_BIT) == 0 || mSkippedScreenOn)) {
- // If we are turning the screen state on, but the screen
- // light is currently off, then make sure that we set the
- // light at this point to 0. This is the case where we are
- // turning on the screen and waiting for the UI to be drawn
- // before showing it to the user. We want the light off
- // until it is ready to be shown to the user, not it using
- // whatever the last value it had.
- // Skip this if the screen is being turned on for the first time
- // after boot (mInitialized is false).
- if (DEBUG_SCREEN_ON) {
- Slog.i(TAG, "Forcing brightness 0: mPowerState=0x"
- + Integer.toHexString(mPowerState)
- + " mSkippedScreenOn=" + mSkippedScreenOn);
- }
- mScreenBrightnessAnimator.animateTo(PowerManager.BRIGHTNESS_OFF, SCREEN_BRIGHT_BIT, 0);
+ updateWakeLockSummaryLocked(dirtyPhase1);
+ updateUserActivitySummaryLocked(now, dirtyPhase1);
+ if (!updateWakefulnessLocked(dirtyPhase1)) {
+ break;
}
}
- int err = nativeSetScreenState(on);
- if (err == 0) {
- mLastScreenOnTime = (on ? SystemClock.elapsedRealtime() : 0);
- if (mUseSoftwareAutoBrightness) {
- enableLightSensorLocked(on);
- if (on) {
- // If AutoBrightness is enabled, set the brightness immediately after the
- // next sensor value is received.
- mWaitingForFirstLightSensor = mAutoBrightessEnabled;
- } else {
- // make sure button and key backlights are off too
- mButtonLight.turnOff();
- mKeyboardLight.turnOff();
- }
- }
- }
- return err;
- }
- private void setPowerState(int state)
- {
- setPowerState(state, false, WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT);
- }
+ // Phase 2: Update dreams and display power state.
+ updateDreamLocked(dirtyPhase2);
+ updateDisplayPowerStateLocked(dirtyPhase2);
- private void setPowerState(int newState, boolean noChangeLights, int reason)
- {
- synchronized (mLocks) {
- int err;
+ // Phase 3: Send notifications, if needed.
+ sendPendingNotificationsLocked();
- if (DEBUG) {
- Slog.d(TAG, "setPowerState: mPowerState=0x" + Integer.toHexString(mPowerState)
- + " newState=0x" + Integer.toHexString(newState)
- + " noChangeLights=" + noChangeLights
- + " reason=" + reason);
- }
-
- if (noChangeLights) {
- newState = (newState & ~LIGHTS_MASK) | (mPowerState & LIGHTS_MASK);
- }
- if (mProximitySensorActive) {
- // don't turn on the screen when the proximity sensor lock is held
- newState = (newState & ~SCREEN_BRIGHT);
- }
+ // Phase 4: Update suspend blocker.
+ // Because we might release the last suspend blocker here, we need to make sure
+ // we finished everything else first!
+ updateSuspendBlockerLocked();
+ }
- if (batteryIsLow()) {
- newState |= BATTERY_LOW_BIT;
- } else {
- newState &= ~BATTERY_LOW_BIT;
- }
- if (newState == mPowerState && mInitialized) {
- return;
+ private void sendPendingNotificationsLocked() {
+ if (mDisplayReady) {
+ if (mSendWakeUpFinishedNotificationWhenReady) {
+ mSendWakeUpFinishedNotificationWhenReady = false;
+ mNotifier.onWakeUpFinished();
}
-
- if (!mBootCompleted && !mUseSoftwareAutoBrightness) {
- newState |= ALL_BRIGHT;
+ if (mSendGoToSleepFinishedNotificationWhenReady) {
+ mSendGoToSleepFinishedNotificationWhenReady = false;
+ mNotifier.onGoToSleepFinished();
}
+ }
+ }
- boolean oldScreenOn = (mPowerState & SCREEN_ON_BIT) != 0;
- boolean newScreenOn = (newState & SCREEN_ON_BIT) != 0;
-
- if (DEBUG) {
- Slog.d(TAG, "setPowerState: mPowerState=" + mPowerState
- + " newState=" + newState + " noChangeLights=" + noChangeLights);
- Slog.d(TAG, " oldKeyboardBright=" + ((mPowerState & KEYBOARD_BRIGHT_BIT) != 0)
- + " newKeyboardBright=" + ((newState & KEYBOARD_BRIGHT_BIT) != 0));
- Slog.d(TAG, " oldScreenBright=" + ((mPowerState & SCREEN_BRIGHT_BIT) != 0)
- + " newScreenBright=" + ((newState & SCREEN_BRIGHT_BIT) != 0));
- Slog.d(TAG, " oldButtonBright=" + ((mPowerState & BUTTON_BRIGHT_BIT) != 0)
- + " newButtonBright=" + ((newState & BUTTON_BRIGHT_BIT) != 0));
- Slog.d(TAG, " oldScreenOn=" + oldScreenOn
- + " newScreenOn=" + newScreenOn);
- Slog.d(TAG, " oldBatteryLow=" + ((mPowerState & BATTERY_LOW_BIT) != 0)
- + " newBatteryLow=" + ((newState & BATTERY_LOW_BIT) != 0));
- }
+ /**
+ * Updates the value of mIsPowered.
+ * Sets DIRTY_IS_POWERED if a change occurred.
+ */
+ private void updateIsPoweredLocked(int dirty) {
+ if ((dirty & DIRTY_BATTERY_STATE) != 0) {
+ boolean wasPowered = mIsPowered;
+ mIsPowered = mBatteryService.isPowered();
- final boolean stateChanged = mPowerState != newState;
+ if (wasPowered != mIsPowered) {
+ mDirty |= DIRTY_IS_POWERED;
- if (stateChanged && !newScreenOn && reason == WindowManagerPolicy.OFF_BECAUSE_OF_TIMEOUT) {
- if (mPolicy != null && mIsPowered && mPolicy.isScreenSaverEnabled()) {
- if (DEBUG) {
- Slog.d(TAG, "setPowerState: running screen saver instead of turning off screen");
- }
- if (mPolicy.startScreenSaver()) {
- // was successful
- return;
- }
+ // Treat plugging and unplugging the devices as a user activity.
+ // Users find it disconcerting when they plug or unplug the device
+ // and it shuts off right away.
+ // Some devices also wake the device when plugged or unplugged because
+ // they don't have a charging LED.
+ final long now = SystemClock.uptimeMillis();
+ if (mWakeUpWhenPluggedOrUnpluggedConfig) {
+ wakeUpNoUpdateLocked(now);
}
+ userActivityNoUpdateLocked(
+ now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
}
+ }
+ }
+ /**
+ * Updates the value of mStayOn.
+ * Sets DIRTY_STAY_ON if a change occurred.
+ */
+ private void updateStayOnLocked(int dirty) {
+ if ((dirty & (DIRTY_BATTERY_STATE | DIRTY_SETTINGS)) != 0) {
+ if (mStayOnWhilePluggedInSetting != 0
+ && !isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) {
+ mStayOn = mBatteryService.isPowered(mStayOnWhilePluggedInSetting);
+ } else {
+ mStayOn = false;
+ }
+ }
+ }
- if (oldScreenOn != newScreenOn) {
- if (newScreenOn) {
- // When the user presses the power button, we need to always send out the
- // notification that it's going to sleep so the keyguard goes on. But
- // we can't do that until the screen fades out, so we don't show the keyguard
- // too early.
- if (mStillNeedSleepNotification) {
- sendNotificationLocked(false, WindowManagerPolicy.OFF_BECAUSE_OF_USER);
- }
-
- // Turn on the screen UNLESS there was a prior
- // preventScreenOn(true) request. (Note that the lifetime
- // of a single preventScreenOn() request is limited to 5
- // seconds to prevent a buggy app from disabling the
- // screen forever; see forceReenableScreen().)
- boolean reallyTurnScreenOn = true;
- if (DEBUG) {
- Slog.d(TAG, "- turning screen on... mPreventScreenOn = "
- + mPreventScreenOn);
- }
-
- if (mPreventScreenOn) {
- if (DEBUG) {
- Slog.d(TAG, "- PREVENTING screen from really turning on!");
+ /**
+ * Updates the value of mWakeLockSummary to summarize the state of all active wake locks.
+ * Note that most wake-locks are ignored when the system is asleep.
+ *
+ * This function must have no other side-effects.
+ */
+ private void updateWakeLockSummaryLocked(int dirty) {
+ if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_WAKEFULNESS)) != 0) {
+ mWakeLockSummary = 0;
+
+ final int numWakeLocks = mWakeLocks.size();
+ for (int i = 0; i < numWakeLocks; i++) {
+ final WakeLock wakeLock = mWakeLocks.get(i);
+ switch (wakeLock.mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
+ case PowerManager.PARTIAL_WAKE_LOCK:
+ mWakeLockSummary |= WAKE_LOCK_CPU;
+ break;
+ case PowerManager.FULL_WAKE_LOCK:
+ if (mWakefulness != WAKEFULNESS_ASLEEP) {
+ mWakeLockSummary |= WAKE_LOCK_CPU
+ | WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_BUTTON_BRIGHT;
}
- reallyTurnScreenOn = false;
- }
- if (reallyTurnScreenOn) {
- err = setScreenStateLocked(true);
- long identity = Binder.clearCallingIdentity();
- try {
- mBatteryStats.noteScreenBrightness(getPreferredBrightness());
- mBatteryStats.noteScreenOn();
- } catch (RemoteException e) {
- Slog.w(TAG, "RemoteException calling noteScreenOn on BatteryStatsService", e);
- } finally {
- Binder.restoreCallingIdentity(identity);
+ break;
+ case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
+ if (mWakefulness != WAKEFULNESS_ASLEEP) {
+ mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_SCREEN_BRIGHT;
}
- } else {
- setScreenStateLocked(false);
- // But continue as if we really did turn the screen on...
- err = 0;
- }
-
- EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 1, reason, 0, 0);
- if (err == 0) {
- sendNotificationLocked(true, -1);
- // Update the lights *after* taking care of turning the
- // screen on, so we do this after our notifications are
- // enqueued and thus will delay turning on the screen light
- // until the windows are correctly displayed.
- if (stateChanged) {
- updateLightsLocked(newState, 0);
+ break;
+ case PowerManager.SCREEN_DIM_WAKE_LOCK:
+ if (mWakefulness != WAKEFULNESS_ASLEEP) {
+ mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_SCREEN_DIM;
}
- mPowerState |= SCREEN_ON_BIT;
- }
+ break;
+ case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
+ if (mWakefulness != WAKEFULNESS_ASLEEP) {
+ mWakeLockSummary |= WAKE_LOCK_CPU | WAKE_LOCK_PROXIMITY_SCREEN_OFF;
+ }
+ break;
+ }
+ }
- } else {
- // Update the lights *before* taking care of turning the
- // screen off, so we can initiate any animations that are desired.
- mScreenOffReason = reason;
- if (stateChanged) {
- updateLightsLocked(newState, 0);
- }
+ if (DEBUG_SPEW) {
+ Slog.d(TAG, "updateWakeLockSummaryLocked: mWakefulness="
+ + wakefulnessToString(mWakefulness)
+ + ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));
+ }
+ }
+ }
- // cancel light sensor task
- mHandler.removeCallbacks(mAutoBrightnessTask);
- mLightSensorPendingDecrease = false;
- mLightSensorPendingIncrease = false;
- mScreenOffTime = SystemClock.elapsedRealtime();
- long identity = Binder.clearCallingIdentity();
- try {
- mBatteryStats.noteScreenOff();
- } catch (RemoteException e) {
- Slog.w(TAG, "RemoteException calling noteScreenOff on BatteryStatsService", e);
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- mPowerState &= ~SCREEN_ON_BIT;
- if (!mScreenBrightnessAnimator.isAnimating()) {
- err = screenOffFinishedAnimatingLocked(reason);
+ /**
+ * Updates the value of mUserActivitySummary to summarize the user requested
+ * state of the system such as whether the screen should be bright or dim.
+ * Note that user activity is ignored when the system is asleep.
+ *
+ * This function must have no other side-effects.
+ */
+ private void updateUserActivitySummaryLocked(long now, int dirty) {
+ // Update the status of the user activity timeout timer.
+ if ((dirty & (DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS | DIRTY_SETTINGS)) != 0) {
+ mHandler.removeMessages(MSG_USER_ACTIVITY_TIMEOUT);
+
+ long nextTimeout = 0;
+ if (mWakefulness != WAKEFULNESS_ASLEEP) {
+ final int screenOffTimeout = getScreenOffTimeoutLocked();
+ final int screenDimDuration = getScreenDimDurationLocked();
+
+ mUserActivitySummary = 0;
+ if (mLastUserActivityTime >= mLastWakeTime) {
+ nextTimeout = mLastUserActivityTime
+ + screenOffTimeout - screenDimDuration;
+ if (now < nextTimeout) {
+ mUserActivitySummary |= USER_ACTIVITY_SCREEN_BRIGHT;
} else {
- err = 0;
- }
-
- // stop the screensaver if user turned screen off
- if (stateChanged && reason == WindowManagerPolicy.OFF_BECAUSE_OF_USER) {
- if (mPolicy != null) {
- mPolicy.stopScreenSaver();
+ nextTimeout = mLastUserActivityTime + screenOffTimeout;
+ if (now < nextTimeout) {
+ mUserActivitySummary |= USER_ACTIVITY_SCREEN_DIM;
}
}
}
- } else if (stateChanged) {
- // Screen on/off didn't change, but lights may have.
- updateLightsLocked(newState, 0);
+ if (mUserActivitySummary == 0
+ && mLastUserActivityTimeNoChangeLights >= mLastWakeTime) {
+ nextTimeout = mLastUserActivityTimeNoChangeLights + screenOffTimeout;
+ if (now < nextTimeout
+ && mDisplayPowerRequest.screenState
+ != DisplayPowerRequest.SCREEN_STATE_OFF) {
+ mUserActivitySummary = mDisplayPowerRequest.screenState
+ == DisplayPowerRequest.SCREEN_STATE_BRIGHT ?
+ USER_ACTIVITY_SCREEN_BRIGHT : USER_ACTIVITY_SCREEN_DIM;
+ }
+ }
+ if (mUserActivitySummary != 0) {
+ Message msg = mHandler.obtainMessage(MSG_USER_ACTIVITY_TIMEOUT);
+ msg.setAsynchronous(true);
+ mHandler.sendMessageAtTime(msg, nextTimeout);
+ }
+ } else {
+ mUserActivitySummary = 0;
}
- mPowerState = (mPowerState & ~LIGHTS_MASK) | (newState & LIGHTS_MASK);
-
- updateNativePowerStateLocked();
+ if (DEBUG_SPEW) {
+ Slog.d(TAG, "updateUserActivitySummaryLocked: mWakefulness="
+ + wakefulnessToString(mWakefulness)
+ + ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
+ + ", nextTimeout=" + TimeUtils.formatUptime(nextTimeout));
+ }
}
}
- private void updateNativePowerStateLocked() {
- if (!mHeadless) {
- nativeSetPowerState(
- (mPowerState & SCREEN_ON_BIT) != 0,
- (mPowerState & SCREEN_BRIGHT) == SCREEN_BRIGHT);
+ /**
+ * Called when a user activity timeout has occurred.
+ * Simply indicates that something about user activity has changed so that the new
+ * state can be recomputed when the power state is updated.
+ *
+ * This function must have no other side-effects besides setting the dirty
+ * bit and calling update power state. Wakefulness transitions are handled elsewhere.
+ */
+ private void handleUserActivityTimeout() { // runs on handler thread
+ synchronized (mLock) {
+ if (DEBUG_SPEW) {
+ Slog.d(TAG, "handleUserActivityTimeout");
+ }
+
+ mDirty |= DIRTY_USER_ACTIVITY;
+ updatePowerStateLocked();
}
}
- private int screenOffFinishedAnimatingLocked(int reason) {
- // I don't think we need to check the current state here because all of these
- // Power.setScreenState and sendNotificationLocked can both handle being
- // called multiple times in the same state. -joeo
- EventLog.writeEvent(EventLogTags.POWER_SCREEN_STATE, 0, reason, 0, 0);
- int err = setScreenStateLocked(false);
- if (err == 0) {
- mScreenOffReason = reason;
- sendNotificationLocked(false, reason);
+ private int getScreenOffTimeoutLocked() {
+ int timeout = mScreenOffTimeoutSetting;
+ if (isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked()) {
+ timeout = Math.min(timeout, mMaximumScreenOffTimeoutFromDeviceAdmin);
}
- return err;
+ return Math.max(timeout, MINIMUM_SCREEN_OFF_TIMEOUT);
}
- private boolean batteryIsLow() {
- return (!mIsPowered &&
- mBatteryService.getBatteryLevel() <= LOW_BATTERY_THRESHOLD);
+ private int getScreenDimDurationLocked() {
+ return SCREEN_DIM_DURATION;
}
- private boolean shouldDeferScreenOnLocked() {
- if (mPreparingForScreenOn) {
- // Currently waiting for confirmation from the policy that it
- // is okay to turn on the screen. Don't allow the screen to go
- // on until that is done.
- if (DEBUG_SCREEN_ON) Slog.i(TAG,
- "updateLights: delaying screen on due to mPreparingForScreenOn");
- return true;
- } else {
- // If there is a screen-on command in the notification queue, we
- // can't turn the screen on until it has been processed (and we
- // have set mPreparingForScreenOn) or it has been dropped.
- for (int i=0; i<mBroadcastQueue.length; i++) {
- if (mBroadcastQueue[i] == 1) {
- if (DEBUG_SCREEN_ON) Slog.i(TAG,
- "updateLights: delaying screen on due to notification queue");
- return true;
+ /**
+ * Updates the wakefulness of the device.
+ *
+ * This is the function that decides whether the device should start napping
+ * based on the current wake locks and user activity state. It may modify mDirty
+ * if the wakefulness changes.
+ *
+ * Returns true if the wakefulness changed and we need to restart power state calculation.
+ */
+ private boolean updateWakefulnessLocked(int dirty) {
+ boolean changed = false;
+ if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_BOOT_COMPLETED
+ | DIRTY_WAKEFULNESS | DIRTY_STAY_ON)) != 0) {
+ if (mWakefulness == WAKEFULNESS_AWAKE && isItBedTimeYetLocked()) {
+ if (DEBUG_SPEW) {
+ Slog.d(TAG, "updateWakefulnessLocked: Nap time...");
}
+ mWakefulness = WAKEFULNESS_NAPPING;
+ mDirty |= DIRTY_WAKEFULNESS;
+ changed = true;
}
}
- return false;
+ return changed;
}
- private void updateLightsLocked(int newState, int forceState) {
- final int oldState = mPowerState;
+ // Also used when exiting a dream to determine whether we should go back
+ // to being fully awake or else go to sleep for good.
+ private boolean isItBedTimeYetLocked() {
+ return mBootCompleted && !mStayOn
+ && (mWakeLockSummary
+ & (WAKE_LOCK_SCREEN_BRIGHT | WAKE_LOCK_SCREEN_DIM)) == 0
+ && (mUserActivitySummary
+ & (USER_ACTIVITY_SCREEN_BRIGHT | USER_ACTIVITY_SCREEN_DIM)) == 0;
+ }
- // If the screen is not currently on, we will want to delay actually
- // turning the lights on if we are still getting the UI put up.
- if ((oldState & SCREEN_ON_BIT) == 0 || mSkippedScreenOn) {
- // Don't turn screen on until we know we are really ready to.
- // This is to avoid letting the screen go on before things like the
- // lock screen have been displayed.
- if ((mSkippedScreenOn = shouldDeferScreenOnLocked())) {
- newState &= ~(SCREEN_ON_BIT|SCREEN_BRIGHT_BIT);
- }
+ /**
+ * Determines whether to post a message to the sandman to update the dream state.
+ */
+ private void updateDreamLocked(int dirty) {
+ if ((dirty & (DIRTY_WAKEFULNESS | DIRTY_SETTINGS
+ | DIRTY_IS_POWERED | DIRTY_STAY_ON)) != 0) {
+ scheduleSandmanLocked();
}
+ }
- if ((newState & SCREEN_ON_BIT) != 0) {
- // Only turn on the buttons or keyboard if the screen is also on.
- // We should never see the buttons on but not the screen.
- newState = applyButtonState(newState);
- newState = applyKeyboardState(newState);
- }
- final int realDifference = (newState ^ oldState);
- final int difference = realDifference | forceState;
- if (difference == 0) {
- return;
+ private void scheduleSandmanLocked() {
+ if (!mSandmanScheduled) {
+ mSandmanScheduled = true;
+ Message msg = mHandler.obtainMessage(MSG_SANDMAN);
+ msg.setAsynchronous(true);
+ mHandler.sendMessage(msg);
}
+ }
- int offMask = 0;
- int dimMask = 0;
- int onMask = 0;
+ /**
+ * Called when the device enters or exits a napping or dreaming state.
+ *
+ * We do this asynchronously because we must call out of the power manager to start
+ * the dream and we don't want to hold our lock while doing so. There is a risk that
+ * the device will wake or go to sleep in the meantime so we have to handle that case.
+ */
+ private void handleSandman() { // runs on handler thread
+ // Handle preconditions.
+ boolean startDreaming = false;
+ synchronized (mLock) {
+ mSandmanScheduled = false;
- int preferredBrightness = getPreferredBrightness();
+ if (DEBUG_SPEW) {
+ Log.d(TAG, "handleSandman: canDream=" + canDreamLocked()
+ + ", mWakefulness=" + wakefulnessToString(mWakefulness));
+ }
- if ((difference & KEYBOARD_BRIGHT_BIT) != 0) {
- if ((newState & KEYBOARD_BRIGHT_BIT) == 0) {
- offMask |= KEYBOARD_BRIGHT_BIT;
- } else {
- onMask |= KEYBOARD_BRIGHT_BIT;
+ if (canDreamLocked() && mWakefulness == WAKEFULNESS_NAPPING) {
+ startDreaming = true;
}
}
- if ((difference & BUTTON_BRIGHT_BIT) != 0) {
- if ((newState & BUTTON_BRIGHT_BIT) == 0) {
- offMask |= BUTTON_BRIGHT_BIT;
- } else {
- onMask |= BUTTON_BRIGHT_BIT;
+ // Get the dream manager, if needed.
+ if (startDreaming && mDreamManager == null) {
+ mDreamManager = IDreamManager.Stub.asInterface(
+ ServiceManager.checkService("dreams"));
+ if (mDreamManager == null) {
+ Slog.w(TAG, "Unable to find IDreamManager.");
}
}
- if ((difference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) {
- int nominalCurrentValue = -1;
- // If there was an actual difference in the light state, then
- // figure out the "ideal" current value based on the previous
- // state. Otherwise, this is a change due to the brightness
- // override, so we want to animate from whatever the current
- // value is.
- if ((realDifference & (SCREEN_ON_BIT | SCREEN_BRIGHT_BIT)) != 0) {
- switch (oldState & (SCREEN_BRIGHT_BIT|SCREEN_ON_BIT)) {
- case SCREEN_BRIGHT_BIT | SCREEN_ON_BIT:
- nominalCurrentValue = preferredBrightness;
- break;
- case SCREEN_ON_BIT:
- nominalCurrentValue = mScreenBrightnessDim;
- break;
- case 0:
- nominalCurrentValue = PowerManager.BRIGHTNESS_OFF;
- break;
- case SCREEN_BRIGHT_BIT:
- default:
- // not possible
- nominalCurrentValue = (int)mScreenBrightnessAnimator.getCurrentBrightness();
- break;
+ // Start dreaming if needed.
+ // We only control the dream on the handler thread, so we don't need to worry about
+ // concurrent attempts to start or stop the dream.
+ boolean isDreaming = false;
+ if (mDreamManager != null) {
+ try {
+ isDreaming = mDreamManager.isDreaming();
+ if (startDreaming && !isDreaming) {
+ Slog.i(TAG, "Entering dreamland.");
+ mDreamManager.dream();
+ isDreaming = mDreamManager.isDreaming();
+ if (!isDreaming) {
+ Slog.i(TAG, "Could not enter dreamland. Sleep will be dreamless.");
+ }
}
+ } catch (RemoteException ex) {
}
- int brightness = preferredBrightness;
- int steps = ANIM_STEPS;
- if ((newState & SCREEN_BRIGHT_BIT) == 0) {
- // dim or turn off backlight, depending on if the screen is on
- // the scale is because the brightness ramp isn't linear and this biases
- // it so the later parts take longer.
- final float scale = 1.5f;
- float ratio = (((float)mScreenBrightnessDim)/preferredBrightness);
- if (ratio > 1.0f) ratio = 1.0f;
- if ((newState & SCREEN_ON_BIT) == 0) {
- if ((oldState & SCREEN_BRIGHT_BIT) != 0) {
- // was bright
- steps = ANIM_STEPS;
- } else {
- // was dim
- steps = (int)(ANIM_STEPS*ratio*scale);
- }
- brightness = PowerManager.BRIGHTNESS_OFF;
- } else {
- if ((oldState & SCREEN_ON_BIT) != 0) {
- // was bright
- steps = (int)(ANIM_STEPS*(1.0f-ratio)*scale);
- } else {
- // was dim
- steps = (int)(ANIM_STEPS*ratio);
- }
- final int stayOnConditions = getStayOnConditionsLocked();
- if (stayOnConditions != 0 && mBatteryService.isPowered(stayOnConditions)) {
- // If the "stay on while plugged in" option is
- // turned on, then the screen will often not
- // automatically turn off while plugged in. To
- // still have a sense of when it is inactive, we
- // will then count going dim as turning off.
- mScreenOffTime = SystemClock.elapsedRealtime();
- }
- brightness = mScreenBrightnessDim;
+ }
+
+ // Update dream state.
+ // We might need to stop the dream again if the preconditions changed.
+ boolean continueDreaming = false;
+ synchronized (mLock) {
+ if (isDreaming && canDreamLocked()) {
+ if (mWakefulness == WAKEFULNESS_NAPPING) {
+ mWakefulness = WAKEFULNESS_DREAMING;
+ mDirty |= DIRTY_WAKEFULNESS;
+ updatePowerStateLocked();
+ continueDreaming = true;
+ } else if (mWakefulness == WAKEFULNESS_DREAMING) {
+ continueDreaming = true;
}
}
- if (mWaitingForFirstLightSensor && (newState & SCREEN_ON_BIT) != 0) {
- steps = IMMEDIATE_ANIM_STEPS;
+ if (!continueDreaming) {
+ handleDreamFinishedLocked();
}
- long identity = Binder.clearCallingIdentity();
- try {
- mBatteryStats.noteScreenBrightness(brightness);
- } catch (RemoteException e) {
- // Nothing interesting to do.
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- if (!mSkippedScreenOn) {
- int dt = steps * NOMINAL_FRAME_TIME_MS;
- mScreenBrightnessAnimator.animateTo(brightness, SCREEN_BRIGHT_BIT, dt);
- if (DEBUG_SCREEN_ON) {
- RuntimeException e = new RuntimeException("here");
- e.fillInStackTrace();
- Slog.i(TAG, "Setting screen brightness: " + brightness, e);
+ // Allow the sandman to detect when the dream has ended.
+ // FIXME: The DreamManagerService should tell us explicitly.
+ if (mWakefulness == WAKEFULNESS_DREAMING
+ || mWakefulness == WAKEFULNESS_NAPPING) {
+ if (!mSandmanScheduled) {
+ mSandmanScheduled = true;
+ Message msg = mHandler.obtainMessage(MSG_SANDMAN);
+ msg.setAsynchronous(true);
+ mHandler.sendMessageDelayed(msg, 1000);
}
}
}
- if (DEBUG) {
- Slog.d(TAG, "offMask=0x" + Integer.toHexString(offMask)
- + " dimMask=0x" + Integer.toHexString(dimMask)
- + " onMask=0x" + Integer.toHexString(onMask)
- + " difference=0x" + Integer.toHexString(difference)
- + " realDifference=0x" + Integer.toHexString(realDifference)
- + " forceState=0x" + Integer.toHexString(forceState)
- );
- }
-
- if (offMask != 0) {
- if (DEBUG) Slog.i(TAG, "Setting brightess off: " + offMask);
- setLightBrightness(offMask, PowerManager.BRIGHTNESS_OFF);
- }
- if (dimMask != 0) {
- int brightness = mScreenBrightnessDim;
- if ((newState & BATTERY_LOW_BIT) != 0 &&
- brightness > PowerManager.BRIGHTNESS_LOW_BATTERY) {
- brightness = PowerManager.BRIGHTNESS_LOW_BATTERY;
- }
- if (DEBUG) Slog.i(TAG, "Setting brightess dim " + brightness + ": " + dimMask);
- setLightBrightness(dimMask, brightness);
- }
- if (onMask != 0) {
- int brightness = getPreferredBrightness();
- if ((newState & BATTERY_LOW_BIT) != 0 &&
- brightness > PowerManager.BRIGHTNESS_LOW_BATTERY) {
- brightness = PowerManager.BRIGHTNESS_LOW_BATTERY;
+ // Stop dreaming if needed.
+ // It's possible that something else changed to make us need to start the dream again.
+ // If so, then the power manager will have posted another message to the handler
+ // to take care of it later.
+ if (mDreamManager != null) {
+ try {
+ if (!continueDreaming && isDreaming) {
+ Slog.i(TAG, "Leaving dreamland.");
+ mDreamManager.awaken();
+ }
+ } catch (RemoteException ex) {
}
- if (DEBUG) Slog.i(TAG, "Setting brightess on " + brightness + ": " + onMask);
- setLightBrightness(onMask, brightness);
}
}
/**
- * Note: by design this class does not hold mLocks while calling native methods.
- * Nor should it. Ever.
+ * Returns true if the device is allowed to dream in its current state,
+ * assuming there has been no recent user activity and no wake locks are held.
*/
- class ScreenBrightnessAnimator extends HandlerThread {
- static final int ANIMATE_LIGHTS = 10;
- static final int ANIMATE_POWER_OFF = 11;
- volatile int startValue;
- volatile int endValue;
- volatile int startSensorValue;
- volatile int endSensorValue;
- volatile int currentValue;
- private int currentMask;
- private int duration;
- private long startTimeMillis;
- private final String prefix;
-
- public ScreenBrightnessAnimator(String name, int priority) {
- super(name, priority);
- prefix = name;
- }
-
- @Override
- protected void onLooperPrepared() {
- mScreenBrightnessHandler = new Handler() {
- public void handleMessage(Message msg) {
- int brightnessMode = (mAutoBrightessEnabled && !mInitialAnimation
- ? LightsService.BRIGHTNESS_MODE_SENSOR
- : LightsService.BRIGHTNESS_MODE_USER);
- if (msg.what == ANIMATE_LIGHTS) {
- final int mask = msg.arg1;
- int value = msg.arg2;
- long tStart = SystemClock.uptimeMillis();
- if ((mask & SCREEN_BRIGHT_BIT) != 0) {
- if (DEBUG_LIGHT_ANIMATION) Slog.v(TAG, "Set brightness: " + value);
- mLcdLight.setBrightness(value, brightnessMode);
- }
- long elapsed = SystemClock.uptimeMillis() - tStart;
- if ((mask & BUTTON_BRIGHT_BIT) != 0) {
- mButtonLight.setBrightness(value);
- }
- if ((mask & KEYBOARD_BRIGHT_BIT) != 0) {
- mKeyboardLight.setBrightness(value);
- }
-
- if (elapsed > 100) {
- Slog.e(TAG, "Excessive delay setting brightness: " + elapsed
- + "ms, mask=" + mask);
- }
-
- // Throttle brightness updates to frame refresh rate
- int delay = elapsed < NOMINAL_FRAME_TIME_MS ? NOMINAL_FRAME_TIME_MS : 1;
- synchronized(this) {
- currentValue = value;
- }
- animateInternal(mask, false, delay);
- } else if (msg.what == ANIMATE_POWER_OFF) {
- int mode = msg.arg1;
- nativeStartSurfaceFlingerAnimation(mode);
- }
- }
- };
- synchronized (this) {
- mInitComplete = true;
- notifyAll();
- }
- }
-
- private void animateInternal(int mask, boolean turningOff, int delay) {
- synchronized (this) {
- if (currentValue != endValue) {
- final long now = SystemClock.elapsedRealtime();
- final int elapsed = (int) (now - startTimeMillis);
- int newValue;
- if (elapsed < duration) {
- int delta = endValue - startValue;
- newValue = startValue + delta * elapsed / duration;
- newValue = Math.max(PowerManager.BRIGHTNESS_OFF, newValue);
- newValue = Math.min(PowerManager.BRIGHTNESS_ON, newValue);
- // Optimization to delay next step until a change will occur.
- if (delay > 0 && newValue == currentValue) {
- final int timePerStep = duration / Math.abs(delta);
- delay = Math.min(duration - elapsed, timePerStep);
- newValue += delta < 0 ? -1 : 1;
- }
- // adjust the peak sensor value until we get to the target sensor value
- delta = endSensorValue - startSensorValue;
- mHighestLightSensorValue = startSensorValue + delta * elapsed / duration;
- } else {
- newValue = endValue;
- mHighestLightSensorValue = endSensorValue;
- if (endValue > 0) {
- mInitialAnimation = false;
- }
- }
-
- if (DEBUG_LIGHT_ANIMATION) {
- Slog.v(TAG, "Animating light: " + "start:" + startValue
- + ", end:" + endValue + ", elapsed:" + elapsed
- + ", duration:" + duration + ", current:" + currentValue
- + ", newValue:" + newValue
- + ", delay:" + delay
- + ", highestSensor:" + mHighestLightSensorValue);
- }
+ private boolean canDreamLocked() {
+ return mIsPowered && mDreamsSupportedConfig && mDreamsEnabledSetting;
+ }
- if (turningOff && !mHeadless && !mAnimateScreenLights) {
- int mode = mScreenOffReason == OFF_BECAUSE_OF_PROX_SENSOR
- ? 0 : mAnimationSetting;
- if (DEBUG_LIGHT_ANIMATION) {
- Slog.v(TAG, "Doing power-off anim, mode=" + mode);
- }
- mScreenBrightnessHandler.obtainMessage(ANIMATE_POWER_OFF, mode, 0)
- .sendToTarget();
- }
- mScreenBrightnessHandler.removeMessages(
- ScreenBrightnessAnimator.ANIMATE_LIGHTS);
- Message msg = mScreenBrightnessHandler
- .obtainMessage(ANIMATE_LIGHTS, mask, newValue);
- mScreenBrightnessHandler.sendMessageDelayed(msg, delay);
- }
+ /**
+ * Called when a dream is ending to figure out what to do next.
+ */
+ private void handleDreamFinishedLocked() {
+ if (mWakefulness == WAKEFULNESS_NAPPING
+ || mWakefulness == WAKEFULNESS_DREAMING) {
+ if (isItBedTimeYetLocked()) {
+ goToSleepNoUpdateLocked(SystemClock.uptimeMillis(),
+ PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
+ updatePowerStateLocked();
+ } else {
+ wakeUpNoUpdateLocked(SystemClock.uptimeMillis());
+ updatePowerStateLocked();
}
}
+ }
- public void dump(PrintWriter pw, String string) {
- pw.println(string);
- pw.println(" animating: " + "start:" + startValue + ", end:" + endValue
- + ", duration:" + duration + ", current:" + currentValue);
- pw.println(" startSensorValue:" + startSensorValue
- + " endSensorValue:" + endSensorValue);
- pw.println(" startTimeMillis:" + startTimeMillis
- + " now:" + SystemClock.elapsedRealtime());
- pw.println(" currentMask:" + dumpPowerState(currentMask));
- }
-
- public void animateTo(int target, int mask, int animationDuration) {
- animateTo(target, mHighestLightSensorValue, mask, animationDuration);
- }
- public void animateTo(int target, int sensorTarget, int mask, int animationDuration) {
- synchronized(this) {
- if ((mask & SCREEN_BRIGHT_BIT) == 0) {
- // We only animate keyboard and button when passed in with SCREEN_BRIGHT_BIT.
- if ((mask & BUTTON_BRIGHT_BIT) != 0) {
- mButtonLight.setBrightness(target);
- }
- if ((mask & KEYBOARD_BRIGHT_BIT) != 0) {
- mKeyboardLight.setBrightness(target);
- }
- return;
- }
- if (isAnimating() && (mask ^ currentMask) != 0) {
- // current animation is unrelated to new animation, jump to final values
- cancelAnimation();
- }
- if (mInitialAnimation) {
- // jump to final value in one step the first time the brightness is set
- animationDuration = 0;
- if (target > 0) {
- mInitialAnimation = false;
- }
- }
- startValue = currentValue;
- endValue = target;
- startSensorValue = mHighestLightSensorValue;
- endSensorValue = sensorTarget;
- currentMask = mask;
- duration = (int) (mWindowScaleAnimation * animationDuration);
- startTimeMillis = SystemClock.elapsedRealtime();
-
- if (DEBUG_LIGHT_ANIMATION) {
- Slog.v(TAG, "animateTo(target=" + target
- + ", sensor=" + sensorTarget
- + ", mask=" + mask
- + ", duration=" + animationDuration +")"
- + ", currentValue=" + currentValue
- + ", startTime=" + startTimeMillis);
+ /**
+ * Updates the display power state asynchronously.
+ * When the update is finished, mDisplayReady will be set to true. The display
+ * controller posts a message to tell us when the actual display power state
+ * has been updated so we come back here to double-check and finish up.
+ *
+ * This function recalculates the display power state each time.
+ */
+ private void updateDisplayPowerStateLocked(int dirty) {
+ if ((dirty & (DIRTY_WAKE_LOCKS | DIRTY_USER_ACTIVITY | DIRTY_WAKEFULNESS
+ | DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED | DIRTY_BOOT_COMPLETED
+ | DIRTY_SETTINGS)) != 0) {
+ int newScreenState = getDesiredScreenPowerState();
+ if (newScreenState != mDisplayPowerRequest.screenState) {
+ if (newScreenState == DisplayPowerRequest.SCREEN_STATE_OFF
+ && mDisplayPowerRequest.screenState
+ != DisplayPowerRequest.SCREEN_STATE_OFF) {
+ mLastScreenOffEventElapsedRealTime = SystemClock.elapsedRealtime();
}
- if (target != currentValue) {
- final boolean doScreenAnim = (mask & (SCREEN_BRIGHT_BIT | SCREEN_ON_BIT)) != 0;
- final boolean turningOff = endValue == PowerManager.BRIGHTNESS_OFF;
- if (turningOff && doScreenAnim) {
- // Cancel all pending animations since we're turning off
- mScreenBrightnessHandler.removeCallbacksAndMessages(null);
- screenOffFinishedAnimatingLocked(mScreenOffReason);
- duration = 200; // TODO: how long should this be?
- }
- if (doScreenAnim) {
- animateInternal(mask, turningOff, 0);
- }
- // TODO: Handle keyboard light animation when we have devices that support it
- }
+ mDisplayPowerRequest.screenState = newScreenState;
+ nativeSetPowerState(
+ newScreenState != DisplayPowerRequest.SCREEN_STATE_OFF,
+ newScreenState == DisplayPowerRequest.SCREEN_STATE_BRIGHT);
}
- }
- public int getCurrentBrightness() {
- synchronized (this) {
- return currentValue;
+ int screenBrightness = mScreenBrightnessSettingDefault;
+ boolean autoBrightness = (mScreenBrightnessModeSetting ==
+ Settings.System.SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
+ if (isValidBrightness(mScreenBrightnessOverrideFromWindowManager)) {
+ screenBrightness = mScreenBrightnessOverrideFromWindowManager;
+ autoBrightness = false;
+ } else if (isValidBrightness(mTemporaryScreenBrightnessSettingOverride)) {
+ screenBrightness = mTemporaryScreenBrightnessSettingOverride;
+ } else if (isValidBrightness(mScreenBrightnessSetting)) {
+ screenBrightness = mScreenBrightnessSetting;
}
- }
-
- public boolean isAnimating() {
- synchronized (this) {
- return currentValue != endValue;
+ if (autoBrightness) {
+ screenBrightness = mScreenBrightnessSettingDefault;
}
- }
+ screenBrightness = Math.max(Math.min(screenBrightness,
+ mScreenBrightnessSettingMaximum), mScreenBrightnessSettingMinimum);
+ mDisplayPowerRequest.screenBrightness = screenBrightness;
+ mDisplayPowerRequest.useAutoBrightness = autoBrightness;
- public void cancelAnimation() {
- animateTo(endValue, currentMask, 0);
- }
- }
+ mDisplayPowerRequest.useProximitySensor = shouldUseProximitySensorLocked();
- private void setLightBrightness(int mask, int value) {
- mScreenBrightnessAnimator.animateTo(value, mask, 0);
- }
+ mDisplayReady = mDisplayPowerController.requestPowerState(mDisplayPowerRequest,
+ mRequestWaitForNegativeProximity);
+ mRequestWaitForNegativeProximity = false;
- private int getPreferredBrightness() {
- int brightness = mScreenBrightnessSetting;
- if (mScreenBrightnessOverride >= 0) {
- brightness = mScreenBrightnessOverride;
- } else if (mLightSensorScreenBrightness >= 0 && mUseSoftwareAutoBrightness
- && mAutoBrightessEnabled) {
- brightness = mLightSensorScreenBrightness;
- }
- // Don't let applications turn the screen all the way off
- return Math.max(brightness, mScreenBrightnessDim);
- }
-
- private int applyButtonState(int state) {
- int brightness = -1;
- if ((state & BATTERY_LOW_BIT) != 0) {
- // do not override brightness if the battery is low
- return state;
- }
- if (mButtonBrightnessOverride >= 0) {
- brightness = mButtonBrightnessOverride;
- } else if (mLightSensorButtonBrightness >= 0 && mUseSoftwareAutoBrightness) {
- brightness = mLightSensorButtonBrightness;
- }
- if (brightness > 0) {
- return state | BUTTON_BRIGHT_BIT;
- } else if (brightness == 0) {
- return state & ~BUTTON_BRIGHT_BIT;
- } else {
- return state;
+ if (DEBUG_SPEW) {
+ Slog.d(TAG, "updateScreenStateLocked: displayReady=" + mDisplayReady
+ + ", newScreenState=" + newScreenState
+ + ", mWakefulness=" + mWakefulness
+ + ", mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary)
+ + ", mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary)
+ + ", mBootCompleted=" + mBootCompleted);
+ }
}
}
- private int applyKeyboardState(int state) {
- int brightness = -1;
- if ((state & BATTERY_LOW_BIT) != 0) {
- // do not override brightness if the battery is low
- return state;
- }
- if (!mKeyboardVisible) {
- brightness = 0;
- } else if (mButtonBrightnessOverride >= 0) {
- brightness = mButtonBrightnessOverride;
- } else if (mLightSensorKeyboardBrightness >= 0 && mUseSoftwareAutoBrightness) {
- brightness = mLightSensorKeyboardBrightness;
- }
- if (brightness > 0) {
- return state | KEYBOARD_BRIGHT_BIT;
- } else if (brightness == 0) {
- return state & ~KEYBOARD_BRIGHT_BIT;
- } else {
- return state;
- }
+ private static boolean isValidBrightness(int value) {
+ return value >= 0 && value <= 255;
}
- public boolean isScreenOn() {
- synchronized (mLocks) {
- return (mPowerState & SCREEN_ON_BIT) != 0;
+ private int getDesiredScreenPowerState() {
+ if (mWakefulness == WAKEFULNESS_ASLEEP) {
+ return DisplayPowerRequest.SCREEN_STATE_OFF;
}
- }
- boolean isScreenBright() {
- synchronized (mLocks) {
- return (mPowerState & SCREEN_BRIGHT) == SCREEN_BRIGHT;
+ if ((mWakeLockSummary & WAKE_LOCK_SCREEN_BRIGHT) != 0
+ || (mUserActivitySummary & USER_ACTIVITY_SCREEN_BRIGHT) != 0
+ || !mBootCompleted) {
+ return DisplayPowerRequest.SCREEN_STATE_BRIGHT;
}
- }
- private boolean isScreenTurningOffLocked() {
- return (mScreenBrightnessAnimator.isAnimating()
- && mScreenBrightnessAnimator.endValue == PowerManager.BRIGHTNESS_OFF
- && (mScreenBrightnessAnimator.currentMask & SCREEN_BRIGHT_BIT) != 0);
+ return DisplayPowerRequest.SCREEN_STATE_DIM;
}
- private boolean shouldLog(long time) {
- synchronized (mLocks) {
- if (time > (mWarningSpewThrottleTime + (60*60*1000))) {
- mWarningSpewThrottleTime = time;
- mWarningSpewThrottleCount = 0;
- return true;
- } else if (mWarningSpewThrottleCount < 30) {
- mWarningSpewThrottleCount++;
- return true;
- } else {
- return false;
- }
- }
- }
-
- private void forceUserActivityLocked() {
- if (isScreenTurningOffLocked()) {
- // cancel animation so userActivity will succeed
- mScreenBrightnessAnimator.cancelAnimation();
+ private final DisplayPowerController.Callbacks mDisplayPowerControllerCallbacks =
+ new DisplayPowerController.Callbacks() {
+ @Override
+ public void onStateChanged() {
+ mDirty |= DIRTY_ACTUAL_DISPLAY_POWER_STATE_UPDATED;
+ updatePowerStateLocked();
}
- boolean savedActivityAllowed = mUserActivityAllowed;
- mUserActivityAllowed = true;
- userActivity(SystemClock.uptimeMillis(), false);
- mUserActivityAllowed = savedActivityAllowed;
- }
-
- public void userActivityWithForce(long time, boolean noChangeLights, boolean force) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
- userActivity(time, -1, noChangeLights, PowerManager.USER_ACTIVITY_EVENT_OTHER, force, false);
- }
- public void userActivity(long time, boolean noChangeLights) {
- if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER)
- != PackageManager.PERMISSION_GRANTED) {
- if (shouldLog(time)) {
- Slog.w(TAG, "Caller does not have DEVICE_POWER permission. pid="
- + Binder.getCallingPid() + " uid=" + Binder.getCallingUid());
- }
- return;
+ @Override
+ public void onProximityNegative() {
+ userActivityNoUpdateLocked(SystemClock.uptimeMillis(),
+ PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
+ updatePowerStateLocked();
}
+ };
- userActivity(time, -1, noChangeLights, PowerManager.USER_ACTIVITY_EVENT_OTHER, false, false);
- }
-
- public void userActivity(long time, boolean noChangeLights, int eventType) {
- userActivity(time, -1, noChangeLights, eventType, false, false);
- }
-
- public void userActivity(long time, boolean noChangeLights, int eventType, boolean force) {
- userActivity(time, -1, noChangeLights, eventType, force, false);
+ private boolean shouldUseProximitySensorLocked() {
+ return (mWakeLockSummary & WAKE_LOCK_PROXIMITY_SCREEN_OFF) != 0;
}
- /*
- * Reset the user activity timeout to now + timeout. This overrides whatever else is going
- * on with user activity. Don't use this function.
+ /**
+ * Updates the suspend blocker that keeps the CPU alive.
+ *
+ * This function must have no other side-effects.
*/
- public void clearUserActivityTimeout(long now, long timeout) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
- Slog.i(TAG, "clearUserActivity for " + timeout + "ms from now");
- userActivity(now, timeout, false, PowerManager.USER_ACTIVITY_EVENT_OTHER, false, false);
- }
-
- private void userActivity(long time, long timeoutOverride, boolean noChangeLights,
- int eventType, boolean force, boolean ignoreIfScreenOff) {
-
- if (((mPokey & POKE_LOCK_IGNORE_TOUCH_EVENTS) != 0) && (eventType == PowerManager.USER_ACTIVITY_EVENT_TOUCH)) {
- if (false) {
- Slog.d(TAG, "dropping touch mPokey=0x" + Integer.toHexString(mPokey));
- }
- return;
- }
-
- synchronized (mLocks) {
- if (DEBUG) {
- Slog.d(TAG, "userActivity mLastEventTime=" + mLastEventTime + " time=" + time
- + " mUserActivityAllowed=" + mUserActivityAllowed
- + " mUserState=0x" + Integer.toHexString(mUserState)
- + " mWakeLockState=0x" + Integer.toHexString(mWakeLockState)
- + " mProximitySensorActive=" + mProximitySensorActive
- + " timeoutOverride=" + timeoutOverride
- + " force=" + force);
- }
- // ignore user activity if we are in the process of turning off the screen
- if (isScreenTurningOffLocked()) {
- Slog.d(TAG, "ignoring user activity while turning off screen");
- return;
- }
- // ignore if the caller doesn't want this to allow the screen to turn
- // on, and the screen is currently off.
- if (ignoreIfScreenOff && (mPowerState & SCREEN_ON_BIT) == 0) {
- return;
- }
- // Disable proximity sensor if if user presses power key while we are in the
- // "waiting for proximity sensor to go negative" state.
- if (mProximitySensorActive && mProximityWakeLockCount == 0) {
- mProximitySensorActive = false;
- }
- if (mLastEventTime <= time || force) {
- mLastEventTime = time;
- if ((mUserActivityAllowed && !mProximitySensorActive) || force) {
- // Only turn on button backlights if a button was pressed
- // and auto brightness is disabled
- if (eventType == PowerManager.USER_ACTIVITY_EVENT_BUTTON && !mUseSoftwareAutoBrightness) {
- mUserState = (mKeyboardVisible ? ALL_BRIGHT : SCREEN_BUTTON_BRIGHT);
- } else {
- // don't clear button/keyboard backlights when the screen is touched.
- mUserState |= SCREEN_BRIGHT;
- }
-
- int uid = Binder.getCallingUid();
- long ident = Binder.clearCallingIdentity();
- try {
- mBatteryStats.noteUserActivity(uid, eventType);
- } catch (RemoteException e) {
- // Ignore
- } finally {
- Binder.restoreCallingIdentity(ident);
- }
-
- mWakeLockState = mLocks.reactivateScreenLocksLocked();
- setPowerState(mUserState | mWakeLockState, noChangeLights,
- WindowManagerPolicy.OFF_BECAUSE_OF_USER);
- setTimeoutLocked(time, timeoutOverride, SCREEN_BRIGHT);
+ private void updateSuspendBlockerLocked() {
+ boolean wantCpu = isCpuNeededLocked();
+ if (wantCpu != mHoldingWakeLockSuspendBlocker) {
+ mHoldingWakeLockSuspendBlocker = wantCpu;
+ if (wantCpu) {
+ if (DEBUG) {
+ Slog.d(TAG, "updateSuspendBlockerLocked: Acquiring suspend blocker.");
}
+ mWakeLockSuspendBlocker.acquire();
+ } else {
+ if (DEBUG) {
+ Slog.d(TAG, "updateSuspendBlockerLocked: Releasing suspend blocker.");
+ }
+ mWakeLockSuspendBlocker.release();
}
}
+ }
- if (mPolicy != null) {
- mPolicy.userActivity();
- }
+ private boolean isCpuNeededLocked() {
+ return !mBootCompleted
+ || mWakeLockSummary != 0
+ || mUserActivitySummary != 0
+ || mDisplayPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF
+ || !mDisplayReady;
}
- private int getAutoBrightnessValue(int sensorValue, int[] values) {
+ @Override // Binder call
+ public boolean isScreenOn() {
+ final long ident = Binder.clearCallingIdentity();
try {
- int i;
- for (i = 0; i < mAutoBrightnessLevels.length; i++) {
- if (sensorValue < mAutoBrightnessLevels[i]) {
- break;
- }
- }
- // This is the range of brightness values that we can use.
- final int minval = values[0];
- final int maxval = values[mAutoBrightnessLevels.length];
- // This is the range we will be scaling. We put some padding
- // at the low and high end to give the adjustment a little better
- // impact on the actual observed value.
- final int range = (maxval-minval) + LIGHT_SENSOR_RANGE_EXPANSION;
- // This is the desired brightness value from 0.0 to 1.0.
- float valf = ((values[i]-minval+(LIGHT_SENSOR_RANGE_EXPANSION/2))/(float)range);
- // Apply a scaling to the value based on the adjustment.
- if (mLightSensorAdjustSetting > 0 && mLightSensorAdjustSetting <= 1) {
- float adj = (float)Math.sqrt(1.0f-mLightSensorAdjustSetting);
- if (adj <= .00001) {
- valf = 1;
- } else {
- valf /= adj;
- }
- } else if (mLightSensorAdjustSetting < 0 && mLightSensorAdjustSetting >= -1) {
- float adj = (float)Math.sqrt(1.0f+mLightSensorAdjustSetting);
- valf *= adj;
- }
- // Apply an additional offset to the value based on the adjustment.
- valf += mLightSensorAdjustSetting/LIGHT_SENSOR_OFFSET_SCALE;
- // Convert the 0.0-1.0 value back to a brightness integer.
- int val = (int)((valf*range)+minval) - (LIGHT_SENSOR_RANGE_EXPANSION/2);
- if (val < minval) val = minval;
- else if (val > maxval) val = maxval;
- return val;
- } catch (Exception e) {
- // guard against null pointer or index out of bounds errors
- Slog.e(TAG, "Values array must be non-empty and must be one element longer than "
- + "the auto-brightness levels array. Check config.xml.", e);
- return 255;
- }
- }
-
- private Runnable mProximityTask = new Runnable() {
- public void run() {
- synchronized (mLocks) {
- if (mProximityPendingValue != -1) {
- proximityChangedLocked(mProximityPendingValue == 1);
- mProximityPendingValue = -1;
- }
- if (mProximityPartialLock.isHeld()) {
- mProximityPartialLock.release();
- }
- }
- }
- };
-
- private Runnable mAutoBrightnessTask = new Runnable() {
- public void run() {
- synchronized (mLocks) {
- if (mLightSensorPendingDecrease || mLightSensorPendingIncrease) {
- int value = (int)mLightSensorPendingValue;
- mLightSensorPendingDecrease = false;
- mLightSensorPendingIncrease = false;
- lightSensorChangedLocked(value, false);
- }
- }
- }
- };
-
- /** used to prevent lightsensor changes while turning on. */
- private boolean mInitialAnimation = true;
-
- private void dockStateChanged(int state) {
- synchronized (mLocks) {
- mIsDocked = (state != Intent.EXTRA_DOCK_STATE_UNDOCKED);
- if (mIsDocked) {
- // allow brightness to decrease when docked
- mHighestLightSensorValue = -1;
- }
- if ((mPowerState & SCREEN_ON_BIT) != 0) {
- // force lights recalculation
- int value = (int)mLightSensorValue;
- mLightSensorValue = -1;
- lightSensorChangedLocked(value, false);
- }
+ return isScreenOnInternal();
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
}
- private void lightSensorChangedLocked(int value, boolean immediate) {
- if (DEBUG_LIGHT_SENSOR) {
- Slog.d(TAG, "lightSensorChangedLocked value=" + value + " immediate=" + immediate);
+ private boolean isScreenOnInternal() {
+ synchronized (mLock) {
+ return !mSystemReady
+ || mDisplayPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF;
}
+ }
- // Don't do anything if the screen is off.
- if ((mPowerState & SCREEN_ON_BIT) == 0) {
- if (DEBUG_LIGHT_SENSOR) {
- Slog.d(TAG, "dropping lightSensorChangedLocked because screen is off");
- }
- return;
- }
-
- if (mLightSensorValue != value) {
- mLightSensorValue = value;
- if ((mPowerState & BATTERY_LOW_BIT) == 0) {
- // use maximum light sensor value seen since screen went on for LCD to avoid flicker
- // we only do this if we are undocked, since lighting should be stable when
- // stationary in a dock.
- int lcdValue = getAutoBrightnessValue(value, mLcdBacklightValues);
- int buttonValue = getAutoBrightnessValue(value, mButtonBacklightValues);
- int keyboardValue;
- if (mKeyboardVisible) {
- keyboardValue = getAutoBrightnessValue(value, mKeyboardBacklightValues);
- } else {
- keyboardValue = 0;
- }
- mLightSensorScreenBrightness = lcdValue;
- mLightSensorButtonBrightness = buttonValue;
- mLightSensorKeyboardBrightness = keyboardValue;
-
- if (DEBUG_LIGHT_SENSOR) {
- Slog.d(TAG, "lcdValue " + lcdValue);
- Slog.d(TAG, "buttonValue " + buttonValue);
- Slog.d(TAG, "keyboardValue " + keyboardValue);
- }
-
- if (mAutoBrightessEnabled && mScreenBrightnessOverride < 0) {
- if (!mSkippedScreenOn && !mInitialAnimation) {
- final int steps;
- if (immediate) {
- steps = IMMEDIATE_ANIM_STEPS;
- } else {
- synchronized (mScreenBrightnessAnimator) {
- if (mScreenBrightnessAnimator.currentValue <= lcdValue) {
- steps = AUTOBRIGHTNESS_ANIM_STEPS;
- } else {
- steps = AUTODIMNESS_ANIM_STEPS;
- }
- }
- }
- mScreenBrightnessAnimator.animateTo(lcdValue, value,
- SCREEN_BRIGHT_BIT, steps * NOMINAL_FRAME_TIME_MS);
- }
- }
- if (mButtonBrightnessOverride < 0) {
- mButtonLight.setBrightness(buttonValue);
- }
- if (mButtonBrightnessOverride < 0 || !mKeyboardVisible) {
- mKeyboardLight.setBrightness(keyboardValue);
- }
- }
- }
+ private void handleBatteryStateChangedLocked() {
+ mDirty |= DIRTY_BATTERY_STATE;
+ updatePowerStateLocked();
}
- /**
- * The user requested that we go to sleep (probably with the power button).
- * This overrides all wake locks that are held.
- */
- public void goToSleep(long time)
- {
- goToSleepWithReason(time, WindowManagerPolicy.OFF_BECAUSE_OF_USER);
+ private void handleBootCompletedLocked() {
+ final long now = SystemClock.uptimeMillis();
+ mBootCompleted = true;
+ mDirty |= DIRTY_BOOT_COMPLETED;
+ userActivityNoUpdateLocked(
+ now, PowerManager.USER_ACTIVITY_EVENT_OTHER, 0, Process.SYSTEM_UID);
+ updatePowerStateLocked();
}
- /**
- * The user requested that we go to sleep (probably with the power button).
- * This overrides all wake locks that are held.
- */
- public void goToSleepWithReason(long time, int reason)
- {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
- synchronized (mLocks) {
- goToSleepLocked(time, reason);
- }
+ private void handleDockStateChangedLocked(int dockState) {
+ // TODO
}
/**
* Reboot the device immediately, passing 'reason' (may be null)
* to the underlying __reboot system call. Should not return.
*/
- public void reboot(String reason)
- {
+ @Override // Binder call
+ public void reboot(String reason) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
- if (mHandler == null || !ActivityManagerNative.isSystemReady()) {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ rebootInternal(reason);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ private void rebootInternal(final String reason) {
+ if (mHandler == null || !mSystemReady) {
throw new IllegalStateException("Too early to call reboot()");
}
- final String finalReason = reason;
Runnable runnable = new Runnable() {
public void run() {
synchronized (this) {
- ShutdownThread.reboot(mContext, finalReason, false);
+ ShutdownThread.reboot(mContext, reason, false);
}
-
}
};
+
// ShutdownThread must run on a looper capable of displaying the UI.
- mHandler.post(runnable);
+ Message msg = Message.obtain(mHandler, runnable);
+ msg.setAsynchronous(true);
+ mHandler.sendMessage(msg);
// PowerManager.reboot() is documented not to return so just wait for the inevitable.
synchronized (runnable) {
@@ -2798,11 +1463,23 @@ public class PowerManagerService extends IPowerManager.Stub
* Crash the runtime (causing a complete restart of the Android framework).
* Requires REBOOT permission. Mostly for testing. Should not return.
*/
- public void crash(final String message)
- {
+ @Override // Binder call
+ public void crash(String message) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.REBOOT, null);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ crashInternal(message);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
+ }
+ }
+
+ private void crashInternal(final String message) {
Thread t = new Thread("PowerManagerService.crash()") {
- public void run() { throw new RuntimeException(message); }
+ public void run() {
+ throw new RuntimeException(message);
+ }
};
try {
t.start();
@@ -2812,581 +1489,554 @@ public class PowerManagerService extends IPowerManager.Stub
}
}
- private void goToSleepLocked(long time, int reason) {
- if (DEBUG) {
- Exception ex = new Exception();
- ex.fillInStackTrace();
- Slog.d(TAG, "goToSleep mLastEventTime=" + mLastEventTime + " time=" + time
- + " reason=" + reason, ex);
- }
-
- if (mLastEventTime <= time) {
- mLastEventTime = time;
- // cancel all of the wake locks
- mWakeLockState = SCREEN_OFF;
- int N = mLocks.size();
- int numCleared = 0;
- boolean proxLock = false;
- for (int i=0; i<N; i++) {
- WakeLock wl = mLocks.get(i);
- if (isScreenLock(wl.flags)) {
- if (((wl.flags & LOCK_MASK) == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)
- && reason == WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR) {
- proxLock = true;
- } else {
- mLocks.get(i).activated = false;
- numCleared++;
- }
- }
- }
- if (!proxLock) {
- mProxIgnoredBecauseScreenTurnedOff = true;
- if (DEBUG_PROXIMITY_SENSOR) {
- Slog.d(TAG, "setting mProxIgnoredBecauseScreenTurnedOff");
- }
- }
- EventLog.writeEvent(EventLogTags.POWER_SLEEP_REQUESTED, numCleared);
- mStillNeedSleepNotification = true;
- mUserState = SCREEN_OFF;
- setPowerState(SCREEN_OFF, false, reason);
- cancelTimerLocked();
+ @Override // Binder call
+ public void clearUserActivityTimeout(long now, long timeout) {
+ // TODO Auto-generated method stub
+ // Only used by phone app, delete this
+ }
+
+ @Override // Binder call
+ public void setPokeLock(int pokey, IBinder lock, String tag) {
+ // TODO Auto-generated method stub
+ // Only used by phone app, delete this
+ }
+
+ /**
+ * Set the setting that determines whether the device stays on when plugged in.
+ * The argument is a bit string, with each bit specifying a power source that,
+ * when the device is connected to that source, causes the device to stay on.
+ * See {@link android.os.BatteryManager} for the list of power sources that
+ * can be specified. Current values include {@link android.os.BatteryManager#BATTERY_PLUGGED_AC}
+ * and {@link android.os.BatteryManager#BATTERY_PLUGGED_USB}
+ *
+ * Used by "adb shell svc power stayon ..."
+ *
+ * @param val an {@code int} containing the bits that specify which power sources
+ * should cause the device to stay on.
+ */
+ @Override // Binder call
+ public void setStayOnSetting(int val) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.WRITE_SETTINGS, null);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ setStayOnSettingInternal(val);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
}
- public long timeSinceScreenOn() {
- synchronized (mLocks) {
- if ((mPowerState & SCREEN_ON_BIT) != 0) {
- return 0;
- }
- return SystemClock.elapsedRealtime() - mScreenOffTime;
+ private void setStayOnSettingInternal(int val) {
+ Settings.System.putInt(mContext.getContentResolver(),
+ Settings.System.STAY_ON_WHILE_PLUGGED_IN, val);
+ }
+
+ /**
+ * Used by device administration to set the maximum screen off timeout.
+ *
+ * This method must only be called by the device administration policy manager.
+ */
+ @Override // Binder call
+ public void setMaximumScreenOffTimeoutFromDeviceAdmin(int timeMs) {
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ setMaximumScreenOffTimeoutFromDeviceAdminInternal(timeMs);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
}
- public void setKeyboardVisibility(boolean visible) {
- synchronized (mLocks) {
- if (DEBUG) {
- Slog.d(TAG, "setKeyboardVisibility: " + visible);
- }
- if (mKeyboardVisible != visible) {
- mKeyboardVisible = visible;
- // don't signal user activity if the screen is off; other code
- // will take care of turning on due to a true change to the lid
- // switch and synchronized with the lock screen.
- if ((mPowerState & SCREEN_ON_BIT) != 0) {
- if (mUseSoftwareAutoBrightness) {
- // force recompute of backlight values
- if (mLightSensorValue >= 0) {
- int value = (int)mLightSensorValue;
- mLightSensorValue = -1;
- lightSensorChangedLocked(value, false);
- }
- }
- userActivity(SystemClock.uptimeMillis(), false, PowerManager.USER_ACTIVITY_EVENT_BUTTON, true);
- }
- }
+ private void setMaximumScreenOffTimeoutFromDeviceAdminInternal(int timeMs) {
+ synchronized (mLock) {
+ mMaximumScreenOffTimeoutFromDeviceAdmin = timeMs;
+ mDirty |= DIRTY_SETTINGS;
+ updatePowerStateLocked();
}
}
+ private boolean isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked() {
+ return mMaximumScreenOffTimeoutFromDeviceAdmin >= 0
+ && mMaximumScreenOffTimeoutFromDeviceAdmin < Integer.MAX_VALUE;
+ }
+
+ @Override // Binder call
+ public void preventScreenOn(boolean prevent) {
+ // TODO Auto-generated method stub
+ // Only used by phone app, delete this
+ }
+
/**
- * When the keyguard is up, it manages the power state, and userActivity doesn't do anything.
- * When disabling user activity we also reset user power state so the keyguard can reset its
- * short screen timeout when keyguard is unhidden.
+ * Used by the phone application to make the attention LED flash when ringing.
*/
- public void enableUserActivity(boolean enabled) {
- if (DEBUG) {
- Slog.d(TAG, "enableUserActivity " + enabled);
- }
- synchronized (mLocks) {
- mUserActivityAllowed = enabled;
- if (!enabled) {
- // cancel timeout and clear mUserState so the keyguard can set a short timeout
- setTimeoutLocked(SystemClock.uptimeMillis(), 0);
- }
+ @Override // Binder call
+ public void setAttentionLight(boolean on, int color) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ setAttentionLightInternal(on, color);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
}
- private void setScreenBrightnessMode(int mode) {
- synchronized (mLocks) {
- boolean enabled = (mode == SCREEN_BRIGHTNESS_MODE_AUTOMATIC);
- if (mUseSoftwareAutoBrightness && mAutoBrightessEnabled != enabled) {
- mAutoBrightessEnabled = enabled;
- // This will get us a new value
- enableLightSensorLocked(mAutoBrightessEnabled && isScreenOn());
+ private void setAttentionLightInternal(boolean on, int color) {
+ LightsService.Light light;
+ synchronized (mLock) {
+ if (!mSystemReady) {
+ return;
}
+ light = mAttentionLight;
}
+
+ // Control light outside of lock.
+ light.setFlashing(color, LightsService.LIGHT_FLASH_HARDWARE, (on ? 3 : 0), 0);
}
- /** Sets the screen off timeouts:
- * mKeylightDelay
- * mDimDelay
- * mScreenOffDelay
- * */
- private void setScreenOffTimeoutsLocked() {
- if ((mPokey & POKE_LOCK_SHORT_TIMEOUT) != 0) {
- mKeylightDelay = mShortKeylightDelay; // Configurable via secure settings
- mDimDelay = -1;
- mScreenOffDelay = 0;
- } else if ((mPokey & POKE_LOCK_MEDIUM_TIMEOUT) != 0) {
- mKeylightDelay = MEDIUM_KEYLIGHT_DELAY;
- mDimDelay = -1;
- mScreenOffDelay = 0;
- } else {
- int totalDelay = mScreenOffTimeoutSetting;
- if (totalDelay > mMaximumScreenOffTimeout) {
- totalDelay = mMaximumScreenOffTimeout;
- }
- mKeylightDelay = LONG_KEYLIGHT_DELAY;
- if (totalDelay < 0) {
- // negative number means stay on as long as possible.
- mScreenOffDelay = mMaximumScreenOffTimeout;
- } else if (mKeylightDelay < totalDelay) {
- // subtract the time that the keylight delay. This will give us the
- // remainder of the time that we need to sleep to get the accurate
- // screen off timeout.
- mScreenOffDelay = totalDelay - mKeylightDelay;
- } else {
- mScreenOffDelay = 0;
- }
- if (mDimScreen && totalDelay >= (LONG_KEYLIGHT_DELAY + LONG_DIM_TIME)) {
- mDimDelay = mScreenOffDelay - LONG_DIM_TIME;
- mScreenOffDelay = LONG_DIM_TIME;
- } else {
- mDimDelay = -1;
+ /**
+ * Used by the Watchdog.
+ */
+ public long timeSinceScreenWasLastOn() {
+ synchronized (mLock) {
+ if (mDisplayPowerRequest.screenState != DisplayPowerRequest.SCREEN_STATE_OFF) {
+ return 0;
}
- }
- if (DEBUG) {
- Slog.d(TAG, "setScreenOffTimeouts mKeylightDelay=" + mKeylightDelay
- + " mDimDelay=" + mDimDelay + " mScreenOffDelay=" + mScreenOffDelay
- + " mDimScreen=" + mDimScreen);
+ return SystemClock.elapsedRealtime() - mLastScreenOffEventElapsedRealTime;
}
}
/**
- * Refreshes cached secure settings. Called once on startup, and
- * on subsequent changes to secure settings.
+ * Used by the window manager to override the screen brightness based on the
+ * current foreground activity.
+ *
+ * This method must only be called by the window manager.
+ *
+ * @param brightness The overridden brightness, or -1 to disable the override.
*/
- private void updateSettingsValues() {
- mShortKeylightDelay = Settings.Secure.getInt(
- mContext.getContentResolver(),
- Settings.Secure.SHORT_KEYLIGHT_DELAY_MS,
- SHORT_KEYLIGHT_DELAY_DEFAULT);
- // Slog.i(TAG, "updateSettingsValues(): mShortKeylightDelay now " + mShortKeylightDelay);
- }
-
- private class LockList extends ArrayList<WakeLock>
- {
- void addLock(WakeLock wl)
- {
- int index = getIndex(wl.binder);
- if (index < 0) {
- this.add(wl);
- }
+ public void setScreenBrightnessOverrideFromWindowManager(int brightness) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ setScreenBrightnessOverrideFromWindowManagerInternal(brightness);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
+ }
- WakeLock removeLock(IBinder binder)
- {
- int index = getIndex(binder);
- if (index >= 0) {
- return this.remove(index);
- } else {
- return null;
+ private void setScreenBrightnessOverrideFromWindowManagerInternal(int brightness) {
+ synchronized (mLock) {
+ if (mScreenBrightnessOverrideFromWindowManager != brightness) {
+ mScreenBrightnessOverrideFromWindowManager = brightness;
+ mDirty |= DIRTY_SETTINGS;
+ updatePowerStateLocked();
}
}
+ }
- int getIndex(IBinder binder)
- {
- int N = this.size();
- for (int i=0; i<N; i++) {
- if (this.get(i).binder == binder) {
- return i;
- }
- }
- return -1;
- }
-
- int gatherState()
- {
- int result = 0;
- int N = this.size();
- for (int i=0; i<N; i++) {
- WakeLock wl = this.get(i);
- if (wl.activated) {
- if (isScreenLock(wl.flags)) {
- result |= wl.minState;
- }
- }
- }
- return result;
+ /**
+ * Used by the window manager to override the button brightness based on the
+ * current foreground activity.
+ *
+ * This method must only be called by the window manager.
+ *
+ * @param brightness The overridden brightness, or -1 to disable the override.
+ */
+ public void setButtonBrightnessOverrideFromWindowManager(int brightness) {
+ // Do nothing.
+ // Button lights are not currently supported in the new implementation.
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
+ }
+
+ /**
+ * Used by the settings application and brightness control widgets to
+ * temporarily override the current screen brightness setting so that the
+ * user can observe the effect of an intended settings change without applying
+ * it immediately.
+ *
+ * The override will be canceled when the setting value is next updated.
+ *
+ * @param brightness The overridden brightness.
+ *
+ * @see Settings.System#SCREEN_BRIGHTNESS
+ */
+ @Override // Binder call
+ public void setTemporaryScreenBrightnessSettingOverride(int brightness) {
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
+
+ final long ident = Binder.clearCallingIdentity();
+ try {
+ setTemporaryScreenBrightnessSettingOverrideInternal(brightness);
+ } finally {
+ Binder.restoreCallingIdentity(ident);
}
+ }
- int reactivateScreenLocksLocked()
- {
- int result = 0;
- int N = this.size();
- for (int i=0; i<N; i++) {
- WakeLock wl = this.get(i);
- if (isScreenLock(wl.flags)) {
- wl.activated = true;
- result |= wl.minState;
- }
- }
- if (DEBUG_PROXIMITY_SENSOR) {
- Slog.d(TAG, "reactivateScreenLocksLocked mProxIgnoredBecauseScreenTurnedOff="
- + mProxIgnoredBecauseScreenTurnedOff);
+ private void setTemporaryScreenBrightnessSettingOverrideInternal(int brightness) {
+ synchronized (mLock) {
+ if (mTemporaryScreenBrightnessSettingOverride != brightness) {
+ mTemporaryScreenBrightnessSettingOverride = brightness;
+ mDirty |= DIRTY_SETTINGS;
+ updatePowerStateLocked();
}
- mProxIgnoredBecauseScreenTurnedOff = false;
- return result;
}
}
- public void setPolicy(WindowManagerPolicy p) {
- synchronized (mLocks) {
- mPolicy = p;
- mLocks.notifyAll();
- }
+ /**
+ * Used by the settings application and brightness control widgets to
+ * temporarily override the current screen auto-brightness adjustment setting so that the
+ * user can observe the effect of an intended settings change without applying
+ * it immediately.
+ *
+ * The override will be canceled when the setting value is next updated.
+ *
+ * @param adj The overridden brightness, or -1 to disable the override.
+ *
+ * @see Settings.System#SCREEN_AUTO_BRIGHTNESS_ADJ
+ */
+ @Override // Binder call
+ public void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float adj) {
+ // Not implemented.
+ // The SCREEN_AUTO_BRIGHTNESS_ADJ setting is not currently supported.
+ mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
}
- WindowManagerPolicy getPolicyLocked() {
- while (mPolicy == null || !mDoneBooting) {
- try {
- mLocks.wait();
- } catch (InterruptedException e) {
- // Ignore
- }
+ /**
+ * Low-level function turn the device off immediately, without trying
+ * to be clean. Most people should use {@link ShutdownThread} for a clean shutdown.
+ */
+ public static void lowLevelShutdown() {
+ nativeShutdown();
+ }
+
+ /**
+ * Low-level function to reboot the device.
+ *
+ * @param reason code to pass to the kernel (e.g. "recovery"), or null.
+ * @throws IOException if reboot fails for some reason (eg, lack of
+ * permission)
+ */
+ public static void lowLevelReboot(String reason) throws IOException {
+ nativeReboot(reason);
+ }
+
+ @Override // Watchdog.Monitor implementation
+ public void monitor() {
+ // Grab and release lock for watchdog monitor to detect deadlocks.
+ synchronized (mLock) {
}
- return mPolicy;
}
- public void systemReady() {
- mSensorManager = new SystemSensorManager(mHandlerThread.getLooper());
- mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
- // don't bother with the light sensor if auto brightness is handled in hardware
- if (mUseSoftwareAutoBrightness) {
- mLightSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_LIGHT);
- }
-
- // wait until sensors are enabled before turning on screen.
- // some devices will not activate the light sensor properly on boot
- // unless we do this.
- if (mUseSoftwareAutoBrightness) {
- // turn the screen on
- setPowerState(SCREEN_BRIGHT);
- } else {
- // turn everything on
- setPowerState(ALL_BRIGHT);
+ @Override // Binder call
+ protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+ if (mContext.checkCallingOrSelfPermission(Manifest.permission.DUMP)
+ != PackageManager.PERMISSION_GRANTED) {
+ pw.println("Permission Denial: can't dump PowerManager from from pid="
+ + Binder.getCallingPid()
+ + ", uid=" + Binder.getCallingUid());
+ return;
}
- synchronized (mLocks) {
- Slog.d(TAG, "system ready!");
- mDoneBooting = true;
+ pw.println("POWER MANAGER (dumpsys power)\n");
- enableLightSensorLocked(mUseSoftwareAutoBrightness && mAutoBrightessEnabled);
+ final DisplayPowerController dpc;
+ synchronized (mLock) {
+ pw.println("Power Manager State:");
+ pw.println(" mDirty=0x" + Integer.toHexString(mDirty));
+ pw.println(" mWakefulness=" + wakefulnessToString(mWakefulness));
+ pw.println(" mIsPowered=" + mIsPowered);
+ pw.println(" mStayOn=" + mStayOn);
+ pw.println(" mBootCompleted=" + mBootCompleted);
+ pw.println(" mSystemReady=" + mSystemReady);
+ pw.println(" mWakeLockSummary=0x" + Integer.toHexString(mWakeLockSummary));
+ pw.println(" mUserActivitySummary=0x" + Integer.toHexString(mUserActivitySummary));
+ pw.println(" mRequestWaitForNegativeProximity=" + mRequestWaitForNegativeProximity);
+ pw.println(" mSandmanScheduled=" + mSandmanScheduled);
+ pw.println(" mLastWakeTime=" + TimeUtils.formatUptime(mLastWakeTime));
+ pw.println(" mLastSleepTime=" + TimeUtils.formatUptime(mLastSleepTime));
+ pw.println(" mSendWakeUpFinishedNotificationWhenReady="
+ + mSendWakeUpFinishedNotificationWhenReady);
+ pw.println(" mSendGoToSleepFinishedNotificationWhenReady="
+ + mSendGoToSleepFinishedNotificationWhenReady);
+ pw.println(" mLastUserActivityTime=" + TimeUtils.formatUptime(mLastUserActivityTime));
+ pw.println(" mLastUserActivityTimeNoChangeLights="
+ + TimeUtils.formatUptime(mLastUserActivityTimeNoChangeLights));
+ pw.println(" mDisplayReady=" + mDisplayReady);
+ pw.println(" mHoldingWakeLockSuspendBlocker=" + mHoldingWakeLockSuspendBlocker);
- long identity = Binder.clearCallingIdentity();
- try {
- mBatteryStats.noteScreenBrightness(getPreferredBrightness());
- mBatteryStats.noteScreenOn();
- } catch (RemoteException e) {
- // Nothing interesting to do.
- } finally {
- Binder.restoreCallingIdentity(identity);
+ pw.println();
+ pw.println("Settings and Configuration:");
+ pw.println(" mDreamsSupportedConfig=" + mDreamsSupportedConfig);
+ pw.println(" mDreamsEnabledSetting=" + mDreamsEnabledSetting);
+ pw.println(" mScreenOffTimeoutSetting=" + mScreenOffTimeoutSetting);
+ pw.println(" mMaximumScreenOffTimeoutFromDeviceAdmin="
+ + mMaximumScreenOffTimeoutFromDeviceAdmin + " (enforced="
+ + isMaximumScreenOffTimeoutFromDeviceAdminEnforcedLocked() + ")");
+ pw.println(" mStayOnWhilePluggedInSetting=" + mStayOnWhilePluggedInSetting);
+ pw.println(" mScreenBrightnessSetting=" + mScreenBrightnessSetting);
+ pw.println(" mScreenBrightnessModeSetting=" + mScreenBrightnessModeSetting);
+ pw.println(" mScreenBrightnessOverrideFromWindowManager="
+ + mScreenBrightnessOverrideFromWindowManager);
+ pw.println(" mTemporaryScreenBrightnessSettingOverride="
+ + mTemporaryScreenBrightnessSettingOverride);
+ pw.println(" mScreenBrightnessSettingMinimum=" + mScreenBrightnessSettingMinimum);
+ pw.println(" mScreenBrightnessSettingMaximum=" + mScreenBrightnessSettingMaximum);
+ pw.println(" mScreenBrightnessSettingDefault=" + mScreenBrightnessSettingDefault);
+
+ pw.println();
+ pw.println("Wake Locks: size=" + mWakeLocks.size());
+ for (WakeLock wl : mWakeLocks) {
+ pw.println(" " + wl);
+ }
+
+ pw.println();
+ pw.println("Suspend Blockers: size=" + mSuspendBlockers.size());
+ for (SuspendBlocker sb : mSuspendBlockers) {
+ pw.println(" " + sb);
}
+
+ dpc = mDisplayPowerController;
}
- }
- void bootCompleted() {
- Slog.d(TAG, "bootCompleted");
- synchronized (mLocks) {
- mBootCompleted = true;
- userActivity(SystemClock.uptimeMillis(), false, PowerManager.USER_ACTIVITY_EVENT_BUTTON, true);
- updateWakeLockLocked();
- mLocks.notifyAll();
+ if (dpc != null) {
+ dpc.dump(pw);
}
}
- // for watchdog
- public void monitor() {
- synchronized (mLocks) { }
+ private SuspendBlocker createSuspendBlockerLocked(String name) {
+ SuspendBlocker suspendBlocker = new SuspendBlockerImpl(name);
+ mSuspendBlockers.add(suspendBlocker);
+ return suspendBlocker;
}
- public int getSupportedWakeLockFlags() {
- int result = PowerManager.PARTIAL_WAKE_LOCK
- | PowerManager.FULL_WAKE_LOCK
- | PowerManager.SCREEN_DIM_WAKE_LOCK;
-
- if (mProximitySensor != null) {
- result |= PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK;
+ private static String wakefulnessToString(int wakefulness) {
+ switch (wakefulness) {
+ case WAKEFULNESS_ASLEEP:
+ return "Asleep";
+ case WAKEFULNESS_AWAKE:
+ return "Awake";
+ case WAKEFULNESS_DREAMING:
+ return "Dreaming";
+ case WAKEFULNESS_NAPPING:
+ return "Napping";
+ default:
+ return Integer.toString(wakefulness);
}
+ }
- return result;
+ private static WorkSource copyWorkSource(WorkSource workSource) {
+ return workSource != null ? new WorkSource(workSource) : null;
}
- public void setBacklightBrightness(int brightness) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
- // Don't let applications turn the screen all the way off
- synchronized (mLocks) {
- brightness = Math.max(brightness, mScreenBrightnessDim);
- mLcdLight.setBrightness(brightness);
- mKeyboardLight.setBrightness(mKeyboardVisible ? brightness : 0);
- mButtonLight.setBrightness(brightness);
- long identity = Binder.clearCallingIdentity();
- try {
- mBatteryStats.noteScreenBrightness(brightness);
- } catch (RemoteException e) {
- Slog.w(TAG, "RemoteException calling noteScreenBrightness on BatteryStatsService", e);
- } finally {
- Binder.restoreCallingIdentity(identity);
+ private final class BatteryReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ synchronized (mLock) {
+ handleBatteryStateChangedLocked();
}
- mScreenBrightnessAnimator.animateTo(brightness, SCREEN_BRIGHT_BIT, 0);
}
}
- public void setAutoBrightnessAdjustment(float adj) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
- synchronized (mLocks) {
- mLightSensorAdjustSetting = adj;
- if (mSensorManager != null && mLightSensorEnabled) {
- // clear calling identity so sensor manager battery stats are accurate
- long identity = Binder.clearCallingIdentity();
- try {
- // force recompute of backlight values
- if (mLightSensorValue >= 0) {
- int value = (int)mLightSensorValue;
- mLightSensorValue = -1;
- handleLightSensorValue(value, true);
- }
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
+ private final class BootCompletedReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ synchronized (mLock) {
+ handleBootCompletedLocked();
}
}
}
- public void setAttentionLight(boolean on, int color) {
- mContext.enforceCallingOrSelfPermission(android.Manifest.permission.DEVICE_POWER, null);
- mAttentionLight.setFlashing(color, LightsService.LIGHT_FLASH_HARDWARE, (on ? 3 : 0), 0);
- }
-
- private void enableProximityLockLocked() {
- if (DEBUG_PROXIMITY_SENSOR) {
- Slog.d(TAG, "enableProximityLockLocked");
- }
- if (!mProximitySensorEnabled) {
- // clear calling identity so sensor manager battery stats are accurate
- long identity = Binder.clearCallingIdentity();
- try {
- mSensorManager.registerListener(mProximityListener, mProximitySensor,
- SensorManager.SENSOR_DELAY_NORMAL);
- mProximitySensorEnabled = true;
- } finally {
- Binder.restoreCallingIdentity(identity);
+ private final class DockReceiver extends BroadcastReceiver {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ synchronized (mLock) {
+ int dockState = intent.getIntExtra(Intent.EXTRA_DOCK_STATE,
+ Intent.EXTRA_DOCK_STATE_UNDOCKED);
+ handleDockStateChangedLocked(dockState);
}
}
}
- private void disableProximityLockLocked() {
- if (DEBUG_PROXIMITY_SENSOR) {
- Slog.d(TAG, "disableProximityLockLocked");
+ private final class SettingsObserver extends ContentObserver {
+ public SettingsObserver(Handler handler) {
+ super(handler);
}
- if (mProximitySensorEnabled) {
- // clear calling identity so sensor manager battery stats are accurate
- long identity = Binder.clearCallingIdentity();
- try {
- mSensorManager.unregisterListener(mProximityListener);
- mHandler.removeCallbacks(mProximityTask);
- if (mProximityPartialLock.isHeld()) {
- mProximityPartialLock.release();
- }
- mProximitySensorEnabled = false;
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
- if (mProximitySensorActive) {
- mProximitySensorActive = false;
- if (DEBUG_PROXIMITY_SENSOR) {
- Slog.d(TAG, "disableProximityLockLocked mProxIgnoredBecauseScreenTurnedOff="
- + mProxIgnoredBecauseScreenTurnedOff);
- }
- if (!mProxIgnoredBecauseScreenTurnedOff) {
- forceUserActivityLocked();
- }
+
+ @Override
+ public void onChange(boolean selfChange, Uri uri) {
+ synchronized (mLock) {
+ handleSettingsChangedLocked();
}
}
}
- private void proximityChangedLocked(boolean active) {
- if (DEBUG_PROXIMITY_SENSOR) {
- Slog.d(TAG, "proximityChangedLocked, active: " + active);
+ private final WindowManagerPolicy.ScreenOnListener mScreenOnListener =
+ new WindowManagerPolicy.ScreenOnListener() {
+ @Override
+ public void onScreenOn() {
}
- if (!mProximitySensorEnabled) {
- Slog.d(TAG, "Ignoring proximity change after sensor is disabled");
- return;
+ };
+
+ /**
+ * Handler for asynchronous operations performed by the power manager.
+ */
+ private final class PowerManagerHandler extends Handler {
+ public PowerManagerHandler(Looper looper) {
+ super(looper);
}
- if (active) {
- if (DEBUG_PROXIMITY_SENSOR) {
- Slog.d(TAG, "b mProxIgnoredBecauseScreenTurnedOff="
- + mProxIgnoredBecauseScreenTurnedOff);
- }
- if (!mProxIgnoredBecauseScreenTurnedOff) {
- goToSleepLocked(SystemClock.uptimeMillis(),
- WindowManagerPolicy.OFF_BECAUSE_OF_PROX_SENSOR);
- }
- mProximitySensorActive = true;
- } else {
- // proximity sensor negative events trigger as user activity.
- // temporarily set mUserActivityAllowed to true so this will work
- // even when the keyguard is on.
- mProximitySensorActive = false;
- if (DEBUG_PROXIMITY_SENSOR) {
- Slog.d(TAG, "b mProxIgnoredBecauseScreenTurnedOff="
- + mProxIgnoredBecauseScreenTurnedOff);
- }
- if (!mProxIgnoredBecauseScreenTurnedOff) {
- forceUserActivityLocked();
- }
- if (mProximityWakeLockCount == 0) {
- // disable sensor if we have no listeners left after proximity negative
- disableProximityLockLocked();
+ @Override
+ public void handleMessage(Message msg) {
+ switch (msg.what) {
+ case MSG_USER_ACTIVITY_TIMEOUT:
+ handleUserActivityTimeout();
+ break;
+ case MSG_SANDMAN:
+ handleSandman();
+ break;
}
}
}
- private void enableLightSensorLocked(boolean enable) {
- if (DEBUG_LIGHT_SENSOR) {
- Slog.d(TAG, "enableLightSensorLocked enable=" + enable
- + " mLightSensorEnabled=" + mLightSensorEnabled
- + " mAutoBrightessEnabled=" + mAutoBrightessEnabled
- + " mWaitingForFirstLightSensor=" + mWaitingForFirstLightSensor);
+ /**
+ * Represents a wake lock that has been acquired by an application.
+ */
+ private final class WakeLock implements IBinder.DeathRecipient {
+ public final IBinder mLock;
+ public int mFlags;
+ public String mTag;
+ public WorkSource mWorkSource;
+ public int mOwnerUid;
+ public int mOwnerPid;
+
+ public WakeLock(IBinder lock, int flags, String tag, WorkSource workSource,
+ int ownerUid, int ownerPid) {
+ mLock = lock;
+ mFlags = flags;
+ mTag = tag;
+ mWorkSource = copyWorkSource(workSource);
+ mOwnerUid = ownerUid;
+ mOwnerPid = ownerPid;
+ }
+
+ @Override
+ public void binderDied() {
+ PowerManagerService.this.handleWakeLockDeath(this);
}
- if (!mAutoBrightessEnabled) {
- enable = false;
+
+ public boolean hasSameProperties(int flags, String tag, WorkSource workSource,
+ int ownerUid, int ownerPid) {
+ return mFlags == flags
+ && mTag.equals(tag)
+ && hasSameWorkSource(workSource)
+ && mOwnerUid == ownerUid
+ && mOwnerPid == ownerPid;
}
- if (mSensorManager != null && mLightSensorEnabled != enable) {
- mLightSensorEnabled = enable;
- // clear calling identity so sensor manager battery stats are accurate
- long identity = Binder.clearCallingIdentity();
- try {
- if (enable) {
- // reset our highest value when reenabling
- mHighestLightSensorValue = -1;
- // force recompute of backlight values
- final int value = (int)mLightSensorValue;
- if (value >= 0) {
- mLightSensorValue = -1;
- handleLightSensorValue(value, true);
- }
- mSensorManager.registerListener(mLightListener, mLightSensor,
- LIGHT_SENSOR_RATE);
- } else {
- mSensorManager.unregisterListener(mLightListener);
- mHandler.removeCallbacks(mAutoBrightnessTask);
- mLightSensorPendingDecrease = false;
- mLightSensorPendingIncrease = false;
- }
- } finally {
- Binder.restoreCallingIdentity(identity);
- }
+
+ public void updateProperties(int flags, String tag, WorkSource workSource,
+ int ownerUid, int ownerPid) {
+ mFlags = flags;
+ mTag = tag;
+ updateWorkSource(workSource);
+ mOwnerUid = ownerUid;
+ mOwnerPid = ownerPid;
}
- }
- SensorEventListener mProximityListener = new SensorEventListener() {
- public void onSensorChanged(SensorEvent event) {
- long milliseconds = SystemClock.elapsedRealtime();
- synchronized (mLocks) {
- float distance = event.values[0];
- long timeSinceLastEvent = milliseconds - mLastProximityEventTime;
- mLastProximityEventTime = milliseconds;
- mHandler.removeCallbacks(mProximityTask);
- boolean proximityTaskQueued = false;
+ public boolean hasSameWorkSource(WorkSource workSource) {
+ return Objects.equal(mWorkSource, workSource);
+ }
- // compare against getMaximumRange to support sensors that only return 0 or 1
- boolean active = (distance >= 0.0 && distance < PROXIMITY_THRESHOLD &&
- distance < mProximitySensor.getMaximumRange());
+ public void updateWorkSource(WorkSource workSource) {
+ mWorkSource = copyWorkSource(workSource);
+ }
- if (DEBUG_PROXIMITY_SENSOR) {
- Slog.d(TAG, "mProximityListener.onSensorChanged active: " + active);
- }
- if (timeSinceLastEvent < PROXIMITY_SENSOR_DELAY) {
- // enforce delaying atleast PROXIMITY_SENSOR_DELAY before processing
- mProximityPendingValue = (active ? 1 : 0);
- mHandler.postDelayed(mProximityTask, PROXIMITY_SENSOR_DELAY - timeSinceLastEvent);
- proximityTaskQueued = true;
- } else {
- // process the value immediately
- mProximityPendingValue = -1;
- proximityChangedLocked(active);
- }
+ @Override
+ public String toString() {
+ return getLockLevelString()
+ + " '" + mTag + "'" + getLockFlagsString()
+ + " (uid=" + mOwnerUid + ", pid=" + mOwnerPid + ", ws=" + mWorkSource + ")";
+ }
- // update mProximityPartialLock state
- boolean held = mProximityPartialLock.isHeld();
- if (!held && proximityTaskQueued) {
- // hold wakelock until mProximityTask runs
- mProximityPartialLock.acquire();
- } else if (held && !proximityTaskQueued) {
- mProximityPartialLock.release();
- }
+ private String getLockLevelString() {
+ switch (mFlags & PowerManager.WAKE_LOCK_LEVEL_MASK) {
+ case PowerManager.FULL_WAKE_LOCK:
+ return "FULL_WAKE_LOCK ";
+ case PowerManager.SCREEN_BRIGHT_WAKE_LOCK:
+ return "SCREEN_BRIGHT_WAKE_LOCK ";
+ case PowerManager.SCREEN_DIM_WAKE_LOCK:
+ return "SCREEN_DIM_WAKE_LOCK ";
+ case PowerManager.PARTIAL_WAKE_LOCK:
+ return "PARTIAL_WAKE_LOCK ";
+ case PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK:
+ return "PROXIMITY_SCREEN_OFF_WAKE_LOCK";
+ default:
+ return "??? ";
}
}
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- // ignore
+ private String getLockFlagsString() {
+ String result = "";
+ if ((mFlags & PowerManager.ACQUIRE_CAUSES_WAKEUP) != 0) {
+ result += " ACQUIRE_CAUSES_WAKEUP";
+ }
+ if ((mFlags & PowerManager.ON_AFTER_RELEASE) != 0) {
+ result += " ON_AFTER_RELEASE";
+ }
+ return result;
}
- };
+ }
- private void handleLightSensorValue(int value, boolean immediate) {
- long milliseconds = SystemClock.elapsedRealtime();
- if (mLightSensorValue == -1
- || milliseconds < mLastScreenOnTime + mLightSensorWarmupTime
- || mWaitingForFirstLightSensor) {
- // process the value immediately if screen has just turned on
- mHandler.removeCallbacks(mAutoBrightnessTask);
- mLightSensorPendingDecrease = false;
- mLightSensorPendingIncrease = false;
- lightSensorChangedLocked(value, immediate);
- } else {
- if ((value > mLightSensorValue && mLightSensorPendingDecrease) ||
- (value < mLightSensorValue && mLightSensorPendingIncrease) ||
- (value == mLightSensorValue) ||
- (!mLightSensorPendingDecrease && !mLightSensorPendingIncrease)) {
- // delay processing to debounce the sensor
- mHandler.removeCallbacks(mAutoBrightnessTask);
- mLightSensorPendingDecrease = (value < mLightSensorValue);
- mLightSensorPendingIncrease = (value > mLightSensorValue);
- if (mLightSensorPendingDecrease || mLightSensorPendingIncrease) {
- mLightSensorPendingValue = value;
- mHandler.postDelayed(mAutoBrightnessTask, LIGHT_SENSOR_DELAY);
+ private final class SuspendBlockerImpl implements SuspendBlocker {
+ private final String mName;
+ private int mReferenceCount;
+
+ public SuspendBlockerImpl(String name) {
+ mName = name;
+ }
+
+ @Override
+ protected void finalize() throws Throwable {
+ try {
+ if (mReferenceCount != 0) {
+ Log.wtf(TAG, "Suspend blocker \"" + mName
+ + "\" was finalized without being released!");
+ mReferenceCount = 0;
+ nativeReleaseSuspendBlocker(mName);
}
- } else {
- mLightSensorPendingValue = value;
+ } finally {
+ super.finalize();
}
}
- }
- SensorEventListener mLightListener = new SensorEventListener() {
@Override
- public void onSensorChanged(SensorEvent event) {
- if (DEBUG_LIGHT_SENSOR) {
- Slog.d(TAG, "onSensorChanged: light value: " + event.values[0]);
- }
- synchronized (mLocks) {
- // ignore light sensor while screen is turning off
- if (isScreenTurningOffLocked()) {
- return;
+ public void acquire() {
+ synchronized (this) {
+ mReferenceCount += 1;
+ if (mReferenceCount == 1) {
+ nativeAcquireSuspendBlocker(mName);
}
- handleLightSensorValue((int)event.values[0], mWaitingForFirstLightSensor);
- if (mWaitingForFirstLightSensor && !mPreparingForScreenOn) {
- if (DEBUG_LIGHT_ANIMATION) {
- Slog.d(TAG, "onSensorChanged: Clearing mWaitingForFirstLightSensor.");
- }
- mWaitingForFirstLightSensor = false;
+ }
+ }
+
+ @Override
+ public void release() {
+ synchronized (this) {
+ mReferenceCount -= 1;
+ if (mReferenceCount == 0) {
+ nativeReleaseSuspendBlocker(mName);
+ } else if (mReferenceCount < 0) {
+ Log.wtf(TAG, "Suspend blocker \"" + mName
+ + "\" was released without being acquired!", new Throwable());
+ mReferenceCount = 0;
}
}
}
@Override
- public void onAccuracyChanged(Sensor sensor, int accuracy) {
- // ignore
+ public String toString() {
+ synchronized (this) {
+ return mName + ": ref count=" + mReferenceCount;
+ }
}
- };
+ }
}
diff --git a/services/java/com/android/server/power/RampAnimator.java b/services/java/com/android/server/power/RampAnimator.java
new file mode 100644
index 0000000..6f063c3
--- /dev/null
+++ b/services/java/com/android/server/power/RampAnimator.java
@@ -0,0 +1,131 @@
+/*
+ * 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;
+ final float amount = timeDelta * mRate / ValueAnimator.getDurationScale();
+ 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.
+ int oldCurrentValue = mCurrentValue;
+ if (mTargetValue > mCurrentValue) {
+ mAnimatedValue = Math.min(mAnimatedValue + amount, mTargetValue);
+ } else {
+ mAnimatedValue = Math.max(mAnimatedValue - amount, mTargetValue);
+ }
+ mCurrentValue = (int)Math.round(mAnimatedValue);
+
+ if (oldCurrentValue != mCurrentValue) {
+ mProperty.setValue(mObject, mCurrentValue);
+ }
+
+ if (mTargetValue != mCurrentValue) {
+ postCallback();
+ } else {
+ mAnimating = false;
+ }
+ }
+ };
+}
diff --git a/services/java/com/android/server/power/SuspendBlocker.java b/services/java/com/android/server/power/SuspendBlocker.java
new file mode 100644
index 0000000..70b278a
--- /dev/null
+++ b/services/java/com/android/server/power/SuspendBlocker.java
@@ -0,0 +1,43 @@
+/*
+ * 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;
+
+/**
+ * Low-level suspend blocker mechanism equivalent to holding a partial wake lock.
+ *
+ * This interface is used internally to avoid introducing internal dependencies
+ * on the high-level wake lock mechanism.
+ */
+interface SuspendBlocker {
+ /**
+ * Acquires the suspend blocker.
+ * Prevents the CPU from going to sleep.
+ *
+ * Calls to acquire() nest and must be matched by the same number
+ * of calls to release().
+ */
+ void acquire();
+
+ /**
+ * Releases the suspend blocker.
+ * Allows the CPU to go to sleep if no other suspend blockers are held.
+ *
+ * It is an error to call release() if the suspend blocker has not been acquired.
+ * The system may crash.
+ */
+ void release();
+}
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 9e62a16..40a9eed 100755
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -855,7 +855,7 @@ public class WindowManagerService extends IWindowManager.Stub
android.os.Process.setThreadPriority(
android.os.Process.THREAD_PRIORITY_FOREGROUND);
android.os.Process.setCanSelfBackground(false);
- mPolicy.init(mContext, mService, mService, mPM);
+ mPolicy.init(mContext, mService, mService);
mService.mAnimator.mAboveUniverseLayer = mPolicy.getAboveUniverseLayer()
* TYPE_LAYER_MULTIPLIER
+ TYPE_LAYER_OFFSET;
@@ -910,7 +910,7 @@ public class WindowManagerService extends IWindowManager.Stub
mContext.registerReceiver(mBroadcastReceiver, filter);
mHoldingScreenWakeLock = pmc.newWakeLock(PowerManager.SCREEN_BRIGHT_WAKE_LOCK
- | PowerManager.ON_AFTER_RELEASE, "KEEP_SCREEN_ON_FLAG");
+ | PowerManager.ON_AFTER_RELEASE, PowerManager.KEEP_SCREEN_ON_FLAG_TAG);
mHoldingScreenWakeLock.setReferenceCounted(false);
mInputManager = new InputManagerService(context, mInputMonitor);
@@ -9074,16 +9074,16 @@ public class WindowManagerService extends IWindowManager.Stub
setHoldScreenLocked(mInnerFields.mHoldScreen != null);
if (!mDisplayFrozen) {
if (mInnerFields.mScreenBrightness < 0 || mInnerFields.mScreenBrightness > 1.0f) {
- mPowerManager.setScreenBrightnessOverride(-1);
+ mPowerManager.setScreenBrightnessOverrideFromWindowManager(-1);
} else {
- mPowerManager.setScreenBrightnessOverride((int)
- (mInnerFields.mScreenBrightness * PowerManager.BRIGHTNESS_ON));
+ mPowerManager.setScreenBrightnessOverrideFromWindowManager(
+ toBrightnessOverride(mInnerFields.mScreenBrightness));
}
if (mInnerFields.mButtonBrightness < 0 || mInnerFields.mButtonBrightness > 1.0f) {
- mPowerManager.setButtonBrightnessOverride(-1);
+ mPowerManager.setButtonBrightnessOverrideFromWindowManager(-1);
} else {
- mPowerManager.setButtonBrightnessOverride((int)
- (mInnerFields.mButtonBrightness * PowerManager.BRIGHTNESS_ON));
+ mPowerManager.setButtonBrightnessOverrideFromWindowManager(
+ toBrightnessOverride(mInnerFields.mButtonBrightness));
}
}
if (mInnerFields.mHoldScreen != mHoldingScreenOn) {
@@ -9094,8 +9094,7 @@ public class WindowManagerService extends IWindowManager.Stub
if (mTurnOnScreen) {
if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
- mPowerManager.userActivity(SystemClock.uptimeMillis(), false,
- PowerManager.USER_ACTIVITY_EVENT_BUTTON, true);
+ mPowerManager.wakeUp(SystemClock.uptimeMillis());
mTurnOnScreen = false;
}
@@ -9126,6 +9125,10 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ private int toBrightnessOverride(float value) {
+ return (int)(value * PowerManager.BRIGHTNESS_ON);
+ }
+
void checkDrawnWindowsLocked() {
if (mWaitingForDrawn.size() > 0) {
for (int j=mWaitingForDrawn.size()-1; j>=0; j--) {
diff --git a/services/jni/com_android_server_LightsService.cpp b/services/jni/com_android_server_LightsService.cpp
index 9ed4951..401e1aa 100644
--- a/services/jni/com_android_server_LightsService.cpp
+++ b/services/jni/com_android_server_LightsService.cpp
@@ -120,7 +120,10 @@ static void setLight_native(JNIEnv *env, jobject clazz, int ptr,
state.flashOffMS = offMS;
state.brightnessMode = brightnessMode;
- devices->lights[light]->set_light(devices->lights[light], &state);
+ {
+ ALOGD_IF_SLOW(50, "Excessive delay setting light");
+ devices->lights[light]->set_light(devices->lights[light], &state);
+ }
}
static JNINativeMethod method_table[] = {
diff --git a/services/jni/com_android_server_input_InputManagerService.cpp b/services/jni/com_android_server_input_InputManagerService.cpp
index 35c2142..701b15a 100644
--- a/services/jni/com_android_server_input_InputManagerService.cpp
+++ b/services/jni/com_android_server_input_InputManagerService.cpp
@@ -143,7 +143,7 @@ static void loadSystemIconAsSprite(JNIEnv* env, jobject contextObj, int32_t styl
enum {
WM_ACTION_PASS_TO_USER = 1,
- WM_ACTION_POKE_USER_ACTIVITY = 2,
+ WM_ACTION_WAKE_UP = 2,
WM_ACTION_GO_TO_SLEEP = 4,
};
@@ -899,11 +899,11 @@ void NativeInputManager::handleInterceptActions(jint wmActions, nsecs_t when,
android_server_PowerManagerService_goToSleep(when);
}
- if (wmActions & WM_ACTION_POKE_USER_ACTIVITY) {
+ if (wmActions & WM_ACTION_WAKE_UP) {
#if DEBUG_INPUT_DISPATCHER_POLICY
- ALOGD("handleInterceptActions: Poking user activity.");
+ ALOGD("handleInterceptActions: Waking up.");
#endif
- android_server_PowerManagerService_userActivity(when, USER_ACTIVITY_EVENT_BUTTON);
+ android_server_PowerManagerService_wakeUp(when);
}
if (wmActions & WM_ACTION_PASS_TO_USER) {
diff --git a/services/jni/com_android_server_power_PowerManagerService.cpp b/services/jni/com_android_server_power_PowerManagerService.cpp
index 8307d25..3f3970b 100644
--- a/services/jni/com_android_server_power_PowerManagerService.cpp
+++ b/services/jni/com_android_server_power_PowerManagerService.cpp
@@ -21,6 +21,8 @@
#include "JNIHelp.h"
#include "jni.h"
+#include <ScopedUtfChars.h>
+
#include <limits.h>
#include <android_runtime/AndroidRuntime.h>
@@ -28,6 +30,7 @@
#include <utils/Timers.h>
#include <utils/misc.h>
#include <utils/String8.h>
+#include <utils/Log.h>
#include <hardware/power.h>
#include <hardware_legacy/power.h>
#include <cutils/android_reboot.h>
@@ -42,8 +45,9 @@ namespace android {
// ----------------------------------------------------------------------------
static struct {
- jmethodID goToSleep;
- jmethodID userActivity;
+ jmethodID wakeUpFromNative;
+ jmethodID goToSleepFromNative;
+ jmethodID userActivityFromNative;
} gPowerManagerServiceClassInfo;
// ----------------------------------------------------------------------------
@@ -106,19 +110,32 @@ void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t
JNIEnv* env = AndroidRuntime::getJNIEnv();
- env->CallVoidMethod(gPowerManagerServiceObj, gPowerManagerServiceClassInfo.userActivity,
- nanoseconds_to_milliseconds(eventTime), false, eventType, false);
- checkAndClearExceptionFromCallback(env, "userActivity");
+ env->CallVoidMethod(gPowerManagerServiceObj,
+ gPowerManagerServiceClassInfo.userActivityFromNative,
+ nanoseconds_to_milliseconds(eventTime), eventType, 0);
+ checkAndClearExceptionFromCallback(env, "userActivityFromNative");
}
}
-void android_server_PowerManagerService_goToSleep(nsecs_t eventTime) {
+void android_server_PowerManagerService_wakeUp(nsecs_t eventTime) {
if (gPowerManagerServiceObj) {
JNIEnv* env = AndroidRuntime::getJNIEnv();
- env->CallVoidMethod(gPowerManagerServiceObj, gPowerManagerServiceClassInfo.goToSleep,
+ env->CallVoidMethod(gPowerManagerServiceObj,
+ gPowerManagerServiceClassInfo.wakeUpFromNative,
nanoseconds_to_milliseconds(eventTime));
- checkAndClearExceptionFromCallback(env, "goToSleep");
+ checkAndClearExceptionFromCallback(env, "wakeUpFromNative");
+ }
+}
+
+void android_server_PowerManagerService_goToSleep(nsecs_t eventTime) {
+ if (gPowerManagerServiceObj) {
+ JNIEnv* env = AndroidRuntime::getJNIEnv();
+
+ env->CallVoidMethod(gPowerManagerServiceObj,
+ gPowerManagerServiceClassInfo.goToSleepFromNative,
+ nanoseconds_to_milliseconds(eventTime), 0);
+ checkAndClearExceptionFromCallback(env, "goToSleepFromNative");
}
}
@@ -137,68 +154,62 @@ static void nativeInit(JNIEnv* env, jobject obj) {
}
static void nativeSetPowerState(JNIEnv* env,
- jobject serviceObj, jboolean screenOn, jboolean screenBright) {
+ jclass clazz, jboolean screenOn, jboolean screenBright) {
AutoMutex _l(gPowerManagerLock);
gScreenOn = screenOn;
gScreenBright = screenBright;
}
-static void nativeStartSurfaceFlingerAnimation(JNIEnv* env,
- jobject obj, jint mode) {
- // this is not handled by surfaceflinger anymore
+static void nativeAcquireSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) {
+ ScopedUtfChars name(env, nameStr);
+ acquire_wake_lock(PARTIAL_WAKE_LOCK, name.c_str());
}
-static void nativeAcquireWakeLock(JNIEnv *env, jobject clazz, jint lock, jstring idObj) {
- if (idObj == NULL) {
- jniThrowNullPointerException(env, "id is null");
- return;
- }
-
- const char *id = env->GetStringUTFChars(idObj, NULL);
-
- acquire_wake_lock(lock, id);
-
- env->ReleaseStringUTFChars(idObj, id);
+static void nativeReleaseSuspendBlocker(JNIEnv *env, jclass clazz, jstring nameStr) {
+ ScopedUtfChars name(env, nameStr);
+ release_wake_lock(name.c_str());
}
-static void nativeReleaseWakeLock(JNIEnv *env, jobject clazz, jstring idObj) {
- if (idObj == NULL) {
- jniThrowNullPointerException(env, "id is null");
- return ;
- }
-
- const char *id = env->GetStringUTFChars(idObj, NULL);
-
- release_wake_lock(id);
-
- env->ReleaseStringUTFChars(idObj, id);
-
-}
-
-static int nativeSetScreenState(JNIEnv *env, jobject clazz, jboolean on) {
+static void nativeSetScreenState(JNIEnv *env, jclass clazz, jboolean on) {
sp<ISurfaceComposer> s(ComposerService::getComposerService());
if (on) {
- autosuspend_disable();
+ {
+ ALOGD_IF_SLOW(50, "Excessive delay in autosuspend_disable() while turning screen on");
+ autosuspend_disable();
+ }
+
if (gPowerModule) {
+ ALOGD_IF_SLOW(10, "Excessive delay in setInteractive(true) while turning screen on");
gPowerModule->setInteractive(gPowerModule, true);
}
- s->unblank();
+
+ {
+ ALOGD_IF_SLOW(20, "Excessive delay in unblank() while turning screen on");
+ s->unblank();
+ }
} else {
- s->blank();
+ {
+ ALOGD_IF_SLOW(20, "Excessive delay in blank() while turning screen off");
+ s->blank();
+ }
+
if (gPowerModule) {
+ ALOGD_IF_SLOW(10, "Excessive delay in setInteractive(false) while turning screen off");
gPowerModule->setInteractive(gPowerModule, false);
}
- autosuspend_enable();
- }
- return 0;
+ {
+ ALOGD_IF_SLOW(50, "Excessive delay in autosuspend_enable() while turning screen off");
+ autosuspend_enable();
+ }
+ }
}
-static void nativeShutdown(JNIEnv *env, jobject clazz) {
+static void nativeShutdown(JNIEnv *env, jclass clazz) {
android_reboot(ANDROID_RB_POWEROFF, 0, 0);
}
-static void nativeReboot(JNIEnv *env, jobject clazz, jstring reason) {
+static void nativeReboot(JNIEnv *env, jclass clazz, jstring reason) {
if (reason == NULL) {
android_reboot(ANDROID_RB_RESTART, 0, 0);
} else {
@@ -218,13 +229,11 @@ static JNINativeMethod gPowerManagerServiceMethods[] = {
(void*) nativeInit },
{ "nativeSetPowerState", "(ZZ)V",
(void*) nativeSetPowerState },
- { "nativeStartSurfaceFlingerAnimation", "(I)V",
- (void*) nativeStartSurfaceFlingerAnimation },
- { "nativeAcquireWakeLock", "(ILjava/lang/String;)V",
- (void*) nativeAcquireWakeLock },
- { "nativeReleaseWakeLock", "(Ljava/lang/String;)V",
- (void*) nativeReleaseWakeLock },
- { "nativeSetScreenState", "(Z)I",
+ { "nativeAcquireSuspendBlocker", "(Ljava/lang/String;)V",
+ (void*) nativeAcquireSuspendBlocker },
+ { "nativeReleaseSuspendBlocker", "(Ljava/lang/String;)V",
+ (void*) nativeReleaseSuspendBlocker },
+ { "nativeSetScreenState", "(Z)V",
(void*) nativeSetScreenState },
{ "nativeShutdown", "()V",
(void*) nativeShutdown },
@@ -254,11 +263,14 @@ int register_android_server_PowerManagerService(JNIEnv* env) {
jclass clazz;
FIND_CLASS(clazz, "com/android/server/power/PowerManagerService");
- GET_METHOD_ID(gPowerManagerServiceClassInfo.goToSleep, clazz,
- "goToSleep", "(J)V");
+ GET_METHOD_ID(gPowerManagerServiceClassInfo.wakeUpFromNative, clazz,
+ "wakeUpFromNative", "(J)V");
+
+ GET_METHOD_ID(gPowerManagerServiceClassInfo.goToSleepFromNative, clazz,
+ "goToSleepFromNative", "(JI)V");
- GET_METHOD_ID(gPowerManagerServiceClassInfo.userActivity, clazz,
- "userActivity", "(JZIZ)V");
+ GET_METHOD_ID(gPowerManagerServiceClassInfo.userActivityFromNative, clazz,
+ "userActivityFromNative", "(JII)V");
// Initialize
for (int i = 0; i <= USER_ACTIVITY_EVENT_LAST; i++) {
diff --git a/services/jni/com_android_server_power_PowerManagerService.h b/services/jni/com_android_server_power_PowerManagerService.h
index cc3b5ef5..0808b80 100644
--- a/services/jni/com_android_server_power_PowerManagerService.h
+++ b/services/jni/com_android_server_power_PowerManagerService.h
@@ -27,6 +27,7 @@ namespace android {
extern bool android_server_PowerManagerService_isScreenOn();
extern bool android_server_PowerManagerService_isScreenBright();
extern void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType);
+extern void android_server_PowerManagerService_wakeUp(nsecs_t eventTime);
extern void android_server_PowerManagerService_goToSleep(nsecs_t eventTime);
} // namespace android
diff --git a/tests/StatusBar/src/com/android/statusbartest/PowerTest.java b/tests/StatusBar/src/com/android/statusbartest/PowerTest.java
index 31a1cf5..e38bb6c 100644
--- a/tests/StatusBar/src/com/android/statusbartest/PowerTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/PowerTest.java
@@ -16,32 +16,15 @@
package com.android.statusbartest;
-import android.app.ListActivity;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.widget.ArrayAdapter;
-import android.view.View;
import android.os.Binder;
import android.os.IBinder;
import android.os.IPowerManager;
-import android.widget.ListView;
-import android.content.Intent;
import android.content.ComponentName;
import android.content.pm.PackageManager;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.StatusBarManager;
import android.os.RemoteException;
-import android.os.Vibrator;
-import android.os.Bundle;
import android.os.Handler;
import android.os.LocalPowerManager;
import android.os.ServiceManager;
-import android.util.Log;
-import android.net.Uri;
-import android.os.SystemClock;
-import android.widget.RemoteViews;
-import android.widget.Toast;
import android.os.PowerManager;
public class PowerTest extends TestActivity
@@ -101,6 +84,28 @@ public class PowerTest extends TestActivity
mProx.release(PowerManager.WAIT_FOR_PROXIMITY_NEGATIVE);
}
},
+ new Test("Enable proximity, wait 5 seconds then disable") {
+ public void run() {
+ mProx.acquire();
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ mProx.release();
+ }
+ }, 5000);
+ }
+ },
+ new Test("Enable proximity, wait 5 seconds then disable (WAIT_FOR_PROXIMITY_NEGATIVE)") {
+ public void run() {
+ mProx.acquire();
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ mProx.release(PowerManager.WAIT_FOR_PROXIMITY_NEGATIVE);
+ }
+ }, 5000);
+ }
+ },
new Test("Touch events don't poke") {
public void run() {
mPokeState |= LocalPowerManager.POKE_LOCK_IGNORE_TOUCH_EVENTS;
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index 0a1191b..292e4fc 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -440,7 +440,7 @@ public final class BridgeContext extends Context {
}
if (POWER_SERVICE.equals(service)) {
- return new PowerManager(new BridgePowerManager(), new Handler());
+ return new PowerManager(this, new BridgePowerManager(), new Handler());
}
throw new UnsupportedOperationException("Unsupported Service: " + service);
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
index 6071a6b..0c85204 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgePowerManager.java
@@ -39,7 +39,7 @@ public class BridgePowerManager implements IPowerManager {
}
@Override
- public void acquireWakeLock(int arg0, IBinder arg1, String arg2, WorkSource arg3)
+ public void acquireWakeLock(IBinder arg0, int arg1, String arg2, WorkSource arg3)
throws RemoteException {
// pass for now.
}
@@ -55,18 +55,7 @@ public class BridgePowerManager implements IPowerManager {
}
@Override
- public int getSupportedWakeLockFlags() throws RemoteException {
- // pass for now.
- return 0;
- }
-
- @Override
- public void goToSleep(long arg0) throws RemoteException {
- // pass for now.
- }
-
- @Override
- public void goToSleepWithReason(long arg0, int arg1) throws RemoteException {
+ public void goToSleep(long arg0, int arg1) throws RemoteException {
// pass for now.
}
@@ -91,17 +80,17 @@ public class BridgePowerManager implements IPowerManager {
}
@Override
- public void setAutoBrightnessAdjustment(float arg0) throws RemoteException {
+ public void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float arg0) throws RemoteException {
// pass for now.
}
@Override
- public void setBacklightBrightness(int arg0) throws RemoteException {
+ public void setTemporaryScreenBrightnessSettingOverride(int arg0) throws RemoteException {
// pass for now.
}
@Override
- public void setMaximumScreenOffTimeount(int arg0) throws RemoteException {
+ public void setMaximumScreenOffTimeoutFromDeviceAdmin(int arg0) throws RemoteException {
// pass for now.
}
@@ -121,12 +110,18 @@ public class BridgePowerManager implements IPowerManager {
}
@Override
- public void userActivity(long arg0, boolean arg1) throws RemoteException {
+ public boolean isWakeLockLevelSupported(int level) throws RemoteException {
+ // pass for now.
+ return true;
+ }
+
+ @Override
+ public void userActivity(long time, int event, int flags) throws RemoteException {
// pass for now.
}
@Override
- public void userActivityWithForce(long arg0, boolean arg1, boolean arg2) throws RemoteException {
+ public void wakeUp(long time) throws RemoteException {
// pass for now.
}
}