summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/view/InsetsController.java30
-rw-r--r--core/java/android/view/InsetsSource.java7
-rw-r--r--core/java/android/view/InsetsState.java30
-rw-r--r--core/java/android/view/PendingInsetsController.java9
-rw-r--r--core/java/android/view/View.java5
-rw-r--r--core/java/android/view/ViewRootImpl.java17
-rw-r--r--core/java/android/view/Window.java5
-rw-r--r--core/java/android/view/WindowInsets.java1
-rw-r--r--core/java/android/view/WindowInsetsController.java9
-rw-r--r--core/java/com/android/internal/policy/DecorView.java37
-rw-r--r--core/java/com/android/internal/widget/DecorCaptionView.java29
-rw-r--r--core/tests/coretests/src/android/view/InsetsControllerTest.java22
-rw-r--r--core/tests/coretests/src/android/view/InsetsStateTest.java29
13 files changed, 184 insertions, 46 deletions
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index e6bd84391fef..40a460dfece0 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -16,6 +16,7 @@
package android.view;
+import static android.view.InsetsState.ITYPE_CAPTION_BAR;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.toInternalType;
import static android.view.InsetsState.toPublicType;
@@ -367,6 +368,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
private int mLastLegacySystemUiFlags;
private DisplayCutout mLastDisplayCutout;
private boolean mStartingAnimation;
+ private int mCaptionInsetsHeight = 0;
private SyncRtSurfaceTransactionApplier mApplier;
@@ -460,7 +462,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
@VisibleForTesting
public boolean onStateChanged(InsetsState state) {
- boolean localStateChanged = !mState.equals(state);
+ boolean localStateChanged = !mState.equals(state, true /* excludingCaptionInsets */)
+ || !captionInsetsUnchanged();
if (!localStateChanged && mLastDispachedState.equals(state)) {
return false;
}
@@ -470,7 +473,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
if (localStateChanged) {
mViewRoot.notifyInsetsChanged();
}
- if (!mState.equals(mLastDispachedState)) {
+ if (!mState.equals(mLastDispachedState, true /* excludingCaptionInsets */)) {
sendStateToWindowManager();
}
return true;
@@ -488,6 +491,23 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
mState.removeSource(source.getType());
}
}
+ if (mCaptionInsetsHeight != 0) {
+ mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(mFrame.left, mFrame.top,
+ mFrame.right, mFrame.top + mCaptionInsetsHeight));
+ }
+ }
+
+ private boolean captionInsetsUnchanged() {
+ if (mState.peekSource(ITYPE_CAPTION_BAR) == null
+ && mCaptionInsetsHeight == 0) {
+ return true;
+ }
+ if (mState.peekSource(ITYPE_CAPTION_BAR) != null
+ && mCaptionInsetsHeight
+ == mState.peekSource(ITYPE_CAPTION_BAR).getFrame().height()) {
+ return true;
+ }
+ return false;
}
/**
@@ -964,6 +984,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
InsetsState tmpState = new InsetsState();
for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
final InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
+ if (consumer.getType() == ITYPE_CAPTION_BAR) continue;
if (consumer.getControl() != null) {
tmpState.addSource(mState.getSource(consumer.getType()));
}
@@ -1105,6 +1126,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
}
@Override
+ public void setCaptionInsetsHeight(int height) {
+ mCaptionInsetsHeight = height;
+ }
+
+ @Override
public void setSystemBarsBehavior(@Behavior int behavior) {
mViewRoot.mWindowAttributes.privateFlags |= PRIVATE_FLAG_BEHAVIOR_CONTROLLED;
if (mViewRoot.mWindowAttributes.insetsFlags.behavior != behavior) {
diff --git a/core/java/android/view/InsetsSource.java b/core/java/android/view/InsetsSource.java
index 294faaf0b5c8..033ccef3666d 100644
--- a/core/java/android/view/InsetsSource.java
+++ b/core/java/android/view/InsetsSource.java
@@ -16,6 +16,7 @@
package android.view;
+import static android.view.InsetsState.ITYPE_CAPTION_BAR;
import static android.view.InsetsState.ITYPE_IME;
import android.annotation.NonNull;
@@ -118,6 +119,12 @@ public class InsetsSource implements Parcelable {
if (!getIntersection(frame, relativeFrame, mTmpFrame)) {
return Insets.NONE;
}
+ // During drag-move and drag-resizing, the caption insets position may not get updated
+ // before the app frame get updated. To layout the app content correctly during drag events,
+ // we always return the insets with the corresponding height covering the top.
+ if (getType() == ITYPE_CAPTION_BAR) {
+ return Insets.of(0, frame.height(), 0, 0);
+ }
// TODO: Currently, non-floating IME always intersects at bottom due to issues with cutout.
// However, we should let the policy decide from the server.
diff --git a/core/java/android/view/InsetsState.java b/core/java/android/view/InsetsState.java
index 40e6f57f2286..c5154662928e 100644
--- a/core/java/android/view/InsetsState.java
+++ b/core/java/android/view/InsetsState.java
@@ -45,6 +45,8 @@ import android.view.WindowInsets.Type;
import android.view.WindowInsets.Type.InsetsType;
import android.view.WindowManager.LayoutParams.SoftInputModeFlags;
+import com.android.internal.annotations.VisibleForTesting;
+
import java.io.PrintWriter;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -498,6 +500,19 @@ public class InsetsState implements Parcelable {
@Override
public boolean equals(Object o) {
+ return equals(o, false);
+ }
+
+ /**
+ * An equals method can exclude the caption insets. This is useful because we assemble the
+ * caption insets information on the client side, and when we communicate with server, it's
+ * excluded.
+ * @param excludingCaptionInsets {@code true} if we want to compare two InsetsState objects but
+ * ignore the caption insets source value.
+ * @return {@code true} if the two InsetsState objects are equal, {@code false} otherwise.
+ */
+ @VisibleForTesting
+ public boolean equals(Object o, boolean excludingCaptionInsets) {
if (this == o) { return true; }
if (o == null || getClass() != o.getClass()) { return false; }
@@ -506,11 +521,24 @@ public class InsetsState implements Parcelable {
if (!mDisplayFrame.equals(state.mDisplayFrame)) {
return false;
}
- if (mSources.size() != state.mSources.size()) {
+ int size = mSources.size();
+ int otherSize = state.mSources.size();
+ if (excludingCaptionInsets) {
+ if (mSources.get(ITYPE_CAPTION_BAR) != null) {
+ size--;
+ }
+ if (state.mSources.get(ITYPE_CAPTION_BAR) != null) {
+ otherSize--;
+ }
+ }
+ if (size != otherSize) {
return false;
}
for (int i = mSources.size() - 1; i >= 0; i--) {
InsetsSource source = mSources.valueAt(i);
+ if (excludingCaptionInsets) {
+ if (source.getType() == ITYPE_CAPTION_BAR) continue;
+ }
InsetsSource otherSource = state.mSources.get(source.getType());
if (otherSource == null) {
return false;
diff --git a/core/java/android/view/PendingInsetsController.java b/core/java/android/view/PendingInsetsController.java
index 229ee03521bc..a106b2c4726d 100644
--- a/core/java/android/view/PendingInsetsController.java
+++ b/core/java/android/view/PendingInsetsController.java
@@ -42,6 +42,7 @@ public class PendingInsetsController implements WindowInsetsController {
private InsetsController mReplayedInsetsController;
private ArrayList<OnControllableInsetsChangedListener> mControllableInsetsChangedListeners
= new ArrayList<>();
+ private int mCaptionInsetsHeight = 0;
@Override
public void show(int types) {
@@ -80,6 +81,11 @@ public class PendingInsetsController implements WindowInsetsController {
}
@Override
+ public void setCaptionInsetsHeight(int height) {
+ mCaptionInsetsHeight = height;
+ }
+
+ @Override
public void setSystemBarsBehavior(int behavior) {
if (mReplayedInsetsController != null) {
mReplayedInsetsController.setSystemBarsBehavior(behavior);
@@ -134,6 +140,9 @@ public class PendingInsetsController implements WindowInsetsController {
if (mAppearanceMask != 0) {
controller.setSystemBarsAppearance(mAppearance, mAppearanceMask);
}
+ if (mCaptionInsetsHeight != 0) {
+ controller.setCaptionInsetsHeight(mCaptionInsetsHeight);
+ }
int size = mRequests.size();
for (int i = 0; i < size; i++) {
mRequests.get(i).replay(controller);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 4922917c911c..da186087a34a 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -28768,6 +28768,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
publicAlternatives = "Use {@link WindowInsets#getInsets(int)}")
final Rect mStableInsets = new Rect();
+ /**
+ * Current caption insets to the display coordinate.
+ */
+ final Rect mCaptionInsets = new Rect();
+
final DisplayCutout.ParcelableWrapper mDisplayCutout =
new DisplayCutout.ParcelableWrapper(DisplayCutout.NO_CUTOUT);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 50202aed36d2..51304dcfe8cb 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -158,6 +158,7 @@ import com.android.internal.annotations.GuardedBy;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.os.IResultReceiver;
import com.android.internal.os.SomeArgs;
+import com.android.internal.policy.DecorView;
import com.android.internal.policy.PhoneFallbackEventHandler;
import com.android.internal.util.Preconditions;
import com.android.internal.view.BaseSurfaceHolder;
@@ -2221,6 +2222,19 @@ public final class ViewRootImpl implements ViewParent,
Trace.traceEnd(Trace.TRACE_TAG_VIEW);
}
+ private boolean updateCaptionInsets() {
+ if (!(mView instanceof DecorView)) return false;
+ final int captionInsetsHeight = ((DecorView) mView).getCaptionInsetsHeight();
+ final Rect captionFrame = new Rect();
+ if (captionInsetsHeight != 0) {
+ captionFrame.set(mWinFrame.left, mWinFrame.top, mWinFrame.right,
+ mWinFrame.top + captionInsetsHeight);
+ }
+ if (mAttachInfo.mCaptionInsets.equals(captionFrame)) return false;
+ mAttachInfo.mCaptionInsets.set(captionFrame);
+ return true;
+ }
+
private boolean shouldDispatchCutout() {
return mWindowAttributes.layoutInDisplayCutoutMode
== LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS
@@ -2592,6 +2606,9 @@ public final class ViewRootImpl implements ViewParent,
mAttachInfo.mAlwaysConsumeSystemBars = mPendingAlwaysConsumeSystemBars;
dispatchApplyInsets = true;
}
+ if (updateCaptionInsets()) {
+ dispatchApplyInsets = true;
+ }
if (dispatchApplyInsets || mLastSystemUiVisibility !=
mAttachInfo.mSystemUiVisibility || mApplyInsetsRequested) {
mLastSystemUiVisibility = mAttachInfo.mSystemUiVisibility;
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 0c5c18316e61..ae9afabad533 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -49,9 +49,6 @@ import android.transition.Transition;
import android.transition.TransitionManager;
import android.util.Pair;
import android.view.View.OnApplyWindowInsetsListener;
-import android.view.ViewGroup.LayoutParams;
-import android.view.WindowInsets.Side.InsetsSide;
-import android.view.WindowInsets.Type.InsetsType;
import android.view.accessibility.AccessibilityEvent;
import java.util.Collections;
@@ -323,7 +320,7 @@ public abstract class Window {
@UnsupportedAppUsage
private boolean mDestroyed;
- private boolean mOverlayWithDecorCaptionEnabled = false;
+ private boolean mOverlayWithDecorCaptionEnabled = true;
private boolean mCloseOnSwipeEnabled = false;
// The current window attributes.
diff --git a/core/java/android/view/WindowInsets.java b/core/java/android/view/WindowInsets.java
index fde184ccfb0e..9b2a6cbce48f 100644
--- a/core/java/android/view/WindowInsets.java
+++ b/core/java/android/view/WindowInsets.java
@@ -17,6 +17,7 @@
package android.view;
+import static android.view.WindowInsets.Type.CAPTION_BAR;
import static android.view.WindowInsets.Type.DISPLAY_CUTOUT;
import static android.view.WindowInsets.Type.FIRST;
import static android.view.WindowInsets.Type.IME;
diff --git a/core/java/android/view/WindowInsetsController.java b/core/java/android/view/WindowInsetsController.java
index 0282ecac8920..439223cf568b 100644
--- a/core/java/android/view/WindowInsetsController.java
+++ b/core/java/android/view/WindowInsetsController.java
@@ -196,6 +196,15 @@ public interface WindowInsetsController {
@Appearance int getSystemBarsAppearance();
/**
+ * Notify the caption insets height change. The information will be used on the client side to,
+ * make sure the InsetsState has the correct caption insets.
+ *
+ * @param height the height of caption bar insets.
+ * @hide
+ */
+ void setCaptionInsetsHeight(int height);
+
+ /**
* Controls the behavior of system bars.
*
* @param behavior Determines how the bars behave when being hidden by the application.
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 51b73fc674e7..d2508f3616e4 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -78,7 +78,6 @@ import android.view.ContextThemeWrapper;
import android.view.Gravity;
import android.view.InputQueue;
import android.view.InsetsState;
-import android.view.InsetsController;
import android.view.InsetsState.InternalInsetsType;
import android.view.KeyEvent;
import android.view.KeyboardShortcutGroup;
@@ -1174,6 +1173,12 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
false /* matchVertical */, statusBarNeedsLeftInset, statusBarSideInset,
animate && !disallowAnimate,
mForceWindowDrawsBarBackgrounds, state);
+
+ if (mHasCaption) {
+ final int captionColor = calculateStatusBarColor();
+ mDecorCaptionView.getCaption().setBackgroundColor(captionColor);
+ updateDecorCaptionShade();
+ }
}
// When we expand the window with FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS or
@@ -1355,7 +1360,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
: state.attributes.isPresent(insetsState, mWindow.getAttributes().flags, force);
boolean show = state.attributes.isVisible(state.present, color,
mWindow.getAttributes().flags, force);
- boolean showView = show && !isResizing() && size > 0;
+ boolean showView = show && !isResizing() && !mHasCaption && size > 0;
boolean visibilityChanged = false;
View view = state.view;
@@ -2021,6 +2026,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
if (getForeground() != null) {
drawableChanged();
}
+ getWindowInsetsController().setCaptionInsetsHeight(getCaptionInsetsHeight());
}
}
@@ -2094,6 +2100,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
mDecorCaptionView.onConfigurationChanged(displayWindowDecor);
enableCaption(displayWindowDecor);
}
+ getWindowInsetsController().setCaptionInsetsHeight(getCaptionInsetsHeight());
}
void onResourcesLoaded(LayoutInflater inflater, int layoutResource) {
@@ -2182,11 +2189,11 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
inflater = inflater.from(context);
final DecorCaptionView view = (DecorCaptionView) inflater.inflate(R.layout.decor_caption,
null);
- setDecorCaptionShade(context, view);
+ setDecorCaptionShade(view);
return view;
}
- private void setDecorCaptionShade(Context context, DecorCaptionView view) {
+ private void setDecorCaptionShade(DecorCaptionView view) {
final int shade = mWindow.getDecorCaptionShade();
switch (shade) {
case DECOR_CAPTION_SHADE_LIGHT:
@@ -2196,15 +2203,10 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
setDarkDecorCaptionShade(view);
break;
default: {
- TypedValue value = new TypedValue();
- context.getTheme().resolveAttribute(R.attr.colorPrimary, value, true);
- // We invert the shade depending on brightness of the theme. Dark shade for light
- // theme and vice versa. Thanks to this the buttons should be visible on the
- // background.
- if (Color.luminance(value.data) < 0.5) {
- setLightDecorCaptionShade(view);
- } else {
+ if ((getWindowSystemUiVisibility() & SYSTEM_UI_FLAG_LIGHT_STATUS_BAR) != 0) {
setDarkDecorCaptionShade(view);
+ } else {
+ setLightDecorCaptionShade(view);
}
break;
}
@@ -2213,7 +2215,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
void updateDecorCaptionShade() {
if (mDecorCaptionView != null) {
- setDecorCaptionShade(getContext(), mDecorCaptionView);
+ setDecorCaptionShade(mDecorCaptionView);
}
}
@@ -2484,6 +2486,15 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
}
/**
+ * @hide
+ * @return the height of insets covering the top of window content area.
+ */
+ public int getCaptionInsetsHeight() {
+ if (!mWindow.isOverlayWithDecorCaptionEnabled()) return 0;
+ return getCaptionHeight();
+ }
+
+ /**
* Converts a DIP measure into physical pixels.
* @param dip The dip value.
* @return Returns the number of pixels.
diff --git a/core/java/com/android/internal/widget/DecorCaptionView.java b/core/java/com/android/internal/widget/DecorCaptionView.java
index b5d787c24fbd..7a01024ffc36 100644
--- a/core/java/com/android/internal/widget/DecorCaptionView.java
+++ b/core/java/com/android/internal/widget/DecorCaptionView.java
@@ -17,7 +17,6 @@
package com.android.internal.widget;
import android.content.Context;
-import android.graphics.Color;
import android.graphics.Rect;
import android.os.RemoteException;
import android.util.AttributeSet;
@@ -53,8 +52,7 @@ import java.util.ArrayList;
* <li>..</li>
* </ul>
*
- * Although this ViewGroup has only two direct sub-Views, its behavior is more complex due to
- * overlaying caption on the content and drawing.
+ * Here describe the behavior of overlaying caption on the content and drawing.
*
* First, no matter where the content View gets added, it will always be the first child and the
* caption will be the second. This way the caption will always be drawn on top of the content when
@@ -66,11 +64,9 @@ import java.util.ArrayList;
* <li>DecorCaptionView.onInterceptTouchEvent() will try intercepting the touch events if the
* down action is performed on top close or maximize buttons; the reason for that is we want these
* buttons to always work.</li>
- * <li>The content View will receive the touch event. Mind that content is actually underneath the
- * caption, so we need to introduce our own dispatch ordering. We achieve this by overriding
- * {@link #buildTouchDispatchChildList()}.</li>
- * <li>If the touch event is not consumed by the content View, it will go to the caption View
- * and the dragging logic will be executed.</li>
+ * <li>The caption view will try to consume the event to apply the dragging logic.</li>
+ * <li>If the touch event is not consumed by the caption, the content View will receive the touch
+ * event</li>
* </ul>
*/
public class DecorCaptionView extends ViewGroup implements View.OnTouchListener,
@@ -137,11 +133,6 @@ public class DecorCaptionView extends ViewGroup implements View.OnTouchListener,
mOwner = owner;
mShow = show;
mOverlayWithAppContent = owner.isOverlayWithDecorCaptionEnabled();
- if (mOverlayWithAppContent) {
- // The caption is covering the content, so we make its background transparent to make
- // the content visible.
- mCaption.setBackgroundColor(Color.TRANSPARENT);
- }
updateCaptionVisibility();
// By changing the outline provider to BOUNDS, the window can remove its
// background without removing the shadow.
@@ -236,18 +227,6 @@ public class DecorCaptionView extends ViewGroup implements View.OnTouchListener,
}
@Override
- public ArrayList<View> buildTouchDispatchChildList() {
- mTouchDispatchList.ensureCapacity(3);
- if (mCaption != null) {
- mTouchDispatchList.add(mCaption);
- }
- if (mContent != null) {
- mTouchDispatchList.add(mContent);
- }
- return mTouchDispatchList;
- }
-
- @Override
public boolean shouldDelayChildPressedState() {
return false;
}
diff --git a/core/tests/coretests/src/android/view/InsetsControllerTest.java b/core/tests/coretests/src/android/view/InsetsControllerTest.java
index efdb51dcdfa9..cbb379bf8207 100644
--- a/core/tests/coretests/src/android/view/InsetsControllerTest.java
+++ b/core/tests/coretests/src/android/view/InsetsControllerTest.java
@@ -21,6 +21,7 @@ import static android.view.InsetsController.ANIMATION_TYPE_NONE;
import static android.view.InsetsController.ANIMATION_TYPE_SHOW;
import static android.view.InsetsSourceConsumer.ShowResult.IME_SHOW_DELAYED;
import static android.view.InsetsSourceConsumer.ShowResult.SHOW_IMMEDIATELY;
+import static android.view.InsetsState.ITYPE_CAPTION_BAR;
import static android.view.InsetsState.ITYPE_IME;
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
import static android.view.InsetsState.ITYPE_STATUS_BAR;
@@ -88,7 +89,6 @@ import java.util.concurrent.CountDownLatch;
@Presubmit
@RunWith(AndroidJUnit4.class)
public class InsetsControllerTest {
-
private InsetsController mController;
private SurfaceSession mSession = new SurfaceSession();
private SurfaceControl mLeash;
@@ -665,6 +665,26 @@ public class InsetsControllerTest {
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
}
+ @Test
+ public void testCaptionInsetsStateAssemble() {
+ InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
+ mController.onFrameChanged(new Rect(0, 0, 100, 300));
+ final InsetsState state = new InsetsState(mController.getState(), true);
+ final Rect captionFrame = new Rect(0, 0, 100, 100);
+ mController.setCaptionInsetsHeight(100);
+ mController.onStateChanged(state);
+ final InsetsState currentState = new InsetsState(mController.getState());
+ // The caption bar source should be synced with the info in mAttachInfo.
+ assertEquals(captionFrame, currentState.peekSource(ITYPE_CAPTION_BAR).getFrame());
+ assertTrue(currentState.equals(state, true /* excludingCaptionInsets*/));
+ mController.setCaptionInsetsHeight(0);
+ mController.onStateChanged(state);
+ // The caption bar source should not be there at all, because we don't add empty
+ // caption to the state from the server.
+ assertNull(mController.getState().peekSource(ITYPE_CAPTION_BAR));
+ });
+ }
+
private void waitUntilNextFrame() throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
Choreographer.getMainThreadInstance().postCallback(Choreographer.CALLBACK_COMMIT,
diff --git a/core/tests/coretests/src/android/view/InsetsStateTest.java b/core/tests/coretests/src/android/view/InsetsStateTest.java
index 721dc98ff4d1..2884777fc997 100644
--- a/core/tests/coretests/src/android/view/InsetsStateTest.java
+++ b/core/tests/coretests/src/android/view/InsetsStateTest.java
@@ -153,6 +153,35 @@ public class InsetsStateTest {
}
}
+
+ @Test
+ public void testCalculateInsets_captionStatusBarOverlap() throws Exception {
+ try (InsetsModeSession session =
+ new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
+ mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));
+ mState.getSource(ITYPE_STATUS_BAR).setVisible(true);
+ mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(0, 0, 100, 300));
+ mState.getSource(ITYPE_CAPTION_BAR).setVisible(true);
+
+ Rect visibleInsets = mState.calculateVisibleInsets(
+ new Rect(0, 0, 100, 400), SOFT_INPUT_ADJUST_NOTHING);
+ assertEquals(new Rect(0, 300, 0, 0), visibleInsets);
+ }
+ }
+
+ @Test
+ public void testCalculateInsets_captionBarOffset() throws Exception {
+ try (InsetsModeSession session =
+ new InsetsModeSession(ViewRootImpl.NEW_INSETS_MODE_FULL)) {
+ mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(0, 0, 100, 300));
+ mState.getSource(ITYPE_CAPTION_BAR).setVisible(true);
+
+ Rect visibleInsets = mState.calculateVisibleInsets(
+ new Rect(0, 0, 150, 400), SOFT_INPUT_ADJUST_NOTHING);
+ assertEquals(new Rect(0, 300, 0, 0), visibleInsets);
+ }
+ }
+
@Test
public void testStripForDispatch() {
mState.getSource(ITYPE_STATUS_BAR).setFrame(new Rect(0, 0, 100, 100));