From 5e6f95454c0a028920f759220a3db2c17be99a5d Mon Sep 17 00:00:00 2001 From: Tiger Date: Wed, 30 Nov 2022 20:28:28 +0800 Subject: [PATCH] Let InsetsController control requested visible types We plan to make the insets source consumer exist only when there is a corresponding insets source, which means the consumer won't always exist. This CL makes InsetsController set the requested types on its own, instead of telling the consumer to do so. Thus, show and hide are removed from InsetsSourceConsumer. This CL adds onAnimationStateChanged to the consumer, so that it can apply the requested visibility at the proper timing. Bug: 234093736 Test: atest ImeInsetsSourceConsumerTest InsetsAnimationControlImplTest InsetsControllerTest InsetsSourceConsumerTest WindowInsetsControllerTests CtsInputMethodTestCases Change-Id: Ib54c75e5fb1188c83074e06abf7af509974af2b1 --- .../android/view/ImeInsetsSourceConsumer.java | 89 +++++---- core/java/android/view/InsetsController.java | 174 ++++++++---------- .../android/view/InsetsSourceConsumer.java | 82 +++------ .../view/InsetsAnimationControlImplTest.java | 3 +- .../android/view/InsetsControllerTest.java | 19 +- .../view/InsetsSourceConsumerTest.java | 28 +-- 6 files changed, 175 insertions(+), 220 deletions(-) diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java index 02e0fccd7d6cb..e34aef97a8abd 100644 --- a/core/java/android/view/ImeInsetsSourceConsumer.java +++ b/core/java/android/view/ImeInsetsSourceConsumer.java @@ -16,21 +16,20 @@ package android.view; -import static android.os.Trace.TRACE_TAG_VIEW; import static android.view.ImeInsetsSourceConsumerProto.INSETS_SOURCE_CONSUMER; import static android.view.ImeInsetsSourceConsumerProto.IS_HIDE_ANIMATION_RUNNING; import static android.view.ImeInsetsSourceConsumerProto.IS_REQUESTED_VISIBLE_AWAITING_CONTROL; import static android.view.ImeInsetsSourceConsumerProto.IS_SHOW_REQUESTED_DURING_HIDE_ANIMATION; -import static android.view.InsetsController.AnimationType; import static android.view.InsetsState.ITYPE_IME; import android.annotation.Nullable; import android.os.IBinder; -import android.os.Trace; import android.util.proto.ProtoOutputStream; import android.view.SurfaceControl.Transaction; import android.view.inputmethod.InputMethodManager; +import com.android.internal.inputmethod.ImeTracing; + import java.util.function.Supplier; /** @@ -61,6 +60,38 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { super(ITYPE_IME, state, transactionSupplier, controller); } + @Override + public boolean onAnimationStateChanged(boolean running) { + if (!running) { + ImeTracing.getInstance().triggerClientDump( + "ImeInsetsSourceConsumer#onAnimationFinished", + mController.getHost().getInputMethodManager(), null /* icProto */); + } + final boolean insetsChanged = super.onAnimationStateChanged(running); + final boolean showRequested = (mController.getRequestedVisibleTypes() & getType()) != 0; + if (showRequested) { + onShowRequested(); + } else { + mIsRequestedVisibleAwaitingControl = false; + if (!running) { + // Remove IME surface as IME has finished hide animation, if there is no pending + // show request. + if (!mIsShowRequestedDuringHideAnimation) { + notifyHidden(); + removeSurface(); + } + } + // Here is reached + // (1) before the hide animation starts. + // (2) after the hide animation ends. + // (3) if the IME is not controllable (animationFinished == true in this case). + // We should reset mIsShowRequestedDuringHideAnimation in all cases. + mIsHideAnimationRunning = running; + mIsShowRequestedDuringHideAnimation = false; + } + return insetsChanged; + } + @Override public void onWindowFocusGained(boolean hasViewFocus) { super.onWindowFocusGained(hasViewFocus); @@ -78,36 +109,11 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { } @Override - public void show(boolean fromIme) { - super.show(fromIme); - onShowRequested(); - } - - @Override - public void hide() { - super.hide(); - mIsRequestedVisibleAwaitingControl = false; - } - - @Override - void hide(boolean animationFinished, @AnimationType int animationType) { - hide(); - - if (animationFinished) { - // Remove IME surface as IME has finished hide animation, if there is no pending - // show request. - if (!mIsShowRequestedDuringHideAnimation) { - notifyHidden(); - removeSurface(); - } - } - // This method is called - // (1) before the hide animation starts. - // (2) after the hide animation ends. - // (3) if the IME is not controllable (animationFinished == true in this case). - // We should reset mIsShowRequestedDuringHideAnimation in all cases. - mIsHideAnimationRunning = !animationFinished; - mIsShowRequestedDuringHideAnimation = false; + public boolean applyLocalVisibilityOverride() { + ImeTracing.getInstance().triggerClientDump( + "ImeInsetsSourceConsumer#applyLocalVisibilityOverride", + mController.getHost().getInputMethodManager(), null /* icProto */); + return super.applyLocalVisibilityOverride(); } /** @@ -116,6 +122,12 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { */ @Override public @ShowResult int requestShow(boolean fromIme) { + if (fromIme) { + ImeTracing.getInstance().triggerClientDump( + "ImeInsetsSourceConsumer#requestShow", + mController.getHost().getInputMethodManager(), null /* icProto */); + } + // TODO: ResultReceiver for IME. // TODO: Set mShowOnNextImeRender to automatically show IME and guard it with a flag. if (getControl() == null) { @@ -137,10 +149,8 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { * Notify {@link com.android.server.inputmethod.InputMethodManagerService} that * IME insets are hidden. */ - @Override - void notifyHidden() { + private void notifyHidden() { getImm().notifyImeHidden(mController.getHost().getWindowToken()); - Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.hideRequestFromApi", 0); } @Override @@ -154,11 +164,13 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { @Override public boolean setControl(@Nullable InsetsSourceControl control, int[] showTypes, int[] hideTypes) { + ImeTracing.getInstance().triggerClientDump("ImeInsetsSourceConsumer#setControl", + mController.getHost().getInputMethodManager(), null /* icProto */); if (!super.setControl(control, showTypes, hideTypes)) { return false; } if (control == null && !mIsRequestedVisibleAwaitingControl) { - hide(); + mController.setRequestedVisibleTypes(0 /* visibleTypes */, getType()); removeSurface(); } if (control != null) { @@ -192,7 +204,8 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { } /** - * Called when {@link #show} or {@link InputMethodManager#showSoftInput(View, int)} is called. + * Called when {@link #onAnimationStateChanged(boolean)} or + * {@link InputMethodManager#showSoftInput(View, int)} is called. */ public void onShowRequested() { if (mIsHideAnimationRunning) { diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java index 421efed838521..e1b27ffe035df 100644 --- a/core/java/android/view/InsetsController.java +++ b/core/java/android/view/InsetsController.java @@ -21,7 +21,6 @@ import static android.view.InsetsControllerProto.CONTROL; import static android.view.InsetsControllerProto.STATE; import static android.view.InsetsState.ITYPE_CAPTION_BAR; import static android.view.InsetsState.ITYPE_IME; -import static android.view.InsetsState.toInternalType; import static android.view.InsetsState.toPublicType; import static android.view.ViewRootImpl.CAPTION_ON_SHELL; import static android.view.WindowInsets.Type.FIRST; @@ -742,6 +741,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation private void updateState(InsetsState newState) { mState.set(newState, 0 /* types */); + @InsetsType int existingTypes = 0; @InsetsType int visibleTypes = 0; @InsetsType int disabledUserAnimationTypes = 0; @InsetsType int[] cancelledUserAnimationTypes = {0}; @@ -760,10 +760,15 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } } getSourceConsumer(type).updateSource(source, animationType); + existingTypes |= insetsType; if (source.isVisible()) { visibleTypes |= insetsType; } } + + // If a type doesn't have a source, treat it as visible if it is visible by default. + visibleTypes |= WindowInsets.Type.defaultVisible() & ~existingTypes; + if (mVisibleTypes != visibleTypes) { if (WindowInsets.Type.hasCompatSystemBars(mVisibleTypes ^ visibleTypes)) { mCompatSysUiVisibilityStaled = true; @@ -1103,6 +1108,29 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation @AnimationType int animationType, @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation, boolean useInsetsAnimationThread, @Nullable ImeTracker.Token statsToken) { + final boolean visible = layoutInsetsDuringAnimation == LAYOUT_INSETS_DURING_ANIMATION_SHOWN; + + // Basically, we accept the requested visibilities from the upstream callers... + setRequestedVisibleTypes(visible ? types : 0, types); + + // However, we might reject the request in some cases, such as delaying showing IME or + // rejecting showing IME. + controlAnimationUncheckedInner(types, cancellationSignal, listener, frame, fromIme, + durationMs, interpolator, animationType, layoutInsetsDuringAnimation, + useInsetsAnimationThread, statsToken); + + // We are finishing setting the requested visible types. Report them to the server and/or + // the app. + reportRequestedVisibleTypes(); + } + + private void controlAnimationUncheckedInner(@InsetsType int types, + @Nullable CancellationSignal cancellationSignal, + WindowInsetsAnimationControlListener listener, @Nullable Rect frame, boolean fromIme, + long durationMs, Interpolator interpolator, + @AnimationType int animationType, + @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation, + boolean useInsetsAnimationThread, @Nullable ImeTracker.Token statsToken) { ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_CONTROL_ANIMATION); if ((types & mTypesBeingCancelled) != 0) { throw new IllegalStateException("Cannot start a new insets animation of " @@ -1119,13 +1147,15 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation && !mState.getSource(ITYPE_IME).isVisible()) { // We've requested IMM to show IME, but the IME is not controllable. We need to // cancel the request. - getSourceConsumer(ITYPE_IME).hide(true, animationType); + setRequestedVisibleTypes(0 /* visibleTypes */, ime()); + if (getSourceConsumer(ITYPE_IME).onAnimationStateChanged(false /* running */)) { + notifyVisibilityChanged(); + } } } if (types == 0) { // nothing to animate. listener.onCancelled(null); - reportRequestedVisibleTypes(); if (DEBUG) Log.d(TAG, "no types to animate in controlAnimationUnchecked"); return; } @@ -1161,7 +1191,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } }); } - reportRequestedVisibleTypes(); + + // The requested visibilities should be delayed as well. Otherwise, the server will + // create already visible leashes for us before we play the show animation. + setRequestedVisibleTypes(mReportedRequestedVisibleTypes, types); + Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.showRequestFromApi", 0); return; } @@ -1169,7 +1203,6 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation if (typesReady == 0) { if (DEBUG) Log.d(TAG, "No types ready. onCancelled()"); listener.onCancelled(null); - reportRequestedVisibleTypes(); return; } @@ -1198,12 +1231,20 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } else { Trace.asyncTraceBegin(TRACE_TAG_VIEW, "IC.pendingAnim", 0); } - if (layoutInsetsDuringAnimation == LAYOUT_INSETS_DURING_ANIMATION_SHOWN) { - showDirectly(types, fromIme); - } else { - hideDirectly(types, false /* animationFinished */, animationType, fromIme); + onAnimationStateChanged(types, true /* running */); + + if (fromIme) { + switch (animationType) { + case ANIMATION_TYPE_SHOW: + Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.showRequestFromIme", 0); + break; + case ANIMATION_TYPE_HIDE: + Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.hideRequestFromIme", 0); + break; + } + } else if (animationType == ANIMATION_TYPE_HIDE) { + Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.hideRequestFromApi", 0); } - reportRequestedVisibleTypes(); } // TODO(b/242962223): Make this setter restrictive. @@ -1228,11 +1269,6 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation boolean canRun = true; if (show) { // Show request - if (fromIme) { - ImeTracing.getInstance().triggerClientDump( - "ImeInsetsSourceConsumer#requestShow", mHost.getInputMethodManager(), - null /* icProto */); - } switch(consumer.requestShow(fromIme)) { case ShowResult.SHOW_IMMEDIATELY: break; @@ -1246,15 +1282,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation // IME cannot be shown (since it didn't have focus), proceed // with animation of other types. canRun = false; + + // Reject the show request. + setRequestedVisibleTypes(0 /* visibleTypes */, consumer.getType()); break; } - } else { - // Hide request - // TODO: Move notifyHidden() to beginning of the hide animation - // (when visibility actually changes using hideDirectly()). - if (!fromIme) { - consumer.notifyHidden(); - } } if (!canRun) { if (WARN) Log.w(TAG, String.format( @@ -1266,24 +1298,6 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation if (control != null && control.getLeash() != null) { controls.put(control.getId(), new InsetsSourceControl(control)); typesReady |= consumer.getType(); - } else if (animationType == ANIMATION_TYPE_SHOW) { - if (DEBUG) Log.d(TAG, "collectSourceControls no control for show(). fromIme: " - + fromIme); - // We don't have a control at the moment. However, we still want to update requested - // visibility state such that in case we get control, we can apply show animation. - if (fromIme) { - ImeTracing.getInstance().triggerClientDump( - "InsetsSourceConsumer#show", mHost.getInputMethodManager(), - null /* icProto */); - } - consumer.show(fromIme); - } else if (animationType == ANIMATION_TYPE_HIDE) { - if (fromIme) { - ImeTracing.getInstance().triggerClientDump( - "InsetsSourceConsumer#hide", mHost.getInputMethodManager(), - null /* icProto */); - } - consumer.hide(); } } return new Pair<>(typesReady, imeReady); @@ -1332,6 +1346,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation @VisibleForTesting @Override public void notifyFinished(InsetsAnimationControlRunner runner, boolean shown) { + setRequestedVisibleTypes(shown ? runner.getTypes() : 0, runner.getTypes()); cancelAnimation(runner, false /* invokeCallback */); if (DEBUG) Log.d(TAG, "notifyFinished. shown: " + shown); if (runner.getAnimationType() == ANIMATION_TYPE_RESIZE) { @@ -1343,15 +1358,13 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation if (shown) { ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_ANIMATION_FINISHED_SHOW); - showDirectly(runner.getTypes(), true /* fromIme */); ImeTracker.get().onShown(statsToken); } else { ImeTracker.get().onProgress(statsToken, ImeTracker.PHASE_CLIENT_ANIMATION_FINISHED_HIDE); - hideDirectly(runner.getTypes(), true /* animationFinished */, - runner.getAnimationType(), true /* fromIme */); ImeTracker.get().onHidden(statsToken); } + reportRequestedVisibleTypes(); } @Override @@ -1388,28 +1401,31 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation "cancelAnimation of types: %d, animType: %d, host: %s", control.getTypes(), control.getAnimationType(), mHost.getRootViewTitle())); } - boolean stateChanged = false; + @InsetsType int removedTypes = 0; for (int i = mRunningAnimations.size() - 1; i >= 0; i--) { RunningAnimation runningAnimation = mRunningAnimations.get(i); if (runningAnimation.runner == control) { mRunningAnimations.remove(i); - ArraySet types = toInternalType(control.getTypes()); - for (int j = types.size() - 1; j >= 0; j--) { - if (types.valueAt(j) == ITYPE_IME) { - ImeTracing.getInstance().triggerClientDump( - "InsetsSourceConsumer#notifyAnimationFinished", - mHost.getInputMethodManager(), null /* icProto */); - } - stateChanged |= getSourceConsumer(types.valueAt(j)).notifyAnimationFinished(); - } + removedTypes = control.getTypes(); if (invokeCallback) { dispatchAnimationEnd(runningAnimation.runner.getAnimation()); } break; } } - if (stateChanged) { - mHost.notifyInsetsChanged(); + onAnimationStateChanged(removedTypes, false /* running */); + } + + private void onAnimationStateChanged(@InsetsType int types, boolean running) { + boolean insetsChanged = false; + for (int i = mSourceConsumers.size() - 1; i >= 0; i--) { + final InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i); + if ((consumer.getType() & types) != 0) { + insetsChanged |= consumer.onAnimationStateChanged(running); + } + } + if (insetsChanged) { + notifyVisibilityChanged(); } } @@ -1472,27 +1488,28 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation return ANIMATION_TYPE_NONE; } - void setRequestedVisibleTypes(@InsetsType int visibleTypes, @InsetsType int mask) { + @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE) + public void setRequestedVisibleTypes(@InsetsType int visibleTypes, @InsetsType int mask) { final @InsetsType int requestedVisibleTypes = (mRequestedVisibleTypes & ~mask) | (visibleTypes & mask); if (mRequestedVisibleTypes != requestedVisibleTypes) { - if (WindowInsets.Type.hasCompatSystemBars( - mRequestedVisibleTypes ^ requestedVisibleTypes)) { - mCompatSysUiVisibilityStaled = true; - } mRequestedVisibleTypes = requestedVisibleTypes; } } /** - * Sends the requested visible types to window manager if any of them is changed. + * Called when finishing setting requested visible types or finishing setting controls. */ private void reportRequestedVisibleTypes() { - updateCompatSysUiVisibility(); if (mReportedRequestedVisibleTypes != mRequestedVisibleTypes) { + final @InsetsType int diff = mRequestedVisibleTypes ^ mReportedRequestedVisibleTypes; + if (WindowInsets.Type.hasCompatSystemBars(diff)) { + mCompatSysUiVisibilityStaled = true; + } mReportedRequestedVisibleTypes = mRequestedVisibleTypes; mHost.updateRequestedVisibleTypes(mReportedRequestedVisibleTypes); } + updateCompatSysUiVisibility(); } @VisibleForTesting @@ -1538,39 +1555,6 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation !hasAnimationCallbacks /* useInsetsAnimationThread */, statsToken); } - private void hideDirectly(@InsetsType int types, boolean animationFinished, - @AnimationType int animationType, boolean fromIme) { - if ((types & ime()) != 0) { - ImeTracing.getInstance().triggerClientDump("InsetsController#hideDirectly", - mHost.getInputMethodManager(), null /* icProto */); - } - final ArraySet internalTypes = InsetsState.toInternalType(types); - for (int i = internalTypes.size() - 1; i >= 0; i--) { - getSourceConsumer(internalTypes.valueAt(i)).hide(animationFinished, animationType); - } - reportRequestedVisibleTypes(); - - if (fromIme) { - Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.hideRequestFromIme", 0); - } - } - - private void showDirectly(@InsetsType int types, boolean fromIme) { - if ((types & ime()) != 0) { - ImeTracing.getInstance().triggerClientDump("InsetsController#showDirectly", - mHost.getInputMethodManager(), null /* icProto */); - } - final ArraySet internalTypes = InsetsState.toInternalType(types); - for (int i = internalTypes.size() - 1; i >= 0; i--) { - getSourceConsumer(internalTypes.valueAt(i)).show(false /* fromIme */); - } - reportRequestedVisibleTypes(); - - if (fromIme) { - Trace.asyncTraceEnd(TRACE_TAG_VIEW, "IC.showRequestFromIme", 0); - } - } - /** * Cancel on-going animation to show/hide {@link InsetsType}. */ diff --git a/core/java/android/view/InsetsSourceConsumer.java b/core/java/android/view/InsetsSourceConsumer.java index b8c4eaa782e7c..7aeada8e9def8 100644 --- a/core/java/android/view/InsetsSourceConsumer.java +++ b/core/java/android/view/InsetsSourceConsumer.java @@ -25,7 +25,6 @@ import static android.view.InsetsSourceConsumerProto.IS_REQUESTED_VISIBLE; import static android.view.InsetsSourceConsumerProto.PENDING_FRAME; import static android.view.InsetsSourceConsumerProto.PENDING_VISIBLE_FRAME; import static android.view.InsetsSourceConsumerProto.SOURCE_CONTROL; -import static android.view.InsetsState.ITYPE_IME; import static android.view.InsetsState.getDefaultVisibility; import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; @@ -40,7 +39,6 @@ import android.view.SurfaceControl.Transaction; import android.view.WindowInsets.Type.InsetsType; import com.android.internal.annotations.VisibleForTesting; -import com.android.internal.inputmethod.ImeTracing; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @@ -116,10 +114,6 @@ public class InsetsSourceConsumer { */ public boolean setControl(@Nullable InsetsSourceControl control, @InsetsType int[] showTypes, @InsetsType int[] hideTypes) { - if (mInternalType == ITYPE_IME) { - ImeTracing.getInstance().triggerClientDump("InsetsSourceConsumer#setControl", - mController.getHost().getInputMethodManager(), null /* icProto */); - } if (Objects.equals(mSourceControl, control)) { if (mSourceControl != null && mSourceControl != control) { mSourceControl.release(SurfaceControl::release); @@ -210,22 +204,27 @@ public class InsetsSourceConsumer { return mInternalType; } - @VisibleForTesting - public void show(boolean fromIme) { - if (DEBUG) Log.d(TAG, String.format("Call show() for type: %s fromIme: %b ", - InsetsState.typeToString(mInternalType), fromIme)); - setRequestedVisible(true); - } + /** + * Called right after the animation is started or finished. + */ + @VisibleForTesting(visibility = PACKAGE) + public boolean onAnimationStateChanged(boolean running) { + boolean insetsChanged = false; + if (!running && mPendingFrame != null) { + InsetsSource source = mState.getSource(mInternalType); + source.setFrame(mPendingFrame); + source.setVisibleFrame(mPendingVisibleFrame); + mPendingFrame = null; + mPendingVisibleFrame = null; + insetsChanged = true; + } - @VisibleForTesting - public void hide() { - if (DEBUG) Log.d(TAG, String.format("Call hide for %s on %s", - InsetsState.typeToString(mInternalType), mController.getHost().getRootViewTitle())); - setRequestedVisible(false); - } - - void hide(boolean animationFinished, @AnimationType int animationType) { - hide(); + // We apply the visibility override after the animation is started. We don't do this before + // that because we need to know the initial insets state while creating the animation. + // We also need to apply the override after the animation is finished because the requested + // visibility can be set when finishing the user animation. + insetsChanged |= applyLocalVisibilityOverride(); + return insetsChanged; } /** @@ -247,19 +246,14 @@ public class InsetsSourceConsumer { return mHasViewFocusWhenWindowFocusGain; } - boolean applyLocalVisibilityOverride() { + @VisibleForTesting(visibility = PACKAGE) + public boolean applyLocalVisibilityOverride() { final InsetsSource source = mState.peekSource(mInternalType); final boolean isVisible = source != null ? source.isVisible() : getDefaultVisibility( mInternalType); final boolean hasControl = mSourceControl != null; final boolean requestedVisible = (mController.getRequestedVisibleTypes() & mType) != 0; - if (mInternalType == ITYPE_IME) { - ImeTracing.getInstance().triggerClientDump( - "InsetsSourceConsumer#applyLocalVisibilityOverride", - mController.getHost().getInputMethodManager(), null /* icProto */); - } - // If we don't have control, we are not able to change the visibility. if (!hasControl) { if (DEBUG) Log.d(TAG, "applyLocalVisibilityOverride: No control in " @@ -298,13 +292,6 @@ public class InsetsSourceConsumer { public void onPerceptible(boolean perceptible) { } - /** - * Notify listeners that window is now hidden. - */ - void notifyHidden() { - // no-op for types that always return ShowResult#SHOW_IMMEDIATELY. - } - /** * Remove surface on which this consumer type is drawn. */ @@ -336,31 +323,6 @@ public class InsetsSourceConsumer { if (DEBUG) Log.d(TAG, "updateSource: " + newSource); } - @VisibleForTesting(visibility = PACKAGE) - public boolean notifyAnimationFinished() { - if (mPendingFrame != null) { - InsetsSource source = mState.getSource(mInternalType); - source.setFrame(mPendingFrame); - source.setVisibleFrame(mPendingVisibleFrame); - mPendingFrame = null; - mPendingVisibleFrame = null; - return true; - } - return false; - } - - /** - * Sets requested visibility from the client, regardless of whether we are able to control it at - * the moment. - */ - protected void setRequestedVisible(boolean requestedVisible) { - mController.setRequestedVisibleTypes(requestedVisible ? mType : 0, mType); - if (DEBUG) Log.d(TAG, "setRequestedVisible: " + requestedVisible); - if (applyLocalVisibilityOverride()) { - mController.notifyVisibilityChanged(); - } - } - private void applyRequestedVisibilityToControl() { if (mSourceControl == null || mSourceControl.getLeash() == null) { return; diff --git a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java index 19ff5982f65f7..597df0ba49494 100644 --- a/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java +++ b/core/tests/coretests/src/android/view/InsetsAnimationControlImplTest.java @@ -102,7 +102,8 @@ public class InsetsAnimationControlImplTest { new InsetsSourceControl(ITYPE_NAVIGATION_BAR, WindowInsets.Type.navigationBars(), mNavLeash, true, new Point(400, 0), Insets.of(0, 0, 100, 0)), new int[1], new int[1]); - navConsumer.hide(); + mMockController.setRequestedVisibleTypes(0, WindowInsets.Type.navigationBars()); + navConsumer.applyLocalVisibilityOverride(); SparseArray controls = new SparseArray<>(); controls.put(ITYPE_STATUS_BAR, topConsumer.getControl()); diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java index fad9a5ca057ca..88249ad0db4c5 100644 --- a/core/tests/coretests/src/android/view/InsetsControllerTest.java +++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java @@ -132,17 +132,10 @@ public class InsetsControllerTest { private boolean mImeRequestedShow; - @Override - public void show(boolean fromIme) { - super.show(fromIme); - if (fromIme) { - mImeRequestedShow = true; - } - } - @Override public int requestShow(boolean fromController) { if (fromController || mImeRequestedShow) { + mImeRequestedShow = true; return SHOW_IMMEDIATELY; } else { return IME_SHOW_DELAYED; @@ -815,10 +808,10 @@ public class InsetsControllerTest { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { prepareControls(); - // Hiding visible system bars should only causes insets change once for each bar. + // Calling to hide system bars once should only cause insets change once. clearInvocations(mTestHost); mController.hide(statusBars() | navigationBars()); - verify(mTestHost, times(2)).notifyInsetsChanged(); + verify(mTestHost, times(1)).notifyInsetsChanged(); // Sending the same insets state should not cause insets change. // This simulates the callback from server after hiding system bars. @@ -826,10 +819,10 @@ public class InsetsControllerTest { mController.onStateChanged(mController.getState()); verify(mTestHost, never()).notifyInsetsChanged(); - // Showing invisible system bars should only causes insets change once for each bar. + // Calling to show system bars once should only cause insets change once. clearInvocations(mTestHost); mController.show(statusBars() | navigationBars()); - verify(mTestHost, times(2)).notifyInsetsChanged(); + verify(mTestHost, times(1)).notifyInsetsChanged(); // Sending the same insets state should not cause insets change. // This simulates the callback from server after showing system bars. @@ -912,7 +905,7 @@ public class InsetsControllerTest { assertNull(imeInsetsConsumer.getControl()); // Verify IME requested visibility should be updated to IME consumer from controller. - mController.show(ime()); + mController.show(ime(), true /* fromIme */, null /* statsToken */); assertTrue(isRequestedVisible(mController, ime())); mController.hide(ime()); diff --git a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java index 521b65edf2bd7..cec3fc5ba2d8f 100644 --- a/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java +++ b/core/tests/coretests/src/android/view/InsetsSourceConsumerTest.java @@ -29,7 +29,6 @@ import static junit.framework.TestCase.assertFalse; import static junit.framework.TestCase.assertTrue; import static org.mockito.ArgumentMatchers.eq; -import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.reset; import static org.mockito.Mockito.verify; @@ -119,30 +118,33 @@ public class InsetsSourceConsumerTest { } @Test - public void testHide() { + public void testOnAnimationStateChanged_requestedInvisible() { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { - mConsumer.hide(); + mController.setRequestedVisibleTypes(0 /* visibleTypes */, mSpyInsetsSource.getType()); + mConsumer.onAnimationStateChanged(false /* running */); verify(mSpyInsetsSource).setVisible(eq(false)); }); - } @Test - public void testShow() { + public void testOnAnimationStateChanged_requestedVisible() { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { // Insets source starts out visible - mConsumer.hide(); - mConsumer.show(false /* fromIme */); + final int type = mSpyInsetsSource.getType(); + mController.setRequestedVisibleTypes(0 /* visibleTypes */, type); + mConsumer.onAnimationStateChanged(false /* running */); + mController.setRequestedVisibleTypes(type, type); + mConsumer.onAnimationStateChanged(false /* running */); verify(mSpyInsetsSource).setVisible(eq(false)); verify(mSpyInsetsSource).setVisible(eq(true)); }); - } @Test public void testPendingStates() { InsetsState state = new InsetsState(); - InsetsController controller = mock(InsetsController.class); + InsetsController controller = new InsetsController(new ViewRootInsetsControllerHost( + mViewRoot)); InsetsSourceConsumer consumer = new InsetsSourceConsumer( ITYPE_IME, state, null, controller); @@ -156,7 +158,7 @@ public class InsetsSourceConsumerTest { assertEquals(new Rect(0, 1, 2, 3), state.peekSource(ITYPE_IME).getFrame()); // Finish the animation, now the pending frame should be applied - assertTrue(consumer.notifyAnimationFinished()); + assertTrue(consumer.onAnimationStateChanged(false /* running */)); assertEquals(new Rect(4, 5, 6, 7), state.peekSource(ITYPE_IME).getFrame()); // Animating again, updates are delayed @@ -169,7 +171,7 @@ public class InsetsSourceConsumerTest { source.setFrame(4, 5, 6, 7); consumer.updateSource(new InsetsSource(source), ANIMATION_TYPE_USER); - assertFalse(consumer.notifyAnimationFinished()); + assertFalse(consumer.onAnimationStateChanged(false /* running */)); assertEquals(new Rect(4, 5, 6, 7), state.peekSource(ITYPE_IME).getFrame()); } @@ -178,7 +180,7 @@ public class InsetsSourceConsumerTest { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { mConsumer.setControl(null, new int[1], new int[1]); reset(mMockTransaction); - mConsumer.hide(); + mController.setRequestedVisibleTypes(0 /* visibleTypes */, statusBars()); verifyZeroInteractions(mMockTransaction); int[] hideTypes = new int[1]; mConsumer.setControl( @@ -193,7 +195,7 @@ public class InsetsSourceConsumerTest { @Test public void testRestore_noAnimation() { InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> { - mConsumer.hide(); + mController.setRequestedVisibleTypes(0 /* visibleTypes */, statusBars()); mConsumer.setControl(null, new int[1], new int[1]); reset(mMockTransaction); verifyZeroInteractions(mMockTransaction);