diff options
author | 2019-10-09 10:08:57 +0000 | |
---|---|---|
committer | 2019-10-09 10:08:57 +0000 | |
commit | 33c921c6b449da4ca6990b969362c38c5338e077 (patch) | |
tree | 28701ae0ecca30662760e0770e4c87417b35cd46 | |
parent | 7e30a95e66f55098f2151fa398c656aa9da3a28a (diff) | |
parent | 87b5a242b606c5d72bef2bc91624b6a5d0dda88b (diff) |
Merge "Introduce display specific all window drawn waiting (3/N)"
8 files changed, 95 insertions, 69 deletions
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java index 237a7712ce9b..ef31ef151d26 100644 --- a/services/core/java/com/android/server/policy/PhoneWindowManager.java +++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java @@ -4575,7 +4575,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { // ... eventually calls finishWindowsDrawn which will finalize our screen turn on // as well as enabling the orientation change logic/sensor. mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback, - WAITING_FOR_DRAWN_TIMEOUT); + WAITING_FOR_DRAWN_TIMEOUT, INVALID_DISPLAY); } // Called on the DisplayManager's DisplayPowerController thread. diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java index 0844323e08fa..f592ac6957cb 100644 --- a/services/core/java/com/android/server/wm/DisplayContent.java +++ b/services/core/java/com/android/server/wm/DisplayContent.java @@ -132,7 +132,6 @@ import static com.android.server.wm.WindowManagerService.dipToPixel; import static com.android.server.wm.WindowState.EXCLUSION_LEFT; import static com.android.server.wm.WindowState.EXCLUSION_RIGHT; import static com.android.server.wm.WindowState.RESIZE_HANDLE_WIDTH_IN_DP; -import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING; import static com.android.server.wm.WindowStateAnimator.READY_TO_SHOW; import static com.android.server.wm.utils.RegionUtils.forEachRectReverse; import static com.android.server.wm.utils.RegionUtils.rectListToRegion; @@ -3519,19 +3518,6 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo mWmService.mWindowPlacerLocked.performSurfacePlacement(); } - void waitForAllWindowsDrawn() { - final WindowManagerPolicy policy = mWmService.mPolicy; - forAllWindows(w -> { - final boolean keyguard = policy.isKeyguardHostWindow(w.mAttrs); - if (w.isVisibleLw() && (w.mAppToken != null || keyguard)) { - w.mWinAnimator.mDrawState = DRAW_PENDING; - // Force add to mResizingWindows. - w.resetLastContentInsets(); - mWmService.mWaitingForDrawn.add(w); - } - }, true /* traverseTopToBottom */); - } - // TODO: Super crazy long method that should be broken down... void applySurfaceChangesTransaction(boolean recoveringMemory) { final WindowSurfacePlacer surfacePlacer = mWmService.mWindowPlacerLocked; diff --git a/services/core/java/com/android/server/wm/DockedStackDividerController.java b/services/core/java/com/android/server/wm/DockedStackDividerController.java index ae3b5f2f70d3..d3e429019767 100644 --- a/services/core/java/com/android/server/wm/DockedStackDividerController.java +++ b/services/core/java/com/android/server/wm/DockedStackDividerController.java @@ -819,9 +819,12 @@ public class DockedStackDividerController { // We put all tasks into drag resizing mode - wait until all of them have completed the // drag resizing switch. - if (!mService.mWaitingForDrawn.isEmpty()) { - mService.mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); - mService.mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, + final Runnable existingWaitingForDrwanCallback = + mService.mWaitingForDrawnCallbacks.get(mService.mRoot); + if (existingWaitingForDrwanCallback != null) { + mService.mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, mService.mRoot); + mService.mH.sendMessageDelayed(mService.mH.obtainMessage(H.WAITING_FOR_DRAWN_TIMEOUT, + mService.mRoot), IME_ADJUST_DRAWN_TIMEOUT); mAnimationStartDelayed = true; if (imeWin != null) { @@ -838,10 +841,8 @@ public class DockedStackDividerController { // still gets executed. // TODO: Have a real system where we can wait on different windows to be drawn with // different callbacks. - if (mService.mWaitingForDrawnCallback != null) { - mService.mWaitingForDrawnCallback.run(); - } - mService.mWaitingForDrawnCallback = () -> { + existingWaitingForDrwanCallback.run(); + mService.mWaitingForDrawnCallbacks.put(mService.mRoot, () -> { synchronized (mService.mGlobalLock) { mAnimationStartDelayed = false; if (mDelayedImeWin != null) { @@ -863,7 +864,7 @@ public class DockedStackDividerController { notifyAdjustedForImeChanged( mAdjustedForIme || mAdjustedForDivider, duration); } - }; + }); } else { notifyAdjustedForImeChanged( adjustedForIme || adjustedForDivider, IME_ADJUST_ANIM_DURATION); diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java index 0c8cd4330d70..6f10d3d291b1 100644 --- a/services/core/java/com/android/server/wm/RootWindowContainer.java +++ b/services/core/java/com/android/server/wm/RootWindowContainer.java @@ -720,7 +720,7 @@ class RootWindowContainer extends WindowContainer<DisplayContent> mUpdateRotation = updateRotationUnchecked(); } - if (mWmService.mWaitingForDrawnCallback != null + if (!mWmService.mWaitingForDrawnCallbacks.isEmpty() || (mOrientationChangeComplete && !isLayoutNeeded() && !mUpdateRotation)) { mWmService.checkDrawnWindowsLocked(); diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java index 19fcb1b96e7b..a4ab66aef550 100644 --- a/services/core/java/com/android/server/wm/WindowContainer.java +++ b/services/core/java/com/android/server/wm/WindowContainer.java @@ -33,6 +33,7 @@ import static com.android.server.wm.WindowContainerProto.VISIBLE; import static com.android.server.wm.WindowManagerDebugConfig.DEBUG_ANIM; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WITH_CLASS_NAME; import static com.android.server.wm.WindowManagerDebugConfig.TAG_WM; +import static com.android.server.wm.WindowStateAnimator.DRAW_PENDING; import android.annotation.CallSuper; import android.annotation.IntDef; @@ -54,9 +55,11 @@ import android.view.SurfaceSession; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ToBooleanFunction; +import com.android.server.policy.WindowManagerPolicy; import com.android.server.wm.SurfaceAnimator.Animatable; import java.io.PrintWriter; +import java.util.ArrayList; import java.util.Comparator; import java.util.LinkedList; import java.util.function.Consumer; @@ -124,6 +127,11 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< private final Transaction mPendingTransaction; /** + * Windows that clients are waiting to have drawn. + */ + final ArrayList<WindowState> mWaitingForDrawn = new ArrayList<>(); + + /** * Applied as part of the animation pass in "prepareSurfaces". */ protected final SurfaceAnimator mSurfaceAnimator; @@ -1434,6 +1442,19 @@ class WindowContainer<E extends WindowContainer> extends ConfigurationContainer< } } + void waitForAllWindowsDrawn() { + final WindowManagerPolicy policy = mWmService.mPolicy; + forAllWindows(w -> { + final boolean keyguard = policy.isKeyguardHostWindow(w.mAttrs); + if (w.isVisibleLw() && (w.mAppToken != null || keyguard)) { + w.mWinAnimator.mDrawState = DRAW_PENDING; + // Force add to mResizingWindows. + w.resetLastContentInsets(); + mWaitingForDrawn.add(w); + } + }, true /* traverseTopToBottom */); + } + Dimmer getDimmer() { if (mParent == null) { return null; diff --git a/services/core/java/com/android/server/wm/WindowManagerInternal.java b/services/core/java/com/android/server/wm/WindowManagerInternal.java index bb3caa9ed4ed..f4b76729b7ea 100644 --- a/services/core/java/com/android/server/wm/WindowManagerInternal.java +++ b/services/core/java/com/android/server/wm/WindowManagerInternal.java @@ -313,10 +313,15 @@ public abstract class WindowManagerInternal { public abstract void showGlobalActions(); /** - * Invalidate all visible windows. Then report back on the callback once all windows have - * redrawn. + * Invalidate all visible windows on a given display, and report back on the callback when all + * windows have redrawn. + * + * @param callback reporting callback to be called when all windows have redrawn. + * @param timeout calls the callback anyway after the timeout. + * @param displayId waits for the windows on the given display, INVALID_DISPLAY to wait for all + * windows on all displays. */ - public abstract void waitForAllWindowsDrawn(Runnable callback, long timeout); + public abstract void waitForAllWindowsDrawn(Runnable callback, long timeout, int displayId); /** * Overrides the display size. diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 20812e98bf4a..0f4d0a8662f4 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -290,6 +290,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Date; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.function.Function; @@ -568,13 +569,10 @@ public class WindowManagerService extends IWindowManager.Stub final ArrayList<WindowState> mForceRemoves = new ArrayList<>(); /** - * Windows that clients are waiting to have drawn. + * The callbacks to make when the windows all have been drawn for a given + * {@link WindowContainer}. */ - ArrayList<WindowState> mWaitingForDrawn = new ArrayList<>(); - /** - * And the callback to make when they've all been drawn. - */ - Runnable mWaitingForDrawnCallback; + final HashMap<WindowContainer, Runnable> mWaitingForDrawnCallbacks = new HashMap<>(); /** List of window currently causing non-system overlay windows to be hidden. */ private ArrayList<WindowState> mHidingNonSystemOverlayWindows = new ArrayList<>(); @@ -4736,12 +4734,12 @@ public class WindowManagerService extends IWindowManager.Stub case WAITING_FOR_DRAWN_TIMEOUT: { Runnable callback = null; + final WindowContainer container = (WindowContainer) msg.obj; synchronized (mGlobalLock) { ProtoLog.w(WM_ERROR, "Timeout waiting for drawn: undrawn=%s", - mWaitingForDrawn); - mWaitingForDrawn.clear(); - callback = mWaitingForDrawnCallback; - mWaitingForDrawnCallback = null; + container.mWaitingForDrawn); + container.mWaitingForDrawn.clear(); + callback = mWaitingForDrawnCallbacks.remove(container); } if (callback != null) { callback.run(); @@ -4773,9 +4771,9 @@ public class WindowManagerService extends IWindowManager.Stub } case ALL_WINDOWS_DRAWN: { Runnable callback; + final WindowContainer container = (WindowContainer) msg.obj; synchronized (mGlobalLock) { - callback = mWaitingForDrawnCallback; - mWaitingForDrawnCallback = null; + callback = mWaitingForDrawnCallbacks.remove(container); } if (callback != null) { callback.run(); @@ -5265,30 +5263,32 @@ public class WindowManagerService extends IWindowManager.Stub } void checkDrawnWindowsLocked() { - if (mWaitingForDrawn.isEmpty() || mWaitingForDrawnCallback == null) { + if (mWaitingForDrawnCallbacks.isEmpty()) { return; } - for (int j = mWaitingForDrawn.size() - 1; j >= 0; j--) { - WindowState win = mWaitingForDrawn.get(j); - ProtoLog.i(WM_DEBUG_SCREEN_ON, + mWaitingForDrawnCallbacks.forEach((container, callback) -> { + for (int j = container.mWaitingForDrawn.size() - 1; j >= 0; j--) { + final WindowState win = (WindowState) container.mWaitingForDrawn.get(j); + ProtoLog.i(WM_DEBUG_SCREEN_ON, "Waiting for drawn %s: removed=%b visible=%b mHasSurface=%b drawState=%d", win, win.mRemoved, win.isVisibleLw(), win.mHasSurface, win.mWinAnimator.mDrawState); - if (win.mRemoved || !win.mHasSurface || !win.isVisibleByPolicy()) { - // Window has been removed or hidden; no draw will now happen, so stop waiting. - ProtoLog.w(WM_DEBUG_SCREEN_ON, "Aborted waiting for drawn: %s", win); - mWaitingForDrawn.remove(win); - } else if (win.hasDrawnLw()) { - // Window is now drawn (and shown). - ProtoLog.d(WM_DEBUG_SCREEN_ON, "Window drawn win=%s", win); - mWaitingForDrawn.remove(win); + if (win.mRemoved || !win.mHasSurface || !win.isVisibleByPolicy()) { + // Window has been removed or hidden; no draw will now happen, so stop waiting. + ProtoLog.w(WM_DEBUG_SCREEN_ON, "Aborted waiting for drawn: %s", win); + container.mWaitingForDrawn.remove(win); + } else if (win.hasDrawnLw()) { + // Window is now drawn (and shown). + ProtoLog.d(WM_DEBUG_SCREEN_ON, "Window drawn win=%s", win); + container.mWaitingForDrawn.remove(win); + } } - } - if (mWaitingForDrawn.isEmpty()) { - ProtoLog.d(WM_DEBUG_SCREEN_ON, "All windows drawn!"); - mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); - mH.sendEmptyMessage(H.ALL_WINDOWS_DRAWN); - } + if (container.mWaitingForDrawn.isEmpty()) { + ProtoLog.d(WM_DEBUG_SCREEN_ON, "All windows drawn!"); + mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, container); + mH.sendMessage(mH.obtainMessage(H.ALL_WINDOWS_DRAWN, container)); + } + }); } void setHoldScreenLocked(final Session newHoldScreen) { @@ -5934,13 +5934,18 @@ public class WindowManagerService extends IWindowManager.Stub } } } - if (mWaitingForDrawn.size() > 0) { + if (!mWaitingForDrawnCallbacks.isEmpty()) { pw.println(); pw.println(" Clients waiting for these windows to be drawn:"); - for (int i=mWaitingForDrawn.size()-1; i>=0; i--) { - WindowState win = mWaitingForDrawn.get(i); - pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(win); - } + mWaitingForDrawnCallbacks.forEach((wc, callback) -> { + pw.print(" WindowContainer "); + pw.println(wc.getName()); + for (int i = wc.mWaitingForDrawn.size() - 1; i >= 0; i--) { + final WindowState win = (WindowState) wc.mWaitingForDrawn.get(i); + pw.print(" Waiting #"); pw.print(i); pw.print(' '); pw.print(win); + } + }); + } pw.println(); pw.print(" mGlobalConfiguration="); pw.println(mRoot.getConfiguration()); @@ -7096,17 +7101,25 @@ public class WindowManagerService extends IWindowManager.Stub } @Override - public void waitForAllWindowsDrawn(Runnable callback, long timeout) { + public void waitForAllWindowsDrawn(Runnable callback, long timeout, int displayId) { + final WindowContainer container = displayId == INVALID_DISPLAY + ? mRoot : mRoot.getDisplayContent(displayId); + if (container == null) { + // The waiting container doesn't exist, no need to wait to run the callback. Run and + // return; + callback.run(); + return; + } boolean allWindowsDrawn = false; synchronized (mGlobalLock) { - mWaitingForDrawnCallback = callback; - getDefaultDisplayContentLocked().waitForAllWindowsDrawn(); + container.waitForAllWindowsDrawn(); mWindowPlacerLocked.requestTraversal(); - mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT); - if (mWaitingForDrawn.isEmpty()) { + mH.removeMessages(H.WAITING_FOR_DRAWN_TIMEOUT, container); + if (container.mWaitingForDrawn.isEmpty()) { allWindowsDrawn = true; } else { - mH.sendEmptyMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, timeout); + mWaitingForDrawnCallbacks.put(container, callback); + mH.sendNewMessageDelayed(H.WAITING_FOR_DRAWN_TIMEOUT, container, timeout); checkDrawnWindowsLocked(); } } diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 82b9d460029d..56e08b2843b5 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -3497,7 +3497,7 @@ class WindowState extends WindowContainer<WindowState> implements WindowManagerP @Override void setWaitingForDrawnIfResizingChanged() { if (isDragResizeChanged()) { - mWmService.mWaitingForDrawn.add(this); + mWmService.mRoot.mWaitingForDrawn.add(this); } super.setWaitingForDrawnIfResizingChanged(); } |