Skip to content

Commit 9630704

Browse files
author
Jeff Brown
committed
Power manager rewrite.
The major goal of this rewrite is to make it easier to implement power management policies correctly. According, the new implementation primarily uses state-based rather than event-based triggers for applying changes to the current power state. For example, when an application requests that the proximity sensor be used to manage the screen state (by way of a wake lock), the power manager makes note of the fact that the set of wake locks changed. Then it executes a common update function that recalculates the entire state, first looking at wake locks, then considering user activity, and eventually determining whether the screen should be turned on or off. At this point it may make a request to a component called the DisplayPowerController to asynchronously update the display's powe state. Likewise, DisplayPowerController makes note of the updated power request and schedules its own update function to figure out what needs to be changed. The big benefit of this approach is that it's easy to mutate multiple properties of the power state simultaneously then apply their joint effects together all at once. Transitions between states are detected and resolved by the update in a consistent manner. The new power manager service has is implemented as a set of loosely coupled components. For the most part, information only flows one way through these components (by issuing a request to that component) although some components support sending a message back to indicate when the work has been completed. For example, the DisplayPowerController posts a callback runnable asynchronously to tell the PowerManagerService when the display is ready. An important feature of this approach is that each component neatly encapsulates its state and maintains its own invariants. Moreover, we do not need to worry about deadlocks or awkward mutual exclusion semantics because most of the requests are asynchronous. The benefits of this design are especially apparent in the implementation of the screen on / off and brightness control animations which are able to take advantage of framework features like properties, ObjectAnimator and Choreographer. The screen on / off animation is now the responsibility of the power manager (instead of surface flinger). This change makes it much easier to ensure that the animation is properly coordinated with other power state changes and eliminates the cause of race conditions in the older implementation. The because of the userActivity() function has been changed so that it never wakes the device from sleep. This change removes ambiguity around forcing or disabling user activity for various purposes. To wake the device, use wakeUp(). To put it to sleep, use goToSleep(). Simple. The power manager service interface and API has been significantly simplified and consolidated. Also fixed some inconsistencies related to how the minimum and maximum screen brightness setting was presented in brightness control widgets and enforced behind the scenes. At present the following features are implemented: - Wake locks. - User activity. - Wake up / go to sleep. - Power state broadcasts. - Battery stats and event log notifications. - Dreams. - Proximity screen off. - Animated screen on / off transitions. - Auto-dimming. - Auto-brightness control for the screen backlight with different timeouts for ramping up versus ramping down. - Auto-on when plugged or unplugged. - Stay on when plugged. - Device administration maximum user activity timeout. - Application controlled brightness via window manager. The following features are not yet implemented: - Reduced user activity timeout for the key guard. - Reduced user activity timeout for the phone application. - Coordinating screen on barriers with the window manager. - Preventing auto-rotation during power state changes. - Auto-brightness adjustment setting (feature was disabled in previous version of the power manager service pending an improved UI design so leaving it out for now). - Interpolated brightness control (a proposed new scheme for more compactly specifying auto-brightness levels in config.xml). - Button / keyboard backlight control. - Change window manager to associated WorkSource with KEEP_SCREEN_ON_FLAG wake lock instead of talking directly to the battery stats service. - Optionally support animating screen brightness when turning on/off instead of playing electron beam animation (config_animateScreenLights). Change-Id: I1d7a52e98f0449f76d70bf421f6a7f245957d1d7
1 parent ff7e6ef commit 9630704

File tree

38 files changed

+4644
-3292
lines changed

38 files changed

+4644
-3292
lines changed

