From 7be2a4c96475b5f8a8a9b435b0887c5d6c575b72 Mon Sep 17 00:00:00 2001 From: Tiger Huang Date: Wed, 9 Jun 2021 00:51:50 +0800 Subject: [PATCH] Defer dispatching insets to app if its window frame will be changed soon If the frames of insets source window and the frame of an app window are changed in the same layout pass, we should dispatch the insets calculated from the new insets source frames and the new app window frame. So when the app frame is not up-to-date, we defer dispatching insets to the app. Fix: 160732586 Test: Add logs to check if we dispatch the correct insets to apps while rotating the display. Change-Id: Ic9e71d8eabde51067b740b35404ae7c9b68228d7 --- core/java/android/view/IWindow.aidl | 11 ++++- core/java/android/view/ViewRootImpl.java | 49 +++++++++++++++---- .../android/internal/view/BaseIWindow.java | 4 +- .../wm/shell/common/SystemWindows.java | 4 +- .../com/android/server/wm/WindowState.java | 8 ++- .../com/android/server/wm/TestIWindow.java | 6 +-- 6 files changed, 61 insertions(+), 21 deletions(-) diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl index 8d59ba0b1f765..b8b13b9ed88a4 100644 --- a/core/java/android/view/IWindow.aidl +++ b/core/java/android/view/IWindow.aidl @@ -65,13 +65,20 @@ oneway interface IWindow { /** * Called when the window insets configuration has changed. + * + * @param willMove The window frame will be moved soon. + * @param willResize The window frame will be resized soon. */ - void insetsChanged(in InsetsState insetsState); + void insetsChanged(in InsetsState insetsState, in boolean willMove, in boolean willResize); /** * Called when this window retrieved control over a specified set of insets sources. + * + * @param willMove The window frame will be moved soon. + * @param willResize The window frame will be resized soon. */ - void insetsControlChanged(in InsetsState insetsState, in InsetsSourceControl[] activeControls); + void insetsControlChanged(in InsetsState insetsState, in InsetsSourceControl[] activeControls, + in boolean willMove, in boolean willResize); /** * Called when a set of insets source window should be shown by policy. diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index afd6878da4290..7a909b1a544ac 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -585,6 +585,10 @@ public final class ViewRootImpl implements ViewParent, final Rect mWinFrame; // frame given by window manager. final Rect mPendingBackDropFrame = new Rect(); + + private boolean mWillMove; + private boolean mWillResize; + boolean mPendingAlwaysConsumeSystemBars; private final InsetsState mTempInsets = new InsetsState(); private final InsetsSourceControl[] mTempControls = new InsetsSourceControl[SIZE]; @@ -1708,6 +1712,10 @@ public final class ViewRootImpl implements ViewParent, void notifyInsetsChanged() { mApplyInsetsRequested = true; + if (mWillMove || mWillResize) { + // The window frame will be changed soon. The following logic will be executed then. + return; + } requestLayout(); // See comment for View.sForceLayoutWhenInsetsChanged @@ -2665,7 +2673,7 @@ public final class ViewRootImpl implements ViewParent, } } - if (mApplyInsetsRequested) { + if (mApplyInsetsRequested && !(mWillMove || mWillResize)) { dispatchApplyInsets(host); if (mLayoutRequested) { // Short-circuit catching a new layout request here, so @@ -5235,16 +5243,25 @@ public final class ViewRootImpl implements ViewParent, break; case MSG_RESIZED: case MSG_RESIZED_REPORT: { + mWillMove = false; + mWillResize = false; final SomeArgs args = (SomeArgs) msg.obj; handleResized(msg.what, args); args.recycle(); break; } - case MSG_INSETS_CHANGED: - mInsetsController.onStateChanged((InsetsState) msg.obj); + case MSG_INSETS_CHANGED: { + SomeArgs args = (SomeArgs) msg.obj; + mWillMove = args.argi1 == 1; + mWillResize = args.argi2 == 1; + mInsetsController.onStateChanged((InsetsState) args.arg1); + args.recycle(); break; + } case MSG_INSETS_CONTROL_CHANGED: { SomeArgs args = (SomeArgs) msg.obj; + mWillMove = args.argi1 == 1; + mWillResize = args.argi2 == 1; // Deliver state change before control change, such that: // a) When gaining control, controller can compare with server state to evaluate @@ -5253,6 +5270,7 @@ public final class ViewRootImpl implements ViewParent, // dispatched state as truth. mInsetsController.onStateChanged((InsetsState) args.arg1); mInsetsController.onControlsChanged((InsetsSourceControl[]) args.arg2); + args.recycle(); break; } case MSG_SHOW_INSETS: { @@ -5270,6 +5288,7 @@ public final class ViewRootImpl implements ViewParent, break; } case MSG_WINDOW_MOVED: + mWillMove = false; if (mAdded) { final int w = mWinFrame.width(); final int h = mWinFrame.height(); @@ -7744,6 +7763,8 @@ public final class ViewRootImpl implements ViewParent, mTranslator.translateSourceControlsInScreenToAppWindow(mTempControls); } setFrame(mTmpFrames.frame); + mWillMove = false; + mWillResize = false; mInsetsController.onStateChanged(mTempInsets); mInsetsController.onControlsChanged(mTempControls); return relayoutResult; @@ -8178,7 +8199,8 @@ public final class ViewRootImpl implements ViewParent, mHandler.sendMessage(msg); } - private void dispatchInsetsChanged(InsetsState insetsState) { + private void dispatchInsetsChanged(InsetsState insetsState, boolean willMove, + boolean willResize) { if (Binder.getCallingPid() == android.os.Process.myPid()) { insetsState = new InsetsState(insetsState, true /* copySource */); } @@ -8189,11 +8211,15 @@ public final class ViewRootImpl implements ViewParent, ImeTracing.getInstance().triggerClientDump("ViewRootImpl#dispatchInsetsChanged", getInsetsController().getHost().getInputMethodManager(), null /* icProto */); } - mHandler.obtainMessage(MSG_INSETS_CHANGED, insetsState).sendToTarget(); + SomeArgs args = SomeArgs.obtain(); + args.arg1 = insetsState; + args.argi1 = willMove ? 1 : 0; + args.argi2 = willResize ? 1 : 0; + mHandler.obtainMessage(MSG_INSETS_CHANGED, args).sendToTarget(); } private void dispatchInsetsControlChanged(InsetsState insetsState, - InsetsSourceControl[] activeControls) { + InsetsSourceControl[] activeControls, boolean willMove, boolean willResize) { if (Binder.getCallingPid() == android.os.Process.myPid()) { insetsState = new InsetsState(insetsState, true /* copySource */); if (activeControls != null) { @@ -8213,6 +8239,8 @@ public final class ViewRootImpl implements ViewParent, SomeArgs args = SomeArgs.obtain(); args.arg1 = insetsState; args.arg2 = activeControls; + args.argi1 = willMove ? 1 : 0; + args.argi2 = willResize ? 1 : 0; mHandler.obtainMessage(MSG_INSETS_CONTROL_CHANGED, args).sendToTarget(); } @@ -9559,19 +9587,20 @@ public final class ViewRootImpl implements ViewParent, } @Override - public void insetsChanged(InsetsState insetsState) { + public void insetsChanged(InsetsState insetsState, boolean willMove, boolean willResize) { final ViewRootImpl viewAncestor = mViewAncestor.get(); if (viewAncestor != null) { - viewAncestor.dispatchInsetsChanged(insetsState); + viewAncestor.dispatchInsetsChanged(insetsState, willMove, willResize); } } @Override public void insetsControlChanged(InsetsState insetsState, - InsetsSourceControl[] activeControls) { + InsetsSourceControl[] activeControls, boolean willMove, boolean willResize) { final ViewRootImpl viewAncestor = mViewAncestor.get(); if (viewAncestor != null) { - viewAncestor.dispatchInsetsControlChanged(insetsState, activeControls); + viewAncestor.dispatchInsetsControlChanged( + insetsState, activeControls, willMove, willResize); } } diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java index 47341cd154d79..f212fc7d12287 100644 --- a/core/java/com/android/internal/view/BaseIWindow.java +++ b/core/java/com/android/internal/view/BaseIWindow.java @@ -66,12 +66,12 @@ public class BaseIWindow extends IWindow.Stub { } @Override - public void insetsChanged(InsetsState insetsState) { + public void insetsChanged(InsetsState insetsState, boolean willMove, boolean willResize) { } @Override public void insetsControlChanged(InsetsState insetsState, - InsetsSourceControl[] activeControls) { + InsetsSourceControl[] activeControls, boolean willMove, boolean willResize) { } @Override diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java index 9dabec7a13d0c..ef113dc5e10ab 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SystemWindows.java @@ -317,11 +317,11 @@ public class SystemWindows { public void locationInParentDisplayChanged(Point offset) {} @Override - public void insetsChanged(InsetsState insetsState) {} + public void insetsChanged(InsetsState insetsState, boolean willMove, boolean willResize) {} @Override public void insetsControlChanged(InsetsState insetsState, - InsetsSourceControl[] activeControls) {} + InsetsSourceControl[] activeControls, boolean willMove, boolean willResize) {} @Override public void showInsets(int types, boolean fromIme) {} diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java index 5f47986501849..97e42053e6052 100644 --- a/services/core/java/com/android/server/wm/WindowState.java +++ b/services/core/java/com/android/server/wm/WindowState.java @@ -3910,7 +3910,9 @@ class WindowState extends WindowContainer implements WindowManagerP void notifyInsetsChanged() { ProtoLog.d(WM_DEBUG_IME, "notifyInsetsChanged for %s ", this); try { - mClient.insetsChanged(getCompatInsetsState()); + mClient.insetsChanged(getCompatInsetsState(), + hasMoved(), + mWindowFrames.isFrameSizeChangeReported()); } catch (RemoteException e) { Slog.w(TAG, "Failed to deliver inset state change w=" + this, e); } @@ -3926,7 +3928,9 @@ class WindowState extends WindowContainer implements WindowManagerP getDisplayContent().getInsetsStateController(); try { mClient.insetsControlChanged(getCompatInsetsState(), - stateController.getControlsForDispatch(this)); + stateController.getControlsForDispatch(this), + hasMoved(), + mWindowFrames.isFrameSizeChangeReported()); } catch (RemoteException e) { Slog.w(TAG, "Failed to deliver inset state change to w=" + this, e); } diff --git a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java index b3a07454c1a0f..4c31ee2ae5fa6 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java +++ b/services/tests/wmtests/src/com/android/server/wm/TestIWindow.java @@ -53,12 +53,12 @@ public class TestIWindow extends IWindow.Stub { } @Override - public void insetsChanged(InsetsState insetsState) throws RemoteException { + public void insetsChanged(InsetsState insetsState, boolean willMove, boolean willResize) { } @Override - public void insetsControlChanged(InsetsState insetsState, InsetsSourceControl[] activeControls) - throws RemoteException { + public void insetsControlChanged(InsetsState insetsState, + InsetsSourceControl[] activeControls, boolean willMove, boolean willResize) { } @Override