diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl index 715fa7b4eacb4..acb13877c7a44 100644 --- a/core/java/android/view/IWindow.aidl +++ b/core/java/android/view/IWindow.aidl @@ -49,6 +49,7 @@ oneway interface IWindow { boolean reportDraw, in Configuration newConfig); void dispatchAppVisibility(boolean visible); void dispatchGetNewSurface(); + void dispatchScreenStatus(boolean on); /** * Tell the window that it is either gaining or losing focus. Keep it up diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 49f6023d1b3ba..1a6c97bd176c7 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -14845,6 +14845,8 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal boolean mHardwareAccelerationRequested; HardwareRenderer mHardwareRenderer; + boolean mScreenOn; + /** * Scale factor used by the compatibility mode */ diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index e0d07635c1e87..3bc867c2a7387 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -46,6 +46,7 @@ import android.os.LatencyTimer; 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; @@ -390,6 +391,9 @@ public final class ViewRootImpl implements ViewParent, mProfileRendering = Boolean.parseBoolean( SystemProperties.get(PROPERTY_PROFILE_RENDERING, "false")); mChoreographer = Choreographer.getInstance(); + + PowerManager powerManager = (PowerManager) context.getSystemService(Context.POWER_SERVICE); + mAttachInfo.mScreenOn = powerManager.isScreenOn(); } /** @@ -757,6 +761,16 @@ public final class ViewRootImpl implements ViewParent, scheduleTraversals(); } + void handleScreenStatusChange(boolean on) { + if (on != mAttachInfo.mScreenOn) { + mAttachInfo.mScreenOn = on; + if (on) { + mFullRedrawNeeded = true; + scheduleTraversals(); + } + } + } + /** * {@inheritDoc} */ @@ -1886,6 +1900,8 @@ public final class ViewRootImpl implements ViewParent, } private void performDraw() { + if (!mAttachInfo.mScreenOn) return; + final long drawStartTime; if (ViewDebug.DEBUG_LATENCY) { drawStartTime = System.nanoTime(); @@ -2018,8 +2034,7 @@ public final class ViewRootImpl implements ViewParent, } if (!dirty.isEmpty() || mIsAnimating) { - if (mAttachInfo.mHardwareRenderer != null - && mAttachInfo.mHardwareRenderer.isEnabled()) { + if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) { // Draw with hardware renderer. mIsAnimating = false; mHardwareYOffset = yoff; @@ -2485,6 +2500,7 @@ public final class ViewRootImpl implements ViewParent, private final static int MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_VIEW_ID = 21; private final static int MSG_FIND_ACCESSIBLITY_NODE_INFO_BY_TEXT = 22; private final static int MSG_PROCESS_INPUT_EVENTS = 23; + private final static int MSG_DISPATCH_SCREEN_STATUS = 24; final class ViewRootHandler extends Handler { @Override @@ -2741,6 +2757,11 @@ public final class ViewRootImpl implements ViewParent, .findAccessibilityNodeInfosByTextUiThread(msg); } } break; + case MSG_DISPATCH_SCREEN_STATUS: { + if (mView != null) { + handleScreenStatusChange(msg.arg1 == 1); + } + } break; } } } @@ -4025,6 +4046,12 @@ public final class ViewRootImpl implements ViewParent, mHandler.sendMessage(msg); } + public void dispatchScreenStatusChange(boolean on) { + Message msg = mHandler.obtainMessage(MSG_DISPATCH_SCREEN_STATUS); + msg.arg1 = on ? 1 : 0; + mHandler.sendMessage(msg); + } + public void dispatchGetNewSurface() { Message msg = mHandler.obtainMessage(MSG_DISPATCH_GET_NEW_SURFACE); mHandler.sendMessage(msg); @@ -4226,6 +4253,13 @@ public final class ViewRootImpl implements ViewParent, } } + public void dispatchScreenStatus(boolean on) { + final ViewRootImpl viewAncestor = mViewAncestor.get(); + if (viewAncestor != null) { + viewAncestor.dispatchScreenStatusChange(on); + } + } + public void dispatchGetNewSurface() { final ViewRootImpl viewAncestor = mViewAncestor.get(); if (viewAncestor != null) { diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java index b22770093014d..e695f8efbcb86 100644 --- a/core/java/com/android/internal/view/BaseIWindow.java +++ b/core/java/com/android/internal/view/BaseIWindow.java @@ -49,6 +49,9 @@ public class BaseIWindow extends IWindow.Stub { public void dispatchGetNewSurface() { } + public void dispatchScreenStatus(boolean on) { + } + public void windowFocusChanged(boolean hasFocus, boolean touchEnabled) { } diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java index 1c5a70fdaef3b..023f97dbb1d42 100644 --- a/services/java/com/android/server/wm/WindowManagerService.java +++ b/services/java/com/android/server/wm/WindowManagerService.java @@ -6347,6 +6347,8 @@ public class WindowManagerService extends IWindowManager.Stub synchronized (mWindowMap) { mInputMonitor.setEventDispatchingLw(enabled); } + + sendScreenStatusToClients(); } /** @@ -6570,6 +6572,20 @@ public class WindowManagerService extends IWindowManager.Stub mPolicy.systemReady(); } + private void sendScreenStatusToClients() { + final ArrayList windows = mWindows; + final int count = windows.size(); + boolean on = mPowerManager.isScreenOn(); + for (int i = count - 1; i >= 0; i--) { + WindowState win = mWindows.get(i); + try { + win.mClient.dispatchScreenStatus(on); + } catch (RemoteException e) { + // Ignored + } + } + } + // This is an animation that does nothing: it just immediately finishes // itself every time it is called. It is used as a stub animation in cases // where we want to synchronize multiple things that may be animating.