Loading core/java/android/view/ImeInsetsSourceConsumer.java +3 −3 Original line number Diff line number Diff line Loading @@ -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; } } Loading Loading @@ -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; } Loading Loading @@ -169,7 +169,7 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { @Override protected boolean isRequestedVisibleAwaitingControl() { return mIsRequestedVisibleAwaitingControl || isRequestedVisible(); return super.isRequestedVisibleAwaitingControl() || mIsRequestedVisibleAwaitingControl; } @Override Loading core/java/android/view/InsetsAnimationControlImpl.java +2 −2 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -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; Loading core/java/android/view/InsetsAnimationControlRunner.java +3 −4 Original line number Diff line number Diff line Loading @@ -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; /** Loading Loading @@ -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; } /** Loading core/java/android/view/InsetsController.java +43 −53 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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. Loading Loading @@ -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); Loading @@ -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 */); } Loading Loading @@ -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); Loading @@ -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) { Loading Loading @@ -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(); } } Loading Loading @@ -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; } } Loading Loading @@ -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); Loading Loading @@ -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); } } Loading core/java/android/view/InsetsSourceConsumer.java +39 −41 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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); } /** Loading @@ -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 */); } Loading @@ -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(); Loading @@ -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. Loading @@ -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(); } Loading @@ -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); } Loading Loading @@ -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 */); Loading @@ -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. * Loading Loading @@ -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; Loading @@ -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; Loading @@ -354,11 +354,8 @@ public class InsetsSourceConsumer { * the moment. */ protected void setRequestedVisible(boolean requestedVisible) { if (mRequestedVisible != requestedVisible) { mRequestedVisible = requestedVisible; mController.onRequestedVisibilityChanged(this); mController.setRequestedVisibleTypes(requestedVisible ? mType : 0, mType); if (DEBUG) Log.d(TAG, "setRequestedVisible: " + requestedVisible); } if (applyLocalVisibilityOverride()) { mController.notifyVisibilityChanged(); } Loading @@ -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); } Loading Loading
core/java/android/view/ImeInsetsSourceConsumer.java +3 −3 Original line number Diff line number Diff line Loading @@ -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; } } Loading Loading @@ -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; } Loading Loading @@ -169,7 +169,7 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { @Override protected boolean isRequestedVisibleAwaitingControl() { return mIsRequestedVisibleAwaitingControl || isRequestedVisible(); return super.isRequestedVisibleAwaitingControl() || mIsRequestedVisibleAwaitingControl; } @Override Loading
core/java/android/view/InsetsAnimationControlImpl.java +2 −2 Original line number Diff line number Diff line Loading @@ -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. Loading @@ -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; Loading
core/java/android/view/InsetsAnimationControlRunner.java +3 −4 Original line number Diff line number Diff line Loading @@ -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; /** Loading Loading @@ -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; } /** Loading
core/java/android/view/InsetsController.java +43 −53 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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. Loading Loading @@ -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); Loading @@ -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 */); } Loading Loading @@ -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); Loading @@ -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) { Loading Loading @@ -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(); } } Loading Loading @@ -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; } } Loading Loading @@ -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); Loading Loading @@ -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); } } Loading
core/java/android/view/InsetsSourceConsumer.java +39 −41 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading @@ -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); } /** Loading @@ -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 */); } Loading @@ -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(); Loading @@ -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. Loading @@ -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(); } Loading @@ -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); } Loading Loading @@ -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 */); Loading @@ -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. * Loading Loading @@ -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; Loading @@ -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; Loading @@ -354,11 +354,8 @@ public class InsetsSourceConsumer { * the moment. */ protected void setRequestedVisible(boolean requestedVisible) { if (mRequestedVisible != requestedVisible) { mRequestedVisible = requestedVisible; mController.onRequestedVisibilityChanged(this); mController.setRequestedVisibleTypes(requestedVisible ? mType : 0, mType); if (DEBUG) Log.d(TAG, "setRequestedVisible: " + requestedVisible); } if (applyLocalVisibilityOverride()) { mController.notifyVisibilityChanged(); } Loading @@ -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); } Loading