summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt50
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java10
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanel.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java53
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java15
-rw-r--r--packages/SystemUI/src/com/android/systemui/qs/TileLayout.java13
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseSceneContainerTest.kt300
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java68
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt8
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt13
-rw-r--r--packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt10
12 files changed, 544 insertions, 26 deletions
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
index 9d689fc25b23..33a630c8086a 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
@@ -25,6 +25,7 @@ import androidx.compose.foundation.clickable
import androidx.compose.foundation.clipScrollableContainer
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Arrangement.Absolute.spacedBy
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
@@ -42,6 +43,7 @@ import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
+import androidx.compose.material3.windowsizeclass.WindowHeightSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
@@ -67,6 +69,7 @@ import com.android.compose.animation.scene.UserActionResult
import com.android.compose.animation.scene.animateSceneFloatAsState
import com.android.compose.modifiers.padding
import com.android.compose.modifiers.thenIf
+import com.android.compose.windowsizeclass.LocalWindowSizeClass
import com.android.systemui.battery.BatteryMeterViewController
import com.android.systemui.common.ui.compose.windowinsets.CutoutLocation
import com.android.systemui.common.ui.compose.windowinsets.LocalDisplayCutout
@@ -235,6 +238,10 @@ private fun SceneScope.SingleShade(
val shouldPunchHoleBehindScrim =
layoutState.isTransitioningBetween(Scenes.Gone, Scenes.Shade) ||
layoutState.isTransitioningBetween(Scenes.Lockscreen, Scenes.Shade)
+ // Media is visible and we are in landscape on a small height screen
+ val mediaInRow =
+ isMediaVisible &&
+ LocalWindowSizeClass.current.heightSizeClass == WindowHeightSizeClass.Compact
Box(
modifier =
@@ -274,22 +281,39 @@ private fun SceneScope.SingleShade(
createBatteryMeterViewController = createBatteryMeterViewController,
statusBarIconController = statusBarIconController,
)
- Box(Modifier.element(QuickSettings.Elements.QuickQuickSettings)) {
- QuickSettings(
- viewModel.qsSceneAdapter,
- { viewModel.qsSceneAdapter.qqsHeight },
- isSplitShade = false,
- squishiness = { tileSquishiness },
+
+ val content: @Composable (Modifier) -> Unit = { modifier ->
+ Box(
+ Modifier.element(QuickSettings.Elements.QuickQuickSettings)
+ .then(modifier)
+ ) {
+ QuickSettings(
+ viewModel.qsSceneAdapter,
+ { viewModel.qsSceneAdapter.qqsHeight },
+ isSplitShade = false,
+ squishiness = { tileSquishiness },
+ )
+ }
+
+ MediaCarousel(
+ isVisible = isMediaVisible,
+ mediaHost = mediaHost,
+ modifier = Modifier.fillMaxWidth().then(modifier),
+ carouselController = mediaCarouselController,
)
}
- MediaCarousel(
- isVisible = isMediaVisible,
- mediaHost = mediaHost,
- modifier = Modifier.fillMaxWidth(),
- carouselController = mediaCarouselController,
- )
-
+ if (!mediaInRow) {
+ content(Modifier)
+ } else {
+ Row(
+ modifier = Modifier.fillMaxWidth(),
+ horizontalArrangement = spacedBy(16.dp),
+ verticalAlignment = Alignment.CenterVertically,
+ ) {
+ content(Modifier.weight(1f))
+ }
+ }
Spacer(modifier = Modifier.height(16.dp))
}
},
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index b34b3701528b..e77bd03b8af2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -485,6 +485,11 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout {
}
@Override
+ public int getMinRows() {
+ return mMinRows;
+ }
+
+ @Override
public boolean setMaxColumns(int maxColumns) {
mMaxColumns = maxColumns;
boolean changed = false;
@@ -497,6 +502,11 @@ public class PagedTileLayout extends ViewPager implements QSTileLayout {
return changed;
}
+ @Override
+ public int getMaxColumns() {
+ return mMaxColumns;
+ }
+
/**
* Set the amount of excess space that we gave this view compared to the actual available
* height. This is because this view is in a scrollview.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 00757b7bd51a..9c8c17bb1ca0 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -42,6 +42,7 @@ import com.android.internal.widget.RemeasuringLinearLayout;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.res.R;
+import com.android.systemui.scene.shared.flag.SceneContainerFlag;
import com.android.systemui.settings.brightness.BrightnessSliderController;
import com.android.systemui.tuner.TunerService;
import com.android.systemui.tuner.TunerService.Tunable;
@@ -441,7 +442,7 @@ public class QSPanel extends LinearLayout implements Tunable {
}
private boolean needsDynamicRowsAndColumns() {
- return true;
+ return !SceneContainerFlag.isEnabled();
}
private void switchAllContentToParent(ViewGroup parent, QSTileLayout newLayout) {
@@ -634,8 +635,7 @@ public class QSPanel extends LinearLayout implements Tunable {
switchAllContentToParent(newParent, mTileLayout);
reAttachMediaHost(mediaHostView, horizontal);
if (needsDynamicRowsAndColumns()) {
- mTileLayout.setMinRows(horizontal ? 2 : 1);
- mTileLayout.setMaxColumns(horizontal ? 2 : 4);
+ setColumnRowLayout(horizontal);
}
updateMargins(mediaHostView);
if (mHorizontalLinearLayout != null) {
@@ -644,6 +644,11 @@ public class QSPanel extends LinearLayout implements Tunable {
}
}
+ void setColumnRowLayout(boolean withMedia) {
+ mTileLayout.setMinRows(withMedia ? 2 : 1);
+ mTileLayout.setMaxColumns(withMedia ? 2 : 4);
+ }
+
private void updateMargins(ViewGroup mediaHostView) {
updateMediaHostContentMargins(mediaHostView);
updateHorizontalLinearLayoutMargins();
@@ -736,6 +741,8 @@ public class QSPanel extends LinearLayout implements Tunable {
return false;
}
+ int getMinRows();
+
/**
* Sets the max number of columns to show
*
@@ -747,6 +754,8 @@ public class QSPanel extends LinearLayout implements Tunable {
return false;
}
+ int getMaxColumns();
+
/**
* Sets the expansion value and proposedTranslation to panel.
*/
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
index e24caf19a14b..f76183ed2d74 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
@@ -30,6 +30,7 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.haptics.qs.QSLongPressEffect;
+import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor;
import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager;
import com.android.systemui.media.controls.ui.view.MediaHost;
import com.android.systemui.media.controls.ui.view.MediaHostState;
@@ -46,10 +47,13 @@ import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
import com.android.systemui.statusbar.policy.SplitShadeStateController;
import com.android.systemui.tuner.TunerService;
+import kotlinx.coroutines.flow.StateFlow;
+
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
+
/**
* Controller for {@link QSPanel}.
*/
@@ -72,6 +76,8 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
private final BrightnessSliderController.Factory mBrightnessSliderControllerFactory;
private final BrightnessController.Factory mBrightnessControllerFactory;
+ protected final MediaCarouselInteractor mMediaCarouselInteractor;
+
private View.OnTouchListener mTileLayoutTouchListener = new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
@@ -94,7 +100,8 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
FalsingManager falsingManager,
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
SplitShadeStateController splitShadeStateController,
- Provider<QSLongPressEffect> longPRessEffectProvider) {
+ Provider<QSLongPressEffect> longPRessEffectProvider,
+ MediaCarouselInteractor mediaCarouselInteractor) {
super(view, qsHost, qsCustomizerController, usingMediaPlayer, mediaHost,
metricsLogger, uiEventLogger, qsLogger, dumpManager, splitShadeStateController,
longPRessEffectProvider);
@@ -113,6 +120,7 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
mStatusBarKeyguardViewManager = statusBarKeyguardViewManager;
mLastDensity = view.getResources().getConfiguration().densityDpi;
mSceneContainerEnabled = SceneContainerFlag.isEnabled();
+ mMediaCarouselInteractor = mediaCarouselInteractor;
}
@Override
@@ -126,6 +134,11 @@ public class QSPanelController extends QSPanelControllerBase<QSPanel> {
}
@Override
+ StateFlow<Boolean> getMediaVisibleFlow() {
+ return mMediaCarouselInteractor.getHasAnyMediaOrRecommendation();
+ }
+
+ @Override
protected void onViewAttached() {
super.onViewAttached();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
index bd1d709b086a..3b5cc61057e6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelControllerBase.java
@@ -41,13 +41,17 @@ import com.android.systemui.qs.customize.QSCustomizerController;
import com.android.systemui.qs.external.CustomTile;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileViewImpl;
+import com.android.systemui.scene.shared.flag.SceneContainerFlag;
import com.android.systemui.statusbar.policy.SplitShadeStateController;
import com.android.systemui.util.ViewController;
import com.android.systemui.util.animation.DisappearParameters;
+import com.android.systemui.util.kotlin.JavaAdapterKt;
import kotlin.Unit;
import kotlin.jvm.functions.Function1;
+import kotlinx.coroutines.flow.StateFlow;
+
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Collection;
@@ -58,6 +62,7 @@ import java.util.stream.Collectors;
import javax.inject.Provider;
+
/**
* Controller for QSPanel views.
*
@@ -95,6 +100,13 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr
private boolean mDestroyed = false;
+ private boolean mMediaVisibleFromInteractor;
+
+ private final Consumer<Boolean> mMediaOrRecommendationVisibleConsumer = mediaVisible -> {
+ mMediaVisibleFromInteractor = mediaVisible;
+ setLayoutForMediaInScene();
+ };
+
@VisibleForTesting
protected final QSPanel.OnConfigurationChangedListener mOnConfigurationChangedListener =
new QSPanel.OnConfigurationChangedListener() {
@@ -117,7 +129,11 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr
/* newScreenLayout= */ mLastScreenLayout,
/* containerName= */ mView.getDumpableTag());
- switchTileLayoutIfNeeded();
+ if (SceneContainerFlag.isEnabled()) {
+ setLayoutForMediaInScene();
+ } else {
+ switchTileLayoutIfNeeded();
+ }
onConfigurationChanged();
if (previousSplitShadeState != mShouldUseSplitNotificationShade) {
onSplitShadeChanged(mShouldUseSplitNotificationShade);
@@ -175,6 +191,9 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr
mView.initialize(mQSLogger, mUsingMediaPlayer);
mQSLogger.logAllTilesChangeListening(mView.isListening(), mView.getDumpableTag(), "");
mHost.addCallback(mQSHostCallback);
+ if (SceneContainerFlag.isEnabled()) {
+ registerForMediaInteractorChanges();
+ }
}
/**
@@ -209,17 +228,32 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr
mQsTileRevealController.setExpansion(mRevealExpansion);
}
- mMediaHost.addVisibilityChangeListener(mMediaHostVisibilityListener);
+ if (!SceneContainerFlag.isEnabled()) {
+ mMediaHost.addVisibilityChangeListener(mMediaHostVisibilityListener);
+ }
mView.addOnConfigurationChangedListener(mOnConfigurationChangedListener);
setTiles();
mLastOrientation = getResources().getConfiguration().orientation;
mLastScreenLayout = getResources().getConfiguration().screenLayout;
mQSLogger.logOnViewAttached(mLastOrientation, mView.getDumpableTag());
+ if (SceneContainerFlag.isEnabled()) {
+ setLayoutForMediaInScene();
+ }
switchTileLayout(true);
mDumpManager.registerDumpable(mView.getDumpableTag(), this);
}
+ private void registerForMediaInteractorChanges() {
+ JavaAdapterKt.collectFlow(
+ mView,
+ getMediaVisibleFlow(),
+ mMediaOrRecommendationVisibleConsumer
+ );
+ }
+
+ abstract StateFlow<Boolean> getMediaVisibleFlow();
+
@Override
protected void onViewDetached() {
mQSLogger.logOnViewDetached(mLastOrientation, mView.getDumpableTag());
@@ -436,6 +470,11 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr
return false;
}
+ void setLayoutForMediaInScene() {
+ boolean withMedia = shouldUseHorizontalInScene();
+ mView.setColumnRowLayout(withMedia);
+ }
+
/**
* Update the way the media disappears based on if we're using the horizontal layout
*/
@@ -476,6 +515,16 @@ public abstract class QSPanelControllerBase<T extends QSPanel> extends ViewContr
== Configuration.SCREENLAYOUT_LONG_YES;
}
+ boolean shouldUseHorizontalInScene() {
+ if (mShouldUseSplitNotificationShade) {
+ return false;
+ }
+ return mMediaVisibleFromInteractor
+ && mLastOrientation == Configuration.ORIENTATION_LANDSCAPE
+ && (mLastScreenLayout & Configuration.SCREENLAYOUT_LONG_MASK)
+ == Configuration.SCREENLAYOUT_LONG_YES;
+ }
+
private void logTiles() {
for (int i = 0; i < mRecords.size(); i++) {
QSTile tile = mRecords.get(i).tile;
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
index 6cda740dd1a8..f207b1de3cba 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSPanelController.java
@@ -26,6 +26,7 @@ import com.android.internal.logging.MetricsLogger;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.dump.DumpManager;
import com.android.systemui.haptics.qs.QSLongPressEffect;
+import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor;
import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager;
import com.android.systemui.media.controls.ui.view.MediaHost;
import com.android.systemui.plugins.qs.QSTile;
@@ -36,6 +37,8 @@ import com.android.systemui.res.R;
import com.android.systemui.statusbar.policy.SplitShadeStateController;
import com.android.systemui.util.leak.RotationUtils;
+import kotlinx.coroutines.flow.StateFlow;
+
import java.util.ArrayList;
import java.util.List;
@@ -43,12 +46,15 @@ import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
+
/** Controller for {@link QuickQSPanel}. */
@QSScope
public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel> {
private final Provider<Boolean> mUsingCollapsedLandscapeMediaProvider;
+ private final MediaCarouselInteractor mMediaCarouselInteractor;
+
@Inject
QuickQSPanelController(QuickQSPanel view, QSHost qsHost,
QSCustomizerController qsCustomizerController,
@@ -58,12 +64,14 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel>
Provider<Boolean> usingCollapsedLandscapeMediaProvider,
MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger,
DumpManager dumpManager, SplitShadeStateController splitShadeStateController,
- Provider<QSLongPressEffect> longPressEffectProvider
+ Provider<QSLongPressEffect> longPressEffectProvider,
+ MediaCarouselInteractor mediaCarouselInteractor
) {
super(view, qsHost, qsCustomizerController, usingMediaPlayer, mediaHost, metricsLogger,
uiEventLogger, qsLogger, dumpManager, splitShadeStateController,
longPressEffectProvider);
mUsingCollapsedLandscapeMediaProvider = usingCollapsedLandscapeMediaProvider;
+ mMediaCarouselInteractor = mediaCarouselInteractor;
}
@Override
@@ -74,6 +82,11 @@ public class QuickQSPanelController extends QSPanelControllerBase<QuickQSPanel>
mMediaHost.init(MediaHierarchyManager.LOCATION_QQS);
}
+ @Override
+ StateFlow<Boolean> getMediaVisibleFlow() {
+ return mMediaCarouselInteractor.getHasActiveMediaOrRecommendation();
+ }
+
private void updateMediaExpansion() {
int rotation = getRotation();
boolean isLandscape = rotation == RotationUtils.ROTATION_LANDSCAPE
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index dcb9288f74be..ef44e5fb8757 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -12,6 +12,7 @@ import android.view.accessibility.AccessibilityNodeInfo;
import android.widget.TextView;
import androidx.annotation.Nullable;
+import androidx.annotation.VisibleForTesting;
import com.android.internal.logging.UiEventLogger;
import com.android.systemui.FontSizeUtils;
@@ -97,12 +98,24 @@ public class TileLayout extends ViewGroup implements QSTileLayout {
return false;
}
+ @VisibleForTesting
+ @Override
+ public int getMinRows() {
+ return mMinRows;
+ }
+
@Override
public boolean setMaxColumns(int maxColumns) {
mMaxColumns = maxColumns;
return updateColumns();
}
+ @VisibleForTesting
+ @Override
+ public int getMaxColumns() {
+ return mMaxColumns;
+ }
+
public void addTile(TileRecord tile) {
mRecords.add(tile);
tile.tile.setListening(this, mListening);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseSceneContainerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseSceneContainerTest.kt
new file mode 100644
index 000000000000..07ec38e6ae6c
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseSceneContainerTest.kt
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2024 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.qs
+
+import android.content.res.Configuration
+import android.content.res.Resources
+import android.testing.TestableLooper.RunWithLooper
+import android.view.ViewTreeObserver
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.internal.logging.MetricsLogger
+import com.android.internal.logging.UiEventLogger
+import com.android.internal.logging.testing.UiEventLoggerFake
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.flags.EnableSceneContainer
+import com.android.systemui.haptics.qs.QSLongPressEffect
+import com.android.systemui.haptics.qs.qsLongPressEffect
+import com.android.systemui.kosmos.testDispatcher
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.lifecycle.InstantTaskExecutorRule
+import com.android.systemui.media.controls.ui.view.MediaHost
+import com.android.systemui.qs.customize.QSCustomizerController
+import com.android.systemui.qs.logging.QSLogger
+import com.android.systemui.statusbar.policy.SplitShadeStateController
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import javax.inject.Provider
+import kotlinx.coroutines.Dispatchers
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.test.resetMain
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import kotlinx.coroutines.test.setMain
+import org.junit.After
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.MockitoAnnotations
+import org.mockito.kotlin.clearInvocations
+import org.mockito.kotlin.verify
+import org.mockito.kotlin.whenever
+
+@RunWith(AndroidJUnit4::class)
+@SmallTest
+@RunWithLooper
+@OptIn(ExperimentalCoroutinesApi::class)
+@EnableSceneContainer
+class QSPanelControllerBaseSceneContainerTest : SysuiTestCase() {
+
+ @Rule @JvmField val mInstantTaskExecutor = InstantTaskExecutorRule()
+
+ private val kosmos = testKosmos()
+
+ @Mock private lateinit var qsPanel: QSPanel
+ @Mock private lateinit var qsHost: QSHost
+ @Mock private lateinit var qsCustomizerController: QSCustomizerController
+ @Mock private lateinit var metricsLogger: MetricsLogger
+ private val uiEventLogger = UiEventLoggerFake()
+ @Mock private lateinit var qsLogger: QSLogger
+ private val dumpManager = DumpManager()
+ @Mock private lateinit var tileLayout: PagedTileLayout
+ @Mock private lateinit var resources: Resources
+ private val configuration = Configuration()
+ @Mock private lateinit var viewTreeObserver: ViewTreeObserver
+ @Mock private lateinit var mediaHost: MediaHost
+
+ private var isSplitShade = false
+ private val splitShadeStateController =
+ object : SplitShadeStateController {
+ override fun shouldUseSplitNotificationShade(resources: Resources): Boolean {
+ return isSplitShade
+ }
+ }
+ private val longPressEffectProvider: Provider<QSLongPressEffect> = Provider {
+ kosmos.qsLongPressEffect
+ }
+
+ private val mediaVisible = MutableStateFlow(false)
+
+ private lateinit var underTest: TestableQSPanelControllerBase
+
+ @Before
+ fun setUp() {
+ MockitoAnnotations.initMocks(this)
+ allowTestableLooperAsMainThread()
+ Dispatchers.setMain(kosmos.testDispatcher)
+
+ whenever(qsPanel.isAttachedToWindow).thenReturn(true)
+ whenever(qsPanel.orCreateTileLayout).thenReturn(tileLayout)
+ whenever(qsPanel.tileLayout).thenReturn(tileLayout)
+ whenever(qsPanel.resources).thenReturn(resources)
+ whenever(qsPanel.viewTreeObserver).thenReturn(viewTreeObserver)
+ whenever(qsHost.tiles).thenReturn(emptyList())
+ whenever(resources.configuration).thenReturn(configuration)
+
+ underTest = createUnderTest()
+ underTest.init()
+ }
+
+ @After
+ fun tearDown() {
+ disallowTestableLooperAsMainThread()
+ Dispatchers.resetMain()
+ }
+
+ @Test
+ fun configurationChange_onlySplitShadeConfigChanges_horizontalInSceneUpdated() =
+ with(kosmos) {
+ testScope.runTest {
+ clearInvocations(qsPanel)
+
+ mediaVisible.value = true
+ runCurrent()
+ isSplitShade = false
+ configuration.orientation = Configuration.ORIENTATION_LANDSCAPE
+ configuration.screenLayout = Configuration.SCREENLAYOUT_LONG_YES
+ underTest.mOnConfigurationChangedListener.onConfigurationChange(configuration)
+
+ assertThat(underTest.shouldUseHorizontalInScene()).isTrue()
+ verify(qsPanel).setColumnRowLayout(true)
+ clearInvocations(qsPanel)
+
+ isSplitShade = true
+ underTest.mOnConfigurationChangedListener.onConfigurationChange(configuration)
+
+ assertThat(underTest.shouldUseHorizontalInScene()).isFalse()
+ verify(qsPanel).setColumnRowLayout(false)
+ }
+ }
+
+ @Test
+ fun configurationChange_shouldUseHorizontalInSceneInLongDevices() =
+ with(kosmos) {
+ testScope.runTest {
+ clearInvocations(qsPanel)
+
+ mediaVisible.value = true
+ runCurrent()
+ isSplitShade = false
+ // When device is rotated to landscape and is long
+ configuration.orientation = Configuration.ORIENTATION_LANDSCAPE
+ configuration.screenLayout = Configuration.SCREENLAYOUT_LONG_YES
+ underTest.mOnConfigurationChangedListener.onConfigurationChange(configuration)
+
+ // Then the layout changes
+ assertThat(underTest.shouldUseHorizontalInScene()).isTrue()
+ verify(qsPanel).setColumnRowLayout(true)
+ clearInvocations(qsPanel)
+
+ // When device changes to not-long
+ configuration.screenLayout = Configuration.SCREENLAYOUT_LONG_NO
+ underTest.mOnConfigurationChangedListener.onConfigurationChange(configuration)
+
+ // Then the layout changes back
+ assertThat(underTest.shouldUseHorizontalInScene()).isFalse()
+ verify(qsPanel).setColumnRowLayout(false)
+ }
+ }
+
+ @Test
+ fun configurationChange_horizontalInScene_onlyInLandscape() =
+ with(kosmos) {
+ testScope.runTest {
+ clearInvocations(qsPanel)
+
+ mediaVisible.value = true
+ runCurrent()
+ isSplitShade = false
+
+ // When device is rotated to landscape and is long
+ configuration.orientation = Configuration.ORIENTATION_LANDSCAPE
+ configuration.screenLayout = Configuration.SCREENLAYOUT_LONG_YES
+ underTest.mOnConfigurationChangedListener.onConfigurationChange(configuration)
+
+ // Then the layout changes
+ assertThat(underTest.shouldUseHorizontalInScene()).isTrue()
+ verify(qsPanel).setColumnRowLayout(true)
+ clearInvocations(qsPanel)
+
+ // When it is rotated back to portrait
+ configuration.orientation = Configuration.ORIENTATION_PORTRAIT
+ underTest.mOnConfigurationChangedListener.onConfigurationChange(configuration)
+
+ // Then the layout changes back
+ assertThat(underTest.shouldUseHorizontalInScene()).isFalse()
+ verify(qsPanel).setColumnRowLayout(false)
+ }
+ }
+
+ @Test
+ fun changeMediaVisible_changesHorizontalInScene() =
+ with(kosmos) {
+ testScope.runTest {
+ mediaVisible.value = false
+ runCurrent()
+ isSplitShade = false
+ configuration.orientation = Configuration.ORIENTATION_LANDSCAPE
+ configuration.screenLayout = Configuration.SCREENLAYOUT_LONG_YES
+ underTest.mOnConfigurationChangedListener.onConfigurationChange(configuration)
+
+ assertThat(underTest.shouldUseHorizontalInScene()).isFalse()
+ clearInvocations(qsPanel)
+
+ mediaVisible.value = true
+ runCurrent()
+
+ assertThat(underTest.shouldUseHorizontalInScene()).isTrue()
+ verify(qsPanel).setColumnRowLayout(true)
+ }
+ }
+
+ @Test
+ fun startFromMediaHorizontalLong_shouldUseHorizontal() =
+ with(kosmos) {
+ testScope.runTest {
+ mediaVisible.value = true
+ runCurrent()
+ isSplitShade = false
+ configuration.orientation = Configuration.ORIENTATION_LANDSCAPE
+ configuration.screenLayout = Configuration.SCREENLAYOUT_LONG_YES
+
+ underTest = createUnderTest()
+ underTest.init()
+ runCurrent()
+
+ assertThat(underTest.shouldUseHorizontalInScene()).isTrue()
+ verify(qsPanel).setColumnRowLayout(true)
+ }
+ }
+
+ private fun createUnderTest(): TestableQSPanelControllerBase {
+ return TestableQSPanelControllerBase(
+ qsPanel,
+ qsHost,
+ qsCustomizerController,
+ mediaHost,
+ metricsLogger,
+ uiEventLogger,
+ qsLogger,
+ dumpManager,
+ splitShadeStateController,
+ longPressEffectProvider,
+ mediaVisible,
+ )
+ }
+
+ private class TestableQSPanelControllerBase(
+ view: QSPanel,
+ qsHost: QSHost,
+ qsCustomizerController: QSCustomizerController,
+ mediaHost: MediaHost,
+ metricsLogger: MetricsLogger,
+ uiEventLogger: UiEventLogger,
+ qsLogger: QSLogger,
+ dumpManager: DumpManager,
+ splitShadeStateController: SplitShadeStateController,
+ longPressEffectProvider: Provider<QSLongPressEffect>,
+ private val mediaVisibleFlow: StateFlow<Boolean>
+ ) :
+ QSPanelControllerBase<QSPanel>(
+ view,
+ qsHost,
+ qsCustomizerController,
+ /* usingMediaPlayer= */ false,
+ mediaHost,
+ metricsLogger,
+ uiEventLogger,
+ qsLogger,
+ dumpManager,
+ splitShadeStateController,
+ longPressEffectProvider
+ ) {
+
+ init {
+ whenever(view.dumpableTag).thenReturn(hashCode().toString())
+ }
+ override fun getMediaVisibleFlow(): StateFlow<Boolean> {
+ return mediaVisibleFlow
+ }
+ }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
index 7c5bc7196b24..225adab04ff0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerBaseTest.java
@@ -17,9 +17,13 @@
package com.android.systemui.qs;
import static com.android.systemui.Flags.FLAG_QUICK_SETTINGS_VISUAL_HAPTICS_LONGPRESS;
+import static com.android.systemui.flags.SceneContainerFlagParameterizationKt.parameterizeSceneContainerFlag;
import static com.google.common.truth.Truth.assertThat;
+import static kotlinx.coroutines.flow.FlowKt.asStateFlow;
+import static kotlinx.coroutines.flow.StateFlowKt.MutableStateFlow;
+
import static org.junit.Assert.assertEquals;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -37,9 +41,10 @@ import android.content.res.Configuration;
import android.content.res.Resources;
import android.platform.test.annotations.DisableFlags;
import android.platform.test.annotations.EnableFlags;
-import android.testing.AndroidTestingRunner;
+import android.platform.test.flag.junit.FlagsParameterization;
import android.testing.TestableLooper.RunWithLooper;
import android.view.ContextThemeWrapper;
+import android.view.ViewTreeObserver;
import androidx.test.filters.SmallTest;
@@ -49,18 +54,26 @@ import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
import com.android.internal.logging.testing.UiEventLoggerFake;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dump.DumpManager;
+import com.android.systemui.flags.DisableSceneContainer;
import com.android.systemui.haptics.qs.QSLongPressEffect;
import com.android.systemui.kosmos.KosmosJavaAdapter;
+import com.android.systemui.lifecycle.InstantTaskExecutorRule;
import com.android.systemui.media.controls.ui.view.MediaHost;
import com.android.systemui.plugins.qs.QSTile;
import com.android.systemui.qs.customize.QSCustomizerController;
import com.android.systemui.qs.logging.QSLogger;
import com.android.systemui.qs.tileimpl.QSTileImpl;
import com.android.systemui.res.R;
+import com.android.systemui.scene.shared.flag.SceneContainerFlag;
import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController;
import com.android.systemui.util.animation.DisappearParameters;
+import kotlinx.coroutines.flow.MutableStateFlow;
+import kotlinx.coroutines.flow.StateFlow;
+
+import org.junit.After;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -73,11 +86,22 @@ import java.util.List;
import javax.inject.Provider;
-@RunWith(AndroidTestingRunner.class)
+import platform.test.runner.parameterized.ParameterizedAndroidJunit4;
+import platform.test.runner.parameterized.Parameters;
+
+@RunWith(ParameterizedAndroidJunit4.class)
@RunWithLooper
@SmallTest
public class QSPanelControllerBaseTest extends SysuiTestCase {
+ @Rule
+ public final InstantTaskExecutorRule mInstantTaskExecutor = new InstantTaskExecutorRule();
+
+ @Parameters(name = "{0}")
+ public static List<FlagsParameterization> getParams() {
+ return parameterizeSceneContainerFlag();
+ }
+
private final KosmosJavaAdapter mKosmos = new KosmosJavaAdapter(this);
@Mock
private QSPanel mQSPanel;
@@ -109,10 +133,13 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
Configuration mConfiguration;
@Mock
Runnable mHorizontalLayoutListener;
+ @Mock
+ private ViewTreeObserver mViewTreeObserver;
+
private TestableLongPressEffectProvider mLongPressEffectProvider =
new TestableLongPressEffectProvider();
- private QSPanelControllerBase<QSPanel> mController;
+ private TestableQSPanelControllerBase mController;
/** Implementation needed to ensure we have a reflectively-available class name. */
private class TestableQSPanelControllerBase extends QSPanelControllerBase<QSPanel> {
@@ -120,15 +147,27 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
QSCustomizerController qsCustomizerController, MediaHost mediaHost,
MetricsLogger metricsLogger, UiEventLogger uiEventLogger, QSLogger qsLogger,
DumpManager dumpManager) {
- super(view, host, qsCustomizerController, true, mediaHost, metricsLogger, uiEventLogger,
+ super(view, host, qsCustomizerController, usingMediaPlayer(),
+ mediaHost, metricsLogger, uiEventLogger,
qsLogger, dumpManager, new ResourcesSplitShadeStateController(),
mLongPressEffectProvider);
}
+ private MutableStateFlow<Boolean> mMediaVisible = MutableStateFlow(false);
+
@Override
protected QSTileRevealController createTileRevealController() {
return mQSTileRevealController;
}
+
+ @Override
+ StateFlow<Boolean> getMediaVisibleFlow() {
+ return asStateFlow(mMediaVisible);
+ }
+
+ void setMediaVisible(boolean visible) {
+ mMediaVisible.tryEmit(visible);
+ }
}
private class TestableLongPressEffectProvider implements Provider<QSLongPressEffect> {
@@ -142,16 +181,24 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
}
}
+ public QSPanelControllerBaseTest(FlagsParameterization flags) {
+ super();
+ mSetFlagsRule.setFlagsParameterization(flags);
+ }
+
@Before
public void setup() throws Exception {
MockitoAnnotations.initMocks(this);
+ allowTestableLooperAsMainThread();
+
when(mQSPanel.isAttachedToWindow()).thenReturn(true);
when(mQSPanel.getDumpableTag()).thenReturn("QSPanel");
when(mQSPanel.openPanelEvent()).thenReturn(QSEvent.QS_PANEL_EXPANDED);
when(mQSPanel.closePanelEvent()).thenReturn(QSEvent.QS_PANEL_COLLAPSED);
when(mQSPanel.getOrCreateTileLayout()).thenReturn(mPagedTileLayout);
when(mQSPanel.getTileLayout()).thenReturn(mPagedTileLayout);
+ when(mQSPanel.getViewTreeObserver()).thenReturn(mViewTreeObserver);
when(mQSTile.getTileSpec()).thenReturn("dnd");
when(mQSHost.getTiles()).thenReturn(Collections.singleton(mQSTile));
when(mQSTileRevealControllerFactory.create(any(), any()))
@@ -174,6 +221,11 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
reset(mQSTileRevealController);
}
+ @After
+ public void tearDown() {
+ disallowTestableLooperAsMainThread();
+ }
+
@Test
public void testSetRevealExpansion_preAttach() {
mController.onViewDetached();
@@ -269,6 +321,7 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
@Test
+ @DisableSceneContainer
public void testShouldUseHorizontalLayout_falseForSplitShade() {
mConfiguration.orientation = Configuration.ORIENTATION_LANDSCAPE;
mConfiguration.screenLayout = Configuration.SCREENLAYOUT_LONG_YES;
@@ -294,6 +347,7 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
}
@Test
+ @DisableSceneContainer
public void testChangeConfiguration_shouldUseHorizontalLayoutInLandscape_true() {
when(mMediaHost.getVisible()).thenReturn(true);
mController.setUsingHorizontalLayoutChangeListener(mHorizontalLayoutListener);
@@ -317,6 +371,7 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
}
@Test
+ @DisableSceneContainer
public void testChangeConfiguration_shouldUseHorizontalLayoutInLongDevices_true() {
when(mMediaHost.getVisible()).thenReturn(true);
mController.setUsingHorizontalLayoutChangeListener(mHorizontalLayoutListener);
@@ -353,6 +408,7 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
}
@Test
+ @DisableSceneContainer
public void configurationChange_onlySplitShadeConfigChanges_horizontalLayoutStatusUpdated() {
// Preconditions for horizontal layout
when(mMediaHost.getVisible()).thenReturn(true);
@@ -514,4 +570,8 @@ public class QSPanelControllerBaseTest extends SysuiTestCase {
assertThat(mController.mRecords).isEmpty();
}
+
+ private boolean usingMediaPlayer() {
+ return !SceneContainerFlag.isEnabled();
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
index e50320df2740..545d19dd771e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.kt
@@ -10,6 +10,7 @@ import com.android.internal.logging.UiEventLogger
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
import com.android.systemui.haptics.qs.QSLongPressEffect
+import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor
import com.android.systemui.media.controls.ui.view.MediaHost
import com.android.systemui.media.controls.ui.view.MediaHostState
import com.android.systemui.plugins.FalsingManager
@@ -17,6 +18,7 @@ import com.android.systemui.plugins.qs.QSTile
import com.android.systemui.qs.customize.QSCustomizerController
import com.android.systemui.qs.logging.QSLogger
import com.android.systemui.res.R
+import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.settings.brightness.BrightnessController
import com.android.systemui.settings.brightness.BrightnessSliderController
import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
@@ -63,6 +65,9 @@ class QSPanelControllerTest : SysuiTestCase() {
@Mock private lateinit var configuration: Configuration
@Mock private lateinit var pagedTileLayout: PagedTileLayout
@Mock private lateinit var longPressEffectProvider: Provider<QSLongPressEffect>
+ @Mock private lateinit var mediaCarouselInteractor: MediaCarouselInteractor
+
+ private val usingMediaPlayer: Boolean by lazy { !SceneContainerFlag.isEnabled }
private lateinit var controller: QSPanelController
private val testableResources: TestableResources = mContext.orCreateTestableResources
@@ -88,7 +93,7 @@ class QSPanelControllerTest : SysuiTestCase() {
tunerService,
qsHost,
qsCustomizerController,
- /* usingMediaPlayer= */ true,
+ /* usingMediaPlayer= */ usingMediaPlayer,
mediaHost,
qsTileRevealControllerFactory,
dumpManager,
@@ -101,6 +106,7 @@ class QSPanelControllerTest : SysuiTestCase() {
statusBarKeyguardViewManager,
ResourcesSplitShadeStateController(),
longPressEffectProvider,
+ mediaCarouselInteractor,
)
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt
index 5c6ed70c85a6..e2a4d6727e80 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelTest.kt
@@ -275,6 +275,19 @@ class QSPanelTest : SysuiTestCase() {
ViewUtils.detachView(panel)
}
+ @Test
+ fun setRowColumnLayout() {
+ qsPanel.setColumnRowLayout(/* withMedia= */ false)
+
+ assertThat(qsPanel.tileLayout!!.minRows).isEqualTo(1)
+ assertThat(qsPanel.tileLayout!!.maxColumns).isEqualTo(4)
+
+ qsPanel.setColumnRowLayout(/* withMedia= */ true)
+
+ assertThat(qsPanel.tileLayout!!.minRows).isEqualTo(2)
+ assertThat(qsPanel.tileLayout!!.maxColumns).isEqualTo(2)
+ }
+
private infix fun View.isLeftOf(other: View): Boolean {
val rect = Rect()
getBoundsOnScreen(rect)
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 1eb0a51bcaf6..fee4b534d8dd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QuickQSPanelControllerTest.kt
@@ -25,6 +25,7 @@ import com.android.internal.logging.testing.UiEventLoggerFake
import com.android.systemui.SysuiTestCase
import com.android.systemui.dump.DumpManager
import com.android.systemui.haptics.qs.QSLongPressEffect
+import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor
import com.android.systemui.media.controls.ui.view.MediaHost
import com.android.systemui.media.controls.ui.view.MediaHostState
import com.android.systemui.plugins.qs.QSTile
@@ -62,6 +63,10 @@ class QuickQSPanelControllerTest : SysuiTestCase() {
@Mock private lateinit var tileLayout: TileLayout
@Captor private lateinit var captor: ArgumentCaptor<QSPanel.OnConfigurationChangedListener>
@Mock private lateinit var longPressEffectProvider: Provider<QSLongPressEffect>
+ @Mock private lateinit var mediaCarouselInteractor: MediaCarouselInteractor
+
+ private val usingMediaPlayer: Boolean
+ get() = false
private val uiEventLogger = UiEventLoggerFake()
private val dumpManager = DumpManager()
@@ -86,7 +91,7 @@ class QuickQSPanelControllerTest : SysuiTestCase() {
quickQSPanel,
qsHost,
qsCustomizerController,
- /* usingMediaPlayer = */ false,
+ usingMediaPlayer,
mediaHost,
{ usingCollapsedLandscapeMedia },
metricsLogger,
@@ -94,6 +99,7 @@ class QuickQSPanelControllerTest : SysuiTestCase() {
qsLogger,
dumpManager,
longPressEffectProvider,
+ mediaCarouselInteractor,
)
controller.init()
@@ -163,6 +169,7 @@ class QuickQSPanelControllerTest : SysuiTestCase() {
qsLogger: QSLogger,
dumpManager: DumpManager,
longPressEffectProvider: Provider<QSLongPressEffect>,
+ mediaCarouselInteractor: MediaCarouselInteractor,
) :
QuickQSPanelController(
view,
@@ -177,6 +184,7 @@ class QuickQSPanelControllerTest : SysuiTestCase() {
dumpManager,
ResourcesSplitShadeStateController(),
longPressEffectProvider,
+ mediaCarouselInteractor
) {
private var rotation = RotationUtils.ROTATION_NONE