summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Tiger Huang <tigerhuang@google.com> 2021-05-10 18:36:27 +0800
committer Tiger Huang <tigerhuang@google.com> 2021-05-17 11:10:26 +0800
commita39967f4bcf6a8f413c429403a4f4294190455da (patch)
tree48a909f680841c86f52e80dd9a30388203a79491
parent3ee3029e96912b267fb11e357fd9551631ceda2c (diff)
Force showing navigation bar while IME is visible
This CL revokes navigation bar control to make navigation bar visible while IME is showing, so the button to dismiss IME would be available. This CL also lets IME receive visible navigation bar insets, regardless of the navigation bar visibility. Fix: 167971834 Fix: 186789472 Test: atest WindowStateTests WindowInsetsControllerTests Change-Id: I2e723d4fc50d006127caa473d67c2f6af0d2cbcd
-rw-r--r--core/java/android/view/InsetsAnimationControlImpl.java12
-rw-r--r--core/java/android/view/InsetsAnimationControlRunner.java13
-rw-r--r--core/java/android/view/InsetsAnimationThreadControlRunner.java11
-rw-r--r--core/java/android/view/InsetsController.java4
-rw-r--r--services/core/java/com/android/server/wm/InsetsPolicy.java35
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java18
6 files changed, 86 insertions, 7 deletions
diff --git a/core/java/android/view/InsetsAnimationControlImpl.java b/core/java/android/view/InsetsAnimationControlImpl.java
index a67ec10e1bd7..3255dd65b193 100644
--- a/core/java/android/view/InsetsAnimationControlImpl.java
+++ b/core/java/android/view/InsetsAnimationControlImpl.java
@@ -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) {
@@ -187,6 +189,16 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
}
@Override
+ public int getControllingTypes() {
+ return mControllingTypes;
+ }
+
+ @Override
+ public void notifyControlRevoked(@InsetsType int types) {
+ mControllingTypes &= ~types;
+ }
+
+ @Override
public @AnimationType int getAnimationType() {
return mAnimationType;
}
diff --git a/core/java/android/view/InsetsAnimationControlRunner.java b/core/java/android/view/InsetsAnimationControlRunner.java
index 0275b521a2a2..7787af5e133b 100644
--- a/core/java/android/view/InsetsAnimationControlRunner.java
+++ b/core/java/android/view/InsetsAnimationControlRunner.java
@@ -29,11 +29,22 @@ 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.
*/
void cancel();
diff --git a/core/java/android/view/InsetsAnimationThreadControlRunner.java b/core/java/android/view/InsetsAnimationThreadControlRunner.java
index 6122c90ce06e..436a17c0de0b 100644
--- a/core/java/android/view/InsetsAnimationThreadControlRunner.java
+++ b/core/java/android/view/InsetsAnimationThreadControlRunner.java
@@ -141,6 +141,17 @@ public class InsetsAnimationThreadControlRunner implements InsetsAnimationContro
@Override
@UiThread
+ public int getControllingTypes() {
+ return mControl.getControllingTypes();
+ }
+
+ @Override
+ public void notifyControlRevoked(@InsetsType int types) {
+ mControl.notifyControlRevoked(types);
+ }
+
+ @Override
+ @UiThread
public void cancel() {
InsetsAnimationThread.getHandler().post(mControl::cancel);
}
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index def9ca4e74fb..de7cc18531a9 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -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 */);
}
}
diff --git a/services/core/java/com/android/server/wm/InsetsPolicy.java b/services/core/java/com/android/server/wm/InsetsPolicy.java
index cda3fdaea537..c387d338a3b2 100644
--- a/services/core/java/com/android/server/wm/InsetsPolicy.java
+++ b/services/core/java/com/android/server/wm/InsetsPolicy.java
@@ -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;
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
index 8d067beff44c..e3b0bb263830 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowStateTests.java
@@ -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() {