diff options
5 files changed, 275 insertions, 151 deletions
diff --git a/packages/SystemUI/aconfig/systemui.aconfig b/packages/SystemUI/aconfig/systemui.aconfig index c49ffb49a1da..c1d8d554acdf 100644 --- a/packages/SystemUI/aconfig/systemui.aconfig +++ b/packages/SystemUI/aconfig/systemui.aconfig @@ -1128,6 +1128,16 @@ flag { } flag { + name: "media_controls_umo_inflation_in_background" + namespace: "systemui" + description: "Inflate UMO in background thread" + bug: "368514198" + metadata { + purpose: PURPOSE_BUGFIX + } +} + +flag { namespace: "systemui" name: "enable_view_capture_tracing" description: "Enables view capture tracing in System UI." @@ -1431,4 +1441,4 @@ flag { metadata { purpose: PURPOSE_BUGFIX } -}
\ No newline at end of file +} diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt index bb9517a14142..bbe3d241f007 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt @@ -16,6 +16,7 @@ package com.android.systemui.media.controls.ui.controller +import android.annotation.WorkerThread import android.app.PendingIntent import android.content.Context import android.content.Intent @@ -41,6 +42,7 @@ import com.android.internal.logging.InstanceId import com.android.keyguard.KeyguardUpdateMonitor import com.android.keyguard.KeyguardUpdateMonitorCallback import com.android.systemui.Dumpable +import com.android.systemui.Flags.mediaControlsUmoInflationInBackground import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Background @@ -136,7 +138,7 @@ constructor( private val activityStarter: ActivityStarter, private val systemClock: SystemClock, @Main private val mainDispatcher: CoroutineDispatcher, - @Main executor: DelayableExecutor, + @Main private val uiExecutor: DelayableExecutor, @Background private val bgExecutor: Executor, @Background private val backgroundDispatcher: CoroutineDispatcher, private val mediaManager: MediaDataManager, @@ -224,7 +226,7 @@ constructor( private var carouselLocale: Locale? = null private val animationScaleObserver: ContentObserver = - object : ContentObserver(executor, 0) { + object : ContentObserver(uiExecutor, 0) { override fun onChange(selfChange: Boolean) { if (!SceneContainerFlag.isEnabled) { MediaPlayerData.players().forEach { it.updateAnimatorDurationScale() } @@ -347,7 +349,7 @@ constructor( MediaCarouselScrollHandler( mediaCarousel, pageIndicator, - executor, + uiExecutor, this::onSwipeToDismiss, this::updatePageIndicatorLocation, this::updateSeekbarListening, @@ -455,7 +457,17 @@ constructor( isSsReactivated: Boolean, ) { debugLogger.logMediaLoaded(key, data.active) - if (addOrUpdatePlayer(key, oldKey, data, isSsReactivated)) { + val onUiExecutionEnd = + if (mediaControlsUmoInflationInBackground()) { + Runnable { + if (immediately) { + updateHostVisibility() + } + } + } else { + null + } + if (addOrUpdatePlayer(key, oldKey, data, isSsReactivated, onUiExecutionEnd)) { // Log card received if a new resumable media card is added MediaPlayerData.getMediaPlayer(key)?.let { logSmartspaceCardReported( @@ -970,6 +982,7 @@ constructor( oldKey: String?, data: MediaData, isSsReactivated: Boolean, + onUiExecutionEnd: Runnable? = null, ): Boolean = traceSection("MediaCarouselController#addOrUpdatePlayer") { MediaPlayerData.moveIfExists(oldKey, key) @@ -977,76 +990,119 @@ constructor( val curVisibleMediaKey = MediaPlayerData.visiblePlayerKeys() .elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex) - if (existingPlayer == null) { - val newPlayer = mediaControlPanelFactory.get() - if (SceneContainerFlag.isEnabled) { - newPlayer.mediaViewController.widthInSceneContainerPx = widthInSceneContainerPx - newPlayer.mediaViewController.heightInSceneContainerPx = - heightInSceneContainerPx - } - newPlayer.attachPlayer( - MediaViewHolder.create(LayoutInflater.from(context), mediaContent) - ) - newPlayer.mediaViewController.sizeChangedListener = this::updateCarouselDimensions - val lp = - LinearLayout.LayoutParams( - ViewGroup.LayoutParams.MATCH_PARENT, - ViewGroup.LayoutParams.WRAP_CONTENT, - ) - newPlayer.mediaViewHolder?.player?.setLayoutParams(lp) - newPlayer.bindPlayer(data, key) - newPlayer.setListening( - mediaCarouselScrollHandler.visibleToUser && currentlyExpanded - ) - MediaPlayerData.addMediaPlayer( - key, - data, - newPlayer, - systemClock, - isSsReactivated, - debugLogger, - ) - updateViewControllerToState(newPlayer.mediaViewController, noAnimation = true) - // Media data added from a recommendation card should starts playing. - if ( - (shouldScrollToKey && data.isPlaying == true) || - (!shouldScrollToKey && data.active) - ) { - reorderAllPlayers(curVisibleMediaKey, key) + if (mediaControlsUmoInflationInBackground()) { + if (existingPlayer == null) { + bgExecutor.execute { + val mediaViewHolder = createMediaViewHolderInBg() + // Add the new player in the main thread. + uiExecutor.execute { + setupNewPlayer( + key, + data, + isSsReactivated, + curVisibleMediaKey, + mediaViewHolder, + ) + updatePageIndicator() + mediaCarouselScrollHandler.onPlayersChanged() + mediaFrame.requiresRemeasuring = true + onUiExecutionEnd?.run() + } + } } else { - needsReordering = true + updatePlayer(key, data, isSsReactivated, curVisibleMediaKey, existingPlayer) + updatePageIndicator() + mediaCarouselScrollHandler.onPlayersChanged() + mediaFrame.requiresRemeasuring = true + onUiExecutionEnd?.run() } } else { - existingPlayer.bindPlayer(data, key) - MediaPlayerData.addMediaPlayer( - key, - data, - existingPlayer, - systemClock, - isSsReactivated, - debugLogger, - ) - val packageName = MediaPlayerData.smartspaceMediaData?.packageName ?: String() - // In case of recommendations hits. - // Check the playing status of media player and the package name. - // To make sure we scroll to the right app's media player. - if ( - isReorderingAllowed || - shouldScrollToKey && - data.isPlaying == true && - packageName == data.packageName - ) { - reorderAllPlayers(curVisibleMediaKey, key) + if (existingPlayer == null) { + val mediaViewHolder = + MediaViewHolder.create(LayoutInflater.from(context), mediaContent) + setupNewPlayer(key, data, isSsReactivated, curVisibleMediaKey, mediaViewHolder) } else { - needsReordering = true + updatePlayer(key, data, isSsReactivated, curVisibleMediaKey, existingPlayer) } + updatePageIndicator() + mediaCarouselScrollHandler.onPlayersChanged() + mediaFrame.requiresRemeasuring = true + onUiExecutionEnd?.run() } - updatePageIndicator() - mediaCarouselScrollHandler.onPlayersChanged() - mediaFrame.requiresRemeasuring = true return existingPlayer == null } + private fun updatePlayer( + key: String, + data: MediaData, + isSsReactivated: Boolean, + curVisibleMediaKey: MediaPlayerData.MediaSortKey?, + existingPlayer: MediaControlPanel, + ) { + existingPlayer.bindPlayer(data, key) + MediaPlayerData.addMediaPlayer( + key, + data, + existingPlayer, + systemClock, + isSsReactivated, + debugLogger, + ) + val packageName = MediaPlayerData.smartspaceMediaData?.packageName ?: String() + // In case of recommendations hits. + // Check the playing status of media player and the package name. + // To make sure we scroll to the right app's media player. + if ( + isReorderingAllowed || + shouldScrollToKey && data.isPlaying == true && packageName == data.packageName + ) { + reorderAllPlayers(curVisibleMediaKey, key) + } else { + needsReordering = true + } + } + + private fun setupNewPlayer( + key: String, + data: MediaData, + isSsReactivated: Boolean, + curVisibleMediaKey: MediaPlayerData.MediaSortKey?, + mediaViewHolder: MediaViewHolder, + ) { + val newPlayer = mediaControlPanelFactory.get() + newPlayer.attachPlayer(mediaViewHolder) + newPlayer.mediaViewController.sizeChangedListener = + this@MediaCarouselController::updateCarouselDimensions + val lp = + LinearLayout.LayoutParams( + ViewGroup.LayoutParams.MATCH_PARENT, + ViewGroup.LayoutParams.WRAP_CONTENT, + ) + newPlayer.mediaViewHolder?.player?.setLayoutParams(lp) + newPlayer.bindPlayer(data, key) + newPlayer.setListening(mediaCarouselScrollHandler.visibleToUser && currentlyExpanded) + MediaPlayerData.addMediaPlayer( + key, + data, + newPlayer, + systemClock, + isSsReactivated, + debugLogger, + ) + updateViewControllerToState(newPlayer.mediaViewController, noAnimation = true) + // Media data added from a recommendation card should starts playing. + if ((shouldScrollToKey && data.isPlaying == true) || (!shouldScrollToKey && data.active)) { + reorderAllPlayers(curVisibleMediaKey, key) + } else { + needsReordering = true + } + } + + @WorkerThread + private fun createMediaViewHolderInBg(): MediaViewHolder { + return MediaViewHolder.create(LayoutInflater.from(context), mediaContent) + } + private fun addSmartspaceMediaRecommendations( key: String, data: SmartspaceMediaData, @@ -1163,8 +1219,16 @@ constructor( val previousVisibleKey = MediaPlayerData.visiblePlayerKeys() .elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex) + val onUiExecutionEnd = Runnable { + if (recreateMedia) { + reorderAllPlayers(previousVisibleKey) + } + } - MediaPlayerData.mediaData().forEach { (key, data, isSsMediaRec) -> + val mediaDataList = MediaPlayerData.mediaData() + // Do not loop through the original list of media data because the re-addition of media data + // is being executed in background thread. + mediaDataList.forEach { (key, data, isSsMediaRec) -> if (isSsMediaRec) { val smartspaceMediaData = MediaPlayerData.smartspaceMediaData removePlayer(key, dismissMediaData = false, dismissRecommendation = false) @@ -1175,6 +1239,7 @@ constructor( MediaPlayerData.shouldPrioritizeSs, ) } + onUiExecutionEnd.run() } else { val isSsReactivated = MediaPlayerData.isSsReactivated(key) if (recreateMedia) { @@ -1185,11 +1250,9 @@ constructor( oldKey = null, data = data, isSsReactivated = isSsReactivated, + onUiExecutionEnd = onUiExecutionEnd, ) } - if (recreateMedia) { - reorderAllPlayers(previousVisibleKey) - } } } diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHostStatesManager.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHostStatesManager.kt index 8660d12bcb85..782da4bd6a41 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHostStatesManager.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaHostStatesManager.kt @@ -17,6 +17,7 @@ package com.android.systemui.media.controls.ui.controller import com.android.app.tracing.traceSection +import com.android.systemui.Flags.mediaControlsUmoInflationInBackground import com.android.systemui.dagger.SysUISingleton import com.android.systemui.media.controls.ui.view.MediaHostState import com.android.systemui.util.animation.MeasurementOutput @@ -71,23 +72,34 @@ class MediaHostStatesManager @Inject constructor() { */ fun updateCarouselDimensions( @MediaLocation location: Int, - hostState: MediaHostState + hostState: MediaHostState, ): MeasurementOutput = traceSection("MediaHostStatesManager#updateCarouselDimensions") { val result = MeasurementOutput(0, 0) + var changed = false for (controller in controllers) { val measurement = controller.getMeasurementsForState(hostState) measurement?.let { if (it.measuredHeight > result.measuredHeight) { result.measuredHeight = it.measuredHeight + changed = true } if (it.measuredWidth > result.measuredWidth) { result.measuredWidth = it.measuredWidth + changed = true } } } - carouselSizes[location] = result - return result + if (mediaControlsUmoInflationInBackground()) { + // Set carousel size if result measurements changed. This avoids setting carousel + // size when this method gets called before the addition of media view controllers + if (!carouselSizes.contains(location) || changed) { + carouselSizes[location] = result + } + } else { + carouselSizes[location] = result + } + return carouselSizes[location] ?: result } /** Add a callback to be called when a MediaState has updated */ diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/view/MediaHost.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/view/MediaHost.kt index 09a618110f21..5ddc3470da43 100644 --- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/view/MediaHost.kt +++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/view/MediaHost.kt @@ -20,6 +20,7 @@ import android.graphics.Rect import android.util.ArraySet import android.view.View import android.view.View.OnAttachStateChangeListener +import com.android.systemui.Flags.mediaControlsUmoInflationInBackground import com.android.systemui.media.controls.domain.pipeline.MediaDataManager import com.android.systemui.media.controls.shared.model.MediaData import com.android.systemui.media.controls.shared.model.SmartspaceMediaData @@ -91,8 +92,10 @@ class MediaHost( data: MediaData, immediately: Boolean, receivedSmartspaceCardLatency: Int, - isSsReactivated: Boolean + isSsReactivated: Boolean, ) { + if (mediaControlsUmoInflationInBackground()) return + if (immediately) { updateViewVisibility() } @@ -101,7 +104,7 @@ class MediaHost( override fun onSmartspaceMediaDataLoaded( key: String, data: SmartspaceMediaData, - shouldPrioritize: Boolean + shouldPrioritize: Boolean, ) { updateViewVisibility() } @@ -171,7 +174,7 @@ class MediaHost( input.widthMeasureSpec = View.MeasureSpec.makeMeasureSpec( View.MeasureSpec.getSize(input.widthMeasureSpec), - View.MeasureSpec.EXACTLY + View.MeasureSpec.EXACTLY, ) } // This will trigger a state change that ensures that we now have a state diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt index 03667cfb8a3b..570c64065c4a 100644 --- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt +++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt @@ -21,19 +21,19 @@ import android.content.res.ColorStateList import android.content.res.Configuration import android.database.ContentObserver import android.os.LocaleList +import android.platform.test.flag.junit.FlagsParameterization import android.provider.Settings import android.testing.TestableLooper import android.util.MathUtils.abs import android.view.View -import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.compose.animation.scene.ObservableTransitionState import com.android.compose.animation.scene.SceneKey import com.android.internal.logging.InstanceId import com.android.keyguard.KeyguardUpdateMonitor import com.android.keyguard.KeyguardUpdateMonitorCallback +import com.android.systemui.Flags.mediaControlsUmoInflationInBackground import com.android.systemui.SysuiTestCase -import com.android.systemui.dagger.qualifiers.Main import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor import com.android.systemui.dump.DumpManager import com.android.systemui.flags.DisableSceneContainer @@ -71,7 +71,6 @@ import com.android.systemui.statusbar.notification.collection.provider.OnReorder import com.android.systemui.statusbar.notification.collection.provider.VisualStabilityProvider import com.android.systemui.statusbar.policy.ConfigurationController import com.android.systemui.testKosmos -import com.android.systemui.util.concurrency.DelayableExecutor import com.android.systemui.util.concurrency.FakeExecutor import com.android.systemui.util.settings.GlobalSettings import com.android.systemui.util.settings.unconfinedDispatcherFakeSettings @@ -106,6 +105,8 @@ import org.mockito.MockitoAnnotations import org.mockito.kotlin.any import org.mockito.kotlin.capture import org.mockito.kotlin.eq +import platform.test.runner.parameterized.ParameterizedAndroidJunit4 +import platform.test.runner.parameterized.Parameters private val DATA = MediaTestUtils.emptyMediaData @@ -116,8 +117,8 @@ private const val PLAYING_LOCAL = "playing local" @ExperimentalCoroutinesApi @SmallTest @TestableLooper.RunWithLooper(setAsMainLooper = true) -@RunWith(AndroidJUnit4::class) -class MediaCarouselControllerTest : SysuiTestCase() { +@RunWith(ParameterizedAndroidJunit4::class) +class MediaCarouselControllerTest(flags: FlagsParameterization) : SysuiTestCase() { private val kosmos = testKosmos() private val testDispatcher = kosmos.unconfinedTestDispatcher private val secureSettings = kosmos.unconfinedDispatcherFakeSettings @@ -129,7 +130,6 @@ class MediaCarouselControllerTest : SysuiTestCase() { @Mock lateinit var mediaHostStatesManager: MediaHostStatesManager @Mock lateinit var mediaHostState: MediaHostState @Mock lateinit var activityStarter: ActivityStarter - @Mock @Main private lateinit var executor: DelayableExecutor @Mock lateinit var mediaDataManager: MediaDataManager @Mock lateinit var configurationController: ConfigurationController @Mock lateinit var falsingManager: FalsingManager @@ -153,16 +153,33 @@ class MediaCarouselControllerTest : SysuiTestCase() { private val clock = FakeSystemClock() private lateinit var bgExecutor: FakeExecutor + private lateinit var uiExecutor: FakeExecutor private lateinit var mediaCarouselController: MediaCarouselController private var originalResumeSetting = Settings.Secure.getInt(context.contentResolver, Settings.Secure.MEDIA_CONTROLS_RESUME, 1) + companion object { + @JvmStatic + @Parameters(name = "{0}") + fun getParams(): List<FlagsParameterization> { + return FlagsParameterization.progressionOf( + com.android.systemui.Flags.FLAG_MEDIA_CONTROLS_UMO_INFLATION_IN_BACKGROUND + ) + } + } + + init { + mSetFlagsRule.setFlagsParameterization(flags) + } + @Before fun setup() { MockitoAnnotations.initMocks(this) context.resources.configuration.setLocales(LocaleList(Locale.US, Locale.UK)) bgExecutor = FakeExecutor(clock) + uiExecutor = FakeExecutor(clock) + mediaCarouselController = MediaCarouselController( applicationScope = kosmos.applicationCoroutineScope, @@ -173,7 +190,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { activityStarter = activityStarter, systemClock = clock, mainDispatcher = kosmos.testDispatcher, - executor = executor, + uiExecutor = uiExecutor, bgExecutor = bgExecutor, backgroundDispatcher = testDispatcher, mediaManager = mediaDataManager, @@ -201,10 +218,11 @@ class MediaCarouselControllerTest : SysuiTestCase() { whenever(mediaFlags.isPersistentSsCardEnabled()).thenReturn(false) MediaPlayerData.clear() FakeExecutor.exhaustExecutors(bgExecutor) + FakeExecutor.exhaustExecutors(uiExecutor) verify(globalSettings) .registerContentObserverSync( eq(Settings.Global.getUriFor(Settings.Global.ANIMATOR_DURATION_SCALE)), - capture(settingsObserverCaptor) + capture(settingsObserverCaptor), ) } @@ -213,7 +231,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { Settings.Secure.putInt( context.contentResolver, Settings.Secure.MEDIA_CONTROLS_RESUME, - originalResumeSetting + originalResumeSetting, ) } @@ -227,9 +245,9 @@ class MediaCarouselControllerTest : SysuiTestCase() { active = true, isPlaying = true, playbackLocation = MediaData.PLAYBACK_LOCAL, - resumption = false + resumption = false, ), - 4500L + 4500L, ) val playingCast = @@ -239,9 +257,9 @@ class MediaCarouselControllerTest : SysuiTestCase() { active = true, isPlaying = true, playbackLocation = MediaData.PLAYBACK_CAST_LOCAL, - resumption = false + resumption = false, ), - 5000L + 5000L, ) val pausedLocal = @@ -251,9 +269,9 @@ class MediaCarouselControllerTest : SysuiTestCase() { active = true, isPlaying = false, playbackLocation = MediaData.PLAYBACK_LOCAL, - resumption = false + resumption = false, ), - 1000L + 1000L, ) val pausedCast = @@ -263,9 +281,9 @@ class MediaCarouselControllerTest : SysuiTestCase() { active = true, isPlaying = false, playbackLocation = MediaData.PLAYBACK_CAST_LOCAL, - resumption = false + resumption = false, ), - 2000L + 2000L, ) val playingRcn = @@ -275,9 +293,9 @@ class MediaCarouselControllerTest : SysuiTestCase() { active = true, isPlaying = true, playbackLocation = MediaData.PLAYBACK_CAST_REMOTE, - resumption = false + resumption = false, ), - 5000L + 5000L, ) val pausedRcn = @@ -287,9 +305,9 @@ class MediaCarouselControllerTest : SysuiTestCase() { active = true, isPlaying = false, playbackLocation = MediaData.PLAYBACK_CAST_REMOTE, - resumption = false + resumption = false, ), - 5000L + 5000L, ) val active = @@ -299,9 +317,9 @@ class MediaCarouselControllerTest : SysuiTestCase() { active = true, isPlaying = false, playbackLocation = MediaData.PLAYBACK_LOCAL, - resumption = true + resumption = true, ), - 250L + 250L, ) val resume1 = @@ -311,9 +329,9 @@ class MediaCarouselControllerTest : SysuiTestCase() { active = false, isPlaying = false, playbackLocation = MediaData.PLAYBACK_LOCAL, - resumption = true + resumption = true, ), - 500L + 500L, ) val resume2 = @@ -323,9 +341,9 @@ class MediaCarouselControllerTest : SysuiTestCase() { active = false, isPlaying = false, playbackLocation = MediaData.PLAYBACK_LOCAL, - resumption = true + resumption = true, ), - 1000L + 1000L, ) val activeMoreRecent = @@ -336,9 +354,9 @@ class MediaCarouselControllerTest : SysuiTestCase() { isPlaying = false, playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = true, - lastActive = 2L + lastActive = 2L, ), - 1000L + 1000L, ) val activeLessRecent = @@ -349,9 +367,9 @@ class MediaCarouselControllerTest : SysuiTestCase() { isPlaying = false, playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = true, - lastActive = 1L + lastActive = 1L, ), - 1000L + 1000L, ) // Expected ordering for media players: // Actively playing local sessions @@ -370,7 +388,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { pausedRcn, active, resume2, - resume1 + resume1, ) expected.forEach { @@ -380,7 +398,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { it.second.copy(notificationKey = it.first), panel, clock, - isSsReactivated = false + isSsReactivated = false, ) } @@ -403,7 +421,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { EMPTY_SMARTSPACE_MEDIA_DATA.copy(isActive = true), panel, true, - clock + clock, ) // Then it should be shown immediately after any actively playing controls @@ -421,7 +439,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { listener.value.onSmartspaceMediaDataLoaded( SMARTSPACE_KEY, EMPTY_SMARTSPACE_MEDIA_DATA.copy(isActive = true), - true + true, ) // Then it should be shown immediately after any actively playing controls @@ -439,7 +457,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { EMPTY_SMARTSPACE_MEDIA_DATA.copy(isActive = true), panel, false, - clock + clock, ) // Then it should be shown at the end of the carousel's active entries @@ -461,8 +479,8 @@ class MediaCarouselControllerTest : SysuiTestCase() { active = true, isPlaying = true, playbackLocation = MediaData.PLAYBACK_LOCAL, - resumption = false - ) + resumption = false, + ), ) listener.value.onMediaDataLoaded( PLAYING_LOCAL, @@ -471,19 +489,20 @@ class MediaCarouselControllerTest : SysuiTestCase() { active = true, isPlaying = false, playbackLocation = MediaData.PLAYBACK_LOCAL, - resumption = true - ) + resumption = true, + ), ) + runAllReady() assertEquals( MediaPlayerData.getMediaPlayerIndex(PAUSED_LOCAL), - mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex + mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex, ) // paused player order should stays the same in visibleMediaPLayer map. // paused player order should be first in mediaPlayer map. assertEquals( MediaPlayerData.visiblePlayerKeys().elementAt(3), - MediaPlayerData.playerKeys().elementAt(0) + MediaPlayerData.playerKeys().elementAt(0), ) } @@ -506,7 +525,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { mediaCarouselController.onDesiredLocationChanged( LOCATION_QS, mediaHostState, - animate = false + animate = false, ) bgExecutor.runAllReady() verify(logger).logCarouselPosition(LOCATION_QS) @@ -517,7 +536,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { mediaCarouselController.onDesiredLocationChanged( MediaHierarchyManager.LOCATION_QQS, mediaHostState, - animate = false + animate = false, ) bgExecutor.runAllReady() verify(logger).logCarouselPosition(MediaHierarchyManager.LOCATION_QQS) @@ -528,7 +547,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { mediaCarouselController.onDesiredLocationChanged( MediaHierarchyManager.LOCATION_LOCKSCREEN, mediaHostState, - animate = false + animate = false, ) bgExecutor.runAllReady() verify(logger).logCarouselPosition(MediaHierarchyManager.LOCATION_LOCKSCREEN) @@ -539,7 +558,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { mediaCarouselController.onDesiredLocationChanged( MediaHierarchyManager.LOCATION_DREAM_OVERLAY, mediaHostState, - animate = false + animate = false, ) bgExecutor.runAllReady() verify(logger).logCarouselPosition(MediaHierarchyManager.LOCATION_DREAM_OVERLAY) @@ -570,8 +589,8 @@ class MediaCarouselControllerTest : SysuiTestCase() { active = true, isPlaying = true, playbackLocation = MediaData.PLAYBACK_LOCAL, - resumption = false - ) + resumption = false, + ), ) listener.value.onMediaDataLoaded( PAUSED_LOCAL, @@ -580,14 +599,15 @@ class MediaCarouselControllerTest : SysuiTestCase() { active = true, isPlaying = false, playbackLocation = MediaData.PLAYBACK_LOCAL, - resumption = false - ) + resumption = false, + ), ) + runAllReady() // adding a media recommendation card. listener.value.onSmartspaceMediaDataLoaded( SMARTSPACE_KEY, EMPTY_SMARTSPACE_MEDIA_DATA, - false + false, ) mediaCarouselController.shouldScrollToKey = true // switching between media players. @@ -598,8 +618,8 @@ class MediaCarouselControllerTest : SysuiTestCase() { active = true, isPlaying = false, playbackLocation = MediaData.PLAYBACK_LOCAL, - resumption = true - ) + resumption = true, + ), ) listener.value.onMediaDataLoaded( PAUSED_LOCAL, @@ -608,13 +628,14 @@ class MediaCarouselControllerTest : SysuiTestCase() { active = true, isPlaying = true, playbackLocation = MediaData.PLAYBACK_LOCAL, - resumption = false - ) + resumption = false, + ), ) + runAllReady() assertEquals( MediaPlayerData.getMediaPlayerIndex(PAUSED_LOCAL), - mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex + mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex, ) } @@ -626,7 +647,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { listener.value.onSmartspaceMediaDataLoaded( SMARTSPACE_KEY, EMPTY_SMARTSPACE_MEDIA_DATA.copy(packageName = "PACKAGE_NAME", isActive = true), - false + false, ) listener.value.onMediaDataLoaded( PLAYING_LOCAL, @@ -635,14 +656,15 @@ class MediaCarouselControllerTest : SysuiTestCase() { active = true, isPlaying = true, playbackLocation = MediaData.PLAYBACK_LOCAL, - resumption = false - ) + resumption = false, + ), ) + runAllReady() var playerIndex = MediaPlayerData.getMediaPlayerIndex(PLAYING_LOCAL) assertEquals( playerIndex, - mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex + mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex, ) assertEquals(playerIndex, 0) @@ -657,9 +679,10 @@ class MediaCarouselControllerTest : SysuiTestCase() { isPlaying = true, playbackLocation = MediaData.PLAYBACK_LOCAL, resumption = false, - packageName = "PACKAGE_NAME" - ) + packageName = "PACKAGE_NAME", + ), ) + runAllReady() playerIndex = MediaPlayerData.getMediaPlayerIndex(PLAYING_LOCAL) assertEquals(playerIndex, 0) } @@ -704,7 +727,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { player1.second.copy(notificationKey = player1.first), panel, clock, - isSsReactivated = false + isSsReactivated = false, ) assertEquals(mediaCarouselController.getCurrentVisibleMediaContentIntent(), clickIntent1) @@ -717,7 +740,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { player2.second.copy(notificationKey = player2.first), panel, clock, - isSsReactivated = false + isSsReactivated = false, ) // mediaCarouselScrollHandler.visibleMediaIndex is unchanged (= 0), and the new player is @@ -732,7 +755,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { player3.second.copy(notificationKey = player3.first), panel, clock, - isSsReactivated = false + isSsReactivated = false, ) // mediaCarouselScrollHandler.visibleMediaIndex is unchanged (= 0), and the new player is @@ -822,7 +845,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { listener.value.onSmartspaceMediaDataLoaded( SMARTSPACE_KEY, EMPTY_SMARTSPACE_MEDIA_DATA.copy(isActive = true), - true + true, ) // Then the carousel is updated @@ -841,7 +864,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { listener.value.onSmartspaceMediaDataLoaded( SMARTSPACE_KEY, EMPTY_SMARTSPACE_MEDIA_DATA, - false + false, ) // Then it is added to the carousel with correct state @@ -886,7 +909,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { transitionRepository.sendTransitionSteps( from = KeyguardState.LOCKSCREEN, to = KeyguardState.GONE, - this + this, ) verify(mediaCarousel).visibility = View.VISIBLE @@ -932,7 +955,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { transitionRepository.sendTransitionSteps( from = KeyguardState.GONE, to = KeyguardState.LOCKSCREEN, - this + this, ) assertEquals(true, updatedVisibility) @@ -961,7 +984,7 @@ class MediaCarouselControllerTest : SysuiTestCase() { transitionRepository.sendTransitionSteps( from = KeyguardState.GONE, to = KeyguardState.LOCKSCREEN, - this + this, ) assertEquals(true, updatedVisibility) @@ -1125,12 +1148,14 @@ class MediaCarouselControllerTest : SysuiTestCase() { Settings.Secure.putInt(context.contentResolver, Settings.Secure.MEDIA_CONTROLS_RESUME, 0) val pausedMedia = DATA.copy(isPlaying = false) listener.value.onMediaDataLoaded(PAUSED_LOCAL, PAUSED_LOCAL, pausedMedia) + runAllReady() mediaCarouselController.onSwipeToDismiss() // When it can be removed immediately on update whenever(visualStabilityProvider.isReorderingAllowed).thenReturn(true) val inactiveMedia = pausedMedia.copy(active = false) listener.value.onMediaDataLoaded(PAUSED_LOCAL, PAUSED_LOCAL, inactiveMedia) + runAllReady() // This is processed as a user-initiated dismissal verify(debugLogger).logMediaRemoved(eq(PAUSED_LOCAL), eq(true)) @@ -1148,12 +1173,14 @@ class MediaCarouselControllerTest : SysuiTestCase() { val pausedMedia = DATA.copy(isPlaying = false) listener.value.onMediaDataLoaded(PAUSED_LOCAL, PAUSED_LOCAL, pausedMedia) + runAllReady() mediaCarouselController.onSwipeToDismiss() // When it can't be removed immediately on update whenever(visualStabilityProvider.isReorderingAllowed).thenReturn(false) val inactiveMedia = pausedMedia.copy(active = false) listener.value.onMediaDataLoaded(PAUSED_LOCAL, PAUSED_LOCAL, inactiveMedia) + runAllReady() visualStabilityCallback.value.onReorderingAllowed() // This is processed as a user-initiated dismissal @@ -1175,8 +1202,8 @@ class MediaCarouselControllerTest : SysuiTestCase() { active = true, isPlaying = true, playbackLocation = MediaData.PLAYBACK_LOCAL, - resumption = false - ) + resumption = false, + ), ) listener.value.onMediaDataLoaded( PAUSED_LOCAL, @@ -1185,18 +1212,20 @@ class MediaCarouselControllerTest : SysuiTestCase() { active = true, isPlaying = false, playbackLocation = MediaData.PLAYBACK_LOCAL, - resumption = false - ) + resumption = false, + ), ) + runAllReady() val playersSize = MediaPlayerData.players().size reset(pageIndicator) function() + runAllReady() assertEquals(playersSize, MediaPlayerData.players().size) assertEquals( MediaPlayerData.getMediaPlayerIndex(PLAYING_LOCAL), - mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex + mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex, ) } @@ -1225,4 +1254,11 @@ class MediaCarouselControllerTest : SysuiTestCase() { ) runCurrent() } + + private fun runAllReady() { + if (mediaControlsUmoInflationInBackground()) { + bgExecutor.runAllReady() + uiExecutor.runAllReady() + } + } } |