Make sure views are added back when updating

This CL uses controllerById instead of controllerByViewModel because new
MediaCommonViewModels has updateTime field that gets changed. We cannot
rely on view model as a key anymore. We can use instance Id instead.

Flag: com.android.systemui.scene_container
Bug: 358097462
Test: checked UI using two media players.
Change-Id: I8e3a6a87bbee6ef7f5a13197821699d494084a3f
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 62a7218..c21301c 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
@@ -223,7 +223,7 @@
                 if (!mediaFlags.isSceneContainerEnabled()) {
                     MediaPlayerData.players().forEach { it.updateAnimatorDurationScale() }
                 } else {
-                    controllerByViewModel.values.forEach { it.updateAnimatorDurationScale() }
+                    controllerById.values.forEach { it.updateAnimatorDurationScale() }
                 }
             }
         }
@@ -324,7 +324,7 @@
     private var widthInSceneContainerPx = 0
     private var heightInSceneContainerPx = 0
 
-    private val controllerByViewModel = mutableMapOf<MediaCommonViewModel, MediaViewController>()
+    private val controllerById = mutableMapOf<String, MediaViewController>()
     private val commonViewModels = mutableListOf<MediaCommonViewModel>()
 
     init {
@@ -738,7 +738,7 @@
                     viewController.heightInSceneContainerPx = heightInSceneContainerPx
                 }
                 viewController.attachPlayer(viewHolder)
-                viewController.mediaViewHolder.player.layoutParams = lp
+                viewController.mediaViewHolder?.player?.layoutParams = lp
                 MediaControlViewBinder.bind(
                     viewHolder,
                     commonViewModel.controlViewModel,
@@ -749,12 +749,13 @@
                     mediaFlags
                 )
                 mediaContent.addView(viewHolder.player, position)
+                controllerById[commonViewModel.instanceId.toString()] = viewController
             }
             is MediaCommonViewModel.MediaRecommendations -> {
                 val viewHolder =
                     RecommendationViewHolder.create(LayoutInflater.from(context), mediaContent)
                 viewController.attachRecommendations(viewHolder)
-                viewController.recommendationViewHolder.recommendations.layoutParams = lp
+                viewController.recommendationViewHolder?.recommendations?.layoutParams = lp
                 MediaRecommendationsViewBinder.bind(
                     viewHolder,
                     commonViewModel.recsViewModel,
@@ -762,11 +763,11 @@
                     falsingManager,
                 )
                 mediaContent.addView(viewHolder.recommendations, position)
+                controllerById[commonViewModel.key] = viewController
             }
         }
         onAddOrUpdateVisibleToUserCard(position, isMediaCardUpdate = false)
         viewController.setListening(mediaCarouselScrollHandler.visibleToUser && currentlyExpanded)
