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:
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user