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

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

Merge "Adjust dream overlay margins for mobile" into main

parents 91830b24 0ffc4fc6
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -48,6 +48,9 @@ import androidx.compose.ui.unit.coerceAtMost
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.times
import androidx.window.layout.WindowMetricsCalculator
import com.android.systemui.communal.util.WindowSizeUtils.COMPACT_HEIGHT
import com.android.systemui.communal.util.WindowSizeUtils.COMPACT_WIDTH
import com.android.systemui.communal.util.WindowSizeUtils.MEDIUM_WIDTH

/**
 * Renders a responsive [LazyHorizontalGrid] with dynamic columns and rows. Each cell will maintain
@@ -266,14 +269,14 @@ fun calculateWindowSize(): DpSize {
private fun calculateNumCellsWidth(width: Dp) =
    // See https://developer.android.com/develop/ui/views/layout/use-window-size-classes
    when {
        width >= 840.dp -> 3
        width >= 600.dp -> 2
        width >= MEDIUM_WIDTH -> 3
        width >= COMPACT_WIDTH -> 2
        else -> 1
    }

private fun calculateNumCellsHeight(height: Dp) =
    when {
        height >= 1000.dp -> 3
        height >= 480.dp -> 2
        height >= COMPACT_HEIGHT -> 2
        else -> 1
    }
+38 −3
Original line number Diff line number Diff line
@@ -22,8 +22,12 @@ import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.content.res.Configuration;
import android.graphics.Rect;
import android.os.UserHandle;
import android.provider.Settings;
import android.testing.TestableLooper;
import android.testing.ViewUtils;
import android.view.View;

import androidx.constraintlayout.widget.ConstraintLayout;
@@ -35,6 +39,7 @@ import androidx.test.filters.SmallTest;

import com.android.systemui.SysuiTestCase;
import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.kosmos.KosmosJavaAdapter;
import com.android.systemui.util.settings.FakeSettings;
import com.android.systemui.util.settings.SecureSettings;

@@ -52,8 +57,8 @@ import java.util.HashSet;

@SmallTest
@RunWith(AndroidJUnit4.class)
@TestableLooper.RunWithLooper(setAsMainLooper = true)
public class ComplicationHostViewControllerTest extends SysuiTestCase {
    @Mock
    ConstraintLayout mComplicationHostView;

    @Mock
@@ -99,6 +104,10 @@ public class ComplicationHostViewControllerTest extends SysuiTestCase {

    private SecureSettings mSecureSettings;

    private KosmosJavaAdapter mKosmos;

    private TestableLooper mLooper;

    private static final int CURRENT_USER_ID = UserHandle.USER_SYSTEM;

    @Before
@@ -113,7 +122,10 @@ public class ComplicationHostViewControllerTest extends SysuiTestCase {
        when(mViewHolder.getLayoutParams()).thenReturn(mComplicationLayoutParams);
        when(mComplicationView.getParent()).thenReturn(mComplicationHostView);

        mLooper = TestableLooper.get(this);
        mKosmos = new KosmosJavaAdapter(this);
        mSecureSettings = new FakeSettings();
        mComplicationHostView = new ConstraintLayout(getContext());
        mSecureSettings.putFloatForUser(
                Settings.Global.ANIMATOR_DURATION_SCALE, 1.0f, CURRENT_USER_ID);

@@ -123,11 +135,34 @@ public class ComplicationHostViewControllerTest extends SysuiTestCase {
                mDreamOverlayStateController,
                mLifecycleOwner,
                mViewModel,
                mSecureSettings);
                mSecureSettings,
                mKosmos.getConfigurationInteractor(),
                mKosmos.getTestDispatcher()
        );

        mController.init();
    }

    /**
     * Ensures layout engine update is called on configuration change.
     */
    @Test
    public void testUpdateLayoutEngineOnConfigurationChange() {
        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(bounds);
    }

    /**
     * Ensures the lifecycle of complications is properly handled.
     */
+63 −24
Original line number Diff line number Diff line
@@ -18,10 +18,12 @@ package com.android.systemui.complication;
import static com.google.common.truth.Truth.assertThat;

import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import android.graphics.Rect;
import android.view.View;

