summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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() {