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
This commit is contained in:
Charles Chen
2023-03-29 19:20:25 +08:00
parent 9ed16e1bee
commit 3249642489
2 changed files with 92 additions and 51 deletions

View File

@@ -661,21 +661,14 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
@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 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
@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 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
}
}
@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 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
}
@Nullable
private FoldingFeature getFoldingFeature(@NonNull TaskProperties taskProperties) {
@VisibleForTesting
FoldingFeature getFoldingFeature(@NonNull TaskProperties taskProperties) {
final int displayId = taskProperties.getDisplayId();
final WindowConfiguration windowConfiguration = taskProperties.getConfiguration()
.windowConfiguration;

View File

@@ -572,6 +572,27 @@ public class SplitPresenterTest {
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();