import androidx.constraintlayout.widget.ConstraintLayout;
@@ -56,12 +58,14 @@ public class ComplicationLayoutEngineTest extends SysuiTestCase {
    @Mock
    TouchInsetManager.TouchInsetSession mTouchSession;

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

    ComplicationLayoutEngine createComplicationLayoutEngine() {
        return createComplicationLayoutEngine(0);
    }

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

    @Before
@@ -84,7 +88,7 @@ public class ComplicationLayoutEngineTest extends SysuiTestCase {
                ConstraintLayout layout) {
            this.lp = params;
            this.category = category;
            this.view = Mockito.mock(View.class);
            this.view = mock(View.class);
            this.id = sFactory.getNextId();
            when(view.getId()).thenReturn(sNextId++);
            when(view.getParent()).thenReturn(layout);
@@ -131,15 +135,10 @@ public class ComplicationLayoutEngineTest extends SysuiTestCase {
    @Test
    public void testComplicationMarginPosition() {
        final Random rand = new Random();
        final int startMargin = rand.nextInt();
        final int topMargin = rand.nextInt();
        final int endMargin = rand.nextInt();
        final int bottomMargin = rand.nextInt();
        final int spacing = rand.nextInt();

        final ComplicationLayoutEngine engine = new ComplicationLayoutEngine(mLayout, spacing,
                startMargin, topMargin, endMargin, bottomMargin, mTouchSession, 0, 0);

        mMargins = new Margins(rand.nextInt(), rand.nextInt(), rand.nextInt(),
                rand.nextInt());
        final ComplicationLayoutEngine engine = createComplicationLayoutEngine(spacing);
        final ViewInfo firstViewInfo = new ViewInfo(
                new ComplicationLayoutParams(
                        100,
@@ -167,17 +166,67 @@ public class ComplicationLayoutEngineTest extends SysuiTestCase {

        addComplication(engine, secondViewInfo);


        // The first added view should have margins from both directions from the corner position.
        verifyChange(firstViewInfo, false, lp -> {
            assertThat(lp.topMargin).isEqualTo(topMargin);
            assertThat(lp.getMarginEnd()).isEqualTo(endMargin);
            assertThat(lp.topMargin).isEqualTo(mMargins.top);
            assertThat(lp.getMarginEnd()).isEqualTo(mMargins.end);
        });

        // The second view should be spaced below the first view and have the side end margin.
        verifyChange(secondViewInfo, false, lp -> {
            assertThat(lp.topMargin).isEqualTo(spacing);
            assertThat(lp.getMarginEnd()).isEqualTo(endMargin);
            assertThat(lp.getMarginEnd()).isEqualTo(mMargins.end);
        });
    }

    @Test
    public void testComplicationMarginsOnScreenSizeChange() {
        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_STANDARD,
                mLayout);

        addComplication(engine, secondViewInfo);

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

        // Triggers an update to the layout engine with new margins.
        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));

        // Ensure complication view have new margins
        verifyChange(firstViewInfo, false, lp -> {
            assertThat(lp.topMargin).isEqualTo(newTopMargin);
            assertThat(lp.getMarginEnd()).isEqualTo(newEndMargin);
        });
        verifyChange(secondViewInfo, false, lp -> {
            assertThat(lp.topMargin).isEqualTo(spacing);
            assertThat(lp.getMarginEnd()).isEqualTo(newEndMargin);
        });
    }

@@ -241,7 +290,6 @@ public class ComplicationLayoutEngineTest extends SysuiTestCase {
    @Test
    public void testDirectionLayout() {
        final ComplicationLayoutEngine engine = createComplicationLayoutEngine();

        final ViewInfo firstViewInfo = new ViewInfo(
                new ComplicationLayoutParams(
                        100,
@@ -289,7 +337,6 @@ public class ComplicationLayoutEngineTest extends SysuiTestCase {
    @Test
    public void testPositionLayout() {
        final ComplicationLayoutEngine engine = createComplicationLayoutEngine();

        final ViewInfo firstViewInfo = new ViewInfo(
                new ComplicationLayoutParams(
                        100,
@@ -376,7 +423,6 @@ public class ComplicationLayoutEngineTest extends SysuiTestCase {
    public void testDefaultMargin() {
        final int margin = 5;
        final ComplicationLayoutEngine engine = createComplicationLayoutEngine(margin);

        final ViewInfo firstViewInfo = new ViewInfo(
                new ComplicationLayoutParams(
                        100,
@@ -452,7 +498,6 @@ public class ComplicationLayoutEngineTest extends SysuiTestCase {
        final int defaultMargin = 5;
        final int complicationMargin = 10;
        final ComplicationLayoutEngine engine = createComplicationLayoutEngine(defaultMargin);

        final ViewInfo firstViewInfo = new ViewInfo(
                new ComplicationLayoutParams(
                        100,
@@ -518,7 +563,6 @@ public class ComplicationLayoutEngineTest extends SysuiTestCase {
    public void testWidthConstraint() {
        final int maxWidth = 20;
        final ComplicationLayoutEngine engine = createComplicationLayoutEngine();

        final ViewInfo viewStartDirection = new ViewInfo(
                new ComplicationLayoutParams(
                        100,
@@ -566,7 +610,6 @@ public class ComplicationLayoutEngineTest extends SysuiTestCase {
    public void testHeightConstraint() {
        final int maxHeight = 20;
        final ComplicationLayoutEngine engine = createComplicationLayoutEngine();

        final ViewInfo viewUpDirection = new ViewInfo(
                new ComplicationLayoutParams(
                        100,
@@ -613,7 +656,6 @@ public class ComplicationLayoutEngineTest extends SysuiTestCase {
    @Test
    public void testConstraintNotSetWhenNotSpecified() {
        final ComplicationLayoutEngine engine = createComplicationLayoutEngine();

        final ViewInfo view = new ViewInfo(
                new ComplicationLayoutParams(
                        100,
@@ -641,7 +683,6 @@ public class ComplicationLayoutEngineTest extends SysuiTestCase {
    @Test
    public void testRemoval() {
        final ComplicationLayoutEngine engine = createComplicationLayoutEngine();

        final ViewInfo firstViewInfo = new ViewInfo(
                new ComplicationLayoutParams(
                        100,
@@ -687,7 +728,6 @@ public class ComplicationLayoutEngineTest extends SysuiTestCase {
    @Test
    public void testDoubleRemoval() {
        final ComplicationLayoutEngine engine = createComplicationLayoutEngine();

        final ViewInfo firstViewInfo = new ViewInfo(
                new ComplicationLayoutParams(
                        100,
@@ -716,7 +756,6 @@ public class ComplicationLayoutEngineTest extends SysuiTestCase {
    @Test
    public void testGetViews() {
        final ComplicationLayoutEngine engine = createComplicationLayoutEngine();

        final ViewInfo topEndView = new ViewInfo(
                new ComplicationLayoutParams(
                        100,
+7 −3
Original line number Diff line number Diff line
@@ -1993,10 +1993,14 @@
    </item>

    <!-- The padding applied to the dream overlay container -->
    <dimen name="dream_overlay_container_padding_start">0dp</dimen>
    <dimen name="dream_overlay_container_padding_end">0dp</dimen>
    <dimen name="dream_overlay_container_padding_start">40dp</dimen>
    <dimen name="dream_overlay_container_padding_end">40dp</dimen>
    <dimen name="dream_overlay_container_padding_top">0dp</dimen>
    <dimen name="dream_overlay_container_padding_bottom">0dp</dimen>
    <dimen name="dream_overlay_container_padding_bottom">40dp</dimen>
    <dimen name="dream_overlay_container_small_padding_start">32dp</dimen>
    <dimen name="dream_overlay_container_small_padding_end">32dp</dimen>
    <dimen name="dream_overlay_container_small_padding_top">0dp</dimen>
    <dimen name="dream_overlay_container_small_padding_bottom">32dp</dimen>

    <!-- The margin applied between complications -->
    <dimen name="dream_overlay_complication_margin">0dp</dimen>
+45 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.communal.util

import android.content.Context
import androidx.compose.ui.unit.dp
import androidx.window.layout.WindowMetricsCalculator

/**
 * [WindowSizeUtils] defines viewport breakpoints that helps create responsive mobile layout.
 *
 * @see https://developer.android.com/develop/ui/views/layout/use-window-size-classes
 */
object WindowSizeUtils {
    /** Compact screen width breakpoint. */
    val COMPACT_WIDTH = 600.dp
    /** Medium screen width breakpoint. */
    val MEDIUM_WIDTH = 840.dp
    /** Compact screen height breakpoint. */
    val COMPACT_HEIGHT = 480.dp
    /** Expanded screen height breakpoint. */
    val EXPANDED_HEIGHT = 900.dp

    /** Whether the window size is compact, which reflects most mobile sizes in portrait. */
    @JvmStatic
    fun isCompactWindowSize(context: Context): Boolean {
        val metrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(context)
        val width = metrics.bounds.width()
        return width / metrics.density < COMPACT_WIDTH.value
    }
}
Loading