-        controllerByViewModel[commonViewModel] = viewController
         updateViewControllerToState(viewController, noAnimation = true)
         updatePageIndicator()
         if (
@@ -793,14 +794,19 @@
     }
 
     private fun onRemoved(commonViewModel: MediaCommonViewModel) {
-        controllerByViewModel.remove(commonViewModel)?.let {
+        val id =
+            when (commonViewModel) {
+                is MediaCommonViewModel.MediaControl -> commonViewModel.instanceId.toString()
+                is MediaCommonViewModel.MediaRecommendations -> commonViewModel.key
+            }
+        controllerById.remove(id)?.let {
             when (commonViewModel) {
                 is MediaCommonViewModel.MediaControl -> {
-                    mediaCarouselScrollHandler.onPrePlayerRemoved(it.mediaViewHolder.player)
-                    mediaContent.removeView(it.mediaViewHolder.player)
+                    mediaCarouselScrollHandler.onPrePlayerRemoved(it.mediaViewHolder!!.player)
+                    mediaContent.removeView(it.mediaViewHolder!!.player)
                 }
                 is MediaCommonViewModel.MediaRecommendations -> {
-                    mediaContent.removeView(it.recommendationViewHolder.recommendations)
+                    mediaContent.removeView(it.recommendationViewHolder!!.recommendations)
                 }
             }
             it.onDestroy()
@@ -811,14 +817,19 @@
     }
 
     private fun onMoved(commonViewModel: MediaCommonViewModel, from: Int, to: Int) {
-        controllerByViewModel[commonViewModel]?.let {
+        val id =
+            when (commonViewModel) {
+                is MediaCommonViewModel.MediaControl -> commonViewModel.instanceId.toString()
+                is MediaCommonViewModel.MediaRecommendations -> commonViewModel.key
+            }
+        controllerById[id]?.let {
             mediaContent.removeViewAt(from)
             when (commonViewModel) {
                 is MediaCommonViewModel.MediaControl -> {
-                    mediaContent.addView(it.mediaViewHolder.player, to)
+                    mediaContent.addView(it.mediaViewHolder!!.player, to)
                 }
                 is MediaCommonViewModel.MediaRecommendations -> {
-                    mediaContent.addView(it.recommendationViewHolder.recommendations, to)
+                    mediaContent.addView(it.recommendationViewHolder!!.recommendations, to)
                 }
             }
         }
@@ -855,15 +866,16 @@
                     }
                 }
                 .toHashSet()
-        controllerByViewModel
-            .filter {
-                when (val viewModel = it.key) {
-                    is MediaCommonViewModel.MediaControl ->
-                        !viewIds.contains(viewModel.instanceId.toString())
-                    is MediaCommonViewModel.MediaRecommendations -> !viewIds.contains(viewModel.key)
-                }
+        controllerById
+            .filter { !viewIds.contains(it.key) }
+            .forEach {
+                mediaCarouselScrollHandler.onPrePlayerRemoved(it.value.mediaViewHolder?.player)
+                mediaContent.removeView(it.value.mediaViewHolder?.player)
+                mediaContent.removeView(it.value.recommendationViewHolder?.recommendations)
+                it.value.onDestroy()
+                mediaCarouselScrollHandler.onPlayersChanged()
+                updatePageIndicator()
             }
-            .forEach { onRemoved(it.key) }
     }
 
     private suspend fun getMediaLockScreenSetting(): Boolean {
@@ -1176,12 +1188,12 @@
             commonViewModels.forEach { viewModel ->
                 when (viewModel) {
                     is MediaCommonViewModel.MediaControl -> {
-                        controllerByViewModel[viewModel]?.mediaViewHolder?.let {
+                        controllerById[viewModel.instanceId.toString()]?.mediaViewHolder?.let {
                             mediaContent.addView(it.player)
                         }
                     }
                     is MediaCommonViewModel.MediaRecommendations -> {
-                        controllerByViewModel[viewModel]?.recommendationViewHolder?.let {
+                        controllerById[viewModel.key]?.recommendationViewHolder?.let {
                             mediaContent.addView(it.recommendations)
                         }
                     }
@@ -1234,9 +1246,7 @@
                     updateViewControllerToState(mediaPlayer.mediaViewController, immediately)
                 }
             } else {
-                controllerByViewModel.values.forEach {
-                    updateViewControllerToState(it, immediately)
-                }
+                controllerById.values.forEach { updateViewControllerToState(it, immediately) }
             }
             maybeResetSettingsCog()
             updatePageIndicatorAlpha()
@@ -1296,9 +1306,7 @@
                 player.setListening(visibleToUser && currentlyExpanded)
             }
         } else {
-            controllerByViewModel.values.forEach {
-                it.setListening(visibleToUser && currentlyExpanded)
-            }
+            controllerById.values.forEach { it.setListening(visibleToUser && currentlyExpanded) }
         }
     }
 
@@ -1316,7 +1324,7 @@
                     Math.max(height, controller.currentHeight + controller.translationY.toInt())
             }
         } else {
-            controllerByViewModel.values.forEach {
+            controllerById.values.forEach {
                 // When transitioning the view to gone, the view gets smaller, but the translation
                 // Doesn't, let's add the translation
                 width = Math.max(width, it.currentWidth + it.translationX.toInt())
@@ -1413,7 +1421,7 @@
                         mediaPlayer.mediaViewController.onLocationPreChange(desiredLocation)
                     }
                 } else {
-                    controllerByViewModel.values.forEach { controller ->
+                    controllerById.values.forEach { controller ->
                         if (animate) {
                             controller.animatePendingStateChange(duration, startDelay)
                         }
@@ -1441,7 +1449,7 @@
         if (!mediaFlags.isSceneContainerEnabled()) {
             MediaPlayerData.players().forEach { it.closeGuts(immediate) }
         } else {
-            controllerByViewModel.values.forEach { it.closeGuts(immediate) }
+            controllerById.values.forEach { it.closeGuts(immediate) }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt
index 681bf39..584908f 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaViewController.kt
@@ -196,8 +196,8 @@
     private var isNextButtonAvailable = false
 
     /** View holders for controller */
-    lateinit var recommendationViewHolder: RecommendationViewHolder
-    lateinit var mediaViewHolder: MediaViewHolder
+    var recommendationViewHolder: RecommendationViewHolder? = null
+    var mediaViewHolder: MediaViewHolder? = null
 
     private lateinit var seekBarObserver: SeekBarObserver
     private lateinit var turbulenceNoiseController: TurbulenceNoiseController
@@ -752,16 +752,18 @@
     private fun updateDisplayForScrubbingChange() {
         mainExecutor.execute {
             val isTimeVisible = canShowScrubbingTime && isScrubbing
-            MediaControlViewBinder.setVisibleAndAlpha(
-                expandedLayout,
-                mediaViewHolder.scrubbingTotalTimeView.id,
-                isTimeVisible
-            )
-            MediaControlViewBinder.setVisibleAndAlpha(
-                expandedLayout,
-                mediaViewHolder.scrubbingElapsedTimeView.id,
-                isTimeVisible
-            )
+            mediaViewHolder!!.let {
+                MediaControlViewBinder.setVisibleAndAlpha(
+                    expandedLayout,
+                    it.scrubbingTotalTimeView.id,
+                    isTimeVisible
+                )
+                MediaControlViewBinder.setVisibleAndAlpha(
+                    expandedLayout,
+                    it.scrubbingElapsedTimeView.id,
+                    isTimeVisible
+                )
+            }
 
             MediaControlViewModel.SEMANTIC_ACTIONS_HIDE_WHEN_SCRUBBING.forEach { id ->
                 val isButtonVisible: Boolean
@@ -780,14 +782,16 @@
                         notVisibleValue = ConstraintSet.GONE
                     }
                 }
-                MediaControlViewBinder.setSemanticButtonVisibleAndAlpha(
-                    mediaViewHolder.getAction(id),
-                    expandedLayout,
-                    collapsedLayout,
-                    isButtonVisible,
-                    notVisibleValue,
-                    showInCollapsed = true
-                )
+                mediaViewHolder!!.let {
+                    MediaControlViewBinder.setSemanticButtonVisibleAndAlpha(
+                        it.getAction(id),
+                        expandedLayout,
+                        collapsedLayout,
+                        isButtonVisible,
+                        notVisibleValue,
+                        showInCollapsed = true
+                    )
+                }
             }
 
             if (!metadataAnimationHandler.isRunning) {
@@ -813,39 +817,41 @@
 
     fun setUpTurbulenceNoise() {
         if (!mediaFlags.isSceneContainerEnabled()) return
-        if (!this::turbulenceNoiseAnimationConfig.isInitialized) {
-            turbulenceNoiseAnimationConfig =
-                createTurbulenceNoiseConfig(
-                    mediaViewHolder.loadingEffectView,
-                    mediaViewHolder.turbulenceNoiseView,
-                    colorSchemeTransition
-                )
-        }
-        if (Flags.shaderlibLoadingEffectRefactor()) {
-            if (!this::loadingEffect.isInitialized) {
-                loadingEffect =
-                    LoadingEffect(
-                        TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE,
-                        turbulenceNoiseAnimationConfig,
-                        noiseDrawCallback,
-                        stateChangedCallback
+        mediaViewHolder!!.let {
+            if (!this::turbulenceNoiseAnimationConfig.isInitialized) {
+                turbulenceNoiseAnimationConfig =
+                    createTurbulenceNoiseConfig(
+                        it.loadingEffectView,
+                        it.turbulenceNoiseView,
+                        colorSchemeTransition
                     )
             }
-            colorSchemeTransition.loadingEffect = loadingEffect
-            loadingEffect.play()
-            mainExecutor.executeDelayed(
-                loadingEffect::finish,
-                MediaControlViewModel.TURBULENCE_NOISE_PLAY_MS_DURATION
-            )
-        } else {
-            turbulenceNoiseController.play(
-                TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE,
-                turbulenceNoiseAnimationConfig
-            )
-            mainExecutor.executeDelayed(
-                turbulenceNoiseController::finish,
-                MediaControlViewModel.TURBULENCE_NOISE_PLAY_MS_DURATION
-            )
+            if (Flags.shaderlibLoadingEffectRefactor()) {
+                if (!this::loadingEffect.isInitialized) {
+                    loadingEffect =
+                        LoadingEffect(
+                            TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE,
+                            turbulenceNoiseAnimationConfig,
+                            noiseDrawCallback,
+                            stateChangedCallback
+                        )
+                }
+                colorSchemeTransition.loadingEffect = loadingEffect
+                loadingEffect.play()
+                mainExecutor.executeDelayed(
+                    loadingEffect::finish,
+                    MediaControlViewModel.TURBULENCE_NOISE_PLAY_MS_DURATION
+                )
+            } else {
+                turbulenceNoiseController.play(
+                    TurbulenceNoiseShader.Companion.Type.SIMPLEX_NOISE,
+                    turbulenceNoiseAnimationConfig
+                )
+                mainExecutor.executeDelayed(
+                    turbulenceNoiseController::finish,
+                    MediaControlViewModel.TURBULENCE_NOISE_PLAY_MS_DURATION
+                )
+            }
         }
     }