Loading core/java/android/view/InsetsSourceConsumer.java +21 −3 Original line number Diff line number Diff line Loading @@ -69,6 +69,13 @@ public class InsetsSourceConsumer { private Rect mPendingFrame; private Rect mPendingVisibleFrame; /** * Indicates if we have the pending animation. When we have the control, we need to play the * animation if the requested visibility is different from the current state. But if we haven't * had a leash yet, we will set this flag, and play the animation once we get the leash. */ private boolean mIsAnimationPending; public InsetsSourceConsumer(@InternalInsetsType int type, InsetsState state, Supplier<Transaction> transactionSupplier, InsetsController controller) { mType = type; Loading Loading @@ -107,13 +114,21 @@ public class InsetsSourceConsumer { } else { // We are gaining control, and need to run an animation since previous state // didn't match if (isRequestedVisibleAwaitingControl() != mState.getSource(mType).isVisible()) { if (isRequestedVisibleAwaitingControl()) { final boolean requestedVisible = isRequestedVisibleAwaitingControl(); final boolean needAnimation = requestedVisible != mState.getSource(mType).isVisible(); if (control.getLeash() != null && (needAnimation || mIsAnimationPending)) { if (requestedVisible) { showTypes[0] |= toPublicType(getType()); } else { hideTypes[0] |= toPublicType(getType()); } mIsAnimationPending = false; } else { if (needAnimation) { // We need animation but we haven't had a leash yet. Set this flag that when we // get the leash we can play the deferred animation. mIsAnimationPending = true; } // We are gaining control, but don't need to run an animation. // However make sure that the leash visibility is still up to date. if (applyLocalVisibilityOverride()) { Loading Loading @@ -274,7 +289,10 @@ public class InsetsSourceConsumer { * the moment. */ protected void setRequestedVisible(boolean requestedVisible) { if (mRequestedVisible != requestedVisible) { mRequestedVisible = requestedVisible; mIsAnimationPending = false; } if (applyLocalVisibilityOverride()) { mController.notifyVisibilityChanged(); } Loading services/core/java/com/android/server/wm/InsetsPolicy.java +14 −5 Original line number Diff line number Diff line Loading @@ -126,7 +126,14 @@ class InsetsPolicy { mPolicy.getStatusBarManagerInternal().showTransient(mDisplayContent.getDisplayId(), mShowingTransientTypes.toArray()); updateBarControlTarget(mFocusedWin); InsetsState state = new InsetsState(mStateController.getRawInsetsState()); // The leashes can be created while updating bar control target. The surface transaction // of the new leashes might not be applied yet. The callback posted here ensures we can // get the valid leashes because the surface transaction will be applied in the next // animation frame which will be triggered if a new leash is created. mDisplayContent.mWmService.mAnimator.getChoreographer().postFrameCallback(time -> { synchronized (mDisplayContent.mWmService.mGlobalLock) { final InsetsState state = new InsetsState(mStateController.getRawInsetsState()); startAnimation(true /* show */, () -> { synchronized (mDisplayContent.mWmService.mGlobalLock) { mStateController.notifyInsetsChanged(); Loading @@ -134,6 +141,8 @@ class InsetsPolicy { }, state); mStateController.onInsetsModified(mDummyControlTarget, state); } }); } } void hideTransient() { Loading services/core/java/com/android/server/wm/InsetsSourceProvider.java +18 −4 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ class InsetsSourceProvider { private TriConsumer<DisplayFrames, WindowState, Rect> mFrameProvider; private TriConsumer<DisplayFrames, WindowState, Rect> mImeFrameProvider; private final Rect mImeOverrideFrame = new Rect(); private boolean mIsLeashReadyForDispatching; /** The visibility override from the current controlling window. */ private boolean mClientVisible; Loading Loading @@ -266,9 +267,14 @@ class InsetsSourceProvider { if (getSource().getType() == ITYPE_IME) { setClientVisible(InsetsState.getDefaultVisibility(mSource.getType())); } final Transaction t = mDisplayContent.mWmService.mTransactionFactory.get(); final Transaction t = mDisplayContent.getPendingTransaction(); mWin.startAnimation(t, mAdapter, !mClientVisible /* hidden */, ANIMATION_TYPE_INSETS_CONTROL, null /* animationFinishedCallback */); // The leash was just created. We cannot dispatch it until its surface transaction is // applied. Otherwise, the client's operation to the leash might be overwritten by us. mIsLeashReadyForDispatching = false; final SurfaceControl leash = mAdapter.mCapturedLeash; final long frameNumber = mFinishSeamlessRotateFrameNumber; mFinishSeamlessRotateFrameNumber = -1; Loading @@ -281,9 +287,6 @@ class InsetsSourceProvider { t.deferTransactionUntil(mWin.getSurfaceControl(), barrier, frameNumber); t.deferTransactionUntil(leash, barrier, frameNumber); } // Applying the transaction here can prevent the client from applying its transaction sooner // than us which makes us overwrite the client's operation to the leash. t.apply(); mControlTarget = target; mControl = new InsetsSourceControl(mSource.getType(), leash, new Point(mWin.getWindowFrames().mFrame.left, mWin.getWindowFrames().mFrame.top)); Loading Loading @@ -313,6 +316,10 @@ class InsetsSourceProvider { return true; } void onSurfaceTransactionApplied() { mIsLeashReadyForDispatching = true; } private void setClientVisible(boolean clientVisible) { if (mClientVisible == clientVisible) { return; Loading @@ -334,6 +341,13 @@ class InsetsSourceProvider { InsetsSourceControl getControl(InsetsControlTarget target) { if (target == mControlTarget) { if (!mIsLeashReadyForDispatching && mControl != null) { // The surface transaction of preparing leash is not applied yet. We don't send it // to the client in case that the client applies its transaction sooner than ours // that we could unexpectedly overwrite the surface state. return new InsetsSourceControl(mControl.getType(), null /* leash */, mControl.getSurfacePosition()); } return mControl; } if (target == mFakeControlTarget) { Loading services/core/java/com/android/server/wm/InsetsStateController.java +4 −0 Original line number Diff line number Diff line Loading @@ -407,6 +407,10 @@ class InsetsStateController { return; } mDisplayContent.mWmService.mAnimator.addAfterPrepareSurfacesRunnable(() -> { for (int i = mProviders.size() - 1; i >= 0; i--) { final InsetsSourceProvider provider = mProviders.valueAt(i); provider.onSurfaceTransactionApplied(); } for (int i = mPendingControlChanged.size() - 1; i >= 0; i--) { final InsetsControlTarget controlTarget = mPendingControlChanged.valueAt(i); controlTarget.notifyInsetsControlChanged(); Loading services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java +10 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import android.view.test.InsetsModeSession; import androidx.test.filters.SmallTest; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; Loading @@ -72,6 +73,11 @@ public class InsetsPolicyTest extends WindowTestsBase { sInsetsModeSession.close(); } @Before public void setup() { mWm.mAnimator.ready(); } @Test public void testControlsForDispatch_regular() { addWindow(TYPE_STATUS_BAR, "statusBar"); Loading Loading @@ -194,6 +200,7 @@ public class InsetsPolicyTest extends WindowTestsBase { policy.updateBarControlTarget(mAppWindow); policy.showTransient( IntArray.wrap(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR})); waitUntilWindowAnimatorIdle(); final InsetsSourceControl[] controls = mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow); Loading Loading @@ -221,6 +228,7 @@ public class InsetsPolicyTest extends WindowTestsBase { policy.updateBarControlTarget(mAppWindow); policy.showTransient( IntArray.wrap(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR})); waitUntilWindowAnimatorIdle(); final InsetsSourceControl[] controls = mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow); Loading Loading @@ -249,6 +257,7 @@ public class InsetsPolicyTest extends WindowTestsBase { policy.updateBarControlTarget(mAppWindow); policy.showTransient( IntArray.wrap(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR})); waitUntilWindowAnimatorIdle(); InsetsSourceControl[] controls = mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow); Loading @@ -262,6 +271,7 @@ public class InsetsPolicyTest extends WindowTestsBase { state.setSourceVisible(ITYPE_STATUS_BAR, true); state.setSourceVisible(ITYPE_NAVIGATION_BAR, true); policy.onInsetsModified(mAppWindow, state); waitUntilWindowAnimatorIdle(); controls = mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow); Loading Loading
core/java/android/view/InsetsSourceConsumer.java +21 −3 Original line number Diff line number Diff line Loading @@ -69,6 +69,13 @@ public class InsetsSourceConsumer { private Rect mPendingFrame; private Rect mPendingVisibleFrame; /** * Indicates if we have the pending animation. When we have the control, we need to play the * animation if the requested visibility is different from the current state. But if we haven't * had a leash yet, we will set this flag, and play the animation once we get the leash. */ private boolean mIsAnimationPending; public InsetsSourceConsumer(@InternalInsetsType int type, InsetsState state, Supplier<Transaction> transactionSupplier, InsetsController controller) { mType = type; Loading Loading @@ -107,13 +114,21 @@ public class InsetsSourceConsumer { } else { // We are gaining control, and need to run an animation since previous state // didn't match if (isRequestedVisibleAwaitingControl() != mState.getSource(mType).isVisible()) { if (isRequestedVisibleAwaitingControl()) { final boolean requestedVisible = isRequestedVisibleAwaitingControl(); final boolean needAnimation = requestedVisible != mState.getSource(mType).isVisible(); if (control.getLeash() != null && (needAnimation || mIsAnimationPending)) { if (requestedVisible) { showTypes[0] |= toPublicType(getType()); } else { hideTypes[0] |= toPublicType(getType()); } mIsAnimationPending = false; } else { if (needAnimation) { // We need animation but we haven't had a leash yet. Set this flag that when we // get the leash we can play the deferred animation. mIsAnimationPending = true; } // We are gaining control, but don't need to run an animation. // However make sure that the leash visibility is still up to date. if (applyLocalVisibilityOverride()) { Loading Loading @@ -274,7 +289,10 @@ public class InsetsSourceConsumer { * the moment. */ protected void setRequestedVisible(boolean requestedVisible) { if (mRequestedVisible != requestedVisible) { mRequestedVisible = requestedVisible; mIsAnimationPending = false; } if (applyLocalVisibilityOverride()) { mController.notifyVisibilityChanged(); } Loading
services/core/java/com/android/server/wm/InsetsPolicy.java +14 −5 Original line number Diff line number Diff line Loading @@ -126,7 +126,14 @@ class InsetsPolicy { mPolicy.getStatusBarManagerInternal().showTransient(mDisplayContent.getDisplayId(), mShowingTransientTypes.toArray()); updateBarControlTarget(mFocusedWin); InsetsState state = new InsetsState(mStateController.getRawInsetsState()); // The leashes can be created while updating bar control target. The surface transaction // of the new leashes might not be applied yet. The callback posted here ensures we can // get the valid leashes because the surface transaction will be applied in the next // animation frame which will be triggered if a new leash is created. mDisplayContent.mWmService.mAnimator.getChoreographer().postFrameCallback(time -> { synchronized (mDisplayContent.mWmService.mGlobalLock) { final InsetsState state = new InsetsState(mStateController.getRawInsetsState()); startAnimation(true /* show */, () -> { synchronized (mDisplayContent.mWmService.mGlobalLock) { mStateController.notifyInsetsChanged(); Loading @@ -134,6 +141,8 @@ class InsetsPolicy { }, state); mStateController.onInsetsModified(mDummyControlTarget, state); } }); } } void hideTransient() { Loading
services/core/java/com/android/server/wm/InsetsSourceProvider.java +18 −4 Original line number Diff line number Diff line Loading @@ -66,6 +66,7 @@ class InsetsSourceProvider { private TriConsumer<DisplayFrames, WindowState, Rect> mFrameProvider; private TriConsumer<DisplayFrames, WindowState, Rect> mImeFrameProvider; private final Rect mImeOverrideFrame = new Rect(); private boolean mIsLeashReadyForDispatching; /** The visibility override from the current controlling window. */ private boolean mClientVisible; Loading Loading @@ -266,9 +267,14 @@ class InsetsSourceProvider { if (getSource().getType() == ITYPE_IME) { setClientVisible(InsetsState.getDefaultVisibility(mSource.getType())); } final Transaction t = mDisplayContent.mWmService.mTransactionFactory.get(); final Transaction t = mDisplayContent.getPendingTransaction(); mWin.startAnimation(t, mAdapter, !mClientVisible /* hidden */, ANIMATION_TYPE_INSETS_CONTROL, null /* animationFinishedCallback */); // The leash was just created. We cannot dispatch it until its surface transaction is // applied. Otherwise, the client's operation to the leash might be overwritten by us. mIsLeashReadyForDispatching = false; final SurfaceControl leash = mAdapter.mCapturedLeash; final long frameNumber = mFinishSeamlessRotateFrameNumber; mFinishSeamlessRotateFrameNumber = -1; Loading @@ -281,9 +287,6 @@ class InsetsSourceProvider { t.deferTransactionUntil(mWin.getSurfaceControl(), barrier, frameNumber); t.deferTransactionUntil(leash, barrier, frameNumber); } // Applying the transaction here can prevent the client from applying its transaction sooner // than us which makes us overwrite the client's operation to the leash. t.apply(); mControlTarget = target; mControl = new InsetsSourceControl(mSource.getType(), leash, new Point(mWin.getWindowFrames().mFrame.left, mWin.getWindowFrames().mFrame.top)); Loading Loading @@ -313,6 +316,10 @@ class InsetsSourceProvider { return true; } void onSurfaceTransactionApplied() { mIsLeashReadyForDispatching = true; } private void setClientVisible(boolean clientVisible) { if (mClientVisible == clientVisible) { return; Loading @@ -334,6 +341,13 @@ class InsetsSourceProvider { InsetsSourceControl getControl(InsetsControlTarget target) { if (target == mControlTarget) { if (!mIsLeashReadyForDispatching && mControl != null) { // The surface transaction of preparing leash is not applied yet. We don't send it // to the client in case that the client applies its transaction sooner than ours // that we could unexpectedly overwrite the surface state. return new InsetsSourceControl(mControl.getType(), null /* leash */, mControl.getSurfacePosition()); } return mControl; } if (target == mFakeControlTarget) { Loading
services/core/java/com/android/server/wm/InsetsStateController.java +4 −0 Original line number Diff line number Diff line Loading @@ -407,6 +407,10 @@ class InsetsStateController { return; } mDisplayContent.mWmService.mAnimator.addAfterPrepareSurfacesRunnable(() -> { for (int i = mProviders.size() - 1; i >= 0; i--) { final InsetsSourceProvider provider = mProviders.valueAt(i); provider.onSurfaceTransactionApplied(); } for (int i = mPendingControlChanged.size() - 1; i >= 0; i--) { final InsetsControlTarget controlTarget = mPendingControlChanged.valueAt(i); controlTarget.notifyInsetsControlChanged(); Loading
services/tests/wmtests/src/com/android/server/wm/InsetsPolicyTest.java +10 −0 Original line number Diff line number Diff line Loading @@ -50,6 +50,7 @@ import android.view.test.InsetsModeSession; import androidx.test.filters.SmallTest; import org.junit.AfterClass; import org.junit.Before; import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; Loading @@ -72,6 +73,11 @@ public class InsetsPolicyTest extends WindowTestsBase { sInsetsModeSession.close(); } @Before public void setup() { mWm.mAnimator.ready(); } @Test public void testControlsForDispatch_regular() { addWindow(TYPE_STATUS_BAR, "statusBar"); Loading Loading @@ -194,6 +200,7 @@ public class InsetsPolicyTest extends WindowTestsBase { policy.updateBarControlTarget(mAppWindow); policy.showTransient( IntArray.wrap(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR})); waitUntilWindowAnimatorIdle(); final InsetsSourceControl[] controls = mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow); Loading Loading @@ -221,6 +228,7 @@ public class InsetsPolicyTest extends WindowTestsBase { policy.updateBarControlTarget(mAppWindow); policy.showTransient( IntArray.wrap(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR})); waitUntilWindowAnimatorIdle(); final InsetsSourceControl[] controls = mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow); Loading Loading @@ -249,6 +257,7 @@ public class InsetsPolicyTest extends WindowTestsBase { policy.updateBarControlTarget(mAppWindow); policy.showTransient( IntArray.wrap(new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR})); waitUntilWindowAnimatorIdle(); InsetsSourceControl[] controls = mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow); Loading @@ -262,6 +271,7 @@ public class InsetsPolicyTest extends WindowTestsBase { state.setSourceVisible(ITYPE_STATUS_BAR, true); state.setSourceVisible(ITYPE_NAVIGATION_BAR, true); policy.onInsetsModified(mAppWindow, state); waitUntilWindowAnimatorIdle(); controls = mDisplayContent.getInsetsStateController().getControlsForDispatch(mAppWindow); Loading