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

Commit b67f7cd3 authored by Coco Duan's avatar Coco Duan Committed by Android (Google) Code Review
Browse files

Merge changes from topic "dream-complication-layout-spacing" into main

* changes:
  Update complication layout engine to be responsive
  Provide responsive layoutParams for clock time complication
  Wrap call to updateLayoutEngine with dreamsV2 flag
parents 3c8ec943 2546ce3d
Loading
Loading
Loading
Loading
+26 −2
Original line number Diff line number Diff line
@@ -15,8 +15,11 @@
 */
package com.android.systemui.complication;

import static android.service.dreams.Flags.FLAG_DREAMS_V2;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyMap;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
@@ -25,6 +28,8 @@ import static org.mockito.Mockito.when;
import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.UserHandle;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.provider.Settings;
import android.testing.TestableLooper;
import android.testing.ViewUtils;
@@ -147,7 +152,26 @@ public class ComplicationHostViewControllerTest extends SysuiTestCase {
     * Ensures layout engine update is called on configuration change.
     */
    @Test
    public void testUpdateLayoutEngineOnConfigurationChange() {
    @EnableFlags(FLAG_DREAMS_V2)
    public void updateLayoutEngine_isCalled_onConfigurationChange_flagEnabled() {
        mController.onViewAttached();
        // Attach the complication host view so flows collecting on it start running.
        ViewUtils.attachView(mComplicationHostView);
        mLooper.processAllMessages();

        // emit configuration change
        Rect bounds = new Rect(0, 0, 2000, 2000);
        Configuration config = new Configuration();
        config.windowConfiguration.setMaxBounds(bounds);
        mKosmos.getConfigurationRepository().onConfigurationChange(config);
        mKosmos.getTestScope().getTestScheduler().runCurrent();

        verify(mLayoutEngine).updateLayoutEngine(eq(bounds), anyMap());
    }

    @Test
    @DisableFlags(FLAG_DREAMS_V2)
    public void updateLayoutEngine_notCalled_onConfigurationChange_flagDisabled() {
        mController.onViewAttached();
        // Attach the complication host view so flows collecting on it start running.
        ViewUtils.attachView(mComplicationHostView);
@@ -160,7 +184,7 @@ public class ComplicationHostViewControllerTest extends SysuiTestCase {
        mKosmos.getConfigurationRepository().onConfigurationChange(config);
        mKosmos.getTestScope().getTestScheduler().runCurrent();

        verify(mLayoutEngine).updateLayoutEngine(bounds);
        verify(mLayoutEngine, never()).updateLayoutEngine(eq(bounds), anyMap());
    }

    /**
+291 −2
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@ package com.android.systemui.complication;

import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -24,6 +25,9 @@ import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.graphics.Rect;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
import android.service.dreams.Flags;
import android.view.View;

import androidx.constraintlayout.widget.ConstraintLayout;
@@ -44,7 +48,9 @@ import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.function.Consumer;
import java.util.stream.Collectors;
@@ -60,12 +66,15 @@ public class ComplicationLayoutEngineTest extends SysuiTestCase {

    Margins mMargins = new Margins(0, 0, 0, 0);

    int mSpacing = 0;
    ComplicationLayoutEngine createComplicationLayoutEngine() {
        return createComplicationLayoutEngine(0);
    }

    ComplicationLayoutEngine createComplicationLayoutEngine(int spacing) {
        return new ComplicationLayoutEngine(mLayout, spacing, () -> mMargins, mTouchSession, 0, 0);
        mSpacing = spacing;
        return new ComplicationLayoutEngine(
                mLayout, () -> mSpacing, () -> mMargins, mTouchSession, 0, 0);
    }

    @Before
@@ -180,6 +189,7 @@ public class ComplicationLayoutEngineTest extends SysuiTestCase {
    }

    @Test
    @EnableFlags(Flags.FLAG_DREAMS_V2)
    public void testComplicationMarginsOnScreenSizeChange() {
        final Random rand = new Random();
        final int spacing = rand.nextInt();
@@ -217,7 +227,12 @@ public class ComplicationLayoutEngineTest extends SysuiTestCase {
        final int newTopMargin = rand.nextInt();
        final int newEndMargin = rand.nextInt();
        mMargins = new Margins(0, newTopMargin, newEndMargin, 0);
        engine.updateLayoutEngine(new Rect(0, 0, 800, 1000));

        final Map<ComplicationId, ComplicationLayoutParams> complicationLayoutParams =
                new HashMap<>();
        complicationLayoutParams.put(firstViewInfo.id, firstViewInfo.lp);
        complicationLayoutParams.put(secondViewInfo.id, secondViewInfo.lp);
        engine.updateLayoutEngine(new Rect(0, 0, 800, 1000), complicationLayoutParams);

        // Ensure complication view have new margins
        verifyChange(firstViewInfo, false, lp -> {
@@ -230,6 +245,280 @@ public class ComplicationLayoutEngineTest extends SysuiTestCase {
        });
    }

    @Test
    @DisableFlags(Flags.FLAG_DREAMS_V2)
    public void updateLayoutEngine_willNotUpdateViews_whenFlagDisabled() {
        final ComplicationLayoutEngine engine = createComplicationLayoutEngine();
        final ViewInfo viewInfo = new ViewInfo(
                new ComplicationLayoutParams(
                        100,
                        100,
                        ComplicationLayoutParams.POSITION_TOP
                                | ComplicationLayoutParams.POSITION_END,
                        ComplicationLayoutParams.DIRECTION_DOWN,
                        0),
                Complication.CATEGORY_SYSTEM,
                mLayout);

        addComplication(engine, viewInfo);
        viewInfo.clearInvocations();

        final Map<ComplicationId, ComplicationLayoutParams> complicationLayoutParams =
                new HashMap<>();
        complicationLayoutParams.put(viewInfo.id, viewInfo.lp);
        engine.updateLayoutEngine(new Rect(0, 0, 800, 1000), complicationLayoutParams);
        // Views won't be updated.
        verify(viewInfo.view, never()).setLayoutParams(any());
    }

    @Test
    @EnableFlags(Flags.FLAG_DREAMS_V2)
    public void updateLayoutEngine_willUpdateViews_whenFlagEnabled() {
        final ComplicationLayoutEngine engine = createComplicationLayoutEngine();
        final ViewInfo viewInfo = new ViewInfo(
                new ComplicationLayoutParams(
                        100,
                        100,
                        ComplicationLayoutParams.POSITION_TOP
                                | ComplicationLayoutParams.POSITION_END,
                        ComplicationLayoutParams.DIRECTION_DOWN,
                        0),
                Complication.CATEGORY_SYSTEM,
                mLayout);

        addComplication(engine, viewInfo);
        viewInfo.clearInvocations();

        final Map<ComplicationId, ComplicationLayoutParams> complicationLayoutParams =
                new HashMap<>();
        complicationLayoutParams.put(viewInfo.id, viewInfo.lp);
        engine.updateLayoutEngine(new Rect(0, 0, 800, 1000), complicationLayoutParams);
        // Views will be updated.
        verify(viewInfo.view).setLayoutParams(any());
    }

    @Test
    @EnableFlags(Flags.FLAG_DREAMS_V2)
    public void updateLayoutEngine_whenSpacingBetweenComplicationsChanges() {
        final Random rand = new Random();
        final int spacing = rand.nextInt();
        final ComplicationLayoutEngine engine = createComplicationLayoutEngine(spacing);
        final ViewInfo firstViewInfo = new ViewInfo(
                new ComplicationLayoutParams(
                        100,
                        100,
                        ComplicationLayoutParams.POSITION_TOP
                                | ComplicationLayoutParams.POSITION_END,
                        ComplicationLayoutParams.DIRECTION_DOWN,
                        0),
                Complication.CATEGORY_SYSTEM,
                mLayout);

        addComplication(engine, firstViewInfo);

        final ViewInfo secondViewInfo = new ViewInfo(
                new ComplicationLayoutParams(
                        100,
                        100,
                        ComplicationLayoutParams.POSITION_TOP
                                | ComplicationLayoutParams.POSITION_END,
                        ComplicationLayoutParams.DIRECTION_DOWN,
                        0),
                Complication.CATEGORY_SYSTEM,
                mLayout);

        addComplication(engine, secondViewInfo);

        firstViewInfo.clearInvocations();
        secondViewInfo.clearInvocations();

        // Triggers an update to the layout engine with new spacing between complications.
        final int newSpacing = rand.nextInt();
        mSpacing = newSpacing;
        final Map<ComplicationId, ComplicationLayoutParams> complicationLayoutParams =
                new HashMap<>();
        complicationLayoutParams.put(firstViewInfo.id, firstViewInfo.lp);
        complicationLayoutParams.put(secondViewInfo.id, secondViewInfo.lp);
        engine.updateLayoutEngine(new Rect(0, 0, 800, 1000), complicationLayoutParams);

        // Ensure complication views have new spacing.
        verifyChange(firstViewInfo, false, lp -> {
            assertThat(lp.topMargin).isEqualTo(mMargins.top);
            assertThat(lp.getMarginEnd()).isEqualTo(mMargins.end);
        });
        verifyChange(secondViewInfo, false, lp -> {
            assertThat(lp.topMargin).isEqualTo(newSpacing);
            assertThat(lp.getMarginEnd()).isEqualTo(mMargins.end);
        });
    }

    @Test
    @EnableFlags(Flags.FLAG_DREAMS_V2)
    public void updateLayoutEngine_repositionComplications_withNewDirection() {
        final Random rand = new Random();
        final int spacing = rand.nextInt();
        mMargins = new Margins(rand.nextInt(), rand.nextInt(), rand.nextInt(), rand.nextInt());
        final ComplicationLayoutEngine engine = createComplicationLayoutEngine(spacing);
        final ViewInfo firstViewInfo = new ViewInfo(
                new ComplicationLayoutParams(
                        100,
                        100,
                        ComplicationLayoutParams.POSITION_BOTTOM
                                | ComplicationLayoutParams.POSITION_START,
                        ComplicationLayoutParams.DIRECTION_END,
                        1),
                Complication.CATEGORY_SYSTEM,
                mLayout);
        addComplication(engine, firstViewInfo);

        verifyChange(firstViewInfo, false, lp -> {
            assertThat(lp.bottomToBottom == ConstraintLayout.LayoutParams.PARENT_ID).isTrue();
            assertThat(lp.startToStart == ConstraintLayout.LayoutParams.PARENT_ID).isTrue();
            assertThat(lp.bottomMargin).isEqualTo(mMargins.bottom);
            assertThat(lp.getMarginStart()).isEqualTo(mMargins.start);
        });

        final ViewInfo secondViewInfo = new ViewInfo(
                new ComplicationLayoutParams(
                        100,
                        100,
                        ComplicationLayoutParams.POSITION_BOTTOM
                                | ComplicationLayoutParams.POSITION_START,
                        ComplicationLayoutParams.DIRECTION_END,
                        0),
                Complication.CATEGORY_SYSTEM,
                mLayout);
        addComplication(engine, secondViewInfo);

        // Second complication is to the right of the first complication.
        verifyChange(secondViewInfo, false, lp -> {
            assertThat(lp.bottomToBottom == ConstraintLayout.LayoutParams.PARENT_ID).isTrue();
            assertThat(lp.startToEnd == firstViewInfo.view.getId()).isTrue();
            assertThat(lp.bottomMargin).isEqualTo(mMargins.bottom);
            assertThat(lp.getMarginStart()).isEqualTo(spacing);
        });
        firstViewInfo.clearInvocations();
        secondViewInfo.clearInvocations();

        // Triggers an update with new direction in layout params for each complication.
        final Map<ComplicationId, ComplicationLayoutParams> newParams = new HashMap<>();
        newParams.put(firstViewInfo.id, new ComplicationLayoutParams(
                100,
                100,
                ComplicationLayoutParams.POSITION_BOTTOM
                        | ComplicationLayoutParams.POSITION_START,
                ComplicationLayoutParams.DIRECTION_UP,
                1)
        );
        newParams.put(secondViewInfo.id, new ComplicationLayoutParams(
                100,
                100,
                ComplicationLayoutParams.POSITION_BOTTOM
                        | ComplicationLayoutParams.POSITION_START,
                ComplicationLayoutParams.DIRECTION_UP,
                0)
        );
        engine.updateLayoutEngine(new Rect(0, 0, 800, 1000), newParams);

        // Second complication is on top of the first complication.
        verifyChange(firstViewInfo, false, lp -> {
            assertThat(lp.bottomToBottom == ConstraintLayout.LayoutParams.PARENT_ID).isTrue();
            assertThat(lp.startToStart == ConstraintLayout.LayoutParams.PARENT_ID).isTrue();
            assertThat(lp.bottomMargin).isEqualTo(mMargins.bottom);
            assertThat(lp.getMarginStart()).isEqualTo(mMargins.start);
        });
        verifyChange(secondViewInfo, false, lp -> {
            assertThat(lp.bottomToTop == firstViewInfo.view.getId()).isTrue();
            assertThat(lp.startToStart == ConstraintLayout.LayoutParams.PARENT_ID).isTrue();
            assertThat(lp.bottomMargin).isEqualTo(spacing);
            assertThat(lp.getMarginStart()).isEqualTo(mMargins.start);
        });
    }

    @Test
    @EnableFlags(Flags.FLAG_DREAMS_V2)
    public void updateLayoutEngine_repositionComplications_withNewWeight() {
        final Random rand = new Random();
        final int spacing = rand.nextInt();
        mMargins = new Margins(rand.nextInt(), rand.nextInt(), rand.nextInt(), rand.nextInt());
        final ComplicationLayoutEngine engine = createComplicationLayoutEngine(spacing);
        final ViewInfo firstViewInfo = new ViewInfo(
                new ComplicationLayoutParams(
                        100,
                        100,
                        ComplicationLayoutParams.POSITION_BOTTOM
                                | ComplicationLayoutParams.POSITION_START,
                        ComplicationLayoutParams.DIRECTION_END,
                        1),
                Complication.CATEGORY_SYSTEM,
                mLayout);
        addComplication(engine, firstViewInfo);

        verifyChange(firstViewInfo, false, lp -> {
            assertThat(lp.bottomToBottom == ConstraintLayout.LayoutParams.PARENT_ID).isTrue();
            assertThat(lp.startToStart == ConstraintLayout.LayoutParams.PARENT_ID).isTrue();
            assertThat(lp.bottomMargin).isEqualTo(mMargins.bottom);
            assertThat(lp.getMarginStart()).isEqualTo(mMargins.start);
        });

        final ViewInfo secondViewInfo = new ViewInfo(
                new ComplicationLayoutParams(
                        100,
                        100,
                        ComplicationLayoutParams.POSITION_BOTTOM
                                | ComplicationLayoutParams.POSITION_START,
                        ComplicationLayoutParams.DIRECTION_END,
                        0),
                Complication.CATEGORY_SYSTEM,
                mLayout);
        addComplication(engine, secondViewInfo);

        // Second complication is after the first complication.
        verifyChange(secondViewInfo, false, lp -> {
            assertThat(lp.bottomToBottom == ConstraintLayout.LayoutParams.PARENT_ID).isTrue();
            assertThat(lp.startToEnd == firstViewInfo.view.getId()).isTrue();
            assertThat(lp.bottomMargin).isEqualTo(mMargins.bottom);
            assertThat(lp.getMarginStart()).isEqualTo(spacing);
        });
        firstViewInfo.clearInvocations();
        secondViewInfo.clearInvocations();

        // Triggers an update with new weight in layout params for complications.
        final Map<ComplicationId, ComplicationLayoutParams> newParams = new HashMap<>();
        newParams.put(firstViewInfo.id, new ComplicationLayoutParams(
                100,
                100,
                ComplicationLayoutParams.POSITION_BOTTOM
                        | ComplicationLayoutParams.POSITION_START,
                ComplicationLayoutParams.DIRECTION_END,
                1)
        );
        // Second view has larger weight than the first view.
        newParams.put(secondViewInfo.id, new ComplicationLayoutParams(
                100,
                100,
                ComplicationLayoutParams.POSITION_BOTTOM
                        | ComplicationLayoutParams.POSITION_START,
                ComplicationLayoutParams.DIRECTION_END,
                2)
        );
        engine.updateLayoutEngine(new Rect(0, 0, 800, 1000), newParams);

        // Second complication is in front of the first complication.
        verifyChange(secondViewInfo, false, lp -> {
            assertThat(lp.bottomToBottom == ConstraintLayout.LayoutParams.PARENT_ID).isTrue();
            assertThat(lp.startToStart == ConstraintLayout.LayoutParams.PARENT_ID).isTrue();
            assertThat(lp.bottomMargin).isEqualTo(mMargins.bottom);
            assertThat(lp.getMarginStart()).isEqualTo(mMargins.start);
        });
        verifyChange(firstViewInfo, false, lp -> {
            assertThat(lp.bottomToBottom == ConstraintLayout.LayoutParams.PARENT_ID).isTrue();
            assertThat(lp.startToEnd == secondViewInfo.view.getId()).isTrue();
            assertThat(lp.bottomMargin).isEqualTo(mMargins.bottom);
            assertThat(lp.getMarginStart()).isEqualTo(spacing);
        });
    }

    /**
     * Makes sure the engine properly places a view within the {@link ConstraintLayout}.
     */
+1 −1
Original line number Diff line number Diff line
@@ -137,7 +137,7 @@ public class DreamClockTimeComplicationTest extends SysuiTestCase {
    @Test
    public void testComplicationViewHolderContentAccessors() {
        final DreamClockTimeComplication.DreamClockTimeViewHolder viewHolder =
                new DreamClockTimeComplication.DreamClockTimeViewHolder(mView, mLayoutParams,
                new DreamClockTimeComplication.DreamClockTimeViewHolder(mView, () -> mLayoutParams,
                        mViewController);
        assertThat(viewHolder.getView()).isEqualTo(mView);
        assertThat(viewHolder.getLayoutParams()).isEqualTo(mLayoutParams);
+3 −0
Original line number Diff line number Diff line
@@ -2073,6 +2073,9 @@

    <!-- The margin applied between complications -->
    <dimen name="dream_overlay_complication_margin">0dp</dimen>
    <dimen name="dream_overlay_complication_small_margin">1dp</dimen>
    <dimen name="dream_overlay_complication_medium_margin">9dp</dimen>
    <dimen name="dream_overlay_complication_large_margin">24dp</dimen>

    <dimen name="dream_overlay_y_offset">80dp</dimen>
    <dimen name="dream_overlay_entry_y_offset">40dp</dimen>
+13 −0
Original line number Diff line number Diff line
@@ -42,4 +42,17 @@ object WindowSizeUtils {
        val width = metrics.bounds.width()
        return width / metrics.density < COMPACT_WIDTH.value
    }

    /** Whether the window size reflects most tablet sizes. */
    @JvmStatic
    fun isTabletWindowSize(context: Context): Boolean {
        val metrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(context)
        val width = metrics.bounds.width() / metrics.density
        val height = metrics.bounds.height() / metrics.density
        return height >= EXPANDED_HEIGHT.value ||
            (width >= MEDIUM_WIDTH.value &&
                height in COMPACT_HEIGHT.value..EXPANDED_HEIGHT.value &&
                // aspect ratio to exclude unfolded screen size
                width / height >= 1.5f)
    }
}
Loading