Describe requested visibilities in public types (5/n: consumer)

This CL removes mRequestedVisible from InsetsSourceConsumer since the
information can be queried from InsetsController.

This CL also stores the public insets type in InsetsSourceConsumer.
Eventually, the internal insets type will be removed.

Bug: 253420890
Bug: 234093736
Test: atest ImeInsetsSourceConsumerTest InsetsAnimationControlImplTest
      InsetsControllerTest InsetsSourceConsumerTest
Change-Id: I8e2070676d2161cc9e8fc28a3dd49cefb362f26c
This commit is contained in:
Tiger
2022-11-02 21:25:15 +08:00
parent d7580b3af1
commit a4b747496b
9 changed files with 160 additions and 201 deletions

View File

@@ -65,7 +65,7 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer {
public void onWindowFocusGained(boolean hasViewFocus) {
super.onWindowFocusGained(hasViewFocus);
getImm().registerImeConsumer(this);
if (isRequestedVisible() && getControl() == null) {
if ((mController.getRequestedVisibleTypes() & getType()) != 0 && getControl() == null) {
mIsRequestedVisibleAwaitingControl = true;
}
}
@@ -125,7 +125,7 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer {
// If we had a request before to show from IME (tracked with mImeRequestedShow), reaching
// this code here means that we now got control, so we can start the animation immediately.
// If client window is trying to control IME and IME is already visible, it is immediate.
if (fromIme || mState.getSource(getType()).isVisible() && getControl() != null) {
if (fromIme || (mState.getSource(getInternalType()).isVisible() && getControl() != null)) {
return ShowResult.SHOW_IMMEDIATELY;
}
@@ -169,7 +169,7 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer {
@Override
protected boolean isRequestedVisibleAwaitingControl() {
return mIsRequestedVisibleAwaitingControl || isRequestedVisible();
return super.isRequestedVisibleAwaitingControl() || mIsRequestedVisibleAwaitingControl;
}
@Override

View File

@@ -128,7 +128,7 @@ public class InsetsAnimationControlImpl implements InternalInsetsAnimationContro
null /* typeSideMap */);
mShownInsets = calculateInsets(mInitialInsetsState, frame, controls, true /* shown */,
typeSideMap);
mHasZeroInsetsIme = mShownInsets.bottom == 0 && controlsInternalType(ITYPE_IME);
mHasZeroInsetsIme = mShownInsets.bottom == 0 && controlsType(WindowInsets.Type.ime());
if (mHasZeroInsetsIme) {
// IME has shownInsets of ZERO, and can't map to a side by default.
// Map zero insets IME to bottom, making it a special case of bottom insets.
@@ -141,7 +141,7 @@ public class InsetsAnimationControlImpl implements InternalInsetsAnimationContro
mCurrentInsets = calculateInsets(mInitialInsetsState, controls, true /* shown */);
mHiddenInsets = calculateInsets(null, controls, false /* shown */);
mShownInsets = calculateInsets(null, controls, true /* shown */);
mHasZeroInsetsIme = mShownInsets.bottom == 0 && controlsInternalType(ITYPE_IME);
mHasZeroInsetsIme = mShownInsets.bottom == 0 && controlsType(WindowInsets.Type.ime());
buildSideControlsMap(mSideControlsMap, controls);
}
mPendingInsets = mCurrentInsets;

View File

@@ -19,7 +19,6 @@ package android.view;
import android.util.SparseArray;
import android.util.proto.ProtoOutputStream;
import android.view.InsetsController.AnimationType;
import android.view.InsetsState.InternalInsetsType;
import android.view.WindowInsets.Type.InsetsType;
/**
@@ -63,10 +62,10 @@ public interface InsetsAnimationControlRunner {
WindowInsetsAnimation getAnimation();
/**
* @return Whether {@link #getTypes()} maps to a specific {@link InternalInsetsType}.
* @return Whether {@link #getTypes()} contains a specific {@link InsetsType}.
*/
default boolean controlsInternalType(@InternalInsetsType int type) {
return InsetsState.toInternalType(getTypes()).contains(type);
default boolean controlsType(@InsetsType int type) {
return (getTypes() & type) != 0;
}
/**

View File

@@ -24,6 +24,8 @@ 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;
import static android.view.WindowInsets.Type.LAST;
import static android.view.WindowInsets.Type.all;
import static android.view.WindowInsets.Type.ime;
@@ -744,8 +746,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
for (@InternalInsetsType int type = 0; type < InsetsState.SIZE; type++) {
InsetsSource source = newState.peekSource(type);
if (source == null) continue;
@AnimationType int animationType = getAnimationType(type);
@InsetsType int insetsType = toPublicType(type);
@AnimationType int animationType = getAnimationType(insetsType);
if (!source.isUserControllable()) {
// The user animation is not allowed when visible frame is empty.
disabledUserAnimationTypes |= insetsType;
@@ -788,8 +790,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
if (diff != 0) {
for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
if (consumer.getControl() != null
&& (toPublicType(consumer.getType()) & diff) != 0) {
if (consumer.getControl() != null && (consumer.getType() & diff) != 0) {
mHandler.removeCallbacks(mInvokeControllableInsetsChangedListeners);
mHandler.post(mInvokeControllableInsetsChangedListeners);
break;
@@ -897,7 +898,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
// Ensure to update all existing source consumers
for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
final InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
final InsetsSourceControl control = mTmpControlArray.get(consumer.getType());
final InsetsSourceControl control = mTmpControlArray.get(consumer.getInternalType());
// control may be null, but we still need to update the control to null if it got
// revoked.
@@ -985,25 +986,26 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
// TODO: Support a ResultReceiver for IME.
// TODO(b/123718661): Make show() work for multi-session IME.
int typesReady = 0;
final ArraySet<Integer> internalTypes = InsetsState.toInternalType(types);
for (int i = internalTypes.size() - 1; i >= 0; i--) {
@InternalInsetsType int internalType = internalTypes.valueAt(i);
@AnimationType int animationType = getAnimationType(internalType);
InsetsSourceConsumer consumer = getSourceConsumer(internalType);
if (consumer.isRequestedVisible() && animationType == ANIMATION_TYPE_NONE
for (int type = FIRST; type <= LAST; type = type << 1) {
if ((types & type) == 0) {
continue;
}
final @AnimationType int animationType = getAnimationType(type);
final boolean requestedVisible = (type & mRequestedVisibleTypes) != 0;
if (requestedVisible && animationType == ANIMATION_TYPE_NONE
|| animationType == ANIMATION_TYPE_SHOW) {
// no-op: already shown or animating in (because window visibility is
// applied before starting animation).
if (DEBUG) Log.d(TAG, String.format(
"show ignored for type: %d animType: %d requestedVisible: %s",
consumer.getType(), animationType, consumer.isRequestedVisible()));
type, animationType, requestedVisible));
continue;
}
if (fromIme && animationType == ANIMATION_TYPE_USER) {
// App is already controlling the IME, don't cancel it.
continue;
}
typesReady |= InsetsState.toPublicType(consumer.getType());
typesReady |= type;
}
if (DEBUG) Log.d(TAG, "show typesReady: " + typesReady);
applyAnimation(typesReady, true /* show */, fromIme);
@@ -1024,17 +1026,18 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
Trace.asyncTraceBegin(TRACE_TAG_VIEW, "IC.hideRequestFromApi", 0);
}
int typesReady = 0;
final ArraySet<Integer> internalTypes = InsetsState.toInternalType(types);
for (int i = internalTypes.size() - 1; i >= 0; i--) {
@InternalInsetsType int internalType = internalTypes.valueAt(i);
@AnimationType int animationType = getAnimationType(internalType);
InsetsSourceConsumer consumer = getSourceConsumer(internalType);
if (!consumer.isRequestedVisible() && animationType == ANIMATION_TYPE_NONE
for (int type = FIRST; type <= LAST; type = type << 1) {
if ((types & type) == 0) {
continue;
}
final @AnimationType int animationType = getAnimationType(type);
final boolean requestedVisible = (type & mRequestedVisibleTypes) != 0;
if (!requestedVisible && animationType == ANIMATION_TYPE_NONE
|| animationType == ANIMATION_TYPE_HIDE) {
// no-op: already hidden or animating out.
continue;
}
typesReady |= InsetsState.toPublicType(consumer.getType());
typesReady |= type;
}
applyAnimation(typesReady, false /* show */, fromIme /* fromIme */);
}
@@ -1228,13 +1231,13 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
if (!canRun) {
if (WARN) Log.w(TAG, String.format(
"collectSourceControls can't continue show for type: %s fromIme: %b",
InsetsState.typeToString(consumer.getType()), fromIme));
InsetsState.typeToString(consumer.getInternalType()), fromIme));
continue;
}
final InsetsSourceControl control = consumer.getControl();
if (control != null && control.getLeash() != null) {
controls.put(consumer.getType(), new InsetsSourceControl(control));
typesReady |= toPublicType(consumer.getType());
controls.put(control.getType(), new InsetsSourceControl(control));
typesReady |= consumer.getType();
} else if (animationType == ANIMATION_TYPE_SHOW) {
if (DEBUG) Log.d(TAG, "collectSourceControls no control for show(). fromIme: "
+ fromIme);
@@ -1260,25 +1263,15 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
private @LayoutInsetsDuringAnimation int getLayoutInsetsDuringAnimationMode(
@InsetsType int types) {
final ArraySet<Integer> internalTypes = InsetsState.toInternalType(types);
// Generally, we want to layout the opposite of the current state. This is to make animation
// callbacks easy to use: The can capture the layout values and then treat that as end-state
// during the animation.
//
// However, if controlling multiple sources, we want to treat it as shown if any of the
// types is currently hidden.
for (int i = internalTypes.size() - 1; i >= 0; i--) {
InsetsSourceConsumer consumer = mSourceConsumers.get(internalTypes.valueAt(i));
if (consumer == null) {
continue;
}
if (!consumer.isRequestedVisible()) {
return LAYOUT_INSETS_DURING_ANIMATION_SHOWN;
}
}
return LAYOUT_INSETS_DURING_ANIMATION_HIDDEN;
return (mRequestedVisibleTypes & types) != types
? LAYOUT_INSETS_DURING_ANIMATION_SHOWN
: LAYOUT_INSETS_DURING_ANIMATION_HIDDEN;
}
private void cancelExistingControllers(@InsetsType int types) {
@@ -1332,15 +1325,15 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
}
void notifyControlRevoked(InsetsSourceConsumer consumer) {
final @InsetsType int types = toPublicType(consumer.getType());
final @InsetsType int type = consumer.getType();
for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
InsetsAnimationControlRunner control = mRunningAnimations.get(i).runner;
control.notifyControlRevoked(types);
control.notifyControlRevoked(type);
if (control.getControllingTypes() == 0) {
cancelAnimation(control, true /* invokeCallback */);
}
}
if (consumer.getType() == ITYPE_IME) {
if (type == ime()) {
abortPendingImeControlRequest();
}
}
@@ -1425,27 +1418,25 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
}
@VisibleForTesting
public @AnimationType int getAnimationType(@InternalInsetsType int type) {
public @AnimationType int getAnimationType(@InsetsType int type) {
for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
InsetsAnimationControlRunner control = mRunningAnimations.get(i).runner;
if (control.controlsInternalType(type)) {
if (control.controlsType(type)) {
return mRunningAnimations.get(i).type;
}
}
return ANIMATION_TYPE_NONE;
}
@VisibleForTesting
public void onRequestedVisibilityChanged(InsetsSourceConsumer consumer) {
final @InsetsType int type = InsetsState.toPublicType(consumer.getType());
final int requestedVisibleTypes = consumer.isRequestedVisible()
? mRequestedVisibleTypes | type
: mRequestedVisibleTypes & ~type;
void setRequestedVisibleTypes(@InsetsType int visibleTypes, @InsetsType int mask) {
final @InsetsType int requestedVisibleTypes =
(mRequestedVisibleTypes & ~mask) | (visibleTypes & mask);
if (mRequestedVisibleTypes != requestedVisibleTypes) {
mRequestedVisibleTypes = requestedVisibleTypes;
if (WindowInsets.Type.hasCompatSystemBars(type)) {
if (WindowInsets.Type.hasCompatSystemBars(
mRequestedVisibleTypes ^ requestedVisibleTypes)) {
mCompatSysUiVisibilityStaled = true;
}
mRequestedVisibleTypes = requestedVisibleTypes;
}
}
@@ -1664,9 +1655,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
@InsetsType int result = 0;
for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
InsetsSource source = mState.peekSource(consumer.mType);
InsetsSource source = mState.peekSource(consumer.getInternalType());
if (consumer.getControl() != null && source != null && source.isUserControllable()) {
result |= toPublicType(consumer.mType);
result |= consumer.getType();
}
}
return result & ~mState.calculateUncontrollableInsetsFromFrame(mFrame);
@@ -1707,12 +1698,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
}
@Override
public void reportPerceptible(int types, boolean perceptible) {
final ArraySet<Integer> internalTypes = toInternalType(types);
public void reportPerceptible(@InsetsType int types, boolean perceptible) {
final int size = mSourceConsumers.size();
for (int i = 0; i < size; i++) {
final InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
if (internalTypes.contains(consumer.getType())) {
if ((consumer.getType() & types) != 0) {
consumer.onPerceptible(perceptible);
}
}

View File

@@ -27,7 +27,6 @@ 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 android.view.InsetsState.toPublicType;
import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
@@ -74,9 +73,9 @@ public class InsetsSourceConsumer {
}
protected final InsetsController mController;
protected boolean mRequestedVisible;
protected final InsetsState mState;
protected final @InternalInsetsType int mType;
private final @InternalInsetsType int mInternalType;
private final @InsetsType int mType;
private static final String TAG = "InsetsSourceConsumer";
private final Supplier<Transaction> mTransactionSupplier;
@@ -99,11 +98,11 @@ public class InsetsSourceConsumer {
*/
public InsetsSourceConsumer(@InternalInsetsType int type, InsetsState state,
Supplier<Transaction> transactionSupplier, InsetsController controller) {
mType = type;
mType = InsetsState.toPublicType(type);
mInternalType = type;
mState = state;
mTransactionSupplier = transactionSupplier;
mController = controller;
mRequestedVisible = getDefaultVisibility(type);
}
/**
@@ -117,7 +116,7 @@ public class InsetsSourceConsumer {
*/
public boolean setControl(@Nullable InsetsSourceControl control,
@InsetsType int[] showTypes, @InsetsType int[] hideTypes) {
if (mType == ITYPE_IME) {
if (mInternalType == ITYPE_IME) {
ImeTracing.getInstance().triggerClientDump("InsetsSourceConsumer#setControl",
mController.getHost().getInputMethodManager(), null /* icProto */);
}
@@ -141,9 +140,10 @@ public class InsetsSourceConsumer {
mController.notifyControlRevoked(this);
// Check if we need to restore server visibility.
final InsetsSource source = mState.getSource(mType);
final InsetsSource source = mState.getSource(mInternalType);
final boolean serverVisibility =
mController.getLastDispatchedState().getSourceOrDefaultVisibility(mType);
mController.getLastDispatchedState().getSourceOrDefaultVisibility(
mInternalType);
if (source.isVisible() != serverVisibility) {
source.setVisible(serverVisibility);
mController.notifyVisibilityChanged();
@@ -159,9 +159,9 @@ public class InsetsSourceConsumer {
if (DEBUG) Log.d(TAG, String.format("Gaining leash in %s, requestedVisible: %b",
mController.getHost().getRootViewTitle(), requestedVisible));
if (requestedVisible) {
showTypes[0] |= toPublicType(getType());
showTypes[0] |= mType;
} else {
hideTypes[0] |= toPublicType(getType());
hideTypes[0] |= mType;
}
} else {
// We are gaining control, but don't need to run an animation.
@@ -172,7 +172,7 @@ public class InsetsSourceConsumer {
// If we have a new leash, make sure visibility is up-to-date, even though we
// didn't want to run an animation above.
if (mController.getAnimationType(control.getType()) == ANIMATION_TYPE_NONE) {
if (mController.getAnimationType(mType) == ANIMATION_TYPE_NONE) {
applyRequestedVisibilityToControl();
}
@@ -195,29 +195,32 @@ public class InsetsSourceConsumer {
/**
* Determines if the consumer will be shown after control is available.
* Note: for system bars this method is same as {@link #isRequestedVisible()}.
*
* @return {@code true} if consumer has a pending show.
*/
protected boolean isRequestedVisibleAwaitingControl() {
return isRequestedVisible();
return (mController.getRequestedVisibleTypes() & mType) != 0;
}
int getType() {
@InsetsType int getType() {
return mType;
}
@InternalInsetsType int getInternalType() {
return mInternalType;
}
@VisibleForTesting
public void show(boolean fromIme) {
if (DEBUG) Log.d(TAG, String.format("Call show() for type: %s fromIme: %b ",
InsetsState.typeToString(mType), fromIme));
InsetsState.typeToString(mInternalType), fromIme));
setRequestedVisible(true);
}
@VisibleForTesting
public void hide() {
if (DEBUG) Log.d(TAG, String.format("Call hide for %s on %s",
InsetsState.typeToString(mType), mController.getHost().getRootViewTitle()));
InsetsState.typeToString(mInternalType), mController.getHost().getRootViewTitle()));
setRequestedVisible(false);
}
@@ -245,11 +248,13 @@ public class InsetsSourceConsumer {
}
boolean applyLocalVisibilityOverride() {
final InsetsSource source = mState.peekSource(mType);
final boolean isVisible = source != null ? source.isVisible() : getDefaultVisibility(mType);
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 (mType == ITYPE_IME) {
if (mInternalType == ITYPE_IME) {
ImeTracing.getInstance().triggerClientDump(
"InsetsSourceConsumer#applyLocalVisibilityOverride",
mController.getHost().getInputMethodManager(), null /* icProto */);
@@ -259,23 +264,18 @@ public class InsetsSourceConsumer {
if (!hasControl) {
if (DEBUG) Log.d(TAG, "applyLocalVisibilityOverride: No control in "
+ mController.getHost().getRootViewTitle()
+ " requestedVisible " + mRequestedVisible);
+ " requestedVisible=" + requestedVisible);
return false;
}
if (isVisible == mRequestedVisible) {
if (isVisible == requestedVisible) {
return false;
}
if (DEBUG) Log.d(TAG, String.format("applyLocalVisibilityOverride: %s requestedVisible: %b",
mController.getHost().getRootViewTitle(), mRequestedVisible));
mState.getSource(mType).setVisible(mRequestedVisible);
mController.getHost().getRootViewTitle(), requestedVisible));
mState.getSource(mInternalType).setVisible(requestedVisible);
return true;
}
@VisibleForTesting
public boolean isRequestedVisible() {
return mRequestedVisible;
}
/**
* Request to show current window type.
*
@@ -314,7 +314,7 @@ public class InsetsSourceConsumer {
@VisibleForTesting(visibility = PACKAGE)
public void updateSource(InsetsSource newSource, @AnimationType int animationType) {
InsetsSource source = mState.peekSource(mType);
InsetsSource source = mState.peekSource(mInternalType);
if (source == null || animationType == ANIMATION_TYPE_NONE
|| source.getFrame().equals(newSource.getFrame())) {
mPendingFrame = null;
@@ -339,7 +339,7 @@ public class InsetsSourceConsumer {
@VisibleForTesting(visibility = PACKAGE)
public boolean notifyAnimationFinished() {
if (mPendingFrame != null) {
InsetsSource source = mState.getSource(mType);
InsetsSource source = mState.getSource(mInternalType);
source.setFrame(mPendingFrame);
source.setVisibleFrame(mPendingVisibleFrame);
mPendingFrame = null;
@@ -354,11 +354,8 @@ public class InsetsSourceConsumer {
* the moment.
*/
protected void setRequestedVisible(boolean requestedVisible) {
if (mRequestedVisible != requestedVisible) {
mRequestedVisible = requestedVisible;
mController.onRequestedVisibilityChanged(this);
if (DEBUG) Log.d(TAG, "setRequestedVisible: " + requestedVisible);
}
mController.setRequestedVisibleTypes(requestedVisible ? mType : 0, mType);
if (DEBUG) Log.d(TAG, "setRequestedVisible: " + requestedVisible);
if (applyLocalVisibilityOverride()) {
mController.notifyVisibilityChanged();
}
@@ -369,25 +366,26 @@ public class InsetsSourceConsumer {
return;
}
final boolean requestedVisible = (mController.getRequestedVisibleTypes() & mType) != 0;
try (Transaction t = mTransactionSupplier.get()) {
if (DEBUG) Log.d(TAG, "applyRequestedVisibilityToControl: " + mRequestedVisible);
if (mRequestedVisible) {
if (DEBUG) Log.d(TAG, "applyRequestedVisibilityToControl: " + requestedVisible);
if (requestedVisible) {
t.show(mSourceControl.getLeash());
} else {
t.hide(mSourceControl.getLeash());
}
// Ensure the alpha value is aligned with the actual requested visibility.
t.setAlpha(mSourceControl.getLeash(), mRequestedVisible ? 1 : 0);
t.setAlpha(mSourceControl.getLeash(), requestedVisible ? 1 : 0);
t.apply();
}
onPerceptible(mRequestedVisible);
onPerceptible(requestedVisible);
}
void dumpDebug(ProtoOutputStream proto, long fieldId) {
final long token = proto.start(fieldId);
proto.write(INTERNAL_INSETS_TYPE, InsetsState.typeToString(mType));
proto.write(INTERNAL_INSETS_TYPE, InsetsState.typeToString(mInternalType));
proto.write(HAS_WINDOW_FOCUS, mHasWindowFocus);
proto.write(IS_REQUESTED_VISIBLE, mRequestedVisible);
proto.write(IS_REQUESTED_VISIBLE, (mController.getRequestedVisibleTypes() & mType) != 0);
if (mSourceControl != null) {
mSourceControl.dumpDebug(proto, SOURCE_CONTROL);
}

View File

@@ -100,12 +100,12 @@ public class ImeInsetsSourceConsumerTest {
mImeConsumer.onWindowFocusGained(true);
mController.show(WindowInsets.Type.ime(), true /* fromIme */);
mController.cancelExistingAnimations();
assertTrue(mController.getSourceConsumer(ime.getType()).isRequestedVisible());
assertTrue((mController.getRequestedVisibleTypes() & WindowInsets.Type.ime()) != 0);
// test if setVisibility can hide IME
mController.hide(WindowInsets.Type.ime(), true /* fromIme */);
mController.cancelExistingAnimations();
assertFalse(mController.getSourceConsumer(ime.getType()).isRequestedVisible());
assertFalse((mController.getRequestedVisibleTypes() & WindowInsets.Type.ime()) != 0);
});
}

View File

@@ -27,7 +27,6 @@ import static org.junit.Assert.fail;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -90,7 +89,6 @@ public class InsetsAnimationControlImplTest {
mInsetsState = new InsetsState();
mInsetsState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 500, 100));
mInsetsState.getSource(ITYPE_NAVIGATION_BAR).setFrame(new Rect(400, 0, 500, 500));
doNothing().when(mMockController).onRequestedVisibilityChanged(any());
InsetsSourceConsumer topConsumer = new InsetsSourceConsumer(ITYPE_STATUS_BAR, mInsetsState,
() -> mMockTransaction, mMockController);
topConsumer.setControl(

View File

@@ -255,10 +255,7 @@ public class InsetsControllerTest {
@Test
public void testAnimationEndState() {
InsetsSourceControl[] controls = prepareControls();
InsetsSourceControl navBar = controls[0];
InsetsSourceControl statusBar = controls[1];
InsetsSourceControl ime = controls[2];
prepareControls();
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
mController.getSourceConsumer(ITYPE_IME).onWindowFocusGained(true);
@@ -267,16 +264,13 @@ public class InsetsControllerTest {
mController.show(all());
// quickly jump to final state by cancelling it.
mController.cancelExistingAnimations();
assertTrue(mController.getSourceConsumer(navBar.getType()).isRequestedVisible());
assertTrue(mController.getSourceConsumer(statusBar.getType()).isRequestedVisible());
assertTrue(mController.getSourceConsumer(ime.getType()).isRequestedVisible());
final @InsetsType int types = navigationBars() | statusBars() | ime();
assertEquals(types, mController.getRequestedVisibleTypes() & types);
mController.hide(ime(), true /* fromIme */);
mController.hide(all());
mController.cancelExistingAnimations();
assertFalse(mController.getSourceConsumer(navBar.getType()).isRequestedVisible());
assertFalse(mController.getSourceConsumer(statusBar.getType()).isRequestedVisible());
assertFalse(mController.getSourceConsumer(ime.getType()).isRequestedVisible());
assertEquals(0, mController.getRequestedVisibleTypes() & types);
mController.getSourceConsumer(ITYPE_IME).onWindowFocusLost();
});
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
@@ -290,10 +284,10 @@ public class InsetsControllerTest {
mController.getSourceConsumer(ITYPE_IME).onWindowFocusGained(true);
mController.show(ime(), true /* fromIme */);
mController.cancelExistingAnimations();
assertTrue(mController.getSourceConsumer(ime.getType()).isRequestedVisible());
assertTrue(isRequestedVisible(mController, ime()));
mController.hide(ime(), true /* fromIme */);
mController.cancelExistingAnimations();
assertFalse(mController.getSourceConsumer(ime.getType()).isRequestedVisible());
assertFalse(isRequestedVisible(mController, ime()));
mController.getSourceConsumer(ITYPE_IME).onWindowFocusLost();
});
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
@@ -307,26 +301,22 @@ public class InsetsControllerTest {
InsetsSourceControl ime = controls[2];
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
int types = navigationBars() | systemBars();
int types = navigationBars() | statusBars();
// test hide select types.
mController.hide(types);
assertEquals(ANIMATION_TYPE_HIDE, mController.getAnimationType(ITYPE_NAVIGATION_BAR));
assertEquals(ANIMATION_TYPE_HIDE, mController.getAnimationType(ITYPE_STATUS_BAR));
assertEquals(ANIMATION_TYPE_HIDE, mController.getAnimationType(navigationBars()));
assertEquals(ANIMATION_TYPE_HIDE, mController.getAnimationType(statusBars()));
mController.cancelExistingAnimations();
assertEquals(ANIMATION_TYPE_NONE, mController.getAnimationType(ITYPE_NAVIGATION_BAR));
assertEquals(ANIMATION_TYPE_NONE, mController.getAnimationType(ITYPE_STATUS_BAR));
assertFalse(mController.getSourceConsumer(navBar.getType()).isRequestedVisible());
assertFalse(mController.getSourceConsumer(statusBar.getType()).isRequestedVisible());
assertFalse(mController.getSourceConsumer(ime.getType()).isRequestedVisible());
assertEquals(ANIMATION_TYPE_NONE, mController.getAnimationType(navigationBars()));
assertEquals(ANIMATION_TYPE_NONE, mController.getAnimationType(statusBars()));
assertEquals(0, mController.getRequestedVisibleTypes() & (types | ime()));
// test hide all
// test show all
mController.show(types);
assertEquals(ANIMATION_TYPE_SHOW, mController.getAnimationType(ITYPE_NAVIGATION_BAR));
assertEquals(ANIMATION_TYPE_SHOW, mController.getAnimationType(ITYPE_STATUS_BAR));
assertEquals(ANIMATION_TYPE_SHOW, mController.getAnimationType(navigationBars()));
assertEquals(ANIMATION_TYPE_SHOW, mController.getAnimationType(statusBars()));
mController.cancelExistingAnimations();
assertTrue(mController.getSourceConsumer(navBar.getType()).isRequestedVisible());
assertTrue(mController.getSourceConsumer(statusBar.getType()).isRequestedVisible());
assertFalse(mController.getSourceConsumer(ime.getType()).isRequestedVisible());
assertEquals(types, mController.getRequestedVisibleTypes() & (types | ime()));
});
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
}
@@ -339,33 +329,27 @@ public class InsetsControllerTest {
InsetsSourceControl ime = controls[2];
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
int types = navigationBars() | systemBars();
int types = navigationBars() | statusBars();
// test show select types.
mController.show(types);
mController.cancelExistingAnimations();
assertTrue(mController.getSourceConsumer(navBar.getType()).isRequestedVisible());
assertTrue(mController.getSourceConsumer(statusBar.getType()).isRequestedVisible());
assertFalse(mController.getSourceConsumer(ime.getType()).isRequestedVisible());
assertEquals(types, mController.getRequestedVisibleTypes() & types);
assertEquals(0, mController.getRequestedVisibleTypes() & ime());
// test hide all
mController.hide(all());
mController.cancelExistingAnimations();
assertFalse(mController.getSourceConsumer(navBar.getType()).isRequestedVisible());
assertFalse(mController.getSourceConsumer(statusBar.getType()).isRequestedVisible());
assertFalse(mController.getSourceConsumer(ime.getType()).isRequestedVisible());
assertEquals(0, mController.getRequestedVisibleTypes() & (types | ime()));
// test single show
mController.show(navigationBars());
mController.cancelExistingAnimations();
assertTrue(mController.getSourceConsumer(navBar.getType()).isRequestedVisible());
assertFalse(mController.getSourceConsumer(statusBar.getType()).isRequestedVisible());
assertFalse(mController.getSourceConsumer(ime.getType()).isRequestedVisible());
assertEquals(navigationBars(),
mController.getRequestedVisibleTypes() & (types | ime()));
// test single hide
mController.hide(navigationBars());
assertFalse(mController.getSourceConsumer(navBar.getType()).isRequestedVisible());
assertFalse(mController.getSourceConsumer(statusBar.getType()).isRequestedVisible());
assertFalse(mController.getSourceConsumer(ime.getType()).isRequestedVisible());
assertEquals(0, mController.getRequestedVisibleTypes() & (types | ime()));
});
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
@@ -373,49 +357,38 @@ public class InsetsControllerTest {
@Test
public void testShowHideMultiple() {
InsetsSourceControl[] controls = prepareControls();
InsetsSourceControl navBar = controls[0];
InsetsSourceControl statusBar = controls[1];
InsetsSourceControl ime = controls[2];
prepareControls();
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
// start two animations and see if previous is cancelled and final state is reached.
mController.hide(navigationBars());
mController.hide(systemBars());
assertEquals(ANIMATION_TYPE_HIDE, mController.getAnimationType(ITYPE_NAVIGATION_BAR));
assertEquals(ANIMATION_TYPE_HIDE, mController.getAnimationType(ITYPE_STATUS_BAR));
int types = navigationBars() | statusBars();
assertEquals(ANIMATION_TYPE_HIDE, mController.getAnimationType(navigationBars()));
assertEquals(ANIMATION_TYPE_HIDE, mController.getAnimationType(statusBars()));
mController.cancelExistingAnimations();
assertFalse(mController.getSourceConsumer(navBar.getType()).isRequestedVisible());
assertFalse(mController.getSourceConsumer(statusBar.getType()).isRequestedVisible());
assertFalse(mController.getSourceConsumer(ime.getType()).isRequestedVisible());
assertEquals(0, mController.getRequestedVisibleTypes() & (types | ime()));
mController.show(navigationBars());
mController.show(systemBars());
assertEquals(ANIMATION_TYPE_SHOW, mController.getAnimationType(ITYPE_NAVIGATION_BAR));
assertEquals(ANIMATION_TYPE_SHOW, mController.getAnimationType(ITYPE_STATUS_BAR));
assertEquals(ANIMATION_TYPE_SHOW, mController.getAnimationType(navigationBars()));
assertEquals(ANIMATION_TYPE_SHOW, mController.getAnimationType(statusBars()));
mController.cancelExistingAnimations();
assertTrue(mController.getSourceConsumer(navBar.getType()).isRequestedVisible());
assertTrue(mController.getSourceConsumer(statusBar.getType()).isRequestedVisible());
assertFalse(mController.getSourceConsumer(ime.getType()).isRequestedVisible());
assertEquals(types, mController.getRequestedVisibleTypes() & (types | ime()));
int types = navigationBars() | systemBars();
// show two at a time and hide one by one.
mController.show(types);
mController.hide(navigationBars());
assertEquals(ANIMATION_TYPE_HIDE, mController.getAnimationType(ITYPE_NAVIGATION_BAR));
assertEquals(ANIMATION_TYPE_NONE, mController.getAnimationType(ITYPE_STATUS_BAR));
assertEquals(ANIMATION_TYPE_HIDE, mController.getAnimationType(navigationBars()));
assertEquals(ANIMATION_TYPE_NONE, mController.getAnimationType(statusBars()));
mController.cancelExistingAnimations();
assertFalse(mController.getSourceConsumer(navBar.getType()).isRequestedVisible());
assertTrue(mController.getSourceConsumer(statusBar.getType()).isRequestedVisible());
assertFalse(mController.getSourceConsumer(ime.getType()).isRequestedVisible());
assertEquals(statusBars(), mController.getRequestedVisibleTypes() & (types | ime()));
mController.hide(systemBars());
assertEquals(ANIMATION_TYPE_NONE, mController.getAnimationType(ITYPE_NAVIGATION_BAR));
assertEquals(ANIMATION_TYPE_HIDE, mController.getAnimationType(ITYPE_STATUS_BAR));
assertEquals(ANIMATION_TYPE_NONE, mController.getAnimationType(navigationBars()));
assertEquals(ANIMATION_TYPE_HIDE, mController.getAnimationType(statusBars()));
mController.cancelExistingAnimations();
assertFalse(mController.getSourceConsumer(navBar.getType()).isRequestedVisible());
assertFalse(mController.getSourceConsumer(statusBar.getType()).isRequestedVisible());
assertFalse(mController.getSourceConsumer(ime.getType()).isRequestedVisible());
assertEquals(0, mController.getRequestedVisibleTypes() & (types | ime()));
});
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
}
@@ -428,20 +401,16 @@ public class InsetsControllerTest {
InsetsSourceControl ime = controls[2];
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
int types = navigationBars() | systemBars();
int types = navigationBars() | statusBars();
// show two at a time and hide one by one.
mController.show(types);
mController.hide(navigationBars());
mController.cancelExistingAnimations();
assertFalse(mController.getSourceConsumer(navBar.getType()).isRequestedVisible());
assertTrue(mController.getSourceConsumer(statusBar.getType()).isRequestedVisible());
assertFalse(mController.getSourceConsumer(ime.getType()).isRequestedVisible());
assertEquals(statusBars(), mController.getRequestedVisibleTypes() & (types | ime()));
mController.hide(systemBars());
mController.cancelExistingAnimations();
assertFalse(mController.getSourceConsumer(navBar.getType()).isRequestedVisible());
assertFalse(mController.getSourceConsumer(statusBar.getType()).isRequestedVisible());
assertFalse(mController.getSourceConsumer(ime.getType()).isRequestedVisible());
assertEquals(0, mController.getRequestedVisibleTypes() & (types | ime()));
});
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
}
@@ -453,7 +422,7 @@ public class InsetsControllerTest {
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
mController.hide(statusBars());
mController.cancelExistingAnimations();
assertFalse(mController.getSourceConsumer(ITYPE_STATUS_BAR).isRequestedVisible());
assertFalse(isRequestedVisible(mController, statusBars()));
assertFalse(mController.getState().getSource(ITYPE_STATUS_BAR).isVisible());
// Loosing control
@@ -461,14 +430,14 @@ public class InsetsControllerTest {
state.setSourceVisible(ITYPE_STATUS_BAR, true);
mController.onStateChanged(state);
mController.onControlsChanged(new InsetsSourceControl[0]);
assertFalse(mController.getSourceConsumer(ITYPE_STATUS_BAR).isRequestedVisible());
assertFalse(isRequestedVisible(mController, statusBars()));
assertTrue(mController.getState().getSource(ITYPE_STATUS_BAR).isVisible());
// Gaining control
mController.onControlsChanged(createSingletonControl(ITYPE_STATUS_BAR));
assertEquals(ANIMATION_TYPE_HIDE, mController.getAnimationType(ITYPE_STATUS_BAR));
assertEquals(ANIMATION_TYPE_HIDE, mController.getAnimationType(statusBars()));
mController.cancelExistingAnimations();
assertFalse(mController.getSourceConsumer(ITYPE_STATUS_BAR).isRequestedVisible());
assertFalse(isRequestedVisible(mController, statusBars()));
assertFalse(mController.getState().getSource(ITYPE_STATUS_BAR).isVisible());
});
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
@@ -488,9 +457,9 @@ public class InsetsControllerTest {
// Gaining control shortly after
mController.onControlsChanged(createSingletonControl(ITYPE_IME));
assertEquals(ANIMATION_TYPE_SHOW, mController.getAnimationType(ITYPE_IME));
assertEquals(ANIMATION_TYPE_SHOW, mController.getAnimationType(ime()));
mController.cancelExistingAnimations();
assertTrue(mController.getSourceConsumer(ITYPE_IME).isRequestedVisible());
assertTrue(isRequestedVisible(mController, ime()));
assertTrue(mController.getState().getSource(ITYPE_IME).isVisible());
});
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
@@ -509,9 +478,9 @@ public class InsetsControllerTest {
// Pretend IME is calling
mController.show(ime(), true /* fromIme */);
assertEquals(ANIMATION_TYPE_SHOW, mController.getAnimationType(ITYPE_IME));
assertEquals(ANIMATION_TYPE_SHOW, mController.getAnimationType(ime()));
mController.cancelExistingAnimations();
assertTrue(mController.getSourceConsumer(ITYPE_IME).isRequestedVisible());
assertTrue(isRequestedVisible(mController, ime()));
assertTrue(mController.getState().getSource(ITYPE_IME).isVisible());
});
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
@@ -538,7 +507,7 @@ public class InsetsControllerTest {
});
waitUntilNextFrame();
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
assertFalse(mController.getSourceConsumer(ITYPE_STATUS_BAR).isRequestedVisible());
assertFalse(isRequestedVisible(mController, statusBars()));
});
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
}
@@ -565,7 +534,7 @@ public class InsetsControllerTest {
});
waitUntilNextFrame();
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
assertFalse(mController.getSourceConsumer(ITYPE_STATUS_BAR).isRequestedVisible());
assertFalse(isRequestedVisible(mController, statusBars()));
});
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
}
@@ -701,6 +670,7 @@ public class InsetsControllerTest {
private void doTestResizeAnimation_insetsTypes(@InternalInsetsType int type,
@AnimationType int expectedAnimationType) {
final @InsetsType int publicType = InsetsState.toPublicType(type);
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
final InsetsState state1 = new InsetsState();
state1.getSource(type).setVisible(true);
@@ -711,15 +681,15 @@ public class InsetsControllerTest {
// New insets source won't cause the resize animation.
mController.onStateChanged(state1);
assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(type));
assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(publicType));
// Changing frame might cause the resize animation. This depends on the insets type.
mController.onStateChanged(state2);
assertEquals(message, expectedAnimationType, mController.getAnimationType(type));
assertEquals(message, expectedAnimationType, mController.getAnimationType(publicType));
// Cancel the existing animations for the next iteration.
mController.cancelExistingAnimations();
assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(type));
assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(publicType));
});
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
}
@@ -728,6 +698,7 @@ public class InsetsControllerTest {
public void testResizeAnimation_displayFrame() {
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
final @InternalInsetsType int type = ITYPE_STATUS_BAR;
final @InsetsType int publicType = statusBars();
final InsetsState state1 = new InsetsState();
state1.setDisplayFrame(new Rect(0, 0, 500, 1000));
state1.getSource(type).setFrame(0, 0, 500, 50);
@@ -738,11 +709,11 @@ public class InsetsControllerTest {
// New insets source won't cause the resize animation.
mController.onStateChanged(state1);
assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(type));
assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(publicType));
// Changing frame won't cause the resize animation if the display frame is also changed.
mController.onStateChanged(state2);
assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(type));
assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(publicType));
});
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
}
@@ -751,6 +722,7 @@ public class InsetsControllerTest {
public void testResizeAnimation_visibility() {
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
final @InternalInsetsType int type = ITYPE_STATUS_BAR;
final @InsetsType int publicType = statusBars();
final InsetsState state1 = new InsetsState();
state1.getSource(type).setVisible(true);
state1.getSource(type).setFrame(0, 0, 500, 50);
@@ -764,17 +736,17 @@ public class InsetsControllerTest {
// New insets source won't cause the resize animation.
mController.onStateChanged(state1);
assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(type));
assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(publicType));
// Changing source visibility (visible --> invisible) won't cause the resize animation.
// The previous source and the current one must be both visible.
mController.onStateChanged(state2);
assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(type));
assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(publicType));
// Changing source visibility (invisible --> visible) won't cause the resize animation.
// The previous source and the current one must be both visible.
mController.onStateChanged(state3);
assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(type));
assertEquals(message, ANIMATION_TYPE_NONE, mController.getAnimationType(publicType));
});
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
}
@@ -940,10 +912,10 @@ public class InsetsControllerTest {
// Verify IME requested visibility should be updated to IME consumer from controller.
mController.show(ime());
assertTrue(imeInsetsConsumer.isRequestedVisible());
assertTrue(isRequestedVisible(mController, ime()));
mController.hide(ime());
assertFalse(imeInsetsConsumer.isRequestedVisible());
assertFalse(isRequestedVisible(mController, ime()));
});
}
@@ -980,6 +952,10 @@ public class InsetsControllerTest {
return controls;
}
private static boolean isRequestedVisible(InsetsController controller, @InsetsType int type) {
return (controller.getRequestedVisibleTypes() & type) != 0;
}
public static class TestHost extends ViewRootInsetsControllerHost {
private @InsetsType int mRequestedVisibleTypes = defaultVisible();

View File

@@ -122,7 +122,6 @@ public class InsetsSourceConsumerTest {
public void testHide() {
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
mConsumer.hide();
assertFalse("Consumer should not be visible", mConsumer.isRequestedVisible());
verify(mSpyInsetsSource).setVisible(eq(false));
});
@@ -134,7 +133,6 @@ public class InsetsSourceConsumerTest {
// Insets source starts out visible
mConsumer.hide();
mConsumer.show(false /* fromIme */);
assertTrue("Consumer should be visible", mConsumer.isRequestedVisible());
verify(mSpyInsetsSource).setVisible(eq(false));
verify(mSpyInsetsSource).setVisible(eq(true));
});
@@ -240,7 +238,7 @@ public class InsetsSourceConsumerTest {
// visibility won't be updated when the consumer received the same leash in setControl.
insetsController.controlWindowInsetsAnimation(ime(), 0L,
null /* interpolator */, null /* cancellationSignal */, null /* listener */);
assertTrue(insetsController.getAnimationType(ITYPE_IME) == ANIMATION_TYPE_USER);
assertEquals(ANIMATION_TYPE_USER, insetsController.getAnimationType(ime()));
imeConsumer.setControl(new InsetsSourceControl(ITYPE_IME, mLeash,
true /* initialVisible */, new Point(), Insets.NONE), new int[1], new int[1]);
verify(mMockTransaction, never()).show(mLeash);