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

Commit 32496424 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 SplitPresenterTest
Bug: 263565586
fixes: 275714114

Merged-In: Ibb826c25f072cdffd5b5adcd19571fe446d64f51
Change-Id: Ibb826c25f072cdffd5b5adcd19571fe446d64f51
parent 9ed16e1b
Loading
Loading
Loading
Loading
+48 −28
Original line number Diff line number Diff line
@@ -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,63 +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:"
                        + 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:"
@@ -749,6 +755,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) {
@@ -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;
+21 −0
Original line number Diff line number Diff line
@@ -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();