From 50b665e985b334b3f60f8232043fb088811167de Mon Sep 17 00:00:00 2001 From: Beth Thibodeau Date: Wed, 2 Feb 2022 22:15:13 -0500 Subject: [PATCH] Add compact version of new layout for phone landscape Splits the new session layout into collapsed and expanded versions. If the new layout is being used, the collapsed version will be used in landscape orientation on smaller devices, and everywhere else will use the expanded version. No change for the old layout (collapsed version still used always in QQS and keyguard) Bug: 209655299 Test: visual - toggle flag, rotate device Test: atest KeyguardMediaControllerTest QuickQSPanelControllerTest Change-Id: I5df62996a4823edd19b1bdc217e08cab13d5b7b0 --- .../res/layout/media_session_view.xml | 40 ++------- .../SystemUI/res/values-sw600dp/config.xml | 3 + packages/SystemUI/res/values/config.xml | 3 + packages/SystemUI/res/values/dimens.xml | 2 + .../res/xml/media_session_collapsed.xml | 90 +++++++++++++++++++ .../res/xml/media_session_expanded.xml | 84 +++++++++++++++++ .../systemui/media/KeyguardMediaController.kt | 9 +- .../systemui/media/MediaViewController.kt | 6 +- .../systemui/qs/QuickQSPanelController.java | 32 ++++++- .../systemui/qs/dagger/QSFragmentModule.java | 9 ++ .../src/com/android/systemui/util/Utils.java | 8 ++ .../media/KeyguardMediaControllerTest.kt | 27 +++++- .../systemui/qs/QuickQSPanelControllerTest.kt | 57 +++++++++++- 13 files changed, 331 insertions(+), 39 deletions(-) create mode 100644 packages/SystemUI/res/xml/media_session_collapsed.xml create mode 100644 packages/SystemUI/res/xml/media_session_expanded.xml diff --git a/packages/SystemUI/res/layout/media_session_view.xml b/packages/SystemUI/res/layout/media_session_view.xml index 51d160892a013..978998d6ca2c7 100644 --- a/packages/SystemUI/res/layout/media_session_view.xml +++ b/packages/SystemUI/res/layout/media_session_view.xml @@ -29,14 +29,14 @@ android:theme="@style/MediaPlayer"> + android:layout_marginBottom="0dp" /> + app:layout_constraintHorizontal_bias="1" + app:layout_constraintHorizontal_chainStyle="packed" /> @@ -188,11 +182,7 @@ android:layout_marginBottom="0dp" android:layout_marginTop="0dp" android:layout_marginStart="0dp" - android:layout_marginEnd="0dp" - app:layout_constraintStart_toEndOf="@id/actionPrev" - app:layout_constraintEnd_toStartOf="@id/actionNext" - app:layout_constraintBottom_toBottomOf="parent" - app:layout_constraintTop_toBottomOf="@id/actionPlayPause" /> + android:layout_marginEnd="0dp" /> + android:layout_marginTop="0dp" /> + android:layout_marginTop="0dp" /> + app:layout_constraintHorizontal_chainStyle="packed" /> 4 + + false + left;back,home,recent;right diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml index 079f5d0a28051..1ae3d362cd6e2 100644 --- a/packages/SystemUI/res/values/config.xml +++ b/packages/SystemUI/res/values/config.xml @@ -102,6 +102,9 @@ one_handed_mode_enabled:onehanded + + true + false diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml index dba7290dba09c..fdb56314bcaad 100644 --- a/packages/SystemUI/res/values/dimens.xml +++ b/packages/SystemUI/res/values/dimens.xml @@ -990,6 +990,8 @@ 15dp 16dp + 184dp + 128dp 72dp diff --git a/packages/SystemUI/res/xml/media_session_collapsed.xml b/packages/SystemUI/res/xml/media_session_collapsed.xml new file mode 100644 index 0000000000000..c6e18a6f8740c --- /dev/null +++ b/packages/SystemUI/res/xml/media_session_collapsed.xml @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/SystemUI/res/xml/media_session_expanded.xml b/packages/SystemUI/res/xml/media_session_expanded.xml new file mode 100644 index 0000000000000..18ec7aa4cab4c --- /dev/null +++ b/packages/SystemUI/res/xml/media_session_expanded.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt b/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt index 48f48266fda57..c3f4ce9865969 100644 --- a/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/KeyguardMediaController.kt @@ -45,7 +45,8 @@ class KeyguardMediaController @Inject constructor( private val statusBarStateController: SysuiStatusBarStateController, private val notifLockscreenUserManager: NotificationLockscreenUserManager, private val context: Context, - configurationController: ConfigurationController + configurationController: ConfigurationController, + private val mediaFlags: MediaFlags ) { init { @@ -61,7 +62,11 @@ class KeyguardMediaController @Inject constructor( }) // First let's set the desired state that we want for this host - mediaHost.expansion = MediaHostState.COLLAPSED + mediaHost.expansion = if (mediaFlags.useMediaSessionLayout()) { + MediaHostState.EXPANDED + } else { + MediaHostState.COLLAPSED + } mediaHost.showsOnlyActiveMedia = true mediaHost.falsingProtectionNeeded = true diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt index 791a312f341e4..591aad1014bd0 100644 --- a/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/MediaViewController.kt @@ -471,14 +471,16 @@ class MediaViewController @Inject constructor( private fun updateMediaViewControllerType(type: TYPE) { this.type = type + + // These XML resources contain ConstraintSets that will apply to this player type's layout when (type) { TYPE.PLAYER -> { collapsedLayout.load(context, R.xml.media_collapsed) expandedLayout.load(context, R.xml.media_expanded) } TYPE.PLAYER_SESSION -> { - collapsedLayout.clone(context, R.layout.media_session_view) - expandedLayout.clone(context, R.layout.media_session_view) + collapsedLayout.load(context, R.xml.media_session_collapsed) + expandedLayout.load(context, R.xml.media_session_expanded) } TYPE.RECOMMENDATION -> { collapsedLayout.load(context, R.xml.media_recommendation_collapsed) diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java index 2d2fa1f08452e..a3af0e58c43d7 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java +++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java @@ -17,12 +17,16 @@ package com.android.systemui.qs; import static com.android.systemui.media.dagger.MediaModule.QUICK_QS_PANEL; +import static com.android.systemui.qs.dagger.QSFragmentModule.QS_USING_COLLAPSED_LANDSCAPE_MEDIA; import static com.android.systemui.qs.dagger.QSFragmentModule.QS_USING_MEDIA_PLAYER; +import androidx.annotation.VisibleForTesting; + import com.android.internal.logging.MetricsLogger; import com.android.internal.logging.UiEventLogger; import com.android.systemui.R; import com.android.systemui.dump.DumpManager; +import com.android.systemui.media.MediaFlags; import com.android.systemui.media.MediaHierarchyManager; import com.android.systemui.media.MediaHost; import com.android.systemui.plugins.qs.QSTile; @@ -31,6 +35,7 @@ import com.android.systemui.qs.dagger.QSScope; import com.android.systemui.qs.logging.QSLogger; import com.android.systemui.settings.brightness.BrightnessMirrorHandler; import com.android.systemui.statusbar.policy.BrightnessMirrorController; +import com.android.systemui.util.leak.RotationUtils; import java.util.ArrayList; import java.util.List; @@ -54,11 +59,16 @@ public class QuickQSPanelController extends QSPanelControllerBase private final QuickQSBrightnessController mBrightnessController; private final BrightnessMirrorHandler mBrightnessMirrorHandler; + private final MediaFlags mMediaFlags; + private final boolean mUsingCollapsedLandscapeMedia; + @Inject QuickQSPanelController(QuickQSPanel view, QSTileHost qsTileHost, QSCustomizerController qsCustomizerController, @Named(QS_USING_MEDIA_PLAYER) boolean usingMediaPlayer, @Named(QUICK_QS_PANEL) MediaHost mediaHost, + @Named(QS_USING_COLLAPSED_LANDSCAPE_MEDIA) boolean usingCollapsedLandscapeMedia, + MediaFlags mediaFlags, MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger, DumpManager dumpManager, QuickQSBrightnessController quickQSBrightnessController @@ -67,17 +77,36 @@ public class QuickQSPanelController extends QSPanelControllerBase uiEventLogger, qsLogger, dumpManager); mBrightnessController = quickQSBrightnessController; mBrightnessMirrorHandler = new BrightnessMirrorHandler(mBrightnessController); + mUsingCollapsedLandscapeMedia = usingCollapsedLandscapeMedia; + mMediaFlags = mediaFlags; } @Override protected void onInit() { super.onInit(); - mMediaHost.setExpansion(0.0f); + updateMediaExpansion(); mMediaHost.setShowsOnlyActiveMedia(true); mMediaHost.init(MediaHierarchyManager.LOCATION_QQS); mBrightnessController.init(mShouldUseSplitNotificationShade); } + private void updateMediaExpansion() { + int rotation = getRotation(); + boolean isLandscape = rotation == RotationUtils.ROTATION_LANDSCAPE + || rotation == RotationUtils.ROTATION_SEASCAPE; + if (mMediaFlags.useMediaSessionLayout() + && (!mUsingCollapsedLandscapeMedia || !isLandscape)) { + mMediaHost.setExpansion(MediaHost.EXPANDED); + } else { + mMediaHost.setExpansion(MediaHost.COLLAPSED); + } + } + + @VisibleForTesting + protected int getRotation() { + return RotationUtils.getRotation(getContext()); + } + @Override protected void onViewAttached() { super.onViewAttached(); @@ -116,6 +145,7 @@ public class QuickQSPanelController extends QSPanelControllerBase @Override protected void onConfigurationChanged() { mBrightnessController.refreshVisibility(mShouldUseSplitNotificationShade); + updateMediaExpansion(); } @Override diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java index 776ee1021db28..fdf9ae0d4b635 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java +++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentModule.java @@ -16,6 +16,7 @@ package com.android.systemui.qs.dagger; +import static com.android.systemui.util.Utils.useCollapsedMediaInLandscape; import static com.android.systemui.util.Utils.useQsMediaPlayer; import android.content.Context; @@ -56,6 +57,7 @@ public interface QSFragmentModule { String QS_FGS_MANAGER_FOOTER_VIEW = "qs_fgs_manager_footer"; String QS_SECURITY_FOOTER_VIEW = "qs_security_footer"; String QS_USING_MEDIA_PLAYER = "qs_using_media_player"; + String QS_USING_COLLAPSED_LANDSCAPE_MEDIA = "qs_using_collapsed_landscape_media"; /** * Provide a context themed using the QS theme @@ -171,6 +173,13 @@ public interface QSFragmentModule { return useQsMediaPlayer(context); } + /** */ + @Provides + @Named(QS_USING_COLLAPSED_LANDSCAPE_MEDIA) + static boolean providesQSUsingCollapsedLandscapeMedia(Context context) { + return useCollapsedMediaInLandscape(context.getResources()); + } + /** */ @Provides @QSScope diff --git a/packages/SystemUI/src/com/android/systemui/util/Utils.java b/packages/SystemUI/src/com/android/systemui/util/Utils.java index 407dc5e2787a7..71d8e33449377 100644 --- a/packages/SystemUI/src/com/android/systemui/util/Utils.java +++ b/packages/SystemUI/src/com/android/systemui/util/Utils.java @@ -161,6 +161,14 @@ public class Utils { return useQsMediaPlayer(context) && flag > 0; } + /** + * Returns true if the device should use the collapsed layout for the media player when in + * landscape (or seascape) orientation + */ + public static boolean useCollapsedMediaInLandscape(Resources resources) { + return resources.getBoolean(R.bool.config_quickSettingsMediaLandscapeCollapsed); + } + /** * Returns true if the device should use the split notification shade, based on orientation and * screen width. diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt index dc7026da21946..1484c9d11ba61 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/KeyguardMediaControllerTest.kt @@ -36,6 +36,7 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.Mock +import org.mockito.Mockito.verify import org.mockito.junit.MockitoJUnit import org.mockito.Mockito.`when` as whenever @@ -51,6 +52,8 @@ class KeyguardMediaControllerTest : SysuiTestCase() { private lateinit var statusBarStateController: SysuiStatusBarStateController @Mock private lateinit var configurationController: ConfigurationController + @Mock + private lateinit var mediaFlags: MediaFlags @Mock private lateinit var notificationLockscreenUserManager: NotificationLockscreenUserManager @@ -70,13 +73,15 @@ class KeyguardMediaControllerTest : SysuiTestCase() { .thenReturn(true) whenever(mediaHost.hostView).thenReturn(hostView) hostView.layoutParams = FrameLayout.LayoutParams(100, 100) + whenever(mediaFlags.useMediaSessionLayout()).thenReturn(false) keyguardMediaController = KeyguardMediaController( mediaHost, bypassController, statusBarStateController, notificationLockscreenUserManager, context, - configurationController + configurationController, + mediaFlags ) keyguardMediaController.attachSinglePaneContainer(mediaContainerView) keyguardMediaController.useSplitShade = false @@ -150,4 +155,24 @@ class KeyguardMediaControllerTest : SysuiTestCase() { assertTrue("HostView wasn't attached to the single pane container", mediaContainerView.childCount == 1) } + + @Test + fun testNotificationLayout_collapsedPlayer() { + verify(mediaHost).expansion = MediaHostState.COLLAPSED + } + + @Test + fun testSessionLayout_expandedPlayer() { + whenever(mediaFlags.useMediaSessionLayout()).thenReturn(true) + keyguardMediaController = KeyguardMediaController( + mediaHost, + bypassController, + statusBarStateController, + notificationLockscreenUserManager, + context, + configurationController, + mediaFlags + ) + verify(mediaHost).expansion = MediaHostState.EXPANDED + } } diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt index 09c6d9e86a440..1eb16fd64b854 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt @@ -23,11 +23,14 @@ import com.android.internal.logging.MetricsLogger import com.android.internal.logging.testing.UiEventLoggerFake import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager +import com.android.systemui.media.MediaFlags import com.android.systemui.media.MediaHost +import com.android.systemui.media.MediaHostState import com.android.systemui.plugins.qs.QSTile import com.android.systemui.plugins.qs.QSTileView import com.android.systemui.qs.customize.QSCustomizerController import com.android.systemui.qs.logging.QSLogger +import com.android.systemui.util.leak.RotationUtils import org.junit.After import org.junit.Before import org.junit.Test @@ -55,6 +58,8 @@ class QuickQSPanelControllerTest : SysuiTestCase() { @Mock private lateinit var mediaHost: MediaHost @Mock + private lateinit var mediaFlags: MediaFlags + @Mock private lateinit var metricsLogger: MetricsLogger private val uiEventLogger = UiEventLoggerFake() @Mock @@ -71,7 +76,7 @@ class QuickQSPanelControllerTest : SysuiTestCase() { @Captor private lateinit var captor: ArgumentCaptor - private lateinit var controller: QuickQSPanelController + private lateinit var controller: TestQuickQSPanelController @Before fun setUp() { @@ -82,13 +87,16 @@ class QuickQSPanelControllerTest : SysuiTestCase() { `when`(quickQSPanel.dumpableTag).thenReturn("") `when`(quickQSPanel.resources).thenReturn(mContext.resources) `when`(qsTileHost.createTileView(any(), any(), anyBoolean())).thenReturn(tileView) + `when`(mediaFlags.useMediaSessionLayout()).thenReturn(false) - controller = QuickQSPanelController( + controller = TestQuickQSPanelController( quickQSPanel, qsTileHost, qsCustomizerController, false, mediaHost, + true, + mediaFlags, metricsLogger, uiEventLogger, qsLogger, @@ -133,4 +141,49 @@ class QuickQSPanelControllerTest : SysuiTestCase() { verify(quickQsBrightnessController).refreshVisibility(anyBoolean()) } + + @Test + fun testMediaExpansionUpdatedWhenConfigurationChanged() { + `when`(mediaFlags.useMediaSessionLayout()).thenReturn(true) + + // times(2) because both controller and base controller are registering their listeners + verify(quickQSPanel, times(2)).addOnConfigurationChangedListener(captor.capture()) + + captor.allValues.forEach { it.onConfigurationChange(Configuration.EMPTY) } + verify(mediaHost).expansion = MediaHostState.EXPANDED + + // Rotate device, verify media size updated + controller.setRotation(RotationUtils.ROTATION_LANDSCAPE) + captor.allValues.forEach { it.onConfigurationChange(Configuration.EMPTY) } + + // times(2) because init will have set to collapsed because the flag was off + verify(mediaHost, times(2)).expansion = MediaHostState.COLLAPSED + } + + class TestQuickQSPanelController( + view: QuickQSPanel, + qsTileHost: QSTileHost, + qsCustomizerController: QSCustomizerController, + usingMediaPlayer: Boolean, + mediaHost: MediaHost, + usingCollapsedLandscapeMedia: Boolean, + mediaFlags: MediaFlags, + metricsLogger: MetricsLogger, + uiEventLogger: UiEventLoggerFake, + qsLogger: QSLogger, + dumpManager: DumpManager, + quickQSBrightnessController: QuickQSBrightnessController + ) : QuickQSPanelController(view, qsTileHost, qsCustomizerController, usingMediaPlayer, + mediaHost, usingCollapsedLandscapeMedia, mediaFlags, metricsLogger, uiEventLogger, qsLogger, + dumpManager, quickQSBrightnessController) { + + private var rotation = RotationUtils.ROTATION_NONE + + @Override + override fun getRotation(): Int = rotation + + fun setRotation(newRotation: Int) { + rotation = newRotation + } + } }