Fixed cts failure of WindowInsetsControllerTests
If the device is a tablet, the navigation bar will be taskbar, and it will draw fake rounded corners above itself when it's shown and unstashed. When apps request to hide taskbar from such state, it will cause an extra window insets change from server side. Move the calculation of rounded corner inset to client side so that we can make the window insets change come only once. Bug: 229825307 Test: atest WindowInsetsControllerTests ActivityRecordTests Change-Id: I081142facbe0fe676b89c8883fa690ba5ae13d79
This commit is contained in:
@@ -47,6 +47,7 @@ public class InsetsSource implements Parcelable {
|
||||
private final Rect mFrame;
|
||||
private @Nullable Rect mVisibleFrame;
|
||||
private boolean mVisible;
|
||||
private boolean mInsetsRoundedCornerFrame;
|
||||
|
||||
private final Rect mTmpFrame = new Rect();
|
||||
|
||||
@@ -63,6 +64,7 @@ public class InsetsSource implements Parcelable {
|
||||
mVisibleFrame = other.mVisibleFrame != null
|
||||
? new Rect(other.mVisibleFrame)
|
||||
: null;
|
||||
mInsetsRoundedCornerFrame = other.mInsetsRoundedCornerFrame;
|
||||
}
|
||||
|
||||
public void set(InsetsSource other) {
|
||||
@@ -71,6 +73,7 @@ public class InsetsSource implements Parcelable {
|
||||
mVisibleFrame = other.mVisibleFrame != null
|
||||
? new Rect(other.mVisibleFrame)
|
||||
: null;
|
||||
mInsetsRoundedCornerFrame = other.mInsetsRoundedCornerFrame;
|
||||
}
|
||||
|
||||
public void setFrame(int left, int top, int right, int bottom) {
|
||||
@@ -110,6 +113,14 @@ public class InsetsSource implements Parcelable {
|
||||
return mVisibleFrame == null || !mVisibleFrame.isEmpty();
|
||||
}
|
||||
|
||||
public boolean getInsetsRoundedCornerFrame() {
|
||||
return mInsetsRoundedCornerFrame;
|
||||
}
|
||||
|
||||
public void setInsetsRoundedCornerFrame(boolean insetsRoundedCornerFrame) {
|
||||
mInsetsRoundedCornerFrame = insetsRoundedCornerFrame;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the insets this source will cause to a client window.
|
||||
*
|
||||
@@ -225,6 +236,7 @@ public class InsetsSource implements Parcelable {
|
||||
pw.print(" visibleFrame="); pw.print(mVisibleFrame.toShortString());
|
||||
}
|
||||
pw.print(" visible="); pw.print(mVisible);
|
||||
pw.print(" insetsRoundedCornerFrame="); pw.print(mInsetsRoundedCornerFrame);
|
||||
pw.println();
|
||||
}
|
||||
|
||||
@@ -247,6 +259,7 @@ public class InsetsSource implements Parcelable {
|
||||
if (mVisible != that.mVisible) return false;
|
||||
if (excludeInvisibleImeFrames && !mVisible && mType == ITYPE_IME) return true;
|
||||
if (!Objects.equals(mVisibleFrame, that.mVisibleFrame)) return false;
|
||||
if (mInsetsRoundedCornerFrame != that.mInsetsRoundedCornerFrame) return false;
|
||||
return mFrame.equals(that.mFrame);
|
||||
}
|
||||
|
||||
@@ -256,6 +269,7 @@ public class InsetsSource implements Parcelable {
|
||||
result = 31 * result + mFrame.hashCode();
|
||||
result = 31 * result + (mVisibleFrame != null ? mVisibleFrame.hashCode() : 0);
|
||||
result = 31 * result + (mVisible ? 1 : 0);
|
||||
result = 31 * result + (mInsetsRoundedCornerFrame ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -268,6 +282,7 @@ public class InsetsSource implements Parcelable {
|
||||
mVisibleFrame = null;
|
||||
}
|
||||
mVisible = in.readBoolean();
|
||||
mInsetsRoundedCornerFrame = in.readBoolean();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -286,6 +301,7 @@ public class InsetsSource implements Parcelable {
|
||||
dest.writeInt(0);
|
||||
}
|
||||
dest.writeBoolean(mVisible);
|
||||
dest.writeBoolean(mInsetsRoundedCornerFrame);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -294,6 +310,7 @@ public class InsetsSource implements Parcelable {
|
||||
+ "mType=" + InsetsState.typeToString(mType)
|
||||
+ ", mFrame=" + mFrame.toShortString()
|
||||
+ ", mVisible=" + mVisible
|
||||
+ ", mInsetsRoundedCornerFrame=" + mInsetsRoundedCornerFrame
|
||||
+ "}";
|
||||
}
|
||||
|
||||
|
||||
@@ -294,9 +294,16 @@ public class InsetsState implements Parcelable {
|
||||
return RoundedCorners.NO_ROUNDED_CORNERS;
|
||||
}
|
||||
// If mRoundedCornerFrame is set, we should calculate the new RoundedCorners based on this
|
||||
// frame. It's used for split-screen mode and devices with a task bar.
|
||||
if (!mRoundedCornerFrame.isEmpty() && !mRoundedCornerFrame.equals(mDisplayFrame)) {
|
||||
return mRoundedCorners.insetWithFrame(frame, mRoundedCornerFrame);
|
||||
// frame.
|
||||
final Rect roundedCornerFrame = new Rect(mRoundedCornerFrame);
|
||||
for (InsetsSource source : mSources) {
|
||||
if (source != null && source.getInsetsRoundedCornerFrame()) {
|
||||
final Insets insets = source.calculateInsets(roundedCornerFrame, false);
|
||||
roundedCornerFrame.inset(insets);
|
||||
}
|
||||
}
|
||||
if (!roundedCornerFrame.isEmpty() && !roundedCornerFrame.equals(mDisplayFrame)) {
|
||||
return mRoundedCorners.insetWithFrame(frame, roundedCornerFrame);
|
||||
}
|
||||
if (mDisplayFrame.equals(frame)) {
|
||||
return mRoundedCorners;
|
||||
|
||||
@@ -300,10 +300,6 @@ public class DisplayPolicy {
|
||||
// needs to be opaque.
|
||||
private WindowState mNavBarBackgroundWindow;
|
||||
|
||||
// The window that draws fake rounded corners and should provide insets to calculate the correct
|
||||
// rounded corner insets.
|
||||
private WindowState mRoundedCornerWindow;
|
||||
|
||||
/**
|
||||
* A collection of {@link AppearanceRegion} to indicate that which region of status bar applies
|
||||
* which appearance.
|
||||
@@ -970,16 +966,10 @@ public class DisplayPolicy {
|
||||
mExtraNavBarAltPosition = getAltBarPosition(attrs);
|
||||
}
|
||||
|
||||
if (attrs.insetsRoundedCornerFrame) {
|
||||
// Currently, only support one rounded corner window which is the TaskBar.
|
||||
if (mRoundedCornerWindow != null && mRoundedCornerWindow != win) {
|
||||
throw new IllegalArgumentException("Found multiple rounded corner window :"
|
||||
+ " current = " + mRoundedCornerWindow
|
||||
+ " new = " + win);
|
||||
}
|
||||
mRoundedCornerWindow = win;
|
||||
} else if (mRoundedCornerWindow == win) {
|
||||
mRoundedCornerWindow = null;
|
||||
final InsetsSourceProvider provider = win.getControllableInsetProvider();
|
||||
if (provider != null && provider.getSource().getInsetsRoundedCornerFrame()
|
||||
!= attrs.insetsRoundedCornerFrame) {
|
||||
provider.getSource().setInsetsRoundedCornerFrame(attrs.insetsRoundedCornerFrame);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1326,9 +1316,6 @@ public class DisplayPolicy {
|
||||
if (mLastFocusedWindow == win) {
|
||||
mLastFocusedWindow = null;
|
||||
}
|
||||
if (mRoundedCornerWindow == win) {
|
||||
mRoundedCornerWindow = null;
|
||||
}
|
||||
|
||||
mInsetsSourceWindowsExceptIme.remove(win);
|
||||
}
|
||||
@@ -1360,10 +1347,6 @@ public class DisplayPolicy {
|
||||
return mNavigationBar != null ? mNavigationBar : mNavigationBarAlt;
|
||||
}
|
||||
|
||||
WindowState getRoundedCornerWindow() {
|
||||
return mRoundedCornerWindow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Control the animation to run when a window's state changes. Return a positive number to
|
||||
* force the animation to a specific resource ID, {@link #ANIMATION_STYLEABLE} to use the
|
||||
|
||||
@@ -46,7 +46,6 @@ import android.annotation.Nullable;
|
||||
import android.app.ActivityTaskManager;
|
||||
import android.app.StatusBarManager;
|
||||
import android.app.WindowConfiguration;
|
||||
import android.graphics.Insets;
|
||||
import android.graphics.Rect;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.IntArray;
|
||||
@@ -461,22 +460,10 @@ class InsetsPolicy {
|
||||
|
||||
private InsetsState adjustInsetsForRoundedCorners(WindowState w, InsetsState originalState,
|
||||
boolean copyState) {
|
||||
final WindowState roundedCornerWindow = mPolicy.getRoundedCornerWindow();
|
||||
final Task task = w.getTask();
|
||||
if (task != null && !task.getWindowConfiguration().tasksAreFloating()
|
||||
&& (roundedCornerWindow != null || task.inSplitScreen())) {
|
||||
// Instead of using display frame to calculating rounded corner, for the fake rounded
|
||||
// corners drawn by divider bar or task bar, we need to re-calculate rounded corners
|
||||
// based on task bounds and if the task bounds is intersected with task bar, we should
|
||||
// exclude the intersected part.
|
||||
if (task != null && !task.getWindowConfiguration().tasksAreFloating()) {
|
||||
// Use task bounds to calculating rounded corners if the task is not floating.
|
||||
final Rect roundedCornerFrame = new Rect(task.getBounds());
|
||||
if (roundedCornerWindow != null
|
||||
&& roundedCornerWindow.getControllableInsetProvider() != null) {
|
||||
final InsetsSource source =
|
||||
roundedCornerWindow.getControllableInsetProvider().getSource();
|
||||
final Insets insets = source.calculateInsets(roundedCornerFrame, false);
|
||||
roundedCornerFrame.inset(insets);
|
||||
}
|
||||
final InsetsState state = copyState ? new InsetsState(originalState) : originalState;
|
||||
state.setRoundedCornerFrame(roundedCornerFrame);
|
||||
return state;
|
||||
|
||||
@@ -170,6 +170,7 @@ abstract class InsetsSourceProvider {
|
||||
if (windowContainer == null) {
|
||||
setServerVisible(false);
|
||||
mSource.setVisibleFrame(null);
|
||||
mSource.setInsetsRoundedCornerFrame(false);
|
||||
mSourceFrame.setEmpty();
|
||||
} else {
|
||||
mWindowContainer.getProvidedInsetsSources().put(mSource.getType(), mSource);
|
||||
|
||||
@@ -3139,7 +3139,7 @@ public class ActivityRecordTests extends WindowTestsBase {
|
||||
final WindowState app = createWindow(null, TYPE_APPLICATION, "app");
|
||||
|
||||
InsetsSource imeSource = new InsetsSource(ITYPE_IME);
|
||||
app.getInsetsState().addSource(imeSource);
|
||||
app.mAboveInsetsState.addSource(imeSource);
|
||||
mDisplayContent.setImeLayeringTarget(app);
|
||||
mDisplayContent.updateImeInputAndControlTarget(app);
|
||||
|
||||
@@ -3156,10 +3156,12 @@ public class ActivityRecordTests extends WindowTestsBase {
|
||||
// Simulate app re-start input or turning screen off/on then unlocked by un-secure
|
||||
// keyguard to back to the app, expect IME insets is not frozen
|
||||
mDisplayContent.updateImeInputAndControlTarget(app);
|
||||
app.mActivityRecord.commitVisibility(true, false);
|
||||
assertFalse(app.mActivityRecord.mImeInsetsFrozenUntilStartInput);
|
||||
|
||||
imeSource.setVisible(true);
|
||||
imeSource.setFrame(new Rect(100, 400, 500, 500));
|
||||
app.getInsetsState().addSource(imeSource);
|
||||
app.getInsetsState().setSourceVisible(ITYPE_IME, true);
|
||||
app.mAboveInsetsState.addSource(imeSource);
|
||||
|
||||
// Verify when IME is visible and the app can receive the right IME insets from policy.
|
||||
makeWindowVisibleAndDrawn(app, mImeWindow);
|
||||
|
||||
Reference in New Issue
Block a user