diff options
author | Chad Jones <chadj@google.com> | 2015-02-23 21:17:58 -0800 |
---|---|---|
committer | Chad Jones <chadj@google.com> | 2015-02-23 21:19:58 -0800 |
commit | 1fb55286438967f82e305a8449c0528a7cd07fce (patch) | |
tree | 30bca6153975a4ae82db73c851905ebf90722292 | |
parent | 39fee05ea25c68f6e5156483cc5e5cc44e9b09d9 (diff) | |
parent | 57bb5f5c8bf1875d2c6843237f518e5a1f9fe597 (diff) | |
download | frameworks_base-1fb55286438967f82e305a8449c0528a7cd07fce.zip frameworks_base-1fb55286438967f82e305a8449c0528a7cd07fce.tar.gz frameworks_base-1fb55286438967f82e305a8449c0528a7cd07fce.tar.bz2 |
resolved conflicts for merge of 57bb5f5c to master
Change-Id: Id5dfe7fc919305658312771a031c0764cef5515c
10 files changed, 141 insertions, 3 deletions
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java index d52dd30..e303f61 100644 --- a/core/java/android/os/PowerManager.java +++ b/core/java/android/os/PowerManager.java @@ -205,6 +205,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. * * @hide @@ -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."); diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl index d08ab46..fc0148f 100644 --- a/core/java/android/view/IWindowSession.aidl +++ b/core/java/android/view/IWindowSession.aidl @@ -194,4 +194,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); } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index f392682..3baf3e0 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -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; @@ -838,6 +839,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); @@ -868,6 +870,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(); @@ -1042,6 +1057,7 @@ public final class ViewRootImpl implements ViewParent, scheduleConsumeBatchedInput(); } notifyRendererOfFramePending(); + pokeDrawLockIfNeeded(); } } diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml index 51c6a66..4c0520e 100755 --- a/core/res/res/values/config.xml +++ b/core/res/res/values/config.xml @@ -1852,6 +1852,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 diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml index 37c6d29..615f445 100755 --- a/core/res/res/values/symbols.xml +++ b/core/res/res/values/symbols.xml @@ -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" /> diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java index 9786b42..66c2f5f 100644 --- a/services/core/java/com/android/server/power/PowerManagerService.java +++ b/services/core/java/com/android/server/power/PowerManagerService.java @@ -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 "??? "; } diff --git a/services/core/java/com/android/server/wm/Session.java b/services/core/java/com/android/server/wm/Session.java index d68c056..487483e 100644 --- a/services/core/java/com/android/server/wm/Session.java +++ b/services/core/java/com/android/server/wm/Session.java @@ -461,6 +461,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( diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index de8a2fc..d4a15af5 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -189,6 +189,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; @@ -327,6 +328,7 @@ public class WindowManagerService extends IWindowManager.Stub final boolean mHaveInputMethods; final boolean mHasPermanentDpad; + final long mDrawLockTimeoutMillis; final boolean mAllowBootMessages; @@ -846,6 +848,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(); @@ -2960,6 +2964,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, @@ -9957,7 +9970,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; diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index d58b2b0..04aea84 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -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; @@ -343,6 +346,15 @@ final class WindowState implements WindowManagerPolicy.WindowState { /** When true this window can be displayed on screens owther than mOwnerUid's */ private boolean mShowToOwnerOnly; + /** + * 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) { @@ -1269,6 +1281,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(); @@ -1642,6 +1681,9 @@ final class WindowState implements WindowManagerPolicy.WindowState { pw.print(" mWallpaperDisplayOffsetY="); pw.println(mWallpaperDisplayOffsetY); } + if (mDrawLock != null) { + pw.println("mDrawLock=" + mDrawLock); + } } String makeInputChannelName() { diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java index 62a03e1..4289689 100644 --- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java +++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeWindowSession.java @@ -206,4 +206,9 @@ public final class BridgeWindowSession implements IWindowSession { // pass for now. return null; } + + @Override + public void pokeDrawLock(IBinder window) { + // pass for now. + } } |