Fix NPE when using hinge split type without FoldingFeature
Before this CL, we only compute SplitType in getRelBounds.
However, we actually obtain the bounds to check minimum
dimensions in #computeSplitAttributes.
This CL moves the splitType calculation to
#getPrimaryBounds and #getSecondaryBounds to cover the
minimum dimensions to fix NPE.
Test: atest SplitPresenterTest
Bug: 263565586
fixes: 275714114
Merged-In: Ibb826c25f072cdffd5b5adcd19571fe446d64f51
Change-Id: Ibb826c25f072cdffd5b5adcd19571fe446d64f51
diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
index 668a7d5..c23ac75 100644
--- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
+++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java
@@ -661,21 +661,14 @@
@NonNull SplitAttributes splitAttributes) {
final Configuration taskConfiguration = taskProperties.getConfiguration();
final FoldingFeature foldingFeature = getFoldingFeature(taskProperties);
- final SplitType splitType = computeSplitType(splitAttributes, taskConfiguration,
- foldingFeature);
- final SplitAttributes computedSplitAttributes = new SplitAttributes.Builder()
- .setSplitType(splitType)
- .setLayoutDirection(splitAttributes.getLayoutDirection())
- .build();
- if (!shouldShowSplit(computedSplitAttributes)) {
+ if (!shouldShowSplit(splitAttributes)) {
return new Rect();
}
switch (position) {
case POSITION_START:
- return getPrimaryBounds(taskConfiguration, computedSplitAttributes, foldingFeature);
+ return getPrimaryBounds(taskConfiguration, splitAttributes, foldingFeature);
case POSITION_END:
- return getSecondaryBounds(taskConfiguration, computedSplitAttributes,
- foldingFeature);
+ return getSecondaryBounds(taskConfiguration, splitAttributes, foldingFeature);
case POSITION_FILL:
default:
return new Rect();
@@ -685,29 +678,76 @@
@NonNull
private Rect getPrimaryBounds(@NonNull Configuration taskConfiguration,
@NonNull SplitAttributes splitAttributes, @Nullable FoldingFeature foldingFeature) {
- if (!shouldShowSplit(splitAttributes)) {
+ final SplitAttributes computedSplitAttributes = updateSplitAttributesType(splitAttributes,
+ computeSplitType(splitAttributes, taskConfiguration, foldingFeature));
+ if (!shouldShowSplit(computedSplitAttributes)) {
return new Rect();
}
- switch (splitAttributes.getLayoutDirection()) {
+ switch (computedSplitAttributes.getLayoutDirection()) {
case SplitAttributes.LayoutDirection.LEFT_TO_RIGHT: {
- return getLeftContainerBounds(taskConfiguration, splitAttributes, foldingFeature);
+ return getLeftContainerBounds(taskConfiguration, computedSplitAttributes,
+ foldingFeature);
}
case SplitAttributes.LayoutDirection.RIGHT_TO_LEFT: {
- return getRightContainerBounds(taskConfiguration, splitAttributes, foldingFeature);
+ return getRightContainerBounds(taskConfiguration, computedSplitAttributes,
+ foldingFeature);
}
case SplitAttributes.LayoutDirection.LOCALE: {
final boolean isLtr = taskConfiguration.getLayoutDirection()
== View.LAYOUT_DIRECTION_LTR;
return isLtr
- ? getLeftContainerBounds(taskConfiguration, splitAttributes, foldingFeature)
- : getRightContainerBounds(taskConfiguration, splitAttributes,
+ ? getLeftContainerBounds(taskConfiguration, computedSplitAttributes,
+ foldingFeature)
+ : getRightContainerBounds(taskConfiguration, computedSplitAttributes,
foldingFeature);
}
case SplitAttributes.LayoutDirection.TOP_TO_BOTTOM: {
- return getTopContainerBounds(taskConfiguration, splitAttributes, foldingFeature);
+ return getTopContainerBounds(taskConfiguration, computedSplitAttributes,
+ foldingFeature);
}
case SplitAttributes.LayoutDirection.BOTTOM_TO_TOP: {
- return getBottomContainerBounds(taskConfiguration, splitAttributes, foldingFeature);
+ return getBottomContainerBounds(taskConfiguration, computedSplitAttributes,
+ foldingFeature);
+ }
+ default:
+ throw new IllegalArgumentException("Unknown layout direction:"
+ + computedSplitAttributes.getLayoutDirection());
+ }
+ }
+
+ @NonNull
+ private Rect getSecondaryBounds(@NonNull Configuration taskConfiguration,
+ @NonNull SplitAttributes splitAttributes, @Nullable FoldingFeature foldingFeature) {
+ final SplitAttributes computedSplitAttributes = updateSplitAttributesType(splitAttributes,
+ computeSplitType(splitAttributes, taskConfiguration, foldingFeature));
+ if (!shouldShowSplit(computedSplitAttributes)) {
+ return new Rect();
+ }
+ switch (computedSplitAttributes.getLayoutDirection()) {
+ case SplitAttributes.LayoutDirection.LEFT_TO_RIGHT: {
+ return getRightContainerBounds(taskConfiguration, computedSplitAttributes,
+ foldingFeature);
+ }
+ case SplitAttributes.LayoutDirection.RIGHT_TO_LEFT: {
+ return getLeftContainerBounds(taskConfiguration, computedSplitAttributes,
+ foldingFeature);
+ }
+ case SplitAttributes.LayoutDirection.LOCALE: {
+ final boolean isLtr = taskConfiguration.getLayoutDirection()
+ == View.LAYOUT_DIRECTION_LTR;
+ return isLtr
+ ? getRightContainerBounds(taskConfiguration, computedSplitAttributes,
+ foldingFeature)
+ : getLeftContainerBounds(taskConfiguration, computedSplitAttributes,
+ foldingFeature);
+ }
+ case SplitAttributes.LayoutDirection.TOP_TO_BOTTOM: {
+ return getBottomContainerBounds(taskConfiguration, computedSplitAttributes,
+ foldingFeature);
+ }
+ case SplitAttributes.LayoutDirection.BOTTOM_TO_TOP: {
+ return getTopContainerBounds(taskConfiguration, computedSplitAttributes,
+ foldingFeature);
}
default:
throw new IllegalArgumentException("Unknown layout direction:"
@@ -715,38 +755,17 @@
}
}
- @NonNull
- private Rect getSecondaryBounds(@NonNull Configuration taskConfiguration,
- @NonNull SplitAttributes splitAttributes, @Nullable FoldingFeature foldingFeature) {
- if (!shouldShowSplit(splitAttributes)) {
- return new Rect();
- }
- switch (splitAttributes.getLayoutDirection()) {
- case SplitAttributes.LayoutDirection.LEFT_TO_RIGHT: {
- return getRightContainerBounds(taskConfiguration, splitAttributes, foldingFeature);
- }
- case SplitAttributes.LayoutDirection.RIGHT_TO_LEFT: {
- return getLeftContainerBounds(taskConfiguration, splitAttributes, foldingFeature);
- }
- case SplitAttributes.LayoutDirection.LOCALE: {
- final boolean isLtr = taskConfiguration.getLayoutDirection()
- == View.LAYOUT_DIRECTION_LTR;
- return isLtr
- ? getRightContainerBounds(taskConfiguration, splitAttributes,
- foldingFeature)
- : getLeftContainerBounds(taskConfiguration, splitAttributes,
- foldingFeature);
- }
- case SplitAttributes.LayoutDirection.TOP_TO_BOTTOM: {
- return getBottomContainerBounds(taskConfiguration, splitAttributes, foldingFeature);
- }
- case SplitAttributes.LayoutDirection.BOTTOM_TO_TOP: {
- return getTopContainerBounds(taskConfiguration, splitAttributes, foldingFeature);
- }
- default:
- throw new IllegalArgumentException("Unknown layout direction:"
- + splitAttributes.getLayoutDirection());
- }
+ /**
+ * Returns the {@link SplitAttributes} that update the {@link SplitType} to
+ * {@code splitTypeToUpdate}.
+ */
+ private static SplitAttributes updateSplitAttributesType(
+ @NonNull SplitAttributes splitAttributes, @NonNull SplitType splitTypeToUpdate) {
+ return new SplitAttributes.Builder()
+ .setSplitType(splitTypeToUpdate)
+ .setLayoutDirection(splitAttributes.getLayoutDirection())
+ .setAnimationBackgroundColor(splitAttributes.getAnimationBackgroundColor())
+ .build();
}
@NonNull
@@ -841,7 +860,8 @@
}
@Nullable
- private FoldingFeature getFoldingFeature(@NonNull TaskProperties taskProperties) {
+ @VisibleForTesting
+ FoldingFeature getFoldingFeature(@NonNull TaskProperties taskProperties) {
final int displayId = taskProperties.getDisplayId();
final WindowConfiguration windowConfiguration = taskProperties.getConfiguration()
.windowConfiguration;
diff --git a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
index a288fd6..d286d23 100644
--- a/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
+++ b/libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitPresenterTest.java
@@ -572,6 +572,27 @@
splitPairRule, null /* minDimensionsPair */));
}
+ @Test
+ public void testComputeSplitAttributesOnHingeSplitTypeOnDeviceWithoutFoldingFeature() {
+ final SplitAttributes hingeSplitAttrs = new SplitAttributes.Builder()
+ .setSplitType(new SplitAttributes.SplitType.HingeSplitType(
+ SplitAttributes.SplitType.RatioSplitType.splitEqually()))
+ .build();
+ final SplitPairRule splitPairRule = createSplitPairRuleBuilder(
+ activityPair -> true,
+ activityIntentPair -> true,
+ windowMetrics -> windowMetrics.getBounds().equals(TASK_BOUNDS))
+ .setFinishSecondaryWithPrimary(DEFAULT_FINISH_SECONDARY_WITH_PRIMARY)
+ .setFinishPrimaryWithSecondary(DEFAULT_FINISH_PRIMARY_WITH_SECONDARY)
+ .setDefaultSplitAttributes(hingeSplitAttrs)
+ .build();
+ final TaskContainer.TaskProperties taskProperties = getTaskProperty();
+ doReturn(null).when(mPresenter).getFoldingFeature(any());
+
+ assertEquals(hingeSplitAttrs, mPresenter.computeSplitAttributes(taskProperties,
+ splitPairRule, null /* minDimensionsPair */));
+ }
+
private Activity createMockActivity() {
final Activity activity = mock(Activity.class);
final Configuration activityConfig = new Configuration();