summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/InsetsController.java24
-rw-r--r--core/java/android/view/InsetsState.java24
-rw-r--r--core/tests/coretests/src/android/view/InsetsControllerTest.java16
-rw-r--r--core/tests/coretests/src/android/view/InsetsStateTest.java117
-rw-r--r--services/core/java/com/android/server/wm/DisplayContent.java37
-rw-r--r--services/core/java/com/android/server/wm/InsetsStateController.java1
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java38
-rw-r--r--tests/utils/testutils/java/android/view/test/InsetsModeSession.java37
8 files changed, 248 insertions, 46 deletions
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 7ad97a6d393e..1bf027e77379 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -133,6 +133,10 @@ public class InsetsController implements WindowInsetsController {
}
void onFrameChanged(Rect frame) {
+ if (mFrame.equals(frame)) {
+ return;
+ }
+ mViewRoot.notifyInsetsChanged();
mFrame.set(frame);
}
@@ -257,11 +261,21 @@ public class InsetsController implements WindowInsetsController {
private void controlWindowInsetsAnimation(@InsetType int types,
WindowInsetsAnimationControlListener listener, boolean fromIme) {
+ // If the frame of our window doesn't span the entire display, the control API makes very
+ // little sense, as we don't deal with negative insets. So just cancel immediately.
+ if (!mState.getDisplayFrame().equals(mFrame)) {
+ listener.onCancelled();
+ return;
+ }
+ controlAnimationUnchecked(types, listener, mFrame, fromIme);
+ }
+
+ private void controlAnimationUnchecked(@InsetType int types,
+ WindowInsetsAnimationControlListener listener, Rect frame, boolean fromIme) {
if (types == 0) {
// nothing to animate.
return;
}
-
// TODO: Check whether we already have a controller.
final ArraySet<Integer> internalTypes = mState.toInternalType(types);
final SparseArray<InsetsSourceConsumer> consumers = new SparseArray<>();
@@ -285,7 +299,7 @@ public class InsetsController implements WindowInsetsController {
}
final InsetsAnimationControlImpl controller = new InsetsAnimationControlImpl(consumers,
- mFrame, mState, listener, typesReady,
+ frame, mState, listener, typesReady,
() -> new SyncRtSurfaceTransactionApplier(mViewRoot.mView), this);
mAnimationControls.add(controller);
}
@@ -436,6 +450,7 @@ public class InsetsController implements WindowInsetsController {
// nothing to animate.
return;
}
+
WindowInsetsAnimationControlListener listener = new WindowInsetsAnimationControlListener() {
@Override
public void onReady(WindowInsetsAnimationController controller, int types) {
@@ -479,7 +494,10 @@ public class InsetsController implements WindowInsetsController {
// TODO: Instead of clearing this here, properly wire up
// InsetsAnimationControlImpl.finish() to remove this from mAnimationControls.
mAnimationControls.clear();
- controlWindowInsetsAnimation(types, listener, fromIme);
+
+ // Show/hide animations always need to be relative to the display frame, in order that shown
+ // and hidden state insets are correct.
+ controlAnimationUnchecked(types, listener, mState.getDisplayFrame(), fromIme);
}
private void hideDirectly(@InsetType int types) {
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 4f809fe6d54a..c9273d8cc2a9 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -39,6 +39,7 @@ import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
+import java.util.Objects;
/**
* Holder for state of system windows that cause window insets for all other windows in the system.
@@ -104,6 +105,11 @@ public class InsetsState implements Parcelable {
private final ArrayMap<Integer, InsetsSource> mSources = new ArrayMap<>();
+ /**
+ * The frame of the display these sources are relative to.
+ */
+ private final Rect mDisplayFrame = new Rect();
+
public InsetsState() {
}
@@ -209,6 +215,14 @@ public class InsetsState implements Parcelable {
return mSources.computeIfAbsent(type, InsetsSource::new);
}
+ public void setDisplayFrame(Rect frame) {
+ mDisplayFrame.set(frame);
+ }
+
+ public Rect getDisplayFrame() {
+ return mDisplayFrame;
+ }
+
/**
* Modifies the state of this class to exclude a certain type to make it ready for dispatching
* to the client.
@@ -224,6 +238,7 @@ public class InsetsState implements Parcelable {
}
public void set(InsetsState other, boolean copySources) {
+ mDisplayFrame.set(other.mDisplayFrame);
mSources.clear();
if (copySources) {
for (int i = 0; i < other.mSources.size(); i++) {
@@ -323,6 +338,9 @@ public class InsetsState implements Parcelable {
InsetsState state = (InsetsState) o;
+ if (!mDisplayFrame.equals(state.mDisplayFrame)) {
+ return false;
+ }
if (mSources.size() != state.mSources.size()) {
return false;
}
@@ -341,7 +359,7 @@ public class InsetsState implements Parcelable {
@Override
public int hashCode() {
- return mSources.hashCode();
+ return Objects.hash(mDisplayFrame, mSources);
}
public InsetsState(Parcel in) {
@@ -355,9 +373,10 @@ public class InsetsState implements Parcelable {
@Override
public void writeToParcel(Parcel dest, int flags) {
+ dest.writeParcelable(mDisplayFrame, flags);
dest.writeInt(mSources.size());
for (int i = 0; i < mSources.size(); i++) {
- dest.writeParcelable(mSources.valueAt(i), 0 /* flags */);
+ dest.writeParcelable(mSources.valueAt(i), flags);
}
}
@@ -374,6 +393,7 @@ public class InsetsState implements Parcelable {
public void readFromParcel(Parcel in) {
mSources.clear();
+ mDisplayFrame.set(in.readParcelable(null /* loader */));
final int size = in.readInt();
for (int i = 0; i < size; i++) {
final InsetsSource source = in.readParcelable(null /* loader */);
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index 6dad6a22f7ea..3fc3773ff3da 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -24,6 +24,11 @@ import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.verify;
import android.content.Context;
import android.graphics.Insets;
@@ -95,6 +100,17 @@ public class InsetsControllerTest {
}
@Test
+ public void testFrameDoesntMatchDisplay() {
+ mController.onFrameChanged(new Rect(0, 0, 100, 100));
+ mController.getState().setDisplayFrame(new Rect(0, 0, 200, 200));
+ WindowInsetsAnimationControlListener controlListener =
+ mock(WindowInsetsAnimationControlListener.class);
+ mController.controlWindowInsetsAnimation(0, controlListener);
+ verify(controlListener).onCancelled();
+ verify(controlListener, never()).onReady(any(), anyInt());
+ }
+
+ @Test
public void testAnimationEndState() {
InsetsSourceControl[] controls = prepareControls();
InsetsSourceControl navBar = controls[0];
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
index 03af67df13d0..bfe6e32b6261 100644
--- a/core/tests/coretests/src/android/view/InsetsStateTest.java
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -37,6 +37,7 @@ import android.os.Parcel;
import android.platform.test.annotations.Presubmit;
import android.util.SparseIntArray;
import android.view.WindowInsets.Type;
+import android.view.test.InsetsModeSession;
import androidx.test.filters.FlakyTest;
import androidx.test.runner.AndroidJUnit4;
@@ -53,49 +54,58 @@ public class InsetsStateTest {
private InsetsState mState2 = new InsetsState();
@Test
- public void testCalculateInsets() {
- mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
- mState.getSource(TYPE_TOP_BAR).setVisible(true);
- mState.getSource(TYPE_IME).setFrame(new Rect(0, 200, 100, 300));
- mState.getSource(TYPE_IME).setVisible(true);
- SparseIntArray typeSideMap = new SparseIntArray();
- WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
- DisplayCutout.NO_CUTOUT, null, null, typeSideMap);
- assertEquals(Insets.of(0, 100, 0, 100), insets.getSystemWindowInsets());
- assertEquals(Insets.of(0, 100, 0, 100), insets.getInsets(Type.all()));
- assertEquals(INSET_SIDE_TOP, typeSideMap.get(TYPE_TOP_BAR));
- assertEquals(INSET_SIDE_BOTTOM, typeSideMap.get(TYPE_IME));
- assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.topBar()));
- assertEquals(Insets.of(0, 0, 0, 100), insets.getInsets(Type.ime()));
+ public void testCalculateInsets() throws Exception {
+ try (final InsetsModeSession session =
+ new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
+ mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(TYPE_TOP_BAR).setVisible(true);
+ mState.getSource(TYPE_IME).setFrame(new Rect(0, 200, 100, 300));
+ mState.getSource(TYPE_IME).setVisible(true);
+ SparseIntArray typeSideMap = new SparseIntArray();
+ WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
+ DisplayCutout.NO_CUTOUT, null, null, typeSideMap);
+ assertEquals(Insets.of(0, 100, 0, 100), insets.getSystemWindowInsets());
+ assertEquals(Insets.of(0, 100, 0, 100), insets.getInsets(Type.all()));
+ assertEquals(INSET_SIDE_TOP, typeSideMap.get(TYPE_TOP_BAR));
+ assertEquals(INSET_SIDE_BOTTOM, typeSideMap.get(TYPE_IME));
+ assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.topBar()));
+ assertEquals(Insets.of(0, 0, 0, 100), insets.getInsets(Type.ime()));
+ }
}
@Test
- public void testCalculateInsets_imeAndNav() {
- mState.getSource(TYPE_NAVIGATION_BAR).setFrame(new Rect(0, 200, 100, 300));
- mState.getSource(TYPE_NAVIGATION_BAR).setVisible(true);
- mState.getSource(TYPE_IME).setFrame(new Rect(0, 100, 100, 300));
- mState.getSource(TYPE_IME).setVisible(true);
- WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
- DisplayCutout.NO_CUTOUT, null, null, null);
- assertEquals(100, insets.getStableInsetBottom());
- assertEquals(Insets.of(0, 0, 0, 100), insets.getMaxInsets(Type.all()));
- assertEquals(Insets.of(0, 0, 0, 200), insets.getSystemWindowInsets());
- assertEquals(Insets.of(0, 0, 0, 200), insets.getInsets(Type.all()));
- assertEquals(Insets.of(0, 0, 0, 100), insets.getInsets(Type.sideBars()));
- assertEquals(Insets.of(0, 0, 0, 200), insets.getInsets(Type.ime()));
+ public void testCalculateInsets_imeAndNav() throws Exception{
+ try (final InsetsModeSession session =
+ new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
+ mState.getSource(TYPE_NAVIGATION_BAR).setFrame(new Rect(0, 200, 100, 300));
+ mState.getSource(TYPE_NAVIGATION_BAR).setVisible(true);
+ mState.getSource(TYPE_IME).setFrame(new Rect(0, 100, 100, 300));
+ mState.getSource(TYPE_IME).setVisible(true);
+ WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
+ DisplayCutout.NO_CUTOUT, null, null, null);
+ assertEquals(100, insets.getStableInsetBottom());
+ assertEquals(Insets.of(0, 0, 0, 100), insets.getMaxInsets(Type.systemBars()));
+ assertEquals(Insets.of(0, 0, 0, 200), insets.getSystemWindowInsets());
+ assertEquals(Insets.of(0, 0, 0, 200), insets.getInsets(Type.all()));
+ assertEquals(Insets.of(0, 0, 0, 100), insets.getInsets(Type.sideBars()));
+ assertEquals(Insets.of(0, 0, 0, 200), insets.getInsets(Type.ime()));
+ }
}
@Test
- public void testCalculateInsets_navRightStatusTop() {
- mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
- mState.getSource(TYPE_TOP_BAR).setVisible(true);
- mState.getSource(TYPE_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
- mState.getSource(TYPE_NAVIGATION_BAR).setVisible(true);
- WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
- DisplayCutout.NO_CUTOUT, null, null, null);
- assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
- assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.topBar()));
- assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(Type.sideBars()));
+ public void testCalculateInsets_navRightStatusTop() throws Exception {
+ try (final InsetsModeSession session =
+ new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
+ mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(TYPE_TOP_BAR).setVisible(true);
+ mState.getSource(TYPE_NAVIGATION_BAR).setFrame(new Rect(80, 0, 100, 300));
+ mState.getSource(TYPE_NAVIGATION_BAR).setVisible(true);
+ WindowInsets insets = mState.calculateInsets(new Rect(0, 0, 100, 300), false, false,
+ DisplayCutout.NO_CUTOUT, null, null, null);
+ assertEquals(Insets.of(0, 100, 20, 0), insets.getSystemWindowInsets());
+ assertEquals(Insets.of(0, 100, 0, 0), insets.getInsets(Type.topBar()));
+ assertEquals(Insets.of(0, 0, 20, 0), insets.getInsets(Type.sideBars()));
+ }
}
@Test
@@ -114,14 +124,14 @@ public class InsetsStateTest {
public void testEquals_differentRect() {
mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
mState2.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 10, 10));
- assertNotEquals(mState, mState2);
+ assertNotEqualsAndHashCode();
}
@Test
public void testEquals_differentSource() {
mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
mState2.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
- assertNotEquals(mState, mState2);
+ assertNotEqualsAndHashCode();
}
@Test
@@ -130,7 +140,7 @@ public class InsetsStateTest {
mState.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
mState2.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
mState2.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
- assertEquals(mState, mState2);
+ assertEqualsAndHashCode();
}
@Test
@@ -138,7 +148,21 @@ public class InsetsStateTest {
mState.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
mState.getSource(TYPE_IME).setVisible(true);
mState2.getSource(TYPE_IME).setFrame(new Rect(0, 0, 100, 100));
- assertNotEquals(mState, mState2);
+ assertNotEqualsAndHashCode();
+ }
+
+ @Test
+ public void testEquals_differentFrame() {
+ mState.setDisplayFrame(new Rect(0, 1, 2, 3));
+ mState.setDisplayFrame(new Rect(4, 5, 6, 7));
+ assertNotEqualsAndHashCode();
+ }
+
+ @Test
+ public void testEquals_sameFrame() {
+ mState.setDisplayFrame(new Rect(0, 1, 2, 3));
+ mState2.setDisplayFrame(new Rect(0, 1, 2, 3));
+ assertEqualsAndHashCode();
}
@Test
@@ -148,6 +172,7 @@ public class InsetsStateTest {
mState.getSource(TYPE_TOP_BAR).setFrame(new Rect(0, 0, 100, 100));
Parcel p = Parcel.obtain();
mState.writeToParcel(p, 0 /* flags */);
+ p.setDataPosition(0);
mState2.readFromParcel(p);
p.recycle();
assertEquals(mState, mState2);
@@ -161,4 +186,14 @@ public class InsetsStateTest {
assertTrue(InsetsState.getDefaultVisibility(TYPE_SIDE_BAR_3));
assertFalse(InsetsState.getDefaultVisibility(TYPE_IME));
}
+
+ private void assertEqualsAndHashCode() {
+ assertEquals(mState, mState2);
+ assertEquals(mState.hashCode(), mState2.hashCode());
+ }
+
+ private void assertNotEqualsAndHashCode() {
+ assertNotEquals(mState, mState2);
+ assertNotEquals(mState.hashCode(), mState2.hashCode());
+ }
}
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 7a8fd49361b6..a67c72a79b78 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -38,6 +38,7 @@ import static android.view.Surface.ROTATION_180;
import static android.view.Surface.ROTATION_270;
import static android.view.Surface.ROTATION_90;
import static android.view.View.GONE;
+import static android.view.ViewRootImpl.NEW_INSETS_MODE_NONE;
import static android.view.WindowManager.DOCKED_BOTTOM;
import static android.view.WindowManager.DOCKED_INVALID;
import static android.view.WindowManager.DOCKED_TOP;
@@ -172,6 +173,7 @@ import android.view.SurfaceControl;
import android.view.SurfaceControl.Transaction;
import android.view.SurfaceSession;
import android.view.View;
+import android.view.ViewRootImpl;
import android.view.WindowManager;
import android.view.WindowManagerPolicyConstants.PointerEventListener;
@@ -3251,6 +3253,36 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
mInputMethodTargetWaitingAnim = targetWaitingAnim;
assignWindowLayers(false /* setLayoutNeeded */);
mInsetsStateController.onImeTargetChanged(target);
+ updateImeParent();
+ }
+
+ private void updateImeParent() {
+ if (ViewRootImpl.sNewInsetsMode == NEW_INSETS_MODE_NONE) {
+ return;
+ }
+ final SurfaceControl newParent = computeImeParent();
+ if (newParent != null) {
+ mPendingTransaction.reparent(mImeWindowsContainers.mSurfaceControl, newParent);
+ scheduleAnimation();
+ }
+ }
+
+ /**
+ * Computes the window the IME should be attached to.
+ */
+ @VisibleForTesting
+ SurfaceControl computeImeParent() {
+
+ // Attach it to app if the target is part of an app and such app is covering the entire
+ // screen. If it's not covering the entire screen the IME might extend beyond the apps
+ // bounds.
+ if (mInputMethodTarget != null && mInputMethodTarget.mAppToken != null &&
+ mInputMethodTarget.getWindowingMode() == WINDOWING_MODE_FULLSCREEN) {
+ return mInputMethodTarget.mAppToken.getSurfaceControl();
+ }
+
+ // Otherwise, we just attach it to the display.
+ return mWindowingLayer;
}
boolean getNeedsMenu(WindowState top, WindowManagerPolicy.WindowState bottom) {
@@ -4885,6 +4917,11 @@ class DisplayContent extends WindowContainer<DisplayContent.DisplayChildWindowCo
.reparent(mWindowingLayer, sc).reparent(mOverlayLayer, sc);
}
+ @VisibleForTesting
+ SurfaceControl getWindowingLayer() {
+ return mWindowingLayer;
+ }
+
/**
* Create a portal window handle for input. This window transports any touch to the display
* indicated by {@link InputWindowHandle#portalToDisplayId} if the touch hits this window.
diff --git a/services/core/java/com/android/server/wm/InsetsStateController.java b/services/core/java/com/android/server/wm/InsetsStateController.java
index afae9c4ac228..a1b52f424fee 100644
--- a/services/core/java/com/android/server/wm/InsetsStateController.java
+++ b/services/core/java/com/android/server/wm/InsetsStateController.java
@@ -112,6 +112,7 @@ class InsetsStateController {
* Called when a layout pass has occurred.
*/
void onPostLayout() {
+ mState.setDisplayFrame(mDisplayContent.getBounds());
for (int i = mControllers.size() - 1; i>= 0; i--) {
mControllers.valueAt(i).onPostLayout();
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 3826fac22b05..a62bc713db40 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -51,17 +51,22 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
import android.annotation.SuppressLint;
+import android.app.WindowConfiguration;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.SystemClock;
import android.platform.test.annotations.Presubmit;
import android.util.DisplayMetrics;
import android.view.DisplayCutout;
+import android.view.DisplayInfo;
import android.view.Gravity;
import android.view.MotionEvent;
import android.view.Surface;
+import android.view.ViewRootImpl;
+import android.view.test.InsetsModeSession;
import androidx.test.filters.FlakyTest;
import androidx.test.filters.SmallTest;
@@ -628,6 +633,39 @@ public class DisplayContentTests extends WindowTestsBase {
eq(activityRecord), anyBoolean(), eq(dc.getDisplayId()));
}
+ @Test
+ public void testComputeImeParent_app() throws Exception {
+ try (final InsetsModeSession session =
+ new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
+ final DisplayContent dc = createNewDisplay();
+ dc.mInputMethodTarget = createWindow(null, TYPE_BASE_APPLICATION, "app");
+ assertEquals(dc.mInputMethodTarget.mAppToken.getSurfaceControl(),
+ dc.computeImeParent());
+ }
+ }
+
+ @Test
+ public void testComputeImeParent_app_notFullscreen() throws Exception {
+ try (final InsetsModeSession session =
+ new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
+ final DisplayContent dc = createNewDisplay();
+ dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "app");
+ dc.mInputMethodTarget.setWindowingMode(
+ WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY);
+ assertEquals(dc.getWindowingLayer(), dc.computeImeParent());
+ }
+ }
+
+ @Test
+ public void testComputeImeParent_noApp() throws Exception {
+ try (final InsetsModeSession session =
+ new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_IME)) {
+ final DisplayContent dc = createNewDisplay();
+ dc.mInputMethodTarget = createWindow(null, TYPE_STATUS_BAR, "statusBar");
+ assertEquals(dc.getWindowingLayer(), dc.computeImeParent());
+ }
+ }
+
private boolean isOptionsPanelAtRight(int displayId) {
return (mWm.getPreferredOptionsPanelGravity(displayId) & Gravity.RIGHT) == Gravity.RIGHT;
}
diff --git a/tests/utils/testutils/java/android/view/test/InsetsModeSession.java b/tests/utils/testutils/java/android/view/test/InsetsModeSession.java
new file mode 100644
index 000000000000..c83dfa41d260
--- /dev/null
+++ b/tests/utils/testutils/java/android/view/test/InsetsModeSession.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view.test;
+
+import android.view.ViewRootImpl;
+
+/**
+ * Session to set insets mode for {@link ViewRootImpl#sNewInsetsMode}.
+ */
+public class InsetsModeSession implements AutoCloseable {
+
+ private int mOldMode;
+
+ public InsetsModeSession(int flag) {
+ mOldMode = ViewRootImpl.sNewInsetsMode;
+ ViewRootImpl.sNewInsetsMode = flag;
+ }
+
+ @Override
+ public void close() throws Exception {
+ ViewRootImpl.sNewInsetsMode = mOldMode;
+ }
+}