api/current.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16269,6 +16269,7 @@ package android.os {
1626916269
method public android.os.PowerManager.WakeLock newWakeLock(int, java.lang.String);
1627016270
method public void reboot(java.lang.String);
1627116271
method public void userActivity(long, boolean);
16272+
method public void wakeUp(long);
1627216273
field public static final int ACQUIRE_CAUSES_WAKEUP = 268435456; // 0x10000000
1627316274
field public static final deprecated int FULL_WAKE_LOCK = 26; // 0x1a
1627416275
field public static final int ON_AFTER_RELEASE = 536870912; // 0x20000000
@@ -18759,7 +18760,7 @@ package android.provider {
1875918760
field public static final android.net.Uri DEFAULT_NOTIFICATION_URI;
1876018761
field public static final android.net.Uri DEFAULT_RINGTONE_URI;
1876118762
field public static final deprecated java.lang.String DEVICE_PROVISIONED = "device_provisioned";
18762-
field public static final java.lang.String DIM_SCREEN = "dim_screen";
18763+
field public static final deprecated java.lang.String DIM_SCREEN = "dim_screen";
1876318764
field public static final java.lang.String DTMF_TONE_WHEN_DIALING = "dtmf_tone";
1876418765
field public static final java.lang.String END_BUTTON_BEHAVIOR = "end_button_behavior";
1876518766
field public static final java.lang.String FONT_SCALE = "font_scale";

cmds/svc/src/com/android/commands/svc/PowerCommand.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ else if ("false".equals(args[2])) {
6464
= IPowerManager.Stub.asInterface(ServiceManager.getService(Context.POWER_SERVICE));
6565
try {
6666
IBinder lock = new Binder();
67-
pm.acquireWakeLock(PowerManager.FULL_WAKE_LOCK, lock, "svc power", null);
67+
pm.acquireWakeLock(lock, PowerManager.FULL_WAKE_LOCK, "svc power", null);
6868
pm.setStayOnSetting(val);
6969
pm.releaseWakeLock(lock, 0);
7070
}

core/java/android/app/ContextImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,8 @@ public Object createService(ContextImpl ctx) {
418418
public Object createService(ContextImpl ctx) {
419419
IBinder b = ServiceManager.getService(POWER_SERVICE);
420420
IPowerManager service = IPowerManager.Stub.asInterface(b);
421-
return new PowerManager(service, ctx.mMainThread.getHandler());
421+
return new PowerManager(ctx.getOuterContext(),
422+
service, ctx.mMainThread.getHandler());
422423
}});
423424

424425
registerService(SEARCH_SERVICE, new ServiceFetcher() {

core/java/android/os/IPowerManager.aidl

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,27 +23,33 @@ import android.os.WorkSource;
2323

2424
interface IPowerManager
2525
{
26-
// WARNING: changes in acquireWakeLock() signature must be reflected in IPowerManager.cpp/h
27-
void acquireWakeLock(int flags, IBinder lock, String tag, in WorkSource ws);
28-
void updateWakeLockWorkSource(IBinder lock, in WorkSource ws);
29-
void goToSleep(long time);
30-
void goToSleepWithReason(long time, int reason);
31-
// WARNING: changes in releaseWakeLock() signature must be reflected in IPowerManager.cpp/h
26+
// WARNING: The first two methods must remain the first two methods because their
27+
// transaction numbers must not change unless IPowerManager.cpp is also updated.
28+
void acquireWakeLock(IBinder lock, int flags, String tag, in WorkSource ws);
3229
void releaseWakeLock(IBinder lock, int flags);
33-
void userActivity(long when, boolean noChangeLights);
34-
void userActivityWithForce(long when, boolean noChangeLights, boolean force);
30+
31+
void updateWakeLockWorkSource(IBinder lock, in WorkSource ws);
32+
boolean isWakeLockLevelSupported(int level);
33+
34+
void userActivity(long time, int event, int flags);
35+
void wakeUp(long time);
36+
void goToSleep(long time, int reason);
37+
38+
boolean isScreenOn();
39+
void reboot(String reason);
40+
void crash(String message);
41+
3542
void clearUserActivityTimeout(long now, long timeout);
3643
void setPokeLock(int pokey, IBinder lock, String tag);
37-
int getSupportedWakeLockFlags();
3844
void setStayOnSetting(int val);
39-
void setMaximumScreenOffTimeount(int timeMs);
45+
void setMaximumScreenOffTimeoutFromDeviceAdmin(int timeMs);
4046
void preventScreenOn(boolean prevent);
41-
boolean isScreenOn();
42-
void reboot(String reason);
43-
void crash(String message);
4447

45-
// sets the brightness of the backlights (screen, keyboard, button) 0-255
46-
void setBacklightBrightness(int brightness);
48+
// temporarily overrides the screen brightness settings to allow the user to
49+
// see the effect of a settings change without applying it immediately
50+
void setTemporaryScreenBrightnessSettingOverride(int brightness);
51+
void setTemporaryScreenAutoBrightnessAdjustmentSettingOverride(float adj);
52+
53+
// sets the attention light (used by phone app only)
4754
void setAttentionLight(boolean on, int color);
48-
void setAutoBrightnessAdjustment(float adj);
4955
}

core/java/android/os/LocalPowerManager.java

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,11 @@
1818

1919
/** @hide */
2020
public interface LocalPowerManager {
21+
// FIXME: Replace poke locks with something else.
22+
2123
public static final int POKE_LOCK_IGNORE_TOUCH_EVENTS = 0x1;
2224

2325
public static final int POKE_LOCK_SHORT_TIMEOUT = 0x2;
2426
public static final int POKE_LOCK_MEDIUM_TIMEOUT = 0x4;
2527
public static final int POKE_LOCK_TIMEOUT_MASK = 0x6;
26-
27-
void goToSleep(long time);
28-
29-
// notify power manager when keyboard is opened/closed
30-
void setKeyboardVisibility(boolean visible);
31-
32-
// when the keyguard is up, it manages the power state, and userActivity doesn't do anything.
33-
void enableUserActivity(boolean enabled);
34-
35-
// the same as the method on PowerManager
36-
void userActivity(long time, boolean noChangeLights, int eventType);
37-
38-
boolean isScreenOn();
39-
40-
void setScreenBrightnessOverride(int brightness);
41-
void setButtonBrightnessOverride(int brightness);
4228
}

core/java/android/os/PowerManager.java

Lines changed: 121 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package android.os;
1818

19+
import android.content.Context;
1920
import android.util.Log;
2021

2122
/**
@@ -42,8 +43,8 @@
4243
* wl.release();
4344
* }
4445
* </p><p>
45-
* The following flags are defined, with varying effects on system power.
46-
* <i>These flags are mutually exclusive - you may only specify one of them.</i>
46+
* The following wake lock levels are defined, with varying effects on system power.
47+
* <i>These levels are mutually exclusive - you may only specify one of them.</i>
4748
*
4849
* <table border="2" width="85%" align="center" frame="hsides" rules="rows">
4950
* <thead>
@@ -177,7 +178,7 @@ public final class PowerManager {
177178
/**
178179
* Wake lock level: Turns the screen off when the proximity sensor activates.
179180
* <p>
180-
* Since not all devices have proximity sensors, use {@link #getSupportedWakeLockFlags}
181+
* Since not all devices have proximity sensors, use {@link #isWakeLockLevelSupported}
181182
* to determine whether this wake lock level is supported.
182183
* </p>
183184
*
@@ -226,29 +227,24 @@ public final class PowerManager {
226227
*/
227228
public static final int WAIT_FOR_PROXIMITY_NEGATIVE = 1;
228229

229-
/**
230-
* Brightness value to use when battery is low.
231-
* @hide
232-
*/
233-
public static final int BRIGHTNESS_LOW_BATTERY = 10;
234-
235230
/**
236231
* Brightness value for fully on.
237232
* @hide
238233
*/
239234
public static final int BRIGHTNESS_ON = 255;
240235

241236
/**
242-
* Brightness value for dim backlight.
237+
* Brightness value for fully off.
243238
* @hide
244239
*/
245-
public static final int BRIGHTNESS_DIM = 20;
240+
public static final int BRIGHTNESS_OFF = 0;
246241

247242
/**
248-
* Brightness value for fully off.
243+
* A nominal default brightness value.
244+
* Use {@link #getDefaultScreenBrightnessSetting()} instead.
249245
* @hide
250246
*/
251-
public static final int BRIGHTNESS_OFF = 0;
247+
private static final int BRIGHTNESS_DEFAULT = 102;
252248

253249
// Note: Be sure to update android.os.BatteryStats and PowerManager.h
254250
// if adding or modifying user activity event constants.
@@ -271,17 +267,81 @@ public final class PowerManager {
271267
*/
272268
public static final int USER_ACTIVITY_EVENT_TOUCH = 2;
273269

270+
/**
271+
* User activity flag: Do not restart the user activity timeout or brighten
272+
* the display in response to user activity if it is already dimmed.
273+
* @hide
274+
*/
275+
public static final int USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS = 1 << 0;
276+
277+
/**
278+
* Special wake lock tag used for the wake lock in the Window Manager that handles the
279+
* {@link android.view.WindowManager.LayoutParams#FLAG_KEEP_SCREEN_ON} flag.
280+
* @hide
281+
*/
282+
public static final String KEEP_SCREEN_ON_FLAG_TAG = "KEEP_SCREEN_ON_FLAG";
283+
284+
/**
285+
* Go to sleep reason code: Going to sleep due by user request.
286+
* @hide
287+
*/
288+
public static final int GO_TO_SLEEP_REASON_USER = 0;
289+
290+
/**
291+
* Go to sleep reason code: Going to sleep due by request of the
292+
* device administration policy.
293+
* @hide
294+
*/
295+
public static final int GO_TO_SLEEP_REASON_DEVICE_ADMIN = 1;
296+
297+
/**
298+
* Go to sleep reason code: Going to sleep due to a screen timeout.
299+
* @hide
300+
*/
301+
public static final int GO_TO_SLEEP_REASON_TIMEOUT = 2;
302+
303+
final Context mContext;
274304
final IPowerManager mService;
275305
final Handler mHandler;
276306

277307
/**
278308
* {@hide}
279309
*/
280-
public PowerManager(IPowerManager service, Handler handler) {
310+
public PowerManager(Context context, IPowerManager service, Handler handler) {
311+
mContext = context;
281312
mService = service;
282313
mHandler = handler;
283314
}
284315

316+
/**
317+
* Gets the minimum supported screen brightness setting.
318+
* The screen may be allowed to become dimmer than this value but
319+
* this is the minimum value that can be set by the user.
320+
* @hide
321+
*/
322+
public int getMinimumScreenBrightnessSetting() {
323+
return mContext.getResources().getInteger(
324+
com.android.internal.R.integer.config_screenBrightnessDim);
325+
}
326+
327+
/**
328+
* Gets the maximum supported screen brightness setting.
329+
* The screen may be allowed to become dimmer than this value but
330+
* this is the maximum value that can be set by the user.
331+
* @hide
332+
*/
333+
public int getMaximumScreenBrightnessSetting() {
334+
return BRIGHTNESS_ON;
335+
}
336+
337+
/**
338+
* Gets the default screen brightness setting.
339+
* @hide
340+
*/
341+
public int getDefaultScreenBrightnessSetting() {
342+
return BRIGHTNESS_DEFAULT;
343+
}
344+
285345
/**
286346
* Creates a new wake lock with the specified level and flags.
287347
* <p>
@@ -360,8 +420,10 @@ public static void validateWakeLockParameters(int levelAndFlags, String tag) {
360420
/**
361421
* Notifies the power manager that user activity happened.
362422
* <p>
363-
* Turns the device from whatever state it's in to full on, and resets
364-
* the auto-off timer.
423+
* Resets the auto-off timer and brightens the screen if the device
424+
* is not asleep. This is what happens normally when a key or the touch
425+
* screen is pressed or when some other user activity occurs.
426+
* This method does not wake up the device if it has been put to sleep.
365427
* </p><p>
366428
* Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
367429
* </p>
@@ -375,19 +437,23 @@ public static void validateWakeLockParameters(int levelAndFlags, String tag) {
375437
* We want the device to stay on while the button is down, but we're about
376438
* to turn off the screen so we don't want the keyboard backlight to turn on again.
377439
* Otherwise the lights flash on and then off and it looks weird.
440+
*
441+
* @see #wakeUp
442+
* @see #goToSleep
378443
*/
379444
public void userActivity(long when, boolean noChangeLights) {
380445
try {
381-
mService.userActivity(when, noChangeLights);
446+
mService.userActivity(when, USER_ACTIVITY_EVENT_OTHER,
447+
noChangeLights ? USER_ACTIVITY_FLAG_NO_CHANGE_LIGHTS : 0);
382448
} catch (RemoteException e) {
383449
}
384450
}
385451

386452
/**
387453
* Forces the device to go to sleep.
388454
* <p>
389-
* Overrides all the wake locks that are held. This is what happen when the power
390-
* key is pressed to turn off the screen.
455+
* Overrides all the wake locks that are held.
456+
* This is what happens when the power key is pressed to turn off the screen.
391457
* </p><p>
392458
* Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
393459
* </p>
@@ -396,10 +462,37 @@ public void userActivity(long when, boolean noChangeLights) {
396462
* {@link SystemClock#uptimeMillis()} time base. This timestamp is used to correctly
397463
* order the user activity with other power management functions. It should be set
398464
* to the timestamp of the input event that caused the request to go to sleep.
465+
*
466+
* @see #userActivity
467+
* @see #wakeUp
399468
*/
400469
public void goToSleep(long time) {
401470
try {
402-
mService.goToSleep(time);
471+
mService.goToSleep(time, GO_TO_SLEEP_REASON_USER);
472+
} catch (RemoteException e) {
473+
}
474+
}
475+
476+
/**
477+
* Forces the device to wake up from sleep.
478+
* <p>
479+
* If the device is currently asleep, wakes it up, otherwise does nothing.
480+
* This is what happens when the power key is pressed to turn on the screen.
481+
* </p><p>
482+
* Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
483+
* </p>
484+
*
485+
* @param time The time when the request to wake up was issued, in the
486+
* {@link SystemClock#uptimeMillis()} time base. This timestamp is used to correctly
487+
* order the user activity with other power management functions. It should be set
488+
* to the timestamp of the input event that caused the request to wake up.
489+
*
490+
* @see #userActivity
491+
* @see #goToSleep
492+
*/
493+
public void wakeUp(long time) {
494+
try {
495+
mService.wakeUp(time);
403496
} catch (RemoteException e) {
404497
}
405498
}
@@ -416,34 +509,24 @@ public void goToSleep(long time) {
416509
*/
417510
public void setBacklightBrightness(int brightness) {
418511
try {
419-
mService.setBacklightBrightness(brightness);
512+
mService.setTemporaryScreenBrightnessSettingOverride(brightness);
420513
} catch (RemoteException e) {
421514
}
422515
}
423516

424517
/**
425-
* Returns the set of wake lock levels and flags for {@link #newWakeLock}
426-
* that are supported on the device.
427-
* <p>
428-
* For example, to test to see if the {@link #PROXIMITY_SCREEN_OFF_WAKE_LOCK}
429-
* is supported:
430-
* {@samplecode
431-
* PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
432-
* int supportedFlags = pm.getSupportedWakeLockFlags();
433-
* boolean proximitySupported = ((supportedFlags & PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK)
434-
* == PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK);
435-
* }
436-
* </p>
518+
* Returns true if the specified wake lock level is supported.
437519
*
438-
* @return The set of supported WakeLock flags.
520+
* @param level The wake lock level to check.
521+
* @return True if the specified wake lock level is supported.
439522
*
440523
* {@hide}
441524
*/
442-
public int getSupportedWakeLockFlags() {
525+
public boolean isWakeLockLevelSupported(int level) {
443526
try {
444-
return mService.getSupportedWakeLockFlags();
527+
return mService.isWakeLockLevelSupported(level);
445528
} catch (RemoteException e) {
446-
return 0;
529+
return false;
447530
}
448531
}
449532

@@ -593,7 +676,7 @@ private void acquireLocked() {
593676
// been explicitly released by the keyguard.
594677
mHandler.removeCallbacks(mReleaser);
595678
try {
596-
mService.acquireWakeLock(mFlags, mToken, mTag, mWorkSource);
679+
mService.acquireWakeLock(mToken, mFlags, mTag, mWorkSource);
597680
} catch (RemoteException e) {
598681
}
599682
mHeld = true;

0 commit comments

Comments
 (0)