Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a296b769 authored by Charles Chen's avatar Charles Chen
Browse files

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 ActivityEmbeddingBoundsTests
          on device without foldingFeature
Test: atest SplitPresenterTest
Bug: 263565586
Change-Id: Ibb826c25f072cdffd5b5adcd19571fe446d64f51
parent 6745428b
Loading
Loading
Loading
Loading
+48 −29
Original line number Diff line number Diff line
@@ -710,24 +710,16 @@ 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();
        }
        final Rect bounds;
        switch (position) {
            case POSITION_START:
                bounds = getPrimaryBounds(taskConfiguration, computedSplitAttributes,
                        foldingFeature);
                bounds = getPrimaryBounds(taskConfiguration, splitAttributes, foldingFeature);
                break;
            case POSITION_END:
                bounds = getSecondaryBounds(taskConfiguration, computedSplitAttributes,
                        foldingFeature);
                bounds = getSecondaryBounds(taskConfiguration, splitAttributes, foldingFeature);
                break;
            case POSITION_FILL:
            default:
@@ -742,63 +734,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:"
                        + splitAttributes.getLayoutDirection());
                        + computedSplitAttributes.getLayoutDirection());
        }
    }

    @NonNull
    private Rect getSecondaryBounds(@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 getRightContainerBounds(taskConfiguration, splitAttributes, foldingFeature);
                return getRightContainerBounds(taskConfiguration, computedSplitAttributes,
                        foldingFeature);
            }
            case SplitAttributes.LayoutDirection.RIGHT_TO_LEFT: {
                return getLeftContainerBounds(taskConfiguration, splitAttributes, foldingFeature);
                return getLeftContainerBounds(taskConfiguration, computedSplitAttributes,
                        foldingFeature);
            }
            case SplitAttributes.LayoutDirection.LOCALE: {
                final boolean isLtr = taskConfiguration.getLayoutDirection()
                        == View.LAYOUT_DIRECTION_LTR;
                return isLtr
                        ? getRightContainerBounds(taskConfiguration, splitAttributes,
                        ? getRightContainerBounds(taskConfiguration, computedSplitAttributes,
                                foldingFeature)
                        : getLeftContainerBounds(taskConfiguration, splitAttributes,
                        : getLeftContainerBounds(taskConfiguration, computedSplitAttributes,
                                foldingFeature);
            }
            case SplitAttributes.LayoutDirection.TOP_TO_BOTTOM: {
                return getBottomContainerBounds(taskConfiguration, splitAttributes, foldingFeature);
                return getBottomContainerBounds(taskConfiguration, computedSplitAttributes,
                        foldingFeature);
            }
            case SplitAttributes.LayoutDirection.BOTTOM_TO_TOP: {
                return getTopContainerBounds(taskConfiguration, splitAttributes, foldingFeature);
                return getTopContainerBounds(taskConfiguration, computedSplitAttributes,
                        foldingFeature);
            }
            default:
                throw new IllegalArgumentException("Unknown layout direction:"
@@ -806,6 +811,19 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
        }
    }

    /**
     * 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
    private Rect getLeftContainerBounds(@NonNull Configuration taskConfiguration,
            @NonNull SplitAttributes splitAttributes, @Nullable FoldingFeature foldingFeature) {
@@ -898,7 +916,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;
+21 −0
Original line number Diff line number Diff line
@@ -729,6 +729,27 @@ public class SplitPresenterTest {
                splitPairRule, SPLIT_ATTRIBUTES, 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 = getTaskProperties();
        doReturn(null).when(mPresenter).getFoldingFeature(any());

        assertEquals(hingeSplitAttrs, mPresenter.computeSplitAttributes(taskProperties,
                splitPairRule, hingeSplitAttrs, null /* minDimensionsPair */));
    }

    @Test
    public void testGetTaskWindowMetrics() {
        final Configuration taskConfig = new Configuration();