Merge "Create a general mapping between window types and inset types." into rvc-dev am: e88d949e0a
Change-Id: I9d40f6e4035f8cfa07de512f1327722e93c04302
This commit is contained in:
@@ -89,6 +89,7 @@ import android.view.accessibility.AccessibilityNodeInfo;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -2895,6 +2896,18 @@ public interface WindowManager extends ViewManager {
|
||||
|
||||
private boolean mFitInsetsIgnoringVisibility = false;
|
||||
|
||||
/**
|
||||
* {@link InsetsState.InternalInsetsType}s to be applied to the window
|
||||
* If {@link #type} has the predefined insets (like {@link #TYPE_STATUS_BAR} or
|
||||
* {@link #TYPE_NAVIGATION_BAR}), this field will be ignored.
|
||||
*
|
||||
* <p>Note: provide only one inset corresponding to the window type (like
|
||||
* {@link InsetsState.InternalInsetsType#ITYPE_STATUS_BAR} or
|
||||
* {@link InsetsState.InternalInsetsType#ITYPE_NAVIGATION_BAR})</p>
|
||||
* @hide
|
||||
*/
|
||||
public @InsetsState.InternalInsetsType int[] providesInsetsTypes;
|
||||
|
||||
/**
|
||||
* Specifies types of insets that this window should avoid overlapping during layout.
|
||||
*
|
||||
@@ -3116,6 +3129,12 @@ public interface WindowManager extends ViewManager {
|
||||
out.writeInt(mFitInsetsSides);
|
||||
out.writeBoolean(mFitInsetsIgnoringVisibility);
|
||||
out.writeBoolean(preferMinimalPostProcessing);
|
||||
if (providesInsetsTypes != null) {
|
||||
out.writeInt(providesInsetsTypes.length);
|
||||
out.writeIntArray(providesInsetsTypes);
|
||||
} else {
|
||||
out.writeInt(0);
|
||||
}
|
||||
}
|
||||
|
||||
public static final @android.annotation.NonNull Parcelable.Creator<LayoutParams> CREATOR
|
||||
@@ -3177,6 +3196,11 @@ public interface WindowManager extends ViewManager {
|
||||
mFitInsetsSides = in.readInt();
|
||||
mFitInsetsIgnoringVisibility = in.readBoolean();
|
||||
preferMinimalPostProcessing = in.readBoolean();
|
||||
int insetsTypesLength = in.readInt();
|
||||
if (insetsTypesLength > 0) {
|
||||
providesInsetsTypes = new int[insetsTypesLength];
|
||||
in.readIntArray(providesInsetsTypes);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"PointlessBitwiseExpression"})
|
||||
@@ -3437,6 +3461,11 @@ public interface WindowManager extends ViewManager {
|
||||
changes |= LAYOUT_CHANGED;
|
||||
}
|
||||
|
||||
if (!Arrays.equals(providesInsetsTypes, o.providesInsetsTypes)) {
|
||||
providesInsetsTypes = o.providesInsetsTypes;
|
||||
changes |= LAYOUT_CHANGED;
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
||||
@@ -3609,6 +3638,14 @@ public interface WindowManager extends ViewManager {
|
||||
sb.append(System.lineSeparator());
|
||||
sb.append(prefix).append(" fitIgnoreVis");
|
||||
}
|
||||
if (providesInsetsTypes != null) {
|
||||
sb.append(System.lineSeparator());
|
||||
sb.append(prefix).append(" insetsTypes=");
|
||||
for (int i = 0; i < providesInsetsTypes.length; ++i) {
|
||||
if (i > 0) sb.append(' ');
|
||||
sb.append(InsetsState.typeToString(providesInsetsTypes[i]));
|
||||
}
|
||||
}
|
||||
|
||||
sb.append('}');
|
||||
return sb.toString();
|
||||
|
||||
@@ -28,6 +28,7 @@ import static android.view.Display.TYPE_INTERNAL;
|
||||
import static android.view.InsetsState.ITYPE_BOTTOM_DISPLAY_CUTOUT;
|
||||
import static android.view.InsetsState.ITYPE_BOTTOM_GESTURES;
|
||||
import static android.view.InsetsState.ITYPE_BOTTOM_TAPPABLE_ELEMENT;
|
||||
import static android.view.InsetsState.ITYPE_CAPTION_BAR;
|
||||
import static android.view.InsetsState.ITYPE_IME;
|
||||
import static android.view.InsetsState.ITYPE_LEFT_DISPLAY_CUTOUT;
|
||||
import static android.view.InsetsState.ITYPE_LEFT_GESTURES;
|
||||
@@ -1024,6 +1025,13 @@ public class DisplayPolicy {
|
||||
case TYPE_STATUS_BAR_PANEL:
|
||||
return WindowManagerGlobal.ADD_INVALID_TYPE;
|
||||
}
|
||||
|
||||
if (attrs.providesInsetsTypes != null) {
|
||||
mContext.enforcePermission(
|
||||
android.Manifest.permission.STATUS_BAR_SERVICE, callingPid, callingUid,
|
||||
"DisplayPolicy");
|
||||
enforceSingleInsetsTypeCorrespondingToWindowType(attrs.providesInsetsTypes);
|
||||
}
|
||||
return ADD_OKAY;
|
||||
}
|
||||
|
||||
@@ -1110,6 +1118,28 @@ public class DisplayPolicy {
|
||||
});
|
||||
if (DEBUG_LAYOUT) Slog.i(TAG, "NAVIGATION BAR: " + mNavigationBar);
|
||||
break;
|
||||
default:
|
||||
if (attrs.providesInsetsTypes != null) {
|
||||
for (int insetsType : attrs.providesInsetsTypes) {
|
||||
mDisplayContent.setInsetProvider(insetsType, win, null);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void enforceSingleInsetsTypeCorrespondingToWindowType(int[] insetsTypes) {
|
||||
int count = 0;
|
||||
for (int insetsType : insetsTypes) {
|
||||
switch (insetsType) {
|
||||
case ITYPE_NAVIGATION_BAR:
|
||||
case ITYPE_STATUS_BAR:
|
||||
case ITYPE_CAPTION_BAR:
|
||||
if (++count > 1) {
|
||||
throw new IllegalArgumentException(
|
||||
"Multiple InsetsTypes corresponding to Window type");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ android_test {
|
||||
"mockito-target-extended-minus-junit4",
|
||||
"platform-test-annotations",
|
||||
"servicestests-utils",
|
||||
"testng",
|
||||
"truth-prebuilt",
|
||||
"testables",
|
||||
"ub-uiautomator",
|
||||
|
||||
@@ -20,6 +20,9 @@ import static android.view.Gravity.BOTTOM;
|
||||
import static android.view.Gravity.LEFT;
|
||||
import static android.view.Gravity.RIGHT;
|
||||
import static android.view.Gravity.TOP;
|
||||
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
|
||||
import static android.view.InsetsState.ITYPE_STATUS_BAR;
|
||||
import static android.view.InsetsState.ITYPE_TOP_GESTURES;
|
||||
import static android.view.Surface.ROTATION_0;
|
||||
import static android.view.Surface.ROTATION_270;
|
||||
import static android.view.Surface.ROTATION_90;
|
||||
@@ -42,13 +45,17 @@ import static android.view.WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
import static org.mockito.Mockito.doNothing;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.testng.Assert.expectThrows;
|
||||
|
||||
import android.app.WindowConfiguration;
|
||||
import android.graphics.Insets;
|
||||
@@ -153,6 +160,56 @@ public class DisplayPolicyLayoutTests extends DisplayPolicyTestsBase {
|
||||
assertEquals(0, mWindow.mAttrs.subtreeSystemUiVisibility);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addingWindow_withInsetsTypes() {
|
||||
WindowState win = createWindow(null, TYPE_STATUS_BAR_SUB_PANEL, "StatusBarSubPanel");
|
||||
win.mAttrs.providesInsetsTypes = new int[]{ITYPE_STATUS_BAR, ITYPE_TOP_GESTURES};
|
||||
win.getFrameLw().set(0, 0, 500, 100);
|
||||
|
||||
addWindow(win);
|
||||
InsetsStateController controller = mDisplayContent.getInsetsStateController();
|
||||
controller.onPostLayout();
|
||||
|
||||
InsetsSourceProvider statusBarProvider = controller.getSourceProvider(ITYPE_STATUS_BAR);
|
||||
assertEquals(new Rect(0, 0, 500, 100), statusBarProvider.getSource().getFrame());
|
||||
assertEquals(Insets.of(0, 100, 0, 0),
|
||||
statusBarProvider.getSource().calculateInsets(new Rect(0, 0, 500, 500),
|
||||
false /* ignoreVisibility */));
|
||||
|
||||
InsetsSourceProvider topGesturesProvider = controller.getSourceProvider(ITYPE_TOP_GESTURES);
|
||||
assertEquals(new Rect(0, 0, 500, 100), topGesturesProvider.getSource().getFrame());
|
||||
assertEquals(Insets.of(0, 100, 0, 0),
|
||||
topGesturesProvider.getSource().calculateInsets(new Rect(0, 0, 500, 500),
|
||||
false /* ignoreVisibility */));
|
||||
|
||||
InsetsSourceProvider navigationBarProvider = controller.getSourceProvider(
|
||||
ITYPE_NAVIGATION_BAR);
|
||||
assertNotEquals(new Rect(0, 0, 500, 100), navigationBarProvider.getSource().getFrame());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addingWindow_ignoresInsetsTypes_InWindowTypeWithPredefinedInsets() {
|
||||
mDisplayPolicy.removeWindowLw(mStatusBarWindow); // Removes the existing one.
|
||||
WindowState win = createWindow(null, TYPE_STATUS_BAR, "StatusBar");
|
||||
win.mAttrs.providesInsetsTypes = new int[]{ITYPE_STATUS_BAR};
|
||||
win.getFrameLw().set(0, 0, 500, 100);
|
||||
|
||||
addWindow(win);
|
||||
mDisplayContent.getInsetsStateController().onPostLayout();
|
||||
|
||||
InsetsSourceProvider provider =
|
||||
mDisplayContent.getInsetsStateController().getSourceProvider(ITYPE_STATUS_BAR);
|
||||
assertNotEquals(new Rect(0, 0, 500, 100), provider.getSource().getFrame());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addingWindow_throwsException_WithMultipleInsetTypes() {
|
||||
WindowState win = createWindow(null, TYPE_STATUS_BAR_SUB_PANEL, "StatusBarSubPanel");
|
||||
win.mAttrs.providesInsetsTypes = new int[]{ITYPE_STATUS_BAR, ITYPE_NAVIGATION_BAR};
|
||||
|
||||
expectThrows(IllegalArgumentException.class, () -> addWindow(win));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void layoutWindowLw_fitStatusBars() {
|
||||
assumeTrue(ViewRootImpl.sNewInsetsMode == ViewRootImpl.NEW_INSETS_MODE_FULL);
|
||||
|
||||
Reference in New Issue
Block a user