Merge "Force showing navigation bar while IME is visible" into sc-dev

This commit is contained in:
Tiger Huang
2021-05-19 15:25:17 +00:00
committed by Android (Google) Code Review
6 changed files with 86 additions and 7 deletions

View File

@@ -86,6 +86,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
private final InsetsState mInitialInsetsState;
private final @AnimationType int mAnimationType;
private final @InsetsType int mTypes;
private @InsetsType int mControllingTypes;
private final InsetsAnimationControlCallbacks mController;
private final WindowInsetsAnimation mAnimation;
/** @see WindowInsetsAnimationController#hasZeroInsetsIme */
@@ -112,6 +113,7 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
mControls = controls;
mListener = listener;
mTypes = types;
mControllingTypes = types;
mController = controller;
mInitialInsetsState = new InsetsState(state, true /* copySources */);
if (frame != null) {
@@ -186,6 +188,16 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
return mTypes;
}
@Override
public int getControllingTypes() {
return mControllingTypes;
}
@Override
public void notifyControlRevoked(@InsetsType int types) {
mControllingTypes &= ~types;
}
@Override
public @AnimationType int getAnimationType() {
return mAnimationType;

View File

@@ -29,10 +29,21 @@ import android.view.WindowInsets.Type.InsetsType;
public interface InsetsAnimationControlRunner {
/**
* @return The {@link InsetsType} the animation of this runner is controlling.
* @return The {@link InsetsType} the animation of this runner controls.
*/
@InsetsType int getTypes();
/**
* @return The {@link InsetsType} the animation of this runner is controlling. This can be
* changed if a control is revoked.
*/
@InsetsType int getControllingTypes();
/**
* Notifies {@link InsetsType types} of control are getting revoked.
*/
void notifyControlRevoked(@InsetsType int types);
/**
* Cancels the animation.
*/

View File

@@ -139,6 +139,17 @@ public class InsetsAnimationThreadControlRunner implements InsetsAnimationContro
return mControl.getTypes();
}
@Override
@UiThread
public int getControllingTypes() {
return mControl.getControllingTypes();
}
@Override
public void notifyControlRevoked(@InsetsType int types) {
mControl.notifyControlRevoked(types);
}
@Override
@UiThread
public void cancel() {

View File

@@ -1224,9 +1224,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
}
void notifyControlRevoked(InsetsSourceConsumer consumer) {
final @InsetsType int types = toPublicType(consumer.getType());
for (int i = mRunningAnimations.size() - 1; i >= 0; i--) {
InsetsAnimationControlRunner control = mRunningAnimations.get(i).runner;
if ((control.getTypes() & toPublicType(consumer.getType())) != 0) {
control.notifyControlRevoked(types);
if (control.getControllingTypes() == 0) {
cancelAnimation(control, true /* invokeCallback */);
}
}

View File

@@ -22,6 +22,7 @@ import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.view.InsetsController.ANIMATION_TYPE_HIDE;
import static android.view.InsetsController.ANIMATION_TYPE_SHOW;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.SyncRtSurfaceTransactionApplier.applyParams;
@@ -207,7 +208,8 @@ class InsetsPolicy {
*/
InsetsState getInsetsForWindow(WindowState target) {
final InsetsState originalState = mStateController.getInsetsForWindow(target);
return adjustVisibilityForTransientTypes(originalState);
final InsetsState state = adjustVisibilityForTransientTypes(originalState);
return target.mIsImWindow ? adjustVisibilityForIme(state, state == originalState) : state;
}
/**
@@ -237,6 +239,20 @@ class InsetsPolicy {
return state;
}
// Navigation bar insets is always visible to IME.
private static InsetsState adjustVisibilityForIme(InsetsState originalState,
boolean copyState) {
final InsetsSource originalNavSource = originalState.peekSource(ITYPE_NAVIGATION_BAR);
if (originalNavSource != null && !originalNavSource.isVisible()) {
final InsetsState state = copyState ? new InsetsState(originalState) : originalState;
final InsetsSource navSource = new InsetsSource(originalNavSource);
navSource.setVisible(true);
state.addSource(navSource);
return state;
}
return originalState;
}
void onInsetsModified(InsetsControlTarget caller) {
mStateController.onInsetsModified(caller);
checkAbortTransient(caller);
@@ -245,17 +261,21 @@ class InsetsPolicy {
/**
* Called when a control target modified the insets state. If the target set a insets source to
* visible while it is shown transiently, we need to abort the transient state.
* visible while it is shown transiently, we need to abort the transient state. While IME is
* requested visible, we also need to abort the transient state of navigation bar if it is shown
* transiently.
*
* @param caller who changed the insets state.
*/
private void checkAbortTransient(InsetsControlTarget caller) {
if (mShowingTransientTypes.size() != 0) {
IntArray abortTypes = new IntArray();
final IntArray abortTypes = new IntArray();
final boolean imeRequestedVisible = caller.getRequestedVisibility(ITYPE_IME);
for (int i = mShowingTransientTypes.size() - 1; i >= 0; i--) {
final @InternalInsetsType int type = mShowingTransientTypes.get(i);
if (mStateController.isFakeTarget(type, caller)
&& caller.getRequestedVisibility(type)) {
if ((mStateController.isFakeTarget(type, caller)
&& caller.getRequestedVisibility(type))
|| (type == ITYPE_NAVIGATION_BAR && imeRequestedVisible)) {
mShowingTransientTypes.remove(i);
abortTypes.add(type);
}
@@ -330,6 +350,11 @@ class InsetsPolicy {
private @Nullable InsetsControlTarget getNavControlTarget(@Nullable WindowState focusedWin,
boolean forceShowsSystemBarsForWindowingMode) {
final WindowState imeWin = mDisplayContent.mInputMethodWindow;
if (imeWin != null && imeWin.isVisible()) {
// Force showing navigation bar while IME is visible.
return null;
}
if (mShowingTransientTypes.indexOf(ITYPE_NAVIGATION_BAR) != -1) {
return mDummyControlTarget;
}

View File

@@ -20,6 +20,7 @@ import static android.app.WindowConfiguration.ACTIVITY_TYPE_STANDARD;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
import static android.view.Surface.ROTATION_0;
import static android.view.Surface.ROTATION_270;
@@ -78,6 +79,7 @@ import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import android.view.Gravity;
import android.view.InputWindowHandle;
import android.view.InsetsSource;
import android.view.InsetsState;
import android.view.SurfaceControl;
import android.view.WindowManager;
@@ -880,6 +882,22 @@ public class WindowStateTests extends WindowTestsBase {
verify(app).notifyInsetsChanged();
}
@UseTestDisplay(addWindows = { W_INPUT_METHOD, W_ACTIVITY })
@Test
public void testImeAlwaysReceivesVisibleNavigationBarInsets() {
final InsetsSource navSource = new InsetsSource(ITYPE_NAVIGATION_BAR);
mImeWindow.mAboveInsetsState.addSource(navSource);
mAppWindow.mAboveInsetsState.addSource(navSource);
navSource.setVisible(false);
assertTrue(mImeWindow.getInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
assertFalse(mAppWindow.getInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
navSource.setVisible(true);
assertTrue(mImeWindow.getInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
assertTrue(mAppWindow.getInsetsState().getSourceOrDefaultVisibility(ITYPE_NAVIGATION_BAR));
}
@UseTestDisplay(addWindows = { W_ACTIVITY })
@Test
public void testUpdateImeControlTargetWhenLeavingMultiWindow() {