Merge "Hold a wake lock while dozing when display updates are pending." into lmp-mr1-modular-dev
This commit is contained in:
@@ -204,6 +204,20 @@ public final class PowerManager {
|
||||
*/
|
||||
public static final int DOZE_WAKE_LOCK = 0x00000040;
|
||||
|
||||
/**
|
||||
* Wake lock level: Keep the device awake enough to allow drawing to occur.
|
||||
* <p>
|
||||
* This is used by the window manager to allow applications to draw while the
|
||||
* system is dozing. It currently has no effect unless the power manager is in
|
||||
* the dozing state.
|
||||
* </p><p>
|
||||
* Requires the {@link android.Manifest.permission#DEVICE_POWER} permission.
|
||||
* </p>
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
public static final int DRAW_WAKE_LOCK = 0x00000080;
|
||||
|
||||
/**
|
||||
* Mask for the wake lock level component of a combined wake lock level and flags integer.
|
||||
*
|
||||
@@ -489,6 +503,7 @@ public final class PowerManager {
|
||||
case FULL_WAKE_LOCK:
|
||||
case PROXIMITY_SCREEN_OFF_WAKE_LOCK:
|
||||
case DOZE_WAKE_LOCK:
|
||||
case DRAW_WAKE_LOCK:
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Must specify a valid wake lock level.");
|
||||
|
||||
@@ -197,4 +197,19 @@ interface IWindowSession {
|
||||
void onRectangleOnScreenRequested(IBinder token, in Rect rectangle);
|
||||
|
||||
IWindowId getWindowId(IBinder window);
|
||||
|
||||
/**
|
||||
* When the system is dozing in a low-power partially suspended state, pokes a short
|
||||
* lived wake lock and ensures that the display is ready to accept the next frame
|
||||
* of content drawn in the window.
|
||||
*
|
||||
* This mechanism is bound to the window rather than to the display manager or the
|
||||
* power manager so that the system can ensure that the window is actually visible
|
||||
* and prevent runaway applications from draining the battery. This is similar to how
|
||||
* FLAG_KEEP_SCREEN_ON works.
|
||||
*
|
||||
* This method is synchronous because it may need to acquire a wake lock before returning.
|
||||
* The assumption is that this method will be called rather infrequently.
|
||||
*/
|
||||
void pokeDrawLock(IBinder window);
|
||||
}
|
||||
|
||||
@@ -47,6 +47,7 @@ import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.PowerManager;
|
||||
import android.os.Process;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
@@ -831,6 +832,7 @@ public final class ViewRootImpl implements ViewParent,
|
||||
final int newDisplayState = mDisplay.getState();
|
||||
if (oldDisplayState != newDisplayState) {
|
||||
mAttachInfo.mDisplayState = newDisplayState;
|
||||
pokeDrawLockIfNeeded();
|
||||
if (oldDisplayState != Display.STATE_UNKNOWN) {
|
||||
final int oldScreenState = toViewScreenState(oldDisplayState);
|
||||
final int newScreenState = toViewScreenState(newDisplayState);
|
||||
@@ -861,6 +863,19 @@ public final class ViewRootImpl implements ViewParent,
|
||||
}
|
||||
};
|
||||
|
||||
void pokeDrawLockIfNeeded() {
|
||||
final int displayState = mAttachInfo.mDisplayState;
|
||||
if (mView != null && mAdded && mTraversalScheduled
|
||||
&& (displayState == Display.STATE_DOZE
|
||||
|| displayState == Display.STATE_DOZE_SUSPEND)) {
|
||||
try {
|
||||
mWindowSession.pokeDrawLock(mWindow);
|
||||
} catch (RemoteException ex) {
|
||||
// System server died, oh well.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestFitSystemWindows() {
|
||||
checkThread();
|
||||
@@ -1035,6 +1050,7 @@ public final class ViewRootImpl implements ViewParent,
|
||||
scheduleConsumeBatchedInput();
|
||||
}
|
||||
notifyRendererOfFramePending();
|
||||
pokeDrawLockIfNeeded();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1844,6 +1844,12 @@
|
||||
<item>users</item>
|
||||
</string-array>
|
||||
|
||||
<!-- Number of milliseconds to hold a wake lock to ensure that drawing is fully
|
||||
flushed to the display while dozing. This value needs to be large enough
|
||||
to account for processing and rendering time plus a frame or two of latency
|
||||
in the display pipeline plus some slack just to be sure. -->
|
||||
<integer name="config_drawLockTimeoutMillis">120</integer>
|
||||
|
||||
<!-- default telephony hardware configuration for this platform.
|
||||
-->
|
||||
<!-- this string array should be overridden by the device to present a list
|
||||
|
||||
@@ -345,6 +345,7 @@
|
||||
<java-symbol type="integer" name="config_bluetooth_max_advertisers" />
|
||||
<java-symbol type="integer" name="config_bluetooth_max_scan_filters" />
|
||||
<java-symbol type="integer" name="config_cursorWindowSize" />
|
||||
<java-symbol type="integer" name="config_drawLockTimeoutMillis" />
|
||||
<java-symbol type="integer" name="config_doublePressOnPowerBehavior" />
|
||||
<java-symbol type="integer" name="config_extraFreeKbytesAdjust" />
|
||||
<java-symbol type="integer" name="config_extraFreeKbytesAbsolute" />
|
||||
|
||||
@@ -128,6 +128,7 @@ public final class PowerManagerService extends SystemService
|
||||
private static final int WAKE_LOCK_PROXIMITY_SCREEN_OFF = 1 << 4;
|
||||
private static final int WAKE_LOCK_STAY_AWAKE = 1 << 5; // only set if already awake
|
||||
private static final int WAKE_LOCK_DOZE = 1 << 6;
|
||||
private static final int WAKE_LOCK_DRAW = 1 << 7;
|
||||
|
||||
// Summarizes the user activity state.
|
||||
private static final int USER_ACTIVITY_SCREEN_BRIGHT = 1 << 0;
|
||||
@@ -1398,12 +1399,15 @@ public final class PowerManagerService extends SystemService
|
||||
case PowerManager.DOZE_WAKE_LOCK:
|
||||
mWakeLockSummary |= WAKE_LOCK_DOZE;
|
||||
break;
|
||||
case PowerManager.DRAW_WAKE_LOCK:
|
||||
mWakeLockSummary |= WAKE_LOCK_DRAW;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Cancel wake locks that make no sense based on the current state.
|
||||
if (mWakefulness != WAKEFULNESS_DOZING) {
|
||||
mWakeLockSummary &= ~WAKE_LOCK_DOZE;
|
||||
mWakeLockSummary &= ~(WAKE_LOCK_DOZE | WAKE_LOCK_DRAW);
|
||||
}
|
||||
if (mWakefulness == WAKEFULNESS_ASLEEP
|
||||
|| (mWakeLockSummary & WAKE_LOCK_DOZE) != 0) {
|
||||
@@ -1422,6 +1426,9 @@ public final class PowerManagerService extends SystemService
|
||||
mWakeLockSummary |= WAKE_LOCK_CPU;
|
||||
}
|
||||
}
|
||||
if ((mWakeLockSummary & WAKE_LOCK_DRAW) != 0) {
|
||||
mWakeLockSummary |= WAKE_LOCK_CPU;
|
||||
}
|
||||
|
||||
if (DEBUG_SPEW) {
|
||||
Slog.d(TAG, "updateWakeLockSummaryLocked: mWakefulness="
|
||||
@@ -1845,6 +1852,10 @@ public final class PowerManagerService extends SystemService
|
||||
|
||||
if (mDisplayPowerRequest.policy == DisplayPowerRequest.POLICY_DOZE) {
|
||||
mDisplayPowerRequest.dozeScreenState = mDozeScreenStateOverrideFromDreamManager;
|
||||
if (mDisplayPowerRequest.dozeScreenState == Display.STATE_DOZE_SUSPEND
|
||||
&& (mWakeLockSummary & WAKE_LOCK_DRAW) != 0) {
|
||||
mDisplayPowerRequest.dozeScreenState = Display.STATE_DOZE;
|
||||
}
|
||||
mDisplayPowerRequest.dozeScreenBrightness =
|
||||
mDozeScreenBrightnessOverrideFromDreamManager;
|
||||
} else {
|
||||
@@ -2712,6 +2723,8 @@ public final class PowerManagerService extends SystemService
|
||||
return "PROXIMITY_SCREEN_OFF_WAKE_LOCK";
|
||||
case PowerManager.DOZE_WAKE_LOCK:
|
||||
return "DOZE_WAKE_LOCK ";
|
||||
case PowerManager.DRAW_WAKE_LOCK:
|
||||
return "DRAW_WAKE_LOCK ";
|
||||
default:
|
||||
return "??? ";
|
||||
}
|
||||
|
||||
@@ -475,6 +475,16 @@ final class Session extends IWindowSession.Stub
|
||||
return mService.getWindowId(window);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pokeDrawLock(IBinder window) {
|
||||
final long identity = Binder.clearCallingIdentity();
|
||||
try {
|
||||
mService.pokeDrawLock(this, window);
|
||||
} finally {
|
||||
Binder.restoreCallingIdentity(identity);
|
||||
}
|
||||
}
|
||||
|
||||
void windowAddedLocked() {
|
||||
if (mSurfaceSession == null) {
|
||||
if (WindowManagerService.localLOGV) Slog.v(
|
||||
|
||||
@@ -194,6 +194,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
static final boolean DEBUG_TASK_MOVEMENT = false;
|
||||
static final boolean DEBUG_STACK = false;
|
||||
static final boolean DEBUG_DISPLAY = false;
|
||||
static final boolean DEBUG_POWER = false;
|
||||
static final boolean SHOW_SURFACE_ALLOC = false;
|
||||
static final boolean SHOW_TRANSACTIONS = false;
|
||||
static final boolean SHOW_LIGHT_TRANSACTIONS = false || SHOW_TRANSACTIONS;
|
||||
@@ -338,6 +339,7 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
final boolean mHaveInputMethods;
|
||||
|
||||
final boolean mHasPermanentDpad;
|
||||
final long mDrawLockTimeoutMillis;
|
||||
|
||||
final boolean mAllowBootMessages;
|
||||
|
||||
@@ -827,6 +829,8 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
com.android.internal.R.bool.config_hasPermanentDpad);
|
||||
mInTouchMode = context.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_defaultInTouchMode);
|
||||
mDrawLockTimeoutMillis = context.getResources().getInteger(
|
||||
com.android.internal.R.integer.config_drawLockTimeoutMillis);
|
||||
mInputManager = inputManager; // Must be before createDisplayContentLocked.
|
||||
mDisplayManagerInternal = LocalServices.getService(DisplayManagerInternal.class);
|
||||
mDisplaySettings = new DisplaySettings();
|
||||
@@ -2992,6 +2996,15 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
}
|
||||
}
|
||||
|
||||
public void pokeDrawLock(Session session, IBinder token) {
|
||||
synchronized (mWindowMap) {
|
||||
WindowState window = windowForClientLocked(session, token, false);
|
||||
if (window != null) {
|
||||
window.pokeDrawLockLw(mDrawLockTimeoutMillis);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int relayoutWindow(Session session, IWindow client, int seq,
|
||||
WindowManager.LayoutParams attrs, int requestedWidth,
|
||||
int requestedHeight, int viewVisibility, int flags,
|
||||
@@ -10110,7 +10123,9 @@ public class WindowManagerService extends IWindowManager.Stub
|
||||
if (mAllowTheaterModeWakeFromLayout
|
||||
|| Settings.Global.getInt(mContext.getContentResolver(),
|
||||
Settings.Global.THEATER_MODE_ON, 0) == 0) {
|
||||
if (DEBUG_VISIBILITY) Slog.v(TAG, "Turning screen on after layout!");
|
||||
if (DEBUG_VISIBILITY || DEBUG_POWER) {
|
||||
Slog.v(TAG, "Turning screen on after layout!");
|
||||
}
|
||||
mPowerManager.wakeUp(SystemClock.uptimeMillis());
|
||||
}
|
||||
mTurnOnScreen = false;
|
||||
|
||||
@@ -19,9 +19,9 @@ package com.android.server.wm;
|
||||
import static com.android.server.wm.WindowManagerService.DEBUG_CONFIGURATION;
|
||||
import static com.android.server.wm.WindowManagerService.DEBUG_LAYOUT;
|
||||
import static com.android.server.wm.WindowManagerService.DEBUG_ORIENTATION;
|
||||
import static com.android.server.wm.WindowManagerService.DEBUG_POWER;
|
||||
import static com.android.server.wm.WindowManagerService.DEBUG_RESIZE;
|
||||
import static com.android.server.wm.WindowManagerService.DEBUG_VISIBILITY;
|
||||
|
||||
import static android.view.WindowManager.LayoutParams.FIRST_SUB_WINDOW;
|
||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_KEYGUARD;
|
||||
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_COMPATIBLE_WINDOW;
|
||||
@@ -34,12 +34,15 @@ import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
|
||||
|
||||
import android.app.AppOpsManager;
|
||||
import android.os.Debug;
|
||||
import android.os.PowerManager;
|
||||
import android.os.RemoteCallbackList;
|
||||
import android.os.SystemClock;
|
||||
import android.os.WorkSource;
|
||||
import android.util.TimeUtils;
|
||||
import android.view.Display;
|
||||
import android.view.IWindowFocusObserver;
|
||||
import android.view.IWindowId;
|
||||
|
||||
import com.android.server.input.InputWindowHandle;
|
||||
|
||||
import android.content.Context;
|
||||
@@ -345,6 +348,15 @@ final class WindowState implements WindowManagerPolicy.WindowState {
|
||||
* the status bar */
|
||||
boolean mUnderStatusBar = true;
|
||||
|
||||
/**
|
||||
* Wake lock for drawing.
|
||||
* Even though it's slightly more expensive to do so, we will use a separate wake lock
|
||||
* for each app that is requesting to draw while dozing so that we can accurately track
|
||||
* who is preventing the system from suspending.
|
||||
* This lock is only acquired on first use.
|
||||
*/
|
||||
PowerManager.WakeLock mDrawLock;
|
||||
|
||||
WindowState(WindowManagerService service, Session s, IWindow c, WindowToken token,
|
||||
WindowState attachedWindow, int appOp, int seq, WindowManager.LayoutParams a,
|
||||
int viewVisibility, final DisplayContent displayContent) {
|
||||
@@ -1272,6 +1284,33 @@ final class WindowState implements WindowManagerPolicy.WindowState {
|
||||
}
|
||||
}
|
||||
|
||||
public void pokeDrawLockLw(long timeout) {
|
||||
if (isVisibleOrAdding()) {
|
||||
if (mDrawLock == null) {
|
||||
// We want the tag name to be somewhat stable so that it is easier to correlate
|
||||
// in wake lock statistics. So in particular, we don't want to include the
|
||||
// window's hash code as in toString().
|
||||
CharSequence tag = mAttrs.getTitle();
|
||||
if (tag == null) {
|
||||
tag = mAttrs.packageName;
|
||||
}
|
||||
mDrawLock = mService.mPowerManager.newWakeLock(
|
||||
PowerManager.DRAW_WAKE_LOCK, "Window:" + tag);
|
||||
mDrawLock.setReferenceCounted(false);
|
||||
mDrawLock.setWorkSource(new WorkSource(mOwnerUid, mAttrs.packageName));
|
||||
}
|
||||
// Each call to acquire resets the timeout.
|
||||
if (DEBUG_POWER) {
|
||||
Slog.d(TAG, "pokeDrawLock: poking draw lock on behalf of visible window owned by "
|
||||
+ mAttrs.packageName);
|
||||
}
|
||||
mDrawLock.acquire(timeout);
|
||||
} else if (DEBUG_POWER) {
|
||||
Slog.d(TAG, "pokeDrawLock: suppressed draw lock request for invisible window "
|
||||
+ "owned by " + mAttrs.packageName);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAlive() {
|
||||
return mClient.asBinder().isBinderAlive();
|
||||
@@ -1626,6 +1665,9 @@ final class WindowState implements WindowManagerPolicy.WindowState {
|
||||
pw.print(" mWallpaperDisplayOffsetY=");
|
||||
pw.println(mWallpaperDisplayOffsetY);
|
||||
}
|
||||
if (mDrawLock != null) {
|
||||
pw.println("mDrawLock=" + mDrawLock);
|
||||
}
|
||||
}
|
||||
|
||||
String makeInputChannelName() {
|
||||
|
||||
@@ -212,4 +212,9 @@ public final class BridgeWindowSession implements IWindowSession {
|
||||
// pass for now.
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pokeDrawLock(IBinder window) {
|
||||
// pass for now.